[llvm] r341997 - [InstCombine] add folds for icmp with xor mask constant

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 11 15:00:16 PDT 2018


Author: spatel
Date: Tue Sep 11 15:00:15 2018
New Revision: 341997

URL: http://llvm.org/viewvc/llvm-project?rev=341997&view=rev
Log:
[InstCombine] add folds for icmp with xor mask constant

These are the folds in Alive;
Name: xor_ult
Pre: isPowerOf2(-C1)
%xor = xor i8 %x, C1
%r = icmp ult i8 %xor, C1
=>
%r = icmp ugt i8 %x, ~C1

Name: xor_ugt
Pre: isPowerOf2(C1+1)
%xor = xor i8 %x, C1
%r = icmp ugt i8 %xor, C1
=>
%r = icmp ugt i8 %x, C1

https://rise4fun.com/Alive/Vty

The ugt case in its simplest form was already handled by DemandedBits,
but that's not ideal as shown in the multi-use test.

I'm not sure if these are all of the symmetrical folds, but I adjusted 
the existing code for one of the folds to try to show the similarities.

There's no obvious connection, but this is another preliminary step 
for PR14613...
https://bugs.llvm.org/show_bug.cgi?id=14613

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/test/Transforms/InstCombine/icmp.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=341997&r1=341996&r2=341997&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Tue Sep 11 15:00:15 2018
@@ -1499,16 +1499,25 @@ Instruction *InstCombiner::foldICmpXorCo
     }
   }
 
-  // (icmp ugt (xor X, C), ~C) -> (icmp ult X, C)
-  //   iff -C is a power of 2
-  if (Pred == ICmpInst::ICMP_UGT && *XorC == ~C && (C + 1).isPowerOf2())
-    return new ICmpInst(ICmpInst::ICMP_ULT, X, Y);
-
-  // (icmp ult (xor X, C), -C) -> (icmp uge X, C)
-  //   iff -C is a power of 2
-  if (Pred == ICmpInst::ICMP_ULT && *XorC == -C && C.isPowerOf2())
-    return new ICmpInst(ICmpInst::ICMP_UGE, X, Y);
-
+  // Mask constant magic can eliminate an 'xor' with unsigned compares.
+  if (Pred == ICmpInst::ICMP_UGT) {
+    // (xor X, ~C) >u C --> X <u ~C (when C+1 is a power of 2)
+    if (*XorC == ~C && (C + 1).isPowerOf2())
+      return new ICmpInst(ICmpInst::ICMP_ULT, X, Y);
+    // (xor X, C) >u C --> X >u C (when C+1 is a power of 2)
+    if (*XorC == C && (C + 1).isPowerOf2())
+      return new ICmpInst(ICmpInst::ICMP_UGT, X, Y);
+  }
+  if (Pred == ICmpInst::ICMP_ULT) {
+    // (xor X, -C) <u C --> X >u ~C (when C is a power of 2)
+    if (*XorC == -C && C.isPowerOf2())
+      return new ICmpInst(ICmpInst::ICMP_UGT, X,
+                          ConstantInt::get(X->getType(), ~C));
+    // (xor X, C) <u C --> X >u ~C (when -C is a power of 2)
+    if (*XorC == C && (-C).isPowerOf2())
+      return new ICmpInst(ICmpInst::ICMP_UGT, X,
+                          ConstantInt::get(X->getType(), ~C));
+  }
   return nullptr;
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=341997&r1=341996&r2=341997&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/icmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/icmp.ll Tue Sep 11 15:00:15 2018
@@ -2229,8 +2229,7 @@ define <2 x i1> @icmp_xor_neg4_X_uge_4_v
 
 define <2 x i1> @xor_ult(<2 x i8> %x) {
 ; CHECK-LABEL: @xor_ult(
-; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -4, i8 -4>
-; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[XOR]], <i8 -4, i8 -4>
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt <2 x i8> [[X:%.*]], <i8 3, i8 3>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %xor = xor <2 x i8> %x, <i8 -4, i8 -4>
@@ -2242,7 +2241,7 @@ define i1 @xor_ult_extra_use(i8 %x, i8*
 ; CHECK-LABEL: @xor_ult_extra_use(
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X:%.*]], -32
 ; CHECK-NEXT:    store i8 [[XOR]], i8* [[P:%.*]], align 1
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[XOR]], -32
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[X]], 31
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %xor = xor i8 %x, -32
@@ -2265,7 +2264,7 @@ define i1 @xor_ugt_extra_use(i8 %x, i8*
 ; CHECK-LABEL: @xor_ugt_extra_use(
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[X:%.*]], 63
 ; CHECK-NEXT:    store i8 [[XOR]], i8* [[P:%.*]], align 1
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[XOR]], 63
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[X]], 63
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %xor = xor i8 %x, 63




More information about the llvm-commits mailing list