From bd0fe5642544d4ec3aee1ede7af60c006bae5cbf Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 13 Mar 2012 14:07:05 +0000 Subject: [PATCH] Generalize the "trunc(ptrtoint(x)) - trunc(ptrtoint(y)) -> trunc(ptrtoint(x-y))" optimization introduced by Chandler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152626 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/InstructionSimplify.h | 13 ++++-- lib/Analysis/InstructionSimplify.cpp | 48 +++++++++++++++------ test/Transforms/InstSimplify/reassociate.ll | 9 ++++ 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index d85ae4f2a48..fb07b03aeb3 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -20,13 +20,14 @@ #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H namespace llvm { + template + class ArrayRef; class DominatorTree; class Instruction; - class Value; class TargetData; class TargetLibraryInfo; - template - class ArrayRef; + 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. diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 75afbf1b53a..b095bc42726 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -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(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(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 diff --git a/test/Transforms/InstSimplify/reassociate.ll b/test/Transforms/InstSimplify/reassociate.ll index 3c8169e5e28..e659e6f42c8 100644 --- a/test/Transforms/InstSimplify/reassociate.ll +++ b/test/Transforms/InstSimplify/reassociate.ll @@ -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 +} -- 2.34.1