blob: edb21398179adb64c91b80cf32e5023cfe08da12 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel
*
*/
#ifndef _LOOP_UTILS_H_
#define _LOOP_UTILS_H_
#include "open/types.h"
#include "Opnd.h"
#include "LoopTree.h"
namespace Jitrino {
class OpndLoopInfo;
class InductiveOpndLoopInfo;
class InvariantOpndLoopInfo;
class ConstOpndLoopInfo;
class InductionDetector;
enum IVDetectionMode {
CHOOSE_MAX_IN_BRANCH = 0,
IGNORE_BRANCH
};
enum BoundType {
UNKNOWN_BOUND = 0,
EQ_BOUND,
NE_BOUND,
LOW_BOUND,
LOW_EQ_BOUND,
UPPER_BOUND,
UPPER_EQ_BOUND
};
class OpndLoopInfo {
friend class InductionDetector;
public:
virtual SsaOpnd* getOpnd() const { return mainOpnd; }
virtual bool isInductive() const = 0;
virtual bool isInvariant() const = 0;
virtual bool isConstant() const = 0;
virtual InductiveOpndLoopInfo* asInductive() {
return isInductive() ? (InductiveOpndLoopInfo*)this : NULL;
}
virtual InvariantOpndLoopInfo* asInvarinat() {
return isInvariant() ? (InvariantOpndLoopInfo*)this : NULL;
}
virtual ConstOpndLoopInfo* asConstant() {
return isConstant() ? (ConstOpndLoopInfo*)this : NULL;
}
protected:
OpndLoopInfo(InductionDetector* id, SsaOpnd* opnd):
mainOpnd(opnd), inductionDetector(id) {};
virtual ~OpndLoopInfo() {}
SsaOpnd* mainOpnd;
InductionDetector* inductionDetector;
};
class InductiveOpndLoopInfo : public OpndLoopInfo {
friend class InductionDetector;
public:
virtual bool isInductive() const { return true; }
virtual bool isInvariant() const { return false; }
virtual bool isConstant() const { return false; }
/**
* @returns scale info or null if scale operand is equal to 1.
* @see getBase
*/
InvariantOpndLoopInfo* getScale() { return scale; }
/**
* An induction variable is a variable that gets increased or decreased
* by a fixed amount on every iteration of a loop, or is a linear function
* of another induction variable. Thus it can be represented in general form
* as follows scale * base + stride, where scale and stride are loop invariants,
* base is loop induction variable.
*
* @returns info about dependent induction variable or null if induction variable
* depends on itself.
*/
InductiveOpndLoopInfo* getBase() { return base; }
/**
* @returns stride info or null if stride operand is equal to 0.
* @see getBase
*/
InvariantOpndLoopInfo* getStride() { return stride; }
/**
* Any induction variable takes values between its bounds. Inductive variable is equal to
* its initial value at the first loop iteration.
*
* @returns info about initial value of the inductive variable or NULL if it cant be determined.
* @note if initial value isnt proven to be loop invariant NULL will be returned.
*/
InvariantOpndLoopInfo* getStartValue();
/**
* Any induction variable takes values between its bounds. End value determines maximum
* possible range where induction variable may vary.
*
* @returns info about ending value of the inductive variable or NULL if it cant be determined.
* @note if ending value isnt proven to be loop invariant NULL will be returned.
*/
InvariantOpndLoopInfo* getEndValue();
/**
* Sets up start value of inductive variable.
*/
void setStartValue(InvariantOpndLoopInfo* start);
/**
* Sets up end value of inductive variable.
*/
void setEndValue(InvariantOpndLoopInfo* end);
/**
* Inductive varible can be limited by different type of constraints:
* 1) var == endValue or var != endValue is STRICT_BOUND
* 2) var > endValue or var >= endValue is LOW_BOUND
* 3) var < endValue or var <= endValue is UPPER_BOUND
*
* @returns type of the bound which limits inductive variable.
*/
BoundType getBoundType();
protected:
InductiveOpndLoopInfo(InductionDetector* id, SsaOpnd* opnd,
InvariantOpndLoopInfo* scaleInfo,
InductiveOpndLoopInfo* baseInfo,
InvariantOpndLoopInfo* strideInfo):
OpndLoopInfo(id, opnd), scale(scaleInfo),
base(baseInfo), stride(strideInfo),
startValue(NULL), endValue(NULL), boundType(UNKNOWN_BOUND),
header(NULL), isPhiSplit(false) {
base = (base == NULL) ? this : base;
}
virtual ~InductiveOpndLoopInfo() {}
private:
void findBoundInfo();
InvariantOpndLoopInfo* scale;
InductiveOpndLoopInfo* base;
InvariantOpndLoopInfo* stride;
InvariantOpndLoopInfo* startValue;
InvariantOpndLoopInfo* endValue;
BoundType boundType;
// implementation specific
SsaOpnd* header;
bool isPhiSplit;
};
class InvariantOpndLoopInfo : public OpndLoopInfo {
friend class InductionDetector;
public:
virtual bool isInductive() const { return false; }
virtual bool isInvariant() const { return true; }
virtual bool isConstant() const { return false; }
protected:
InvariantOpndLoopInfo(InductionDetector* id, SsaOpnd* opnd): OpndLoopInfo(id, opnd) {}
virtual ~InvariantOpndLoopInfo() {}
};
class ConstOpndLoopInfo : public InvariantOpndLoopInfo {
friend class InductionDetector;
public:
virtual bool isConstant() const { return true; }
I_32 getValue() const { return value; }
protected:
ConstOpndLoopInfo(InductionDetector* id, SsaOpnd* opnd, I_32 val):
InvariantOpndLoopInfo(id, opnd), value(val) {}
virtual ~ConstOpndLoopInfo() {}
private:
I_32 value;
};
// TODO: Should be able to detect linear induction.
class InductionDetector {
friend class InductiveOpndLoopInfo;
public:
static InductionDetector* create(MemoryManager& mm, LoopNode* loop) {
return new (mm) InductionDetector(mm, loop);
}
InductiveOpndLoopInfo*
createInductiveOpnd(SsaOpnd* opnd,
InvariantOpndLoopInfo* scaleInfo,
InductiveOpndLoopInfo* baseInfo,
InvariantOpndLoopInfo* strideInfo) {
return new (memoryManager)
InductiveOpndLoopInfo(this, opnd, scaleInfo, baseInfo, strideInfo);
}
InvariantOpndLoopInfo* createInvariantOpnd(SsaOpnd* opnd) {
return new (memoryManager) InvariantOpndLoopInfo(this, opnd);
}
ConstOpndLoopInfo* createConstOpnd(SsaOpnd* opnd, I_32 val) {
return new (memoryManager) ConstOpndLoopInfo(this, opnd, val);
}
OpndLoopInfo* getOpndInfo(SsaOpnd * opnd, IVDetectionMode mode = IGNORE_BRANCH);
private:
InductionDetector(MemoryManager& mm, LoopNode* loop);
OpndLoopInfo* processOpnd(SsaOpnd * opnd);
MemoryManager& memoryManager;
LoopNode* loopNode;
StlVector<Inst*> defStack;
ConstOpndLoopInfo* zero;
ConstOpndLoopInfo* one;
IVDetectionMode ivMode;
};
} // namesapce Jitrino
#endif /*_LOOP_UTILS_H_*/