Factorize common code out of the InstructionSimplify shift logic. Add in
authorDuncan Sands <baldrick@free.fr>
Fri, 14 Jan 2011 14:44:12 +0000 (14:44 +0000)
committerDuncan Sands <baldrick@free.fr>
Fri, 14 Jan 2011 14:44:12 +0000 (14:44 +0000)
threading of shifts over selects and phis while there.  This fires here and
there in the testsuite, to not much effect.  For example when compiling spirit
it fires 5 times, during early-cse, resulting in 6 more cse simplifications,
and 3 more terminators being folded by jump threading, but the final bitcode
doesn't change in any interesting way: other optimizations would have caught
the opportunity anyway, only later.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123441 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstSimplify/2011-01-14-Thread.ll [new file with mode: 0644]

index 29ce5cfd4300380b9ebc901ef199f2e9101284ee..d5cf626e60fba0fe38db054306eb88a78045dbbb 100644 (file)
@@ -684,31 +684,27 @@ Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD,
   return ::SimplifyMulInst(Op0, Op1, TD, DT, RecursionLimit);
 }
 
-/// SimplifyShlInst - Given operands for an Shl, see if we can
+/// SimplifyShift - Given operands for an Shl, LShr or AShr, 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 *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1,
+                            const TargetData *TD, const DominatorTree *DT,
+                            unsigned MaxRecurse) {
   if (Constant *C0 = dyn_cast<Constant>(Op0)) {
     if (Constant *C1 = dyn_cast<Constant>(Op1)) {
       Constant *Ops[] = { C0, C1 };
-      return ConstantFoldInstOperands(Instruction::Shl, C0->getType(), Ops, 2,
-                                      TD);
+      return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD);
     }
   }
 
-  // 0 << X -> 0
+  // 0 shift by X -> 0
   if (match(Op0, m_Zero()))
     return Op0;
 
-  // X << 0 -> X
+  // X shift by 0 -> X
   if (match(Op1, m_Zero()))
     return Op0;
 
-  // undef << X -> 0
-  if (isa<UndefValue>(Op0))
-    return Constant::getNullValue(Op0->getType());
-
-  // X << undef -> undef because it may shift by the bitwidth.
+  // X shift by undef -> undef because it may shift by the bitwidth.
   if (isa<UndefValue>(Op1))
     return Op1;
 
@@ -718,6 +714,32 @@ static Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
         Op0->getType()->getScalarSizeInBits())
       return UndefValue::get(Op0->getType());
 
+  // If the operation is with the result of a select instruction, check whether
+  // operating on either branch of the select always yields the same value.
+  if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))
+    if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, TD, DT, MaxRecurse))
+      return V;
+
+  // If the operation is with the result of a phi instruction, check whether
+  // operating on all incoming values of the phi always yields the same value.
+  if (isa<PHINode>(Op0) || isa<PHINode>(Op1))
+    if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, TD, DT, MaxRecurse))
+      return V;
+
+  return 0;
+}
+
+/// 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) {
+  if (Value *V = SimplifyShift(Instruction::Shl, Op0, Op1, TD, DT, MaxRecurse))
+    return V;
+
+  // undef << X -> 0
+  if (isa<UndefValue>(Op0))
+    return Constant::getNullValue(Op0->getType());
+
   return 0;
 }
 
@@ -730,36 +752,13 @@ Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
 /// fold the result.  If not, this returns null.
 static Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
                                const DominatorTree *DT, unsigned MaxRecurse) {
-  if (Constant *C0 = dyn_cast<Constant>(Op0)) {
-    if (Constant *C1 = dyn_cast<Constant>(Op1)) {
-      Constant *Ops[] = { C0, C1 };
-      return ConstantFoldInstOperands(Instruction::LShr, C0->getType(), Ops, 2,
-                                      TD);
-    }
-  }
-
-  // 0 >> X -> 0
-  if (match(Op0, m_Zero()))
-    return Op0;
+  if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, TD, DT, MaxRecurse))
+    return V;
 
   // undef >>l X -> 0
   if (isa<UndefValue>(Op0))
     return Constant::getNullValue(Op0->getType());
 
-  // X >> 0 -> X
-  if (match(Op1, m_Zero()))
-    return Op0;
-
-  // X >> undef -> undef because it may shift by the bitwidth.
-  if (isa<UndefValue>(Op1))
-    return Op1;
-
-  // Shifting by the bitwidth or more is undefined.
-  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
-    if (CI->getValue().getLimitedValue() >=
-        Op0->getType()->getScalarSizeInBits())
-      return UndefValue::get(Op0->getType());
-
   return 0;
 }
 
@@ -772,17 +771,8 @@ Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
 /// fold the result.  If not, this returns null.
 static Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
                               const DominatorTree *DT, unsigned MaxRecurse) {
-  if (Constant *C0 = dyn_cast<Constant>(Op0)) {
-    if (Constant *C1 = dyn_cast<Constant>(Op1)) {
-      Constant *Ops[] = { C0, C1 };
-      return ConstantFoldInstOperands(Instruction::AShr, C0->getType(), Ops, 2,
-                                      TD);
-    }
-  }
-
-  // 0 >> X -> 0
-  if (match(Op0, m_Zero()))
-    return Op0;
+  if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, TD, DT, MaxRecurse))
+    return V;
 
   // all ones >>a X -> all ones
   if (match(Op0, m_AllOnes()))
@@ -792,20 +782,6 @@ static Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
   if (isa<UndefValue>(Op0))
     return Constant::getAllOnesValue(Op0->getType());
 
-  // X >> 0 -> X
-  if (match(Op1, m_Zero()))
-    return Op0;
-
-  // X >> undef -> undef because it may shift by the bitwidth.
-  if (isa<UndefValue>(Op1))
-    return Op1;
-
-  // Shifting by the bitwidth or more is undefined.
-  if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
-    if (CI->getValue().getLimitedValue() >=
-        Op0->getType()->getScalarSizeInBits())
-      return UndefValue::get(Op0->getType());
-
   return 0;
 }
 
diff --git a/test/Transforms/InstSimplify/2011-01-14-Thread.ll b/test/Transforms/InstSimplify/2011-01-14-Thread.ll
new file mode 100644 (file)
index 0000000..8fc4dc5
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+define i32 @shift_select(i1 %cond) {
+; CHECK: @shift_select
+  %s = select i1 %cond, i32 0, i32 1
+  %r = lshr i32 %s, 1
+  ret i32 %r
+; CHECK: ret i32 0
+}