[llvm] 2df6309 - [InstCombine] Transform (icmp eq/ne rotate(X,AX),rotate(Y,AY)) -> (icmp eq/ne rotate(Y,AX-AY))

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 10 12:39:05 PDT 2023


Author: Noah Goldstein
Date: 2023-06-10T14:38:46-05:00
New Revision: 2df6309555963fb9411ed8023a8e585f7981b3bf

URL: https://github.com/llvm/llvm-project/commit/2df6309555963fb9411ed8023a8e585f7981b3bf
DIFF: https://github.com/llvm/llvm-project/commit/2df6309555963fb9411ed8023a8e585f7981b3bf.diff

LOG: [InstCombine] Transform (icmp eq/ne rotate(X,AX),rotate(Y,AY)) -> (icmp eq/ne rotate(Y,AX-AY))

Only do so if we don't create more instructions, so either both
rotates have one use or one of the rotates has one use and both `AX`
and `AY` are constant.
Proof: https://alive2.llvm.org/ce/z/rVmJgz

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
    llvm/test/Transforms/InstCombine/icmp-rotate.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 0865de3d39893..23c161f80a41f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3443,7 +3443,9 @@ Instruction *InstCombinerImpl::foldICmpEqIntrinsicWithConstant(
 }
 
 /// Fold an icmp with LLVM intrinsics
-static Instruction *foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp) {
+static Instruction *
+foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp,
+                               InstCombiner::BuilderTy &Builder) {
   assert(Cmp.isEquality());
 
   ICmpInst::Predicate Pred = Cmp.getPredicate();
@@ -3461,16 +3463,32 @@ static Instruction *foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp) {
     // original values.
     return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0));
   case Intrinsic::fshl:
-  case Intrinsic::fshr:
+  case Intrinsic::fshr: {
     // If both operands are rotated by same amount, just compare the
     // original values.
     if (IIOp0->getOperand(0) != IIOp0->getOperand(1))
       break;
     if (IIOp1->getOperand(0) != IIOp1->getOperand(1))
       break;
-    if (IIOp0->getOperand(2) != IIOp1->getOperand(2))
-      break;
-    return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0));
+    if (IIOp0->getOperand(2) == IIOp1->getOperand(2))
+      return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0));
+
+    // rotate(X, AmtX) == rotate(Y, AmtY)
+    //  -> rotate(X, AmtX - AmtY) == Y
+    // Do this if either both rotates have one use or if only one has one use
+    // and AmtX/AmtY are constants.
+    unsigned OneUses = IIOp0->hasOneUse() + IIOp1->hasOneUse();
+    if (OneUses == 2 ||
+        (OneUses == 1 && match(IIOp0->getOperand(2), m_ImmConstant()) &&
+         match(IIOp1->getOperand(2), m_ImmConstant()))) {
+      Value *SubAmt =
+          Builder.CreateSub(IIOp0->getOperand(2), IIOp1->getOperand(2));
+      Value *CombinedRotate = Builder.CreateIntrinsic(
+          Op0->getType(), IIOp0->getIntrinsicID(),
+          {IIOp0->getOperand(0), IIOp0->getOperand(0), SubAmt});
+      return new ICmpInst(Pred, IIOp1->getOperand(0), CombinedRotate);
+    }
+  } break;
   default:
     break;
   }
@@ -4970,7 +4988,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
     }
   }
 
-  if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I))
+  if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I, Builder))
     return ICmp;
 
   // Canonicalize checking for a power-of-2-or-zero value:

diff  --git a/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll b/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
index 8decf28333953..f87f786e004f8 100644
--- a/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
@@ -63,9 +63,9 @@ define i1 @cmpeq_rorr_to_rorl_multiuse_fail(i8 %x, i8 %C) {
 
 define i1 @cmpne_rorr_rorr(i8 %x, i8 %C0, i8 %C1) {
 ; CHECK-LABEL: @cmpne_rorr_rorr(
-; CHECK-NEXT:    [[X_RORR0:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[C0:%.*]])
-; CHECK-NEXT:    [[X_RORR1:%.*]] = call i8 @llvm.fshr.i8(i8 [[X]], i8 [[X]], i8 [[C1:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X_RORR0]], [[X_RORR1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[C0:%.*]], [[C1:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]])
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[TMP2]], [[X]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x_rorr0 = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %C0)
@@ -76,9 +76,9 @@ define i1 @cmpne_rorr_rorr(i8 %x, i8 %C0, i8 %C1) {
 
 define i1 @cmpne_rorrX_rorrY(i8 %x, i8 %y, i8 %C0, i8 %C1) {
 ; CHECK-LABEL: @cmpne_rorrX_rorrY(
-; CHECK-NEXT:    [[X_RORR0:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[C0:%.*]])
-; CHECK-NEXT:    [[Y_RORR1:%.*]] = call i8 @llvm.fshr.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[C1:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X_RORR0]], [[Y_RORR1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[C0:%.*]], [[C1:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]])
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[TMP2]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x_rorr0 = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %C0)
@@ -132,10 +132,10 @@ define i1 @cmpne_rorl_rorl_multiuse1_fail(i8 %x, i8 %C0) {
 
 define i1 @cmpeq_rorlXC_rorlYC_multiuse1(i8 %x, i8 %y) {
 ; CHECK-LABEL: @cmpeq_rorlXC_rorlYC_multiuse1(
-; CHECK-NEXT:    [[X_RORL0:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 6)
 ; CHECK-NEXT:    [[Y_RORL1:%.*]] = call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 3)
 ; CHECK-NEXT:    call void @use.i8(i8 [[Y_RORL1]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X_RORL0]], [[Y_RORL1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 3)
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x_rorl0 = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 6)

diff  --git a/llvm/test/Transforms/InstCombine/icmp-rotate.ll b/llvm/test/Transforms/InstCombine/icmp-rotate.ll
index abd7caf621a51..2580bb6a865c7 100644
--- a/llvm/test/Transforms/InstCombine/icmp-rotate.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-rotate.ll
@@ -211,9 +211,9 @@ define i1 @wrong_pred(i8 %x, i8 %y, i8 %z) {
 ; negative test - rotate amounts mismatch
 define i1 @amounts_mismatch(i8 %x, i8 %y, i8 %z, i8 %w) {
 ; CHECK-LABEL: @amounts_mismatch(
-; CHECK-NEXT:    [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]])
-; CHECK-NEXT:    [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[W:%.*]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[F]], [[F2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[Z:%.*]], [[W:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]])
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP2]], [[Y:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z)


        


More information about the llvm-commits mailing list