Skip to content

Commit aad3a16

Browse files
authored
[ValueTracking] Respect samesign flag in isKnownInversion (#112390)
In #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 AliveToolkit/alive2#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 #112350.
1 parent 35e937b commit aad3a16

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8522,6 +8522,10 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
85228522
!match(Y, m_c_ICmp(Pred2, m_Specific(A), m_Value(C))))
85238523
return false;
85248524

8525+
// They must both have samesign flag or not.
8526+
if (cast<ICmpInst>(X)->hasSameSign() != cast<ICmpInst>(Y)->hasSameSign())
8527+
return false;
8528+
85258529
if (B == C)
85268530
return Pred1 == ICmpInst::getInversePredicate(Pred2);
85278531

@@ -8530,6 +8534,11 @@ bool llvm::isKnownInversion(const Value *X, const Value *Y) {
85308534
if (!match(B, m_APInt(RHSC1)) || !match(C, m_APInt(RHSC2)))
85318535
return false;
85328536

8537+
// Sign bits of two RHSCs should match.
8538+
if (cast<ICmpInst>(X)->hasSameSign() &&
8539+
RHSC1->isNonNegative() != RHSC2->isNonNegative())
8540+
return false;
8541+
85338542
const auto CR1 = ConstantRange::makeExactICmpRegion(Pred1, *RHSC1);
85348543
const auto CR2 = ConstantRange::makeExactICmpRegion(Pred2, *RHSC2);
85358544

llvm/test/Transforms/InstCombine/select-cmp.ll

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,95 @@ define i1 @test_select_inverse_nonconst4(i64 %x, i64 %y, i64 %z, i1 %cond) {
480480
ret i1 %sel
481481
}
482482

483+
define i1 @test_select_inverse_samesign_true_arm(i64 %x, i64 %y, i1 %cond) {
484+
; CHECK-LABEL: @test_select_inverse_samesign_true_arm(
485+
; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[X:%.*]], [[Y:%.*]]
486+
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[X]], [[Y]]
487+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
488+
; CHECK-NEXT: ret i1 [[SEL]]
489+
;
490+
%cmp1 = icmp samesign ult i64 %x, %y
491+
%cmp2 = icmp uge i64 %x, %y
492+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
493+
ret i1 %sel
494+
}
495+
496+
define i1 @test_select_inverse_samesign_false_arm(i64 %x, i64 %y, i1 %cond) {
497+
; CHECK-LABEL: @test_select_inverse_samesign_false_arm(
498+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[X:%.*]], [[Y:%.*]]
499+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign uge i64 [[X]], [[Y]]
500+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
501+
; CHECK-NEXT: ret i1 [[SEL]]
502+
;
503+
%cmp1 = icmp ult i64 %x, %y
504+
%cmp2 = icmp samesign uge i64 %x, %y
505+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
506+
ret i1 %sel
507+
}
508+
509+
define i1 @test_select_inverse_samesign_both(i64 %x, i64 %y, i1 %cond) {
510+
; CHECK-LABEL: @test_select_inverse_samesign_both(
511+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign uge i64 [[X:%.*]], [[Y:%.*]]
512+
; CHECK-NEXT: [[SEL:%.*]] = xor i1 [[COND:%.*]], [[CMP2]]
513+
; CHECK-NEXT: ret i1 [[SEL]]
514+
;
515+
%cmp1 = icmp samesign ult i64 %x, %y
516+
%cmp2 = icmp samesign uge i64 %x, %y
517+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
518+
ret i1 %sel
519+
}
520+
521+
define i1 @test_select_inverse_samesign_false_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
522+
; CHECK-LABEL: @test_select_inverse_samesign_false_arm_rhsc_same_sign(
523+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[X:%.*]], 11
524+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ugt i64 [[X]], 10
525+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
526+
; CHECK-NEXT: ret i1 [[SEL]]
527+
;
528+
%cmp1 = icmp ult i64 %x, 11
529+
%cmp2 = icmp samesign ugt i64 %x, 10
530+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
531+
ret i1 %sel
532+
}
533+
534+
define i1 @test_select_inverse_samesign_true_arm_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
535+
; CHECK-LABEL: @test_select_inverse_samesign_true_arm_rhsc_same_sign(
536+
; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign ult i64 [[X:%.*]], 11
537+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i64 [[X]], 10
538+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
539+
; CHECK-NEXT: ret i1 [[SEL]]
540+
;
541+
%cmp1 = icmp samesign ult i64 %x, 11
542+
%cmp2 = icmp ugt i64 %x, 10
543+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
544+
ret i1 %sel
545+
}
546+
547+
define i1 @test_select_inverse_samesign_both_rhsc_same_sign(i64 %x, i64 %y, i1 %cond) {
548+
; CHECK-LABEL: @test_select_inverse_samesign_both_rhsc_same_sign(
549+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign ugt i64 [[X:%.*]], 10
550+
; CHECK-NEXT: [[SEL:%.*]] = xor i1 [[COND:%.*]], [[CMP2]]
551+
; CHECK-NEXT: ret i1 [[SEL]]
552+
;
553+
%cmp1 = icmp samesign ult i64 %x, 11
554+
%cmp2 = icmp samesign ugt i64 %x, 10
555+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
556+
ret i1 %sel
557+
}
558+
559+
define i1 @test_select_inverse_samesign_both_rhsc_diff_sign(i64 %x, i64 %y, i1 %cond) {
560+
; CHECK-LABEL: @test_select_inverse_samesign_both_rhsc_diff_sign(
561+
; CHECK-NEXT: [[CMP1:%.*]] = icmp samesign slt i64 [[X:%.*]], 0
562+
; CHECK-NEXT: [[CMP2:%.*]] = icmp samesign sgt i64 [[X]], -1
563+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP1]], i1 [[CMP2]]
564+
; CHECK-NEXT: ret i1 [[SEL]]
565+
;
566+
%cmp1 = icmp samesign slt i64 %x, 0
567+
%cmp2 = icmp samesign sgt i64 %x, -1
568+
%sel = select i1 %cond, i1 %cmp1, i1 %cmp2
569+
ret i1 %sel
570+
}
571+
483572
define i1 @sel_icmp_two_cmp(i1 %c, i32 %a1, i32 %a2, i32 %a3, i32 %a4) {
484573
; CHECK-LABEL: @sel_icmp_two_cmp(
485574
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule i32 [[A1:%.*]], [[A2:%.*]]

0 commit comments

Comments
 (0)