[PATCH] D152348: [InstCombine] Canonicalize (icmp eq/ne X, rotate(X)) to always use rotate-left

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 7 01:15:38 PDT 2023


goldstein.w.n created this revision.
goldstein.w.n added reviewers: nikic, spatel.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

We canonicalize rotate-right -> rotate-left in other places. Makes
sense to do so here as well.
Proof: https://alive2.llvm.org/ce/z/HL3TpK


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152348

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


Index: llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
===================================================================
--- llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
+++ llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll
@@ -30,9 +30,9 @@
 
 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)
@@ -71,10 +71,10 @@
 
 define i1 @cmpeq_rorlC_rorlC_multiuse1(i8 %x, i8 %C0) {
 ; CHECK-LABEL: @cmpeq_rorlC_rorlC_multiuse1(
-; CHECK-NEXT:    [[X_RORL0:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 6)
-; CHECK-NEXT:    [[X_RORL1:%.*]] = call i8 @llvm.fshl.i8(i8 [[X]], i8 [[X]], i8 3)
+; CHECK-NEXT:    [[X_RORL1:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 3)
 ; CHECK-NEXT:    call void @use.i8(i8 [[X_RORL1]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X_RORL0]], [[X_RORL1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.fshl.i8(i8 [[X]], i8 [[X]], i8 3)
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], [[X]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x_rorl0 = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 6)
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3443,7 +3443,9 @@
 }
 
 /// 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();
@@ -3468,9 +3470,30 @@
       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, Amt0) == rotate(X, Amt1)
+    //  -> rotate(X, Amt0 - Amt1) == X
+    // Do this if either both rotates have one use or if only one has one use
+    // and Amt0/Amt1 are constants.
+    if (IIOp0->getOperand(0) == IIOp1->getOperand(0)) {
+        unsigned OneUses = IIOp0->hasOneUse() + IIOp1->hasOneUse();
+        if (OneUses == 2 ||
+            (OneUses == 1 && match(IIOp0->getOperand(2), m_ImmConstant()) &&
+             match(IIOp1->getOperand(2), m_ImmConstant()))) {
+        Module *Mod = Cmp.getModule();
+        Function *Rotate = Intrinsic::getDeclaration(
+            Mod, IIOp0->getIntrinsicID(), Op0->getType());
+        Value *SubAmt =
+            Builder.CreateSub(IIOp0->getOperand(2), IIOp1->getOperand(2));
+        return new ICmpInst(
+            Pred, IIOp0->getOperand(0),
+            Builder.CreateCall(
+                Rotate, {IIOp0->getOperand(0), IIOp0->getOperand(0), SubAmt}));
+        }
+    }
+    break;
   default:
     break;
   }
@@ -4970,7 +4993,7 @@
     }
   }
 
-  if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I))
+  if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I, Builder))
     return ICmp;
 
   // Canonicalize checking for a power-of-2-or-zero value:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D152348.529209.patch
Type: text/x-patch
Size: 3888 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230607/4964f1eb/attachment.bin>


More information about the llvm-commits mailing list