Skip to content

InstCombine: Avoid counting uses of constants #136566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Apr 21, 2025

Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.

Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.
@arsenm arsenm added the llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes label Apr 21, 2025 — with Graphite App
@arsenm arsenm requested review from dtcxzyw and nikic April 21, 2025 13:21
Copy link
Contributor Author

arsenm commented Apr 21, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@arsenm arsenm marked this pull request as ready for review April 21, 2025 13:21
@llvmbot
Copy link
Member

llvmbot commented Apr 21, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Matt Arsenault (arsenm)

Changes

Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.


Full diff: https://github.com/llvm/llvm-project/pull/136566.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+2-2)
  • (modified) llvm/test/Transforms/InstCombine/icmp.ll (+93)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 55afe1258159a..b7b0bb7361359 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5034,8 +5034,8 @@ static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
 
   if (ICmpInst::isEquality(Pred) && Op0->hasOneUse()) {
     // icmp (X | Y) eq/ne Y --> (X & ~Y) eq/ne 0 if Y is freely invertible
-    if (Value *NotOp1 =
-            IC.getFreelyInverted(Op1, !Op1->hasNUsesOrMore(3), &IC.Builder))
+    if (Value *NotOp1 = IC.getFreelyInverted(
+            Op1, !isa<Constant>(Op1) && !Op1->hasNUsesOrMore(3), &IC.Builder))
       return new ICmpInst(Pred, IC.Builder.CreateAnd(A, NotOp1),
                           Constant::getNullValue(Op1->getType()));
     // icmp (X | Y) eq/ne Y --> (~X | Y) eq/ne -1 if X  is freely invertible.
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 6e1486660b24d..f5df8573d6304 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -2954,6 +2954,99 @@ define i1 @or1_eq1(i32 %x) {
   ret i1 %t1
 }
 
+define <2 x i1> @or1_eq1_vec(<2 x i32> %x) {
+; CHECK-LABEL: @or1_eq1_vec(
+; CHECK-NEXT:    [[T1:%.*]] = icmp ult <2 x i32> [[X:%.*]], splat (i32 2)
+; CHECK-NEXT:    ret <2 x i1> [[T1]]
+;
+  %t0 = or <2 x i32> %x, splat (i32 1)
+  %t1 = icmp eq <2 x i32> %t0, splat (i32 1)
+  ret <2 x i1> %t1
+}
+
+define <2 x i1> @or_eq_vec_nonsplat(<2 x i32> %x) {
+; CHECK-LABEL: @or_eq_vec_nonsplat(
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -3>
+; CHECK-NEXT:    [[T1:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[T1]]
+;
+  %t0 = or <2 x i32> %x, <i32 1, i32 2>
+  %t1 = icmp eq <2 x i32> %t0, <i32 1, i32 2>
+  ret <2 x i1> %t1
+}
+
+define void @or_eq_vec_multiple_nonsplat(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z, ptr %ptr0, ptr %ptr1, ptr %ptr2) {
+; CHECK-LABEL: @or_eq_vec_multiple_nonsplat(
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -2, i32 -3>
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT:    store <2 x i1> [[CMP0]], ptr [[PTR0:%.*]], align 1
+; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -2, i32 -3>
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer
+; CHECK-NEXT:    store <2 x i1> [[CMP1]], ptr [[PTR1:%.*]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = and <2 x i32> [[Z:%.*]], <i32 -2, i32 -3>
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq <2 x i32> [[TMP3]], zeroinitializer
+; CHECK-NEXT:    store <2 x i1> [[CMP2]], ptr [[PTR2:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+  %t0 = or <2 x i32> %x, <i32 1, i32 2>
+  %cmp0 = icmp eq <2 x i32> %t0, <i32 1, i32 2>
+  store <2 x i1> %cmp0, ptr %ptr0
+
+  %t1 = or <2 x i32> %y, <i32 1, i32 2>
+  %cmp1 = icmp eq <2 x i32> %t1, <i32 1, i32 2>
+  store <2 x i1> %cmp1, ptr %ptr1
+
+  %t2 = or <2 x i32> %z, <i32 1, i32 2>
+  %cmp2 = icmp eq <2 x i32> %t2, <i32 1, i32 2>
+  store <2 x i1> %cmp2, ptr %ptr2
+  ret void
+}
+
+; Make sure use count of 1 doesn't matter
+define i1 @or1_eq1_multiple(i32 %x, i32 %y, i32 %z, ptr %ptr0, ptr %ptr1) {
+; CHECK-LABEL: @or1_eq1_multiple(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 2
+; CHECK-NEXT:    store i1 [[CMP1]], ptr [[PTR:%.*]], align 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 2
+; CHECK-NEXT:    store i1 [[CMP2]], ptr [[PTR1:%.*]], align 1
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult i32 [[Z:%.*]], 2
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %t0 = or i32 %x, 1
+  %cmp0 = icmp eq i32 %t0, 1
+  store i1 %cmp0, ptr %ptr0
+
+  %t1 = or i32 %y, 1
+  %cmp1 = icmp eq i32 %t1, 1
+  store i1 %cmp1, ptr %ptr1
+
+  %t2 = or i32 %z, 1
+  %cmp2 = icmp eq i32 %t2, 1
+  ret i1 %cmp2
+}
+
+define <2 x i1> @or1_eq1_multiple_vec(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z, ptr %ptr0, ptr %ptr1) {
+; CHECK-LABEL: @or1_eq1_multiple_vec(
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp ult <2 x i32> [[X:%.*]], splat (i32 2)
+; CHECK-NEXT:    store <2 x i1> [[CMP0]], ptr [[PTR0:%.*]], align 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult <2 x i32> [[Y:%.*]], splat (i32 2)
+; CHECK-NEXT:    store <2 x i1> [[CMP1]], ptr [[PTR1:%.*]], align 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i32> [[Z:%.*]], splat (i32 2)
+; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
+;
+  %t0 = or <2 x i32> %x, splat (i32 1)
+  %cmp0 = icmp eq <2 x i32> %t0, splat (i32 1)
+  store <2 x i1> %cmp0, ptr %ptr0
+
+  %t1 = or <2 x i32> %y, splat (i32 1)
+  %cmp1 = icmp eq <2 x i32> %t1, splat (i32 1)
+  store <2 x i1> %cmp1, ptr %ptr1
+
+  %t2 = or <2 x i32> %z, splat (i32 1)
+  %cmp2 = icmp eq <2 x i32> %t2, splat (i32 1)
+  ret <2 x i1> %cmp2
+}
+
 ; X | C == C --> X <=u C (when C+1 is PowerOf2).
 
 define <2 x i1> @or3_eq3_vec(<2 x i8> %x) {

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor Author

arsenm commented Apr 23, 2025

Merge activity

  • Apr 23, 4:51 AM EDT: A user started a stack merge that includes this pull request via Graphite.
  • Apr 23, 4:51 AM EDT: A user merged this pull request with Graphite.

@arsenm arsenm merged commit 48585ca into main Apr 23, 2025
16 checks passed
@arsenm arsenm deleted the users/arsenm/instcombine/avoid-counting-use-of-constants branch April 23, 2025 08:51
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
Logically it does not matter; getFreelyInvertedImpl doesn't
depend on the value for the m_ImmConstant case.

This use count logic should probably sink into getFreelyInvertedImpl,
every use of this appears to just be a hasOneUse or hasNUse count,
so this could change to just be a use count threshold.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants