[llvm] aad3a16 - [ValueTracking] Respect `samesign` flag in `isKnownInversion` (#112390)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 16 09:27:25 PDT 2024
Author: Yingwei Zheng
Date: 2024-10-17T00:27:21+08:00
New Revision: aad3a1630e385a6834f92a5f1d6045451ba21e4e
URL: https://github.com/llvm/llvm-project/commit/aad3a1630e385a6834f92a5f1d6045451ba21e4e
DIFF: https://github.com/llvm/llvm-project/commit/aad3a1630e385a6834f92a5f1d6045451ba21e4e.diff
LOG: [ValueTracking] Respect `samesign` flag in `isKnownInversion` (#112390)
In https://github.com/llvm/llvm-project/pull/93591 we introduced
`isKnownInversion` and assumes `X` is poison implies `Y` is poison
because they share common operands. But after introducing `samesign`
this assumption no longer hold if `X` is an icmp has `samesign` flag.
Alive2 link: https://alive2.llvm.org/ce/z/rj3EwQ (Please run it locally
with this patch and https://github.com/AliveToolkit/alive2/pull/1098).
This approach is the most conservative way in my mind to address this
problem. If `X` has `samesign` flag, it will check if `Y` also has this
flag and make sure constant RHS operands have the same sign.
Fixes https://github.com/llvm/llvm-project/issues/112350.
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/InstCombine/select-cmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eb8d17044a17b5..e9ed8b3c862b55 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8522,6 +8522,10 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
!match(Y, m_c_ICmp(Pred2, m_Specific(A), m_Value(C))))
return false;
+ // They must both have samesign flag or not.
+ if (cast<ICmpInst>(X)->hasSameSign() != cast<ICmpInst>(Y)->hasSameSign())
+ return false;
+
if (B == C)
return Pred1 == ICmpInst::getInversePredicate(Pred2);
@@ -8530,6 +8534,11 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
if (!match(B, m_APInt(RHSC1)) || !match(C, m_APInt(RHSC2)))
return false;
+ // Sign bits of two RHSCs should match.
+ if (cast<ICmpInst>(X)->hasSameSign() &&
+ RHSC1->isNonNegative() != RHSC2->isNonNegative())
+ return false;
+
const auto CR1 = ConstantRange::makeExactICmpRegion(Pred1, *RHSC1);
const auto CR2 = ConstantRange::makeExactICmpRegion(Pred2, *RHSC2);
diff --git a/llvm/test/Transforms/InstCombine/select-cmp.ll b/llvm/test/Transforms/InstCombine/select-cmp.ll
index 234815949d77d4..f7505bd85f89eb 100644
--- a/llvm/test/Transforms/InstCombine/select-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/select-cmp.ll
@@ -480,6 +480,95 @@ define i1 @test_select_inverse_nonconst4(i64 %x, i64 %y, i64 %z, i1 %cond) {
ret i1 %sel
}
+define i1 @test_select_inverse_samesign_true_arm(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_true_arm(
+; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[X]], [[Y]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp samesign ult i64 %x, %y
+ %cmp2 = icmp uge i64 %x, %y
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_false_arm(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_false_arm(
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign uge i64 [[X]], [[Y]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp ult i64 %x, %y
+ %cmp2 = icmp samesign uge i64 %x, %y
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_both(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_both(
+; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign uge i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[SEL:%.*]] = xor i1 [[COND:%.*]], [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp samesign ult i64 %x, %y
+ %cmp2 = icmp samesign uge i64 %x, %y
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_false_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_false_arm_rhsc_same_sign(
+; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[X:%.*]], 11
+; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ugt i64 [[X]], 10
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp ult i64 %x, 11
+ %cmp2 = icmp samesign ugt i64 %x, 10
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_true_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_true_arm_rhsc_same_sign(
+; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[X:%.*]], 11
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i64 [[X]], 10
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp samesign ult i64 %x, 11
+ %cmp2 = icmp ugt i64 %x, 10
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_both_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_both_rhsc_same_sign(
+; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ugt i64 [[X:%.*]], 10
+; CHECK-NEXT: [[SEL:%.*]] = xor i1 [[COND:%.*]], [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp samesign ult i64 %x, 11
+ %cmp2 = icmp samesign ugt i64 %x, 10
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
+define i1 @test_select_inverse_samesign_both_rhsc_
diff _sign(i64 %x, i64 %y, i1 %cond) {
+; CHECK-LABEL: @test_select_inverse_samesign_both_rhsc_
diff _sign(
+; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign slt i64 [[X:%.*]], 0
+; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign sgt i64 [[X]], -1
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+ %cmp1 = icmp samesign slt i64 %x, 0
+ %cmp2 = icmp samesign sgt i64 %x, -1
+ %sel = select i1 %cond, i1 %cmp1, i1 %cmp2
+ ret i1 %sel
+}
+
define i1 @sel_icmp_two_cmp(i1 %c, i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
; CHECK-LABEL: @sel_icmp_two_cmp(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i32 [[A1:%.*]], [[A2:%.*]]
More information about the llvm-commits
mailing list