[llvm-commits] [llvm] r125196 - in /llvm/trunk: include/llvm/Analysis/InstructionSimplify.h lib/Analysis/InstructionSimplify.cpp lib/Transforms/InstCombine/InstCombineShifts.cpp test/Transforms/InstSimplify/exact-nsw-nuw.ll

Chris Lattner sabre at nondot.org
Wed Feb 9 09:15:04 PST 2011


Author: lattner
Date: Wed Feb  9 11:15:04 2011
New Revision: 125196

URL: http://llvm.org/viewvc/llvm-project?rev=125196&view=rev
Log:
Teach instsimplify some tricks about exact/nuw/nsw shifts.
improve interfaces to instsimplify to take this info.


Added:
    llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll
Modified:
    llvm/trunk/include/llvm/Analysis/InstructionSimplify.h
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp

Modified: llvm/trunk/include/llvm/Analysis/InstructionSimplify.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/InstructionSimplify.h?rev=125196&r1=125195&r2=125196&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/InstructionSimplify.h (original)
+++ llvm/trunk/include/llvm/Analysis/InstructionSimplify.h Wed Feb  9 11:15:04 2011
@@ -57,17 +57,18 @@
 
   /// SimplifyShlInst - Given operands for a Shl, see if we can
   /// fold the result.  If not, this returns null.
-  Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
-                         const DominatorTree *DT = 0);
+  Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
+                         const TargetData *TD = 0, const DominatorTree *DT = 0);
 
   /// SimplifyLShrInst - Given operands for a LShr, see if we can
   /// fold the result.  If not, this returns null.
-  Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
-                          const DominatorTree *DT = 0);
+  Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
+                          const TargetData *TD = 0, const DominatorTree *DT=0);
 
   /// SimplifyAShrInst - Given operands for a AShr, see if we can
   /// fold the result.  If not, this returns null.
-  Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
+  Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
+                          const TargetData *TD = 0,
                           const DominatorTree *DT = 0);
 
   /// SimplifyAndInst - Given operands for an And, see if we can

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=125196&r1=125195&r2=125196&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Wed Feb  9 11:15:04 2011
@@ -29,7 +29,7 @@
 using namespace llvm;
 using namespace llvm::PatternMatch;
 
-#define RecursionLimit 3
+enum { RecursionLimit = 3 };
 
 STATISTIC(NumExpand,  "Number of expansions");
 STATISTIC(NumFactor , "Number of factorizations");
@@ -946,8 +946,9 @@
 
 /// SimplifyShlInst - Given operands for an Shl, see if we can
 /// fold the result.  If not, this returns null.
-static Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
-                              const DominatorTree *DT, unsigned MaxRecurse) {
+static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
+                              const TargetData *TD, const DominatorTree *DT,
+                              unsigned MaxRecurse) {
   if (Value *V = SimplifyShift(Instruction::Shl, Op0, Op1, TD, DT, MaxRecurse))
     return V;
 
@@ -955,18 +956,24 @@
   if (match(Op0, m_Undef()))
     return Constant::getNullValue(Op0->getType());
 
+  // (X >> A) << A -> X
+  Value *X;
+  if (match(Op0, m_Shr(m_Value(X), m_Specific(Op1))) &&
+      cast<PossiblyExactOperator>(Op0)->isExact())
+    return X;
   return 0;
 }
 
-Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
-                             const DominatorTree *DT) {
-  return ::SimplifyShlInst(Op0, Op1, TD, DT, RecursionLimit);
+Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
+                             const TargetData *TD, const DominatorTree *DT) {
+  return ::SimplifyShlInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit);
 }
 
 /// SimplifyLShrInst - Given operands for an LShr, see if we can
 /// fold the result.  If not, this returns null.
-static Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
-                               const DominatorTree *DT, unsigned MaxRecurse) {
+static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
+                               const TargetData *TD, const DominatorTree *DT,
+                               unsigned MaxRecurse) {
   if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, TD, DT, MaxRecurse))
     return V;
 
@@ -974,18 +981,25 @@
   if (match(Op0, m_Undef()))
     return Constant::getNullValue(Op0->getType());
 
+  // (X << A) >> A -> X
+  Value *X;
+  if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
+      cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap())
+    return X;
+  
   return 0;
 }
 
-Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
-                              const DominatorTree *DT) {
-  return ::SimplifyLShrInst(Op0, Op1, TD, DT, RecursionLimit);
+Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
+                              const TargetData *TD, const DominatorTree *DT) {
+  return ::SimplifyLShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit);
 }
 
 /// SimplifyAShrInst - Given operands for an AShr, see if we can
 /// fold the result.  If not, this returns null.
