parent
4ee51f4ede
commit
2c6f274188
|
@ -13,48 +13,46 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
class Value;
|
class Value;
|
||||||
class ConstPoolInt;
|
class ConstPoolInt;
|
||||||
struct ExprAnalysisResult;
|
|
||||||
|
namespace analysis {
|
||||||
|
|
||||||
|
struct ExprType;
|
||||||
|
|
||||||
// ClassifyExpression: Analyze an expression to determine the complexity of the
|
// ClassifyExpression: Analyze an expression to determine the complexity of the
|
||||||
// expression, and which other values it depends on.
|
// expression, and which other values it depends on.
|
||||||
//
|
//
|
||||||
ExprAnalysisResult ClassifyExpression(Value *Expr);
|
ExprType ClassifyExpression(Value *Expr);
|
||||||
|
|
||||||
// ExprAnalysisResult - Represent an expression of the form CONST*VAR+CONST
|
// ExprType - Represent an expression of the form CONST*VAR+CONST
|
||||||
// or simpler. The expression form that yields the least information about the
|
// or simpler. The expression form that yields the least information about the
|
||||||
// expression is just the Linear form with no offset.
|
// expression is just the Linear form with no offset.
|
||||||
//
|
//
|
||||||
struct ExprAnalysisResult {
|
struct ExprType {
|
||||||
enum ExpressionType {
|
enum ExpressionType {
|
||||||
Constant, // Expr is a simple constant, Offset is value
|
Constant, // Expr is a simple constant, Offset is value
|
||||||
Linear, // Expr is linear expr, Value is Var+Offset
|
Linear, // Expr is linear expr, Value is Var+Offset
|
||||||
ScaledLinear, // Expr is scaled linear exp, Value is Scale*Var+Offset
|
ScaledLinear, // Expr is scaled linear exp, Value is Scale*Var+Offset
|
||||||
} ExprType;
|
} ExprTy;
|
||||||
|
|
||||||
const ConstPoolInt *Offset; // Offset of expr, or null if 0
|
const ConstPoolInt *Offset; // Offset of expr, or null if 0
|
||||||
Value *Var; // Var referenced, if Linear or above (null if 0)
|
Value *Var; // Var referenced, if Linear or above (null if 0)
|
||||||
const ConstPoolInt *Scale; // Scale of var if ScaledLinear expr (null if 1)
|
const ConstPoolInt *Scale; // Scale of var if ScaledLinear expr (null if 1)
|
||||||
|
|
||||||
inline ExprAnalysisResult(const ConstPoolInt *CPV = 0) {
|
inline ExprType(const ConstPoolInt *CPV = 0) {
|
||||||
Offset = CPV; Var = 0; Scale = 0;
|
Offset = CPV; Var = 0; Scale = 0;
|
||||||
ExprType = Constant;
|
ExprTy = Constant;
|
||||||
}
|
}
|
||||||
inline ExprAnalysisResult(Value *Val) {
|
inline ExprType(Value *Val) {
|
||||||
Var = Val; Offset = Scale = 0;
|
Var = Val; Offset = Scale = 0;
|
||||||
ExprType = Var ? Linear : Constant;
|
ExprTy = Var ? Linear : Constant;
|
||||||
}
|
}
|
||||||
inline ExprAnalysisResult(const ConstPoolInt *scale, Value *var,
|
inline ExprType(const ConstPoolInt *scale, Value *var,
|
||||||
const ConstPoolInt *offset) {
|
const ConstPoolInt *offset) {
|
||||||
assert(!(Scale && !Var) && "Can't have scaled nonvariable!");
|
|
||||||
Scale = scale; Var = var; Offset = offset;
|
Scale = scale; Var = var; Offset = offset;
|
||||||
ExprType = Scale ? ScaledLinear : (Var ? Linear : Constant);
|
ExprTy = Scale ? ScaledLinear : (Var ? Linear : Constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend ExprAnalysisResult ClassifyExpression(Value *);
|
|
||||||
inline ExprAnalysisResult operator+(const ConstPoolInt *Offset);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // End namespace analysis
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,36 @@
|
||||||
#include "llvm/BasicBlock.h"
|
#include "llvm/BasicBlock.h"
|
||||||
|
|
||||||
using namespace opt; // Get all the constant handling stuff
|
using namespace opt; // Get all the constant handling stuff
|
||||||
|
using namespace analysis;
|
||||||
|
|
||||||
|
class DefVal {
|
||||||
|
const ConstPoolInt * const Val;
|
||||||
|
ConstantPool &CP;
|
||||||
|
const Type * const Ty;
|
||||||
|
protected:
|
||||||
|
inline DefVal(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
|
||||||
|
: Val(val), CP(cp), Ty(ty) {}
|
||||||
|
public:
|
||||||
|
inline const Type *getType() const { return Ty; }
|
||||||
|
inline ConstantPool &getCP() const { return CP; }
|
||||||
|
inline const ConstPoolInt *getVal() const { return Val; }
|
||||||
|
inline operator const ConstPoolInt * () const { return Val; }
|
||||||
|
inline const ConstPoolInt *operator->() const { return Val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefZero : public DefVal {
|
||||||
|
inline DefZero(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
|
||||||
|
: DefVal(val, cp, ty) {}
|
||||||
|
inline DefZero(const ConstPoolInt *val)
|
||||||
|
: DefVal(val, (ConstantPool&)val->getParent()->getConstantPool(),
|
||||||
|
val->getType()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefOne : public DefVal {
|
||||||
|
inline DefOne(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
|
||||||
|
: DefVal(val, cp, ty) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// getIntegralConstant - Wrapper around the ConstPoolInt member of the same
|
// getIntegralConstant - Wrapper around the ConstPoolInt member of the same
|
||||||
// name. This method first checks to see if the desired constant is already in
|
// name. This method first checks to see if the desired constant is already in
|
||||||
|
@ -29,15 +59,16 @@ static ConstPoolInt *getIntegralConstant(ConstantPool &CP, unsigned char V,
|
||||||
return CPI;
|
return CPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ConstPoolUInt *getUnsignedConstant(ConstantPool &CP, uint64_t V) {
|
static ConstPoolInt *getUnsignedConstant(ConstantPool &CP, uint64_t V,
|
||||||
|
const Type *Ty) {
|
||||||
// FIXME: Lookup prexisting constant in table!
|
// FIXME: Lookup prexisting constant in table!
|
||||||
|
|
||||||
ConstPoolUInt *CPUI = new ConstPoolUInt(Type::ULongTy, V);
|
ConstPoolInt *CPI;
|
||||||
CP.insert(CPUI);
|
CPI = Ty->isSigned() ? new ConstPoolSInt(Ty, V) : new ConstPoolUInt(Ty, V);
|
||||||
return CPUI;
|
CP.insert(CPI);
|
||||||
|
return CPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add - Helper function to make later code simpler. Basically it just adds
|
// Add - Helper function to make later code simpler. Basically it just adds
|
||||||
// the two constants together, inserts the result into the constant pool, and
|
// the two constants together, inserts the result into the constant pool, and
|
||||||
// returns it. Of course life is not simple, and this is no exception. Factors
|
// returns it. Of course life is not simple, and this is no exception. Factors
|
||||||
|
@ -50,29 +81,20 @@ static ConstPoolUInt *getUnsignedConstant(ConstantPool &CP, uint64_t V) {
|
||||||
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
|
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
|
||||||
// is false, a null return value indicates a value of 0.
|
// is false, a null return value indicates a value of 0.
|
||||||
//
|
//
|
||||||
inline const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1,
|
static const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1,
|
||||||
const ConstPoolInt *Arg2, bool DefOne = false) {
|
const ConstPoolInt *Arg2, bool DefOne) {
|
||||||
if (DefOne == false) { // Handle degenerate cases first...
|
|
||||||
if (Arg1 == 0) return Arg2; // Also handles case of Arg1 == Arg2 == 0
|
|
||||||
if (Arg2 == 0) return Arg1;
|
|
||||||
} else { // These aren't degenerate... :(
|
|
||||||
if (Arg1 == 0 && Arg2 == 0) return getIntegralConstant(CP, 2, Type::UIntTy);
|
|
||||||
if (Arg1 == 0) Arg1 = getIntegralConstant(CP, 1, Arg2->getType());
|
|
||||||
if (Arg2 == 0) Arg2 = getIntegralConstant(CP, 1, Arg2->getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(Arg1 && Arg2 && "No null arguments should exist now!");
|
assert(Arg1 && Arg2 && "No null arguments should exist now!");
|
||||||
|
assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
|
||||||
// FIXME: Make types compatible!
|
|
||||||
|
|
||||||
// Actually perform the computation now!
|
// Actually perform the computation now!
|
||||||
ConstPoolVal *Result = *Arg1 + *Arg2;
|
ConstPoolVal *Result = *Arg1 + *Arg2;
|
||||||
assert(Result && Result->getType()->isIntegral() && "Couldn't perform add!");
|
assert(Result && Result->getType() == Arg1->getType() &&
|
||||||
|
"Couldn't perform addition!");
|
||||||
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
|
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
|
||||||
|
|
||||||
// Check to see if the result is one of the special cases that we want to
|
// Check to see if the result is one of the special cases that we want to
|
||||||
// recognize...
|
// recognize...
|
||||||
if (ResultI->equals(DefOne ? 1 : 0)) {
|
if (ResultI->equalsInt(DefOne ? 1 : 0)) {
|
||||||
// Yes it is, simply delete the constant and return null.
|
// Yes it is, simply delete the constant and return null.
|
||||||
delete ResultI;
|
delete ResultI;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -82,16 +104,28 @@ inline const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1,
|
||||||
return ResultI;
|
return ResultI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ConstPoolInt *operator+(const DefZero &L, const DefZero &R) {
|
||||||
|
if (L == 0) return R;
|
||||||
|
if (R == 0) return L;
|
||||||
|
return Add(L.getCP(), L, R, false);
|
||||||
|
}
|
||||||
|
|
||||||
ExprAnalysisResult ExprAnalysisResult::operator+(const ConstPoolInt *NewOff) {
|
inline const ConstPoolInt *operator+(const DefOne &L, const DefOne &R) {
|
||||||
if (NewOff == 0) return *this; // No change!
|
if (L == 0) {
|
||||||
|
if (R == 0)
|
||||||
ConstantPool &CP = (ConstantPool&)NewOff->getParent()->getConstantPool();
|
return getIntegralConstant(L.getCP(), 2, L.getType());
|
||||||
return ExprAnalysisResult(Scale, Var, Add(CP, Offset, NewOff));
|
else
|
||||||
|
return Add(L.getCP(), getIntegralConstant(L.getCP(), 1, L.getType()),
|
||||||
|
R, true);
|
||||||
|
} else if (R == 0) {
|
||||||
|
return Add(L.getCP(), L,
|
||||||
|
getIntegralConstant(L.getCP(), 1, L.getType()), true);
|
||||||
|
}
|
||||||
|
return Add(L.getCP(), L, R, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Mult - Helper function to make later code simpler. Basically it just
|
// Mul - Helper function to make later code simpler. Basically it just
|
||||||
// multiplies the two constants together, inserts the result into the constant
|
// multiplies the two constants together, inserts the result into the constant
|
||||||
// pool, and returns it. Of course life is not simple, and this is no
|
// pool, and returns it. Of course life is not simple, and this is no
|
||||||
// exception. Factors that complicate matters:
|
// exception. Factors that complicate matters:
|
||||||
|
@ -103,26 +137,20 @@ ExprAnalysisResult ExprAnalysisResult::operator+(const ConstPoolInt *NewOff) {
|
||||||
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
|
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
|
||||||
// is false, a null return value indicates a value of 0.
|
// is false, a null return value indicates a value of 0.
|
||||||
//
|
//
|
||||||
inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1,
|
inline const ConstPoolInt *Mul(ConstantPool &CP, const ConstPoolInt *Arg1,
|
||||||
const ConstPoolInt *Arg2, bool DefOne = false) {
|
const ConstPoolInt *Arg2, bool DefOne = false) {
|
||||||
if (DefOne == false) { // Handle degenerate cases first...
|
|
||||||
if (Arg1 == 0 || Arg2 == 0) return 0; // 0 * x == 0
|
|
||||||
} else { // These aren't degenerate... :(
|
|
||||||
if (Arg1 == 0) return Arg2; // Also handles case of Arg1 == Arg2 == 0
|
|
||||||
if (Arg2 == 0) return Arg1;
|
|
||||||
}
|
|
||||||
assert(Arg1 && Arg2 && "No null arguments should exist now!");
|
assert(Arg1 && Arg2 && "No null arguments should exist now!");
|
||||||
|
assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
|
||||||
// FIXME: Make types compatible!
|
|
||||||
|
|
||||||
// Actually perform the computation now!
|
// Actually perform the computation now!
|
||||||
ConstPoolVal *Result = *Arg1 * *Arg2;
|
ConstPoolVal *Result = *Arg1 * *Arg2;
|
||||||
assert(Result && Result->getType()->isIntegral() && "Couldn't perform mult!");
|
assert(Result && Result->getType() == Arg1->getType() &&
|
||||||
|
"Couldn't perform mult!");
|
||||||
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
|
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
|
||||||
|
|
||||||
// Check to see if the result is one of the special cases that we want to
|
// Check to see if the result is one of the special cases that we want to
|
||||||
// recognize...
|
// recognize...
|
||||||
if (ResultI->equals(DefOne ? 1 : 0)) {
|
if (ResultI->equalsInt(DefOne ? 1 : 0)) {
|
||||||
// Yes it is, simply delete the constant and return null.
|
// Yes it is, simply delete the constant and return null.
|
||||||
delete ResultI;
|
delete ResultI;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -132,6 +160,20 @@ inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1,
|
||||||
return ResultI;
|
return ResultI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ConstPoolInt *operator*(const DefZero &L, const DefZero &R) {
|
||||||
|
if (L == 0 || R == 0) return 0;
|
||||||
|
return Mul(L.getCP(), L, R, false);
|
||||||
|
}
|
||||||
|
inline const ConstPoolInt *operator*(const DefOne &L, const DefZero &R) {
|
||||||
|
if (R == 0) return getIntegralConstant(L.getCP(), 0, L.getType());
|
||||||
|
if (L == 0) return R->equalsInt(1) ? 0 : R.getVal();
|
||||||
|
return Mul(L.getCP(), L, R, false);
|
||||||
|
}
|
||||||
|
inline const ConstPoolInt *operator*(const DefZero &L, const DefOne &R) {
|
||||||
|
return R*L;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ClassifyExpression: Analyze an expression to determine the complexity of the
|
// ClassifyExpression: Analyze an expression to determine the complexity of the
|
||||||
// expression, and which other values it depends on.
|
// expression, and which other values it depends on.
|
||||||
|
@ -139,7 +181,7 @@ inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1,
|
||||||
// Note that this analysis cannot get into infinite loops because it treats PHI
|
// Note that this analysis cannot get into infinite loops because it treats PHI
|
||||||
// nodes as being an unknown linear expression.
|
// nodes as being an unknown linear expression.
|
||||||
//
|
//
|
||||||
ExprAnalysisResult ClassifyExpression(Value *Expr) {
|
ExprType analysis::ClassifyExpression(Value *Expr) {
|
||||||
assert(Expr != 0 && "Can't classify a null expression!");
|
assert(Expr != 0 && "Can't classify a null expression!");
|
||||||
switch (Expr->getValueType()) {
|
switch (Expr->getValueType()) {
|
||||||
case Value::InstructionVal: break; // Instruction... hmmm... investigate.
|
case Value::InstructionVal: break; // Instruction... hmmm... investigate.
|
||||||
|
@ -152,56 +194,89 @@ ExprAnalysisResult ClassifyExpression(Value *Expr) {
|
||||||
ConstPoolVal *CPV = Expr->castConstantAsserting();
|
ConstPoolVal *CPV = Expr->castConstantAsserting();
|
||||||
if (CPV->getType()->isIntegral()) { // It's an integral constant!
|
if (CPV->getType()->isIntegral()) { // It's an integral constant!
|
||||||
ConstPoolInt *CPI = (ConstPoolInt*)Expr;
|
ConstPoolInt *CPI = (ConstPoolInt*)Expr;
|
||||||
return ExprAnalysisResult(CPI->equals(0) ? 0 : (ConstPoolInt*)Expr);
|
return ExprType(CPI->equalsInt(0) ? 0 : (ConstPoolInt*)Expr);
|
||||||
}
|
}
|
||||||
return Expr;
|
return Expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction *I = Expr->castInstructionAsserting();
|
Instruction *I = Expr->castInstructionAsserting();
|
||||||
ConstantPool &CP = I->getParent()->getParent()->getConstantPool();
|
ConstantPool &CP = I->getParent()->getParent()->getConstantPool();
|
||||||
|
const Type *Ty = I->getType();
|
||||||
|
|
||||||
switch (I->getOpcode()) { // Handle each instruction type seperately
|
switch (I->getOpcode()) { // Handle each instruction type seperately
|
||||||
case Instruction::Add: {
|
case Instruction::Add: {
|
||||||
ExprAnalysisResult LeftTy (ClassifyExpression(I->getOperand(0)));
|
ExprType Left (ClassifyExpression(I->getOperand(0)));
|
||||||
ExprAnalysisResult RightTy(ClassifyExpression(I->getOperand(1)));
|
ExprType Right(ClassifyExpression(I->getOperand(1)));
|
||||||
if (LeftTy.ExprType > RightTy.ExprType)
|
if (Left.ExprTy > Right.ExprTy)
|
||||||
swap(LeftTy, RightTy); // Make left be simpler than right
|
swap(Left, Right); // Make left be simpler than right
|
||||||
|
|
||||||
switch (LeftTy.ExprType) {
|
switch (Left.ExprTy) {
|
||||||
case ExprAnalysisResult::Constant:
|
case ExprType::Constant:
|
||||||
return RightTy + LeftTy.Offset;
|
return ExprType(Right.Scale, Right.Var,
|
||||||
case ExprAnalysisResult::Linear: // RHS side must be linear or scaled
|
DefZero(Right.Offset,CP,Ty) + DefZero(Left.Offset, CP,Ty));
|
||||||
case ExprAnalysisResult::ScaledLinear: // RHS must be scaled
|
case ExprType::Linear: // RHS side must be linear or scaled
|
||||||
if (LeftTy.Var != RightTy.Var) // Are they the same variables?
|
case ExprType::ScaledLinear: // RHS must be scaled
|
||||||
return ExprAnalysisResult(I); // if not, we don't know anything!
|
if (Left.Var != Right.Var) // Are they the same variables?
|
||||||
|
return ExprType(I); // if not, we don't know anything!
|
||||||
|
|
||||||
const ConstPoolInt *NewScale = Add(CP, LeftTy.Scale, RightTy.Scale,true);
|
return ExprType(DefOne(Left.Scale ,CP,Ty) + DefOne(Right.Scale , CP,Ty),
|
||||||
const ConstPoolInt *NewOffset = Add(CP, LeftTy.Offset, RightTy.Offset);
|
Left.Var,
|
||||||
return ExprAnalysisResult(NewScale, LeftTy.Var, NewOffset);
|
DefZero(Left.Offset,CP,Ty) + DefZero(Right.Offset, CP,Ty));
|
||||||
}
|
}
|
||||||
} // end case Instruction::Add
|
} // end case Instruction::Add
|
||||||
|
|
||||||
case Instruction::Shl: {
|
case Instruction::Shl: {
|
||||||
ExprAnalysisResult RightTy(ClassifyExpression(I->getOperand(1)));
|
ExprType Right(ClassifyExpression(I->getOperand(1)));
|
||||||
if (RightTy.ExprType != ExprAnalysisResult::Constant)
|
if (Right.ExprTy != ExprType::Constant) break;
|
||||||
break; // TODO: Can get some info if it's (<unsigned> X + <offset>)
|
ExprType Left(ClassifyExpression(I->getOperand(0)));
|
||||||
|
if (Right.Offset == 0) return Left; // shl x, 0 = x
|
||||||
ExprAnalysisResult LeftTy (ClassifyExpression(I->getOperand(0)));
|
assert(Right.Offset->getType() == Type::UByteTy &&
|
||||||
if (RightTy.Offset == 0) return LeftTy; // shl x, 0 = x
|
|
||||||
assert(RightTy.Offset->getType() == Type::UByteTy &&
|
|
||||||
"Shift amount must always be a unsigned byte!");
|
"Shift amount must always be a unsigned byte!");
|
||||||
uint64_t ShiftAmount = ((ConstPoolUInt*)RightTy.Offset)->getValue();
|
uint64_t ShiftAmount = ((ConstPoolUInt*)Right.Offset)->getValue();
|
||||||
ConstPoolUInt *Multiplier = getUnsignedConstant(CP, 1ULL << ShiftAmount);
|
ConstPoolInt *Multiplier = getUnsignedConstant(CP, 1ULL << ShiftAmount, Ty);
|
||||||
|
|
||||||
return ExprAnalysisResult(Mult(CP, LeftTy.Scale, Multiplier, true),
|
return ExprType(DefOne(Left.Scale, CP, Ty) * Multiplier,
|
||||||
LeftTy.Var,
|
Left.Var,
|
||||||
Mult(CP, LeftTy.Offset, Multiplier));
|
DefZero(Left.Offset, CP, Ty) * Multiplier);
|
||||||
} // end case Instruction::Shl
|
} // end case Instruction::Shl
|
||||||
|
|
||||||
// TODO: Handle CAST, SUB, MULT (at least!)
|
case Instruction::Mul: {
|
||||||
|
ExprType Left (ClassifyExpression(I->getOperand(0)));
|
||||||
|
ExprType Right(ClassifyExpression(I->getOperand(1)));
|
||||||
|
if (Left.ExprTy > Right.ExprTy)
|
||||||
|
swap(Left, Right); // Make left be simpler than right
|
||||||
|
|
||||||
|
if (Left.ExprTy != ExprType::Constant) // RHS must be > constant
|
||||||
|
return I; // Quadratic eqn! :(
|
||||||
|
|
||||||
|
const ConstPoolInt *Offs = Left.Offset;
|
||||||
|
if (Offs == 0) return ExprType();
|
||||||
|
return ExprType(DefOne(Right.Scale, CP, Ty) * Offs,
|
||||||
|
Right.Var,
|
||||||
|
DefZero(Right.Offset, CP, Ty) * Offs);
|
||||||
|
} // end case Instruction::Mul
|
||||||
|
|
||||||
|
case Instruction::Cast: {
|
||||||
|
ExprType Src(ClassifyExpression(I->getOperand(0)));
|
||||||
|
if (Src.ExprTy != ExprType::Constant)
|
||||||
|
return I;
|
||||||
|
const ConstPoolInt *Offs = Src.Offset;
|
||||||
|
if (Offs == 0) return ExprType();
|
||||||
|
|
||||||
|
if (I->getType()->isPointerType())
|
||||||
|
return Offs; // Pointer types do not lose precision
|
||||||
|
|
||||||
|
assert(I->getType()->isIntegral() && "Can only handle integral types!");
|
||||||
|
|
||||||
|
const ConstPoolVal *CPV = ConstRules::get(*Offs)->castTo(Offs, I->getType());
|
||||||
|
if (!CPV) return I;
|
||||||
|
assert(CPV->getType()->isIntegral() && "Must have an integral type!");
|
||||||
|
return (ConstPoolInt*)CPV;
|
||||||
|
} // end case Instruction::Cast
|
||||||
|
// TODO: Handle SUB (at least!)
|
||||||
|
|
||||||
} // end switch
|
} // end switch
|
||||||
|
|
||||||
// Otherwise, I don't know anything about this value!
|
// Otherwise, I don't know anything about this value!
|
||||||
return ExprAnalysisResult(I);
|
return I;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue