[llvm] r221325 - InstSimplify: Exact shifts of X by Y are X if X has the lsb set

David Majnemer david.majnemer at gmail.com
Tue Nov 4 16:59:59 PST 2014


Author: majnemer
Date: Tue Nov  4 18:59:59 2014
New Revision: 221325

URL: http://llvm.org/viewvc/llvm-project?rev=221325&view=rev
Log:
InstSimplify: Exact shifts of X by Y are X if X has the lsb set

Exact shifts may not shift out any non-zero bits. Use computeKnownBits
to determine when this occurs and just return the left hand side.

This fixes PR21477.

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=221325&r1=221324&r2=221325&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Tue Nov  4 18:59:59 2014
@@ -1328,6 +1328,32 @@ static Value *SimplifyShift(unsigned Opc
   return nullptr;
 }
 
+/// \brief Given operands for an Shl, LShr or AShr, see if we can
+/// fold the result.  If not, this returns null.
+static Value *SimplifyRightShift(unsigned Opcode, Value *Op0, Value *Op1,
+                                 bool isExact, const Query &Q,
+                                 unsigned MaxRecurse) {
+  if (Value *V = SimplifyShift(Opcode, Op0, Op1, Q, MaxRecurse))
+    return V;
+
+  // X >> X -> 0
+  if (Op0 == Op1)
+    return Constant::getNullValue(Op0->getType());
+
+  // The low bit cannot be shifted out of an exact shift if it is set.
+  if (isExact) {
+    unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
+    APInt Op0KnownZero(BitWidth, 0);
+    APInt Op0KnownOne(BitWidth, 0);
+    computeKnownBits(Op0, Op0KnownZero, Op0KnownOne, Q.DL, /*Depth=*/0, Q.AT, Q.CxtI,
+                     Q.DT);
+    if (Op0KnownOne[0])
+      return Op0;
+  }
+
+  return nullptr;
+}
+
 /// 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, bool isNSW, bool isNUW,
@@ -1358,12 +1384,9 @@ Value *llvm::SimplifyShlInst(Value *Op0,
 /// fold the result.  If not, this returns null.
 static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
                                const Query &Q, unsigned MaxRecurse) {
-  if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, Q, MaxRecurse))
-    return V;
-
-  // X >> X -> 0
-  if (Op0 == Op1)
-    return Constant::getNullValue(Op0->getType());
+  if (Value *V = SimplifyRightShift(Instruction::LShr, Op0, Op1, isExact, Q,
+                                    MaxRecurse))
+      return V;
 
   // undef >>l X -> 0
   if (match(Op0, m_Undef()))
@@ -1391,13 +1414,10 @@ Value *llvm::SimplifyLShrInst(Value *Op0
 /// fold the result.  If not, this returns null.
 static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
                                const Query &Q, unsigned MaxRecurse) {
-  if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, Q, MaxRecurse))
+  if (Value *V = SimplifyRightShift(Instruction::AShr, Op0, Op1, isExact, Q,
+                                    MaxRecurse))
     return V;
 
-  // X >> X -> 0
-  if (Op0 == Op1)
-    return Constant::getNullValue(Op0->getType());
-
   // all ones >>a X -> all ones
   if (match(Op0, m_AllOnes()))
     return Op0;

Modified: llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll?rev=221325&r1=221324&r2=221325&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/shr-nop.ll Tue Nov  4 18:59:59 2014
@@ -330,3 +330,17 @@ define i1 @exact_lshr_ne_noexactlog(i8 %
  %cmp = icmp ne i8 %shr, 30
  ret i1 %cmp
 }
+
+; CHECK-LABEL: @exact_lshr_lowbit
+; CHECK-NEXT: ret i32 7
+define i32 @exact_lshr_lowbit(i32 %shiftval) {
+  %shr = lshr exact i32 7, %shiftval
+  ret i32 %shr
+}
+
+; CHECK-LABEL: @exact_ashr_lowbit
+; CHECK-NEXT: ret i32 7
+define i32 @exact_ashr_lowbit(i32 %shiftval) {
+  %shr = ashr exact i32 7, %shiftval
+  ret i32 %shr
+}





More information about the llvm-commits mailing list