-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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
InstCombine: Avoid counting uses of constants #136566
Conversation
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.
@llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesLogically it does not matter; getFreelyInvertedImpl doesn't This use count logic should probably sink into getFreelyInvertedImpl, Full diff: https://github.com/llvm/llvm-project/pull/136566.diff 2 Files Affected:
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) {
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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.
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.