Generalize the "trunc(ptrtoint(x)) - trunc(ptrtoint(y)) ->
authorDuncan Sands <baldrick@free.fr>
Tue, 13 Mar 2012 14:07:05 +0000 (14:07 +0000)
committerDuncan Sands <baldrick@free.fr>
Tue, 13 Mar 2012 14:07:05 +0000 (14:07 +0000)
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
lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstSimplify/reassociate.ll

index d85ae4f2a482519a6ee7c2e883c99758a5be7658..fb07b03aeb3649693a7f9801b4f4da105164ed75 100644 (file)
 #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
 
 namespace llvm {
+  template<typename T>
+  class ArrayRef;
   class DominatorTree;
   class Instruction;
-  class Value;
   class TargetData;
   class TargetLibraryInfo;
-  template<typename T>
-  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.
 
 
index 75afbf1b53a3c7a1fb39ad1c746c97ab823f5e8b..b095bc42726d14ce6902052a37d8c1f7bd545afd 100644 (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
index 3c8169e5e283ff9e7e95337ad18fc3e9efdb998f..e659e6f42c8dd3148429ecedc0f3691f0f4173b8 100644 (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
+}