-static Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
-                              const DominatorTree *DT, unsigned MaxRecurse) {
+static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
+                               const TargetData *TD, const DominatorTree *DT,
+                               unsigned MaxRecurse) {
   if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, TD, DT, MaxRecurse))
     return V;
 
@@ -997,12 +1011,18 @@
   if (match(Op0, m_Undef()))
     return Constant::getAllOnesValue(Op0->getType());
 
+  // (X << A) >> A -> X
+  Value *X;
+  if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
+      cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
+    return X;
+  
   return 0;
 }
 
-Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
-                              const DominatorTree *DT) {
-  return ::SimplifyAShrInst(Op0, Op1, TD, DT, RecursionLimit);
+Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
+                              const TargetData *TD, const DominatorTree *DT) {
+  return ::SimplifyAShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit);
 }
 
 /// SimplifyAndInst - Given operands for an And, see if we can
@@ -1037,12 +1057,12 @@
     return Op0;
 
   // A & ~A  =  ~A & A  =  0
-  Value *A = 0, *B = 0;
-  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
-      (match(Op1, m_Not(m_Value(A))) && A == Op0))
+  if (match(Op0, m_Not(m_Specific(Op1))) ||
+      match(Op1, m_Not(m_Specific(Op0))))
     return Constant::getNullValue(Op0->getType());
 
   // (A | ?) & A = A
+  Value *A = 0, *B = 0;
   if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
       (A == Op1 || B == Op1))
     return Op1;
@@ -1126,12 +1146,12 @@
     return Op1;
 
   // A | ~A  =  ~A | A  =  -1
-  Value *A = 0, *B = 0;
-  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
-      (match(Op1, m_Not(m_Value(A))) && A == Op0))
+  if (match(Op0, m_Not(m_Specific(Op1))) ||
+      match(Op1, m_Not(m_Specific(Op0))))
     return Constant::getAllOnesValue(Op0->getType());
 
   // (A & ?) | A = A
+  Value *A = 0, *B = 0;
   if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
       (A == Op1 || B == Op1))
     return Op1;
@@ -1206,9 +1226,8 @@
     return Constant::getNullValue(Op0->getType());
 
   // A ^ ~A  =  ~A ^ A  =  -1
-  Value *A = 0;
-  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
-      (match(Op1, m_Not(m_Value(A))) && A == Op0))
+  if (match(Op0, m_Not(m_Specific(Op1))) ||
+      match(Op1, m_Not(m_Specific(Op0))))
     return Constant::getAllOnesValue(Op0->getType());
 
   // Try some generic simplifications for associative operations.
@@ -1794,21 +1813,25 @@
                             const TargetData *TD, const DominatorTree *DT,
                             unsigned MaxRecurse) {
   switch (Opcode) {
-  case Instruction::Add: return SimplifyAddInst(LHS, RHS, /* isNSW */ false,
-                                                /* isNUW */ false, TD, DT,
-                                                MaxRecurse);
-  case Instruction::Sub: return SimplifySubInst(LHS, RHS, /* isNSW */ false,
-                                                /* isNUW */ false, TD, DT,
-                                                MaxRecurse);
-  case Instruction::Mul: return SimplifyMulInst(LHS, RHS, TD, DT, MaxRecurse);
+  case Instruction::Add:
+    return SimplifyAddInst(LHS, RHS, /* isNSW */ false, /* isNUW */ false,
+                           TD, DT, MaxRecurse);
+  case Instruction::Sub:
+    return SimplifySubInst(LHS, RHS, /* isNSW */ false, /* isNUW */ false,
+                           TD, DT, MaxRecurse);
+  case Instruction::Mul:  return SimplifyMulInst (LHS, RHS, TD, DT, MaxRecurse);
   case Instruction::SDiv: return SimplifySDivInst(LHS, RHS, TD, DT, MaxRecurse);
   case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, TD, DT, MaxRecurse);
   case Instruction::FDiv: return SimplifyFDivInst(LHS, RHS, TD, DT, MaxRecurse);
-  case Instruction::Shl: return SimplifyShlInst(LHS, RHS, TD, DT, MaxRecurse);
-  case Instruction::LShr: return SimplifyLShrInst(LHS, RHS, TD, DT, MaxRecurse);
-  case Instruction::AShr: return SimplifyAShrInst(LHS, RHS, TD, DT, MaxRecurse);
+  case Instruction::Shl:
+    return SimplifyShlInst(LHS, RHS, /*NSW*/false, /*NUW*/false,
+                           TD, DT, MaxRecurse);
+  case Instruction::LShr:
+    return SimplifyLShrInst(LHS, RHS, /*isexact*/ false, TD, DT, MaxRecurse);
+  case Instruction::AShr:
+    return SimplifyAShrInst(LHS, RHS, /*isexact*/false, TD, DT, MaxRecurse);
   case Instruction::And: return SimplifyAndInst(LHS, RHS, TD, DT, MaxRecurse);
-  case Instruction::Or:  return SimplifyOrInst(LHS, RHS, TD, DT, MaxRecurse);
+  case Instruction::Or:  return SimplifyOrInst (LHS, RHS, TD, DT, MaxRecurse);
   case Instruction::Xor: return SimplifyXorInst(LHS, RHS, TD, DT, MaxRecurse);
   default:
     if (Constant *CLHS = dyn_cast<Constant>(LHS))
@@ -1895,13 +1918,20 @@
     Result = SimplifyFDivInst(I->getOperand(0), I->getOperand(1), TD, DT);
     break;
   case Instruction::Shl:
-    Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), TD, DT);
+    Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1),
+                             cast<BinaryOperator>(I)->hasNoSignedWrap(),
+                             cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
+                             TD, DT);
     break;
   case Instruction::LShr:
