Generalize the "trunc(ptrtoint(x)) - trunc(ptrtoint(y)) ->

trunc(ptrtoint(x-y))" optimization introduced by Chandler.

llvm-svn: 152626
This commit is contained in:
Duncan Sands 2012-03-13 14:07:05 +00:00
parent b10480f6a4
commit 395ac42dd2
3 changed files with 55 additions and 19 deletions

View File

@ -20,13 +20,14 @@
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
namespace llvm {
class DominatorTree;
class Instruction;
class Value;
class TargetData;
class TargetLibraryInfo;
template<typename T>
class ArrayRef;
class DominatorTree;
class Instruction;
class TargetData;
class TargetLibraryInfo;
class Type;
class Value;
/// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null.
@ -158,6 +159,12 @@ namespace llvm {
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const TargetData *TD = 0,
const TargetLibraryInfo *TLI = 0,
const DominatorTree *DT = 0);
//=== Helper functions for higher up the class hierarchy.

View File

@ -56,6 +56,7 @@ static Value *SimplifyCmpInst(unsigned, Value *, Value *, const Query &,
unsigned);
static Value *SimplifyOrInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyXorInst(Value *, Value *, const Query &, unsigned);
static Value *SimplifyTruncInst(Value *, Type *, const Query &, unsigned);
/// getFalse - For a boolean type, or a vector of boolean type, return false, or
/// a vector with every element false, as appropriate for the type.
@ -777,20 +778,6 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
match(Op0, m_Shl(m_Specific(Op1), m_One())))
return Op1;
if (Q.TD) {
Value *LHSOp, *RHSOp;
if (match(Op0, m_PtrToInt(m_Value(LHSOp))) &&
match(Op1, m_PtrToInt(m_Value(RHSOp))))
if (Constant *Result = computePointerDifference(*Q.TD, LHSOp, RHSOp))
return ConstantExpr::getIntegerCast(Result, Op0->getType(), true);
// trunc(p)-trunc(q) -> trunc(p-q)
if (match(Op0, m_Trunc(m_PtrToInt(m_Value(LHSOp)))) &&
match(Op1, m_Trunc(m_PtrToInt(m_Value(RHSOp)))))
if (Constant *Result = computePointerDifference(*Q.TD, LHSOp, RHSOp))
return ConstantExpr::getIntegerCast(Result, Op0->getType(), true);
}
// (X + Y) - Z -> X + (Y - Z) or Y + (X - Z) if everything simplifies.
// For example, (X + Y) - Y -> X; (Y + X) - Y -> X
Value *Y = 0, *Z = Op1;
@ -848,6 +835,23 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
return W;
}
// trunc(X) - trunc(Y) -> trunc(X - Y) if everything simplifies.
if (MaxRecurse && match(Op0, m_Trunc(m_Value(X))) &&
match(Op1, m_Trunc(m_Value(Y))))
if (X->getType() == Y->getType())
// See if "V === X - Y" simplifies.
if (Value *V = SimplifyBinOp(Instruction::Sub, X, Y, Q, MaxRecurse-1))
// It does! Now see if "trunc V" simplifies.
if (Value *W = SimplifyTruncInst(V, Op0->getType(), Q, MaxRecurse-1))
// It does, return the simplified "trunc V".
return W;
// Variations on GEP(base, I, ...) - GEP(base, i, ...) -> GEP(null, I-i, ...).
if (Q.TD && match(Op0, m_PtrToInt(m_Value(X))) &&
match(Op1, m_PtrToInt(m_Value(Y))))
if (Constant *Result = computePointerDifference(*Q.TD, X, Y))
return ConstantExpr::getIntegerCast(Result, Op0->getType(), true);
// Mul distributes over Sub. Try some generic simplifications based on this.
if (Value *V = FactorizeBinOp(Instruction::Sub, Op0, Op1, Instruction::Mul,
Q, MaxRecurse))
@ -2598,6 +2602,19 @@ static Value *SimplifyPHINode(PHINode *PN, const Query &Q) {
return CommonValue;
}
static Value *SimplifyTruncInst(Value *Op, Type *Ty, const Query &Q, unsigned) {
if (Constant *C = dyn_cast<Constant>(Op))
return ConstantFoldInstOperands(Instruction::Trunc, Ty, C, Q.TD, Q.TLI);
return 0;
}
Value *llvm::SimplifyTruncInst(Value *Op, Type *Ty, const TargetData *TD,
const TargetLibraryInfo *TLI,
const DominatorTree *DT) {
return ::SimplifyTruncInst(Op, Ty, Query (TD, TLI, DT), RecursionLimit);
}
//=== Helper functions for higher up the class hierarchy.
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
@ -2786,6 +2803,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
case Instruction::Call:
Result = SimplifyCallInst(cast<CallInst>(I), Query (TD, TLI, DT));
break;
case Instruction::Trunc:
Result = SimplifyTruncInst(I->getOperand(0), I->getType(), TD, TLI, DT);
break;
}
/// If called on unreachable code, the above logic may report that the

View File

@ -184,3 +184,12 @@ define i32 @udiv5(i32 %x, i32 %y) {
; CHECK: ret i32 %x
}
define i16 @trunc1(i32 %x) {
; CHECK: @trunc1
%y = add i32 %x, 1
%tx = trunc i32 %x to i16
%ty = trunc i32 %y to i16
%d = sub i16 %ty, %tx
ret i16 %d
; CHECK: ret i16 1
}