[PATCH] D23296: [ValueTracking] Improve ValueTracking on left shift with nsw flag

Li Huang via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 22:44:46 PDT 2016


lihuang created this revision.
lihuang added reviewers: hfinkel, sanjoy.
lihuang added a subscriber: llvm-commits.

Improve ValueTracking on left shift with nsw flag

If a left shift has nsw flag, it produces a poison value if it shifts out any bits that disagree with the resultant sign bit. So we can assume the result has the same sign bit as the first operand.

This patch is separated from D18777.

https://reviews.llvm.org/D23296

Files:
  lib/Analysis/ValueTracking.cpp
  test/Analysis/ValueTracking/known-signbit-shift.ll

Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -1020,13 +1020,20 @@
   }
   case Instruction::Shl: {
     // (shl X, C1) & C2 == 0   iff   (X & C2 >>u C1) == 0
-    auto KZF = [BitWidth](const APInt &KnownZero, unsigned ShiftAmt) {
-      return (KnownZero << ShiftAmt) |
+    bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
+    auto KZF = [BitWidth, NSW](const APInt &KnownZero, unsigned ShiftAmt) {
+      APInt KZResult = (KnownZero << ShiftAmt) |
              APInt::getLowBitsSet(BitWidth, ShiftAmt); // Low bits known 0.
+      if (NSW && KnownZero.isNegative())
+        KZResult |= APInt::getSignBit(BitWidth);
+      return KZResult;
     };
 
-    auto KOF = [BitWidth](const APInt &KnownOne, unsigned ShiftAmt) {
-      return KnownOne << ShiftAmt;
+    auto KOF = [BitWidth, NSW](const APInt &KnownOne, unsigned ShiftAmt) {
+      APInt KOResult = KnownOne << ShiftAmt;
+      if (NSW && KnownOne.isNegative())
+        KOResult |= APInt::getSignBit(BitWidth);
+      return KOResult;
     };
 
     computeKnownBitsFromShiftOperator(I, KnownZero, KnownOne,
Index: test/Analysis/ValueTracking/known-signbit-shift.ll
===================================================================
--- test/Analysis/ValueTracking/known-signbit-shift.ll
+++ test/Analysis/ValueTracking/known-signbit-shift.ll
@@ -0,0 +1,24 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; Result of left shifting a non-negative integer 
+; with nsw flag should also be non-negative
+define i1 @test_shift_nonnegative(i32 %a) {
+; CHECK-LABEL: @test_shift_nonnegative(
+; CHECK: ret i1 true
+  %b = lshr i32 %a, 2
+  %shift = shl nsw i32 %b, 3
+  %cmp = icmp sge i32 %shift, 0
+  ret i1 %cmp
+}
+
+; Result of left shifting a negative integer with
+; nsw flag should also be negative
+define i1 @test_shift_negative(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_shift_negative(
+; CHECK: ret i1 true
+  %c = or i32 %a, -2147483648
+  %d = and i32 %b, 7
+  %shift = shl nsw i32 %c, %d
+  %cmp = icmp slt i32 %shift, 0
+  ret i1 %cmp
+}


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23296.67285.patch
Type: text/x-patch
Size: 2167 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160809/403cc696/attachment.bin>


More information about the llvm-commits mailing list