-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstCombine] Fix regressions from canonicalizing (icmp eq/ne (X, Y), Y
-> (icmp eq/ne (~X, Y), 0)
#93656
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
Conversation
…, Y` -> `(icmp eq/ne (~X, Y), 0)` This issue is the canonicalization can consume `not` instruction which are a limitted resource and are use to enable multiple transforms. In this case `foldICmpWithLowBitMaskedVal` is a "better" user of `not` instructions, so just check if that has a result first.
@llvm/pr-subscribers-llvm-transforms Author: None (goldsteinn) ChangesThis issue is the canonicalization can consume In this case Full diff: https://github.com/llvm/llvm-project/pull/93656.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 89193f8ff94b6..08d6a822374ba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4740,6 +4740,11 @@ static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q,
return new ICmpInst(Pred, IC.Builder.CreateOr(A, NotOp1),
Constant::getAllOnesValue(Op1->getType()));
// icmp (X & Y) eq/ne Y --> (~X & Y) eq/ne 0 if X is freely invertible.
+ // Since we may be consuming a `not` here, first check if we match
+ // `foldICmpWithLowBitMaskedVal` as it is a "better" user of `not`
+ // instructions.
+ if (Value *R = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Q, IC))
+ return IC.replaceInstUsesWith(I, R);
if (auto *NotA = IC.getFreelyInverted(A, A->hasOneUse(), &IC.Builder))
return new ICmpInst(Pred, IC.Builder.CreateAnd(Op1, NotA),
Constant::getNullValue(Op1->getType()));
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
index 0a7de501ca022..24ca49386b7e8 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,8 +161,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -196,8 +195,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
diff --git a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
index 54ff87676e71d..271d78d589b60 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll
@@ -144,7 +144,7 @@ define i1 @oneuse0(i8 %x, i8 %y) {
; CHECK-LABEL: @oneuse0(
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: call void @use8(i8 [[T0]])
-; CHECK-NEXT: [[X_HIGHBITS:%.*]] = and i8 [[T0]], [[X:%.*]]
+; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[RET]]
;
@@ -161,8 +161,7 @@ define i1 @oneuse1(i8 %x, i8 %y) {
; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
@@ -196,8 +195,7 @@ define i1 @oneuse3(i8 %x, i8 %y) {
; CHECK-NEXT: call void @use8(i8 [[T0]])
; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
; CHECK-NEXT: call void @use8(i8 [[T1]])
-; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[T0]], [[X:%.*]]
-; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[T1]], [[X:%.*]]
; CHECK-NEXT: ret i1 [[RET]]
;
%t0 = shl i8 -1, %y
|
@dtcxzyw can you test this to see if the regression actually matters? |
Done. I don't think the regression exists. |
Thanks for checking |
This issue is the canonicalization can consume
not
instruction whichare a limitted resource and are use to enable multiple transforms.
In this case
foldICmpWithLowBitMaskedVal
is a "better" user ofnot
instructions, so just check if that has a result first.