[llvm] [InstCombine] Fix regressions from canonicalizing `(icmp eq/ne (X, Y), Y` -> `(icmp eq/ne (~X, Y), 0)` (PR #93656)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 29 00:39:09 PDT 2024
https://github.com/goldsteinn created https://github.com/llvm/llvm-project/pull/93656
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.
>From 152f34e9eb67c735421e5bfcd81b9d3358820f24 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Fri, 22 Mar 2024 11:57:15 -0500
Subject: [PATCH] [InstCombine] Fix regressions from canonicalizing `(icmp
eq/ne (X, Y), 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/lib/Transforms/InstCombine/InstCombineCompares.cpp | 5 +++++
...anonicalize-low-bit-mask-v2-and-icmp-eq-to-icmp-ule.ll | 8 +++-----
...anonicalize-low-bit-mask-v2-and-icmp-ne-to-icmp-ugt.ll | 8 +++-----
3 files changed, 11 insertions(+), 10 deletions(-)
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
More information about the llvm-commits
mailing list