[PATCH] D47041: [ValueTracking] Teach computeKnownBits that the result of an absolute value pattern that uses nsw flag is always positive.

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 17 17:04:57 PDT 2018


craig.topper created this revision.
craig.topper added reviewers: spatel, efriedma.

If the nsw flag is used in the absolute value then it is undefined for INT_MIN. For all other value it will produce a positive number. So we can assume the result is positive.

This breaks some InstCombine abs/nabs combining tests because we simplify the second compare from known bits rather than as the whole pattern. Looks like we can probably fix it by adding a neg+abs/nabs combine to just swap the select operands. Need to check alive to make sure there are no corner cases.


https://reviews.llvm.org/D47041

Files:
  lib/Analysis/ValueTracking.cpp
  test/Transforms/InstCombine/abs_abs.ll


Index: test/Transforms/InstCombine/abs_abs.ll
===================================================================
--- test/Transforms/InstCombine/abs_abs.ll
+++ test/Transforms/InstCombine/abs_abs.ll
@@ -883,8 +883,9 @@
 ; CHECK-LABEL: @nabs_abs_x09(
 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp sgt i32 %x, -1
 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x
-; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]]
+; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond
+; CHECK-NEXT: ret i32 [[SUB16]]
 }
 
 define i32 @nabs_abs_x10(i32 %x) {
@@ -898,8 +899,9 @@
 ; CHECK-LABEL: @nabs_abs_x10(
 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp sgt i32 %x, 0
 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x
-; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]]
+; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond
+; CHECK-NEXT: ret i32 [[SUB16]]
 }
 
 define i32 @nabs_abs_x11(i32 %x) {
@@ -913,8 +915,9 @@
 ; CHECK-LABEL: @nabs_abs_x11(
 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp slt i32 %x, 0
 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x
-; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]]
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x
+; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond
+; CHECK-NEXT: ret i32 [[SUB16]]
 }
 
 define i32 @nabs_abs_x12(i32 %x) {
@@ -928,8 +931,9 @@
 ; CHECK-LABEL: @nabs_abs_x12(
 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp slt i32 %x, 1
 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x
-; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]]
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x
+; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond
+; CHECK-NEXT: ret i32 [[SUB16]]
 }
 
 define i32 @nabs_abs_x13(i32 %x) {
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -1078,6 +1078,12 @@
       // leading zero bits.
       MaxHighZeros =
           std::max(Known.countMinLeadingZeros(), Known2.countMinLeadingZeros());
+    } else if (SPF == SPF_ABS) {
+      // RHS from matchSelectPattern returns the negation part of abs pattern.
+      // If the negate has an NSW flag we can assume the sign bit of the result
+      // will be 0 because that makes abs(INT_MIN) undefined.
+      if (cast<Instruction>(RHS)->hasNoSignedWrap())
+        MaxHighZeros = 1;
     }
 
     // Only known if known in both the LHS and RHS.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47041.147411.patch
Type: text/x-patch
Size: 2830 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180518/301d585d/attachment.bin>


More information about the llvm-commits mailing list