-    Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
+    Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1),
+                              cast<BinaryOperator>(I)->isExact(),
+                              TD, DT);
     break;
   case Instruction::AShr:
-    Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
+    Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1),
+                              cast<BinaryOperator>(I)->isExact(),
+                              TD, DT);
     break;
   case Instruction::And:
     Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT);

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=125196&r1=125195&r2=125196&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Wed Feb  9 11:15:04 2011
@@ -617,13 +617,16 @@
 }
 
 Instruction *InstCombiner::visitShl(BinaryOperator &I) {
-  if (Value *V = SimplifyShlInst(I.getOperand(0), I.getOperand(1), TD))
+  if (Value *V = SimplifyShlInst(I.getOperand(0), I.getOperand(1),
+                                 I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
+                                 TD))
     return ReplaceInstUsesWith(I, V);
   return commonShiftTransforms(I);
 }
 
 Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
-  if (Value *V = SimplifyLShrInst(I.getOperand(0), I.getOperand(1), TD))
+  if (Value *V = SimplifyLShrInst(I.getOperand(0), I.getOperand(1),
+                                  I.isExact(), TD))
     return ReplaceInstUsesWith(I, V);
 
   if (Instruction *R = commonShiftTransforms(I))
@@ -652,7 +655,8 @@
 }
 
 Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
-  if (Value *V = SimplifyAShrInst(I.getOperand(0), I.getOperand(1), TD))
+  if (Value *V = SimplifyAShrInst(I.getOperand(0), I.getOperand(1),
+                                  I.isExact(), TD))
     return ReplaceInstUsesWith(I, V);
 
   if (Instruction *R = commonShiftTransforms(I))

Added: llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll?rev=125196&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll Wed Feb  9 11:15:04 2011
@@ -0,0 +1,44 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; PR8862
+
+; CHECK: @shift1
+; CHECK: ret i32 %A
+define i32 @shift1(i32 %A, i32 %B) {
+  %C = lshr exact i32 %A, %B
+  %D = shl nuw i32 %C, %B
+  ret i32 %D
+}
+
+; CHECK: @shift2
+; CHECK: lshr
+; CHECK: ret i32 %D
+define i32 @shift2(i32 %A, i32 %B) {
+  %C = lshr i32 %A, %B
+  %D = shl nuw i32 %C, %B
+  ret i32 %D
+}
+
+; CHECK: @shift3
+; CHECK: ret i32 %A
+define i32 @shift3(i32 %A, i32 %B) {
+  %C = ashr exact i32 %A, %B
+  %D = shl nuw i32 %C, %B
+  ret i32 %D
+}
+
+; CHECK: @shift4
+; CHECK: ret i32 %A
+define i32 @shift4(i32 %A, i32 %B) {
+  %C = shl nuw i32 %A, %B
+  %D = lshr i32 %C, %B
+  ret i32 %D
+}
+
+; CHECK: @shift5
+; CHECK: ret i32 %A
+define i32 @shift5(i32 %A, i32 %B) {
+  %C = shl nsw i32 %A, %B
+  %D = ashr i32 %C, %B
+  ret i32 %D
+}





More information about the llvm-commits mailing list