[PATCH] D47883: [InstSimplify] shl nuw C, %x -> C iff signbit is set on C.

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 7 07:40:15 PDT 2018


lebedev.ri created this revision.
lebedev.ri added reviewers: spatel, craig.topper.

`%r = shl nuw i8 C, %x`

As per langref:

  If the nuw keyword is present, then the shift produces
  a poison value if it shifts out any non-zero bits.

Thus, if the sign bit is set on `C`, then `%x` can only be `0`, which means that `%r` can only be `C`.
Or in other words, set sign bit means that the signed value is negative, so the constant is `<= 0`.

https://rise4fun.com/Alive/WMk
https://rise4fun.com/Alive/udv

Was mentioned in https://reviews.llvm.org/D47428 review.

We already handle the `0` constant, https://godbolt.org/g/UZq1sJ, so this only handles negative constants.

FIXME: could also use `KnownBits`.


Repository:
  rL LLVM

https://reviews.llvm.org/D47883

Files:
  lib/Analysis/InstructionSimplify.cpp
  test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll


Index: test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll
===================================================================
--- test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll
+++ test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll
@@ -9,28 +9,25 @@
 
 define i8 @shl_nuw (i8 %x) {
 ; CHECK-LABEL: @shl_nuw(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw i8 -1, [[X:%.*]]
-; CHECK-NEXT:    ret i8 [[RET]]
+; CHECK-NEXT:    ret i8 -1
 ;
   %ret = shl nuw i8 -1, %x
   ; nuw here means that %x can only be 0
   ret i8 %ret
 }
 
 define i8 @shl_nuw_nsw (i8 %x) {
 ; CHECK-LABEL: @shl_nuw_nsw(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw nsw i8 -1, [[X:%.*]]
-; CHECK-NEXT:    ret i8 [[RET]]
+; CHECK-NEXT:    ret i8 -1
 ;
   %ret = shl nuw nsw i8 -1, %x
   ; nuw here means that %x can only be 0
   ret i8 %ret
 }
 
 define i8 @shl_128 (i8 %x) {
 ; CHECK-LABEL: @shl_128(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw i8 -128, [[X:%.*]]
-; CHECK-NEXT:    ret i8 [[RET]]
+; CHECK-NEXT:    ret i8 -128
 ;
   %ret = shl nuw i8 128, %x
   ; 128 == 1<<7 == just the sign bit is set
@@ -43,26 +40,23 @@
 
 define <2 x i8> @shl_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @shl_vec(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -1>, [[X:%.*]]
-; CHECK-NEXT:    ret <2 x i8> [[RET]]
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
 ;
   %ret = shl nuw <2 x i8> <i8 -1, i8 -1>, %x
   ret <2 x i8> %ret
 }
 
 define <3 x i8> @shl_vec_undef(<3 x i8> %x) {
 ; CHECK-LABEL: @shl_vec_undef(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, [[X:%.*]]
-; CHECK-NEXT:    ret <3 x i8> [[RET]]
+; CHECK-NEXT:    ret <3 x i8> <i8 -1, i8 undef, i8 -1>
 ;
   %ret = shl nuw <3 x i8> <i8 -1, i8 undef, i8 -1>, %x
   ret <3 x i8> %ret
 }
 
 define <2 x i8> @shl_vec_nonsplat(<2 x i8> %x) {
 ; CHECK-LABEL: @shl_vec_nonsplat(
-; CHECK-NEXT:    [[RET:%.*]] = shl nuw <2 x i8> <i8 -1, i8 -2>, [[X:%.*]]
-; CHECK-NEXT:    ret <2 x i8> [[RET]]
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -2>
 ;
   %ret = shl nuw <2 x i8> <i8 -1, i8 -2>, %x
   ret <2 x i8> %ret
Index: lib/Analysis/InstructionSimplify.cpp
===================================================================
--- lib/Analysis/InstructionSimplify.cpp
+++ lib/Analysis/InstructionSimplify.cpp
@@ -1226,6 +1226,11 @@
   Value *X;
   if (match(Op0, m_Exact(m_Shr(m_Value(X), m_Specific(Op1)))))
     return X;
+
+  // shl nuw i8 C, %x  ->  C  iff C has sign bit set.
+  if (isNUW && match(Op0, m_Negative()))
+    return Op0;
+
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47883.150331.patch
Type: text/x-patch
Size: 2522 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180607/6450837f/attachment.bin>


More information about the llvm-commits mailing list