[llvm] r334222 - [InstSimplify] shl nuw C, %x -> C iff signbit is set on C.

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 7 13:03:46 PDT 2018


Author: lebedevri
Date: Thu Jun  7 13:03:45 2018
New Revision: 334222

URL: http://llvm.org/viewvc/llvm-project?rev=334222&view=rev
Log:
[InstSimplify] shl nuw C, %x -> C iff signbit is set on C.

Summary:
`%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 D47428 review.

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

Could use computeKnownBits() / LazyValueInfo,
but the cost-benefit analysis (https://reviews.llvm.org/D47891)
suggests it isn't worth it.

Reviewers: spatel, craig.topper

Reviewed By: spatel

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D47883

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll
    llvm/trunk/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=334222&r1=334221&r2=334222&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Jun  7 13:03:45 2018
@@ -1226,6 +1226,13 @@ static Value *SimplifyShlInst(Value *Op0
   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;
+  // NOTE: could use computeKnownBits() / LazyValueInfo,
+  // but the cost-benefit analysis suggests it isn't worth it.
+
   return nullptr;
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll?rev=334222&r1=334221&r2=334222&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll Thu Jun  7 13:03:45 2018
@@ -39,9 +39,7 @@ define i32 @shl_add_nsw(i32 %NBits) {
 
 define i32 @shl_add_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_add_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl i32 1, %NBits
   %ret = add nuw i32 %setbit, -1
@@ -50,9 +48,7 @@ define i32 @shl_add_nuw(i32 %NBits) {
 
 define i32 @shl_add_nsw_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_add_nsw_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl i32 1, %NBits
   %ret = add nuw nsw i32 %setbit, -1
@@ -85,9 +81,7 @@ define i32 @shl_nsw_add_nsw(i32 %NBits)
 
 define i32 @shl_nsw_add_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nsw_add_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nsw i32 1, %NBits
   %ret = add nuw i32 %setbit, -1
@@ -96,9 +90,7 @@ define i32 @shl_nsw_add_nuw(i32 %NBits)
 
 define i32 @shl_nsw_add_nsw_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nsw_add_nsw_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nsw i32 1, %NBits
   %ret = add nuw nsw i32 %setbit, -1
@@ -131,9 +123,7 @@ define i32 @shl_nuw_add_nsw(i32 %NBits)
 
 define i32 @shl_nuw_add_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nuw_add_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nuw i32 1, %NBits
   %ret = add nuw i32 %setbit, -1
@@ -142,9 +132,7 @@ define i32 @shl_nuw_add_nuw(i32 %NBits)
 
 define i32 @shl_nuw_add_nsw_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nuw_add_nsw_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nuw i32 1, %NBits
   %ret = add nuw nsw i32 %setbit, -1
@@ -177,9 +165,7 @@ define i32 @shl_nsw_nuw_add_nsw(i32 %NBi
 
 define i32 @shl_nsw_nuw_add_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nsw_nuw_add_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nuw nsw i32 1, %NBits
   %ret = add nuw i32 %setbit, -1
@@ -188,9 +174,7 @@ define i32 @shl_nsw_nuw_add_nuw(i32 %NBi
 
 define i32 @shl_nsw_nuw_add_nsw_nuw(i32 %NBits) {
 ; CHECK-LABEL: @shl_nsw_nuw_add_nsw_nuw(
-; CHECK-NEXT:    [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = xor i32 [[NOTMASK]], -1
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 0
 ;
   %setbit = shl nuw nsw i32 1, %NBits
   %ret = add nuw nsw i32 %setbit, -1

Modified: llvm/trunk/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll?rev=334222&r1=334221&r2=334222&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll Thu Jun  7 13:03:45 2018
@@ -9,8 +9,7 @@
 
 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
@@ -19,8 +18,7 @@ define i8 @shl_nuw (i8 %x) {
 
 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
@@ -29,8 +27,7 @@ define i8 @shl_nuw_nsw (i8 %x) {
 
 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
@@ -75,8 +72,7 @@ define i8 @knownbits_negativeorzero(i8 %
 
 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
@@ -84,8 +80,7 @@ define <2 x i8> @shl_vec(<2 x i8> %x) {
 
 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
@@ -93,8 +88,7 @@ define <3 x i8> @shl_vec_undef(<3 x i8>
 
 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




More information about the llvm-commits mailing list