[llvm] [InstCombine] Respect `samesign` flag in `foldAndOrOfICmpsWithConstEq` (PR #112475)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 15 21:13:02 PDT 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/112475
In https://github.com/llvm/llvm-project/commit/5dbfca30c1a672cd0c5089df2b4fdd171436643a we assume that RHS is poison implies LHS is also poison. It doesn't hold after introducing `samesign` flag. This patch treats this case as logical and swap operands iff `RHS` has `samesign` flag and the original expression is a logical and/or.
Alternative solution 1: just drop `samesign` flag in RHS after folding.
Alternative solution 2: reject this fold if RHS contains `samesign` flag.
Close https://github.com/llvm/llvm-project/issues/112467.
>From 0019d6c1bd2fa774ef061c04e5453904d49a1a66 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 16 Oct 2024 11:50:40 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/and-or-icmps.ll | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index eb4723c86542de..87d53f9b46deba 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -3416,3 +3416,16 @@ define i1 @and_ugt_to_mask_off_by_one(i8 %x) {
%and2 = and i1 %cmp, %cmp2
ret i1 %and2
}
+
+define i1 @logical_or_icmp_eq_const_samesign(i8 %x, i8 %y) {
+; CHECK-LABEL: @logical_or_icmp_eq_const_samesign(
+; CHECK-NEXT: [[CMPEQ:%.*]] = icmp samesign ne i8 [[X:%.*]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 0
+; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[TMP1]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %cmp = icmp sgt i8 %x, %y
+ %cmpeq = icmp samesign ne i8 %x, 0
+ %r = select i1 %cmp, i1 true, i1 %cmpeq
+ ret i1 %r
+}
>From d0ccb329d83f2399277d926cea8743694f6ca8a2 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 16 Oct 2024 12:04:13 +0800
Subject: [PATCH 2/2] [InstCombine] Respect `samesign` flag in
`foldAndOrOfICmpsWithConstEq`
---
.../InstCombine/InstCombineAndOrXor.cpp | 25 +++++++++++++------
.../Transforms/InstCombine/and-or-icmps.ll | 2 +-
2 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 64bee4ab974ede..22728bc8abda46 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1261,7 +1261,8 @@ Value *InstCombinerImpl::foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1,
static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd, bool IsLogical,
InstCombiner::BuilderTy &Builder,
- const SimplifyQuery &Q) {
+ const SimplifyQuery &Q,
+ bool SwapOpOrder) {
// Match an equality compare with a non-poison constant as Cmp0.
// Also, give up if the compare can be constant-folded to avoid looping.
ICmpInst::Predicate Pred0;
@@ -1295,9 +1296,14 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
return nullptr;
SubstituteCmp = Builder.CreateICmp(Pred1, Y, C);
}
- if (IsLogical)
- return IsAnd ? Builder.CreateLogicalAnd(Cmp0, SubstituteCmp)
- : Builder.CreateLogicalOr(Cmp0, SubstituteCmp);
+ if (IsLogical) {
+ Value *LHS = Cmp0;
+ Value *RHS = SubstituteCmp;
+ if (SwapOpOrder)
+ std::swap(LHS, RHS);
+ return IsAnd ? Builder.CreateLogicalAnd(LHS, RHS)
+ : Builder.CreateLogicalOr(LHS, RHS);
+ }
return Builder.CreateBinOp(IsAnd ? Instruction::And : Instruction::Or, Cmp0,
SubstituteCmp);
}
@@ -3363,13 +3369,16 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
/*IsLogical*/ false, Builder))
return V;
- if (Value *V =
- foldAndOrOfICmpsWithConstEq(LHS, RHS, IsAnd, IsLogical, Builder, Q))
+ if (Value *V = foldAndOrOfICmpsWithConstEq(LHS, RHS, IsAnd, IsLogical,
+ Builder, Q, /*SwapOpOrder=*/false))
return V;
// We can convert this case to bitwise and, because both operands are used
- // on the LHS, and as such poison from both will propagate.
+ // on the LHS, and as such poison from both will propagate (unless RHS has
+ // samesign flag).
if (Value *V = foldAndOrOfICmpsWithConstEq(RHS, LHS, IsAnd,
- /*IsLogical*/ false, Builder, Q))
+ /*IsLogical=*/IsLogical &&
+ RHS->hasSameSign(),
+ Builder, Q, /*SwapOpOrder=*/true))
return V;
if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder, *this))
diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 87d53f9b46deba..a02db166acf5da 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -3421,7 +3421,7 @@ define i1 @logical_or_icmp_eq_const_samesign(i8 %x, i8 %y) {
; CHECK-LABEL: @logical_or_icmp_eq_const_samesign(
; CHECK-NEXT: [[CMPEQ:%.*]] = icmp samesign ne i8 [[X:%.*]], 0
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 0
-; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[TMP1]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMPEQ]]
; CHECK-NEXT: ret i1 [[R]]
;
%cmp = icmp sgt i8 %x, %y
More information about the llvm-commits
mailing list