Skip to content

Commit 91836fd

Browse files
committed
[LVI][CVP] Handle (x | y) < C style conditions
InstCombine may convert conditions like (x < C) && (y < C) into (x | y) < C (for some C). This patch teaches LVI to recognize that in this case, it can infer either x < C or y < C along the edge. This fixes the issue reported at rust-lang/rust#73827. Differential Revision: https://reviews.llvm.org/D82715
1 parent 05d7929 commit 91836fd

File tree

2 files changed

+28
-31
lines changed

2 files changed

+28
-31
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,8 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueExtractValue(
10931093
return ValueLatticeElement::getOverdefined();
10941094
}
10951095

1096-
static bool matchICmpOperand(const APInt *&Offset, Value *LHS, Value *Val) {
1096+
static bool matchICmpOperand(const APInt *&Offset, Value *LHS, Value *Val,
1097+
ICmpInst::Predicate Pred) {
10971098
if (LHS == Val)
10981099
return true;
10991100

@@ -1102,6 +1103,16 @@ static bool matchICmpOperand(const APInt *&Offset, Value *LHS, Value *Val) {
11021103
if (match(LHS, m_Add(m_Specific(Val), m_APInt(Offset))))
11031104
return true;
11041105

1106+
// If (x | y) < C, then (x < C) && (y < C).
1107+
if (match(LHS, m_c_Or(m_Specific(Val), m_Value())) &&
1108+
(Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE))
1109+
return true;
1110+
1111+
// If (x & y) > C, then (x > C) && (y > C).
1112+
if (match(LHS, m_c_And(m_Specific(Val), m_Value())) &&
1113+
(Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE))
1114+
return true;
1115+
11051116
return false;
11061117
}
11071118

@@ -1127,10 +1138,10 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
11271138
return ValueLatticeElement::getOverdefined();
11281139

11291140
const APInt *Offset = nullptr;
1130-
if (!matchICmpOperand(Offset, LHS, Val)) {
1141+
if (!matchICmpOperand(Offset, LHS, Val, EdgePred)) {
11311142
std::swap(LHS, RHS);
11321143
EdgePred = CmpInst::getSwappedPredicate(EdgePred);
1133-
if (!matchICmpOperand(Offset, LHS, Val))
1144+
if (!matchICmpOperand(Offset, LHS, Val, EdgePred))
11341145
return ValueLatticeElement::getOverdefined();
11351146
}
11361147

llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -659,10 +659,8 @@ define void @test_icmp_or_ult(i32 %a, i32 %b) {
659659
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[OR]], 42
660660
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
661661
; CHECK: if.true:
662-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[A]], 42
663-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
664-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[B]], 42
665-
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
662+
; CHECK-NEXT: call void @check1(i1 true)
663+
; CHECK-NEXT: call void @check1(i1 true)
666664
; CHECK-NEXT: ret void
667665
; CHECK: if.false:
668666
; CHECK-NEXT: [[CMP4:%.*]] = icmp uge i32 [[A]], 42
@@ -698,10 +696,8 @@ define void @test_icmp_or_ule(i32 %a, i32 %b) {
698696
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[OR]], 42
699697
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
700698
; CHECK: if.true:
701-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[A]], 42
702-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
703-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[B]], 42
704-
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
699+
; CHECK-NEXT: call void @check1(i1 true)
700+
; CHECK-NEXT: call void @check1(i1 true)
705701
; CHECK-NEXT: ret void
706702
; CHECK: if.false:
707703
; CHECK-NEXT: [[CMP4:%.*]] = icmp ugt i32 [[A]], 42
@@ -743,10 +739,8 @@ define void @test_icmp_or_ugt(i32 %a, i32 %b) {
743739
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
744740
; CHECK-NEXT: ret void
745741
; CHECK: if.false:
746-
; CHECK-NEXT: [[CMP4:%.*]] = icmp ule i32 [[A]], 42
747-
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
748-
; CHECK-NEXT: [[CMP5:%.*]] = icmp ule i32 [[B]], 42
749-
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
742+
; CHECK-NEXT: call void @check1(i1 true)
743+
; CHECK-NEXT: call void @check1(i1 true)
750744
; CHECK-NEXT: ret void
751745
;
752746
entry:
@@ -782,10 +776,8 @@ define void @test_icmp_or_uge(i32 %a, i32 %b) {
782776
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
783777
; CHECK-NEXT: ret void
784778
; CHECK: if.false:
785-
; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[A]], 42
786-
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
787-
; CHECK-NEXT: [[CMP5:%.*]] = icmp ult i32 [[B]], 42
788-
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
779+
; CHECK-NEXT: call void @check1(i1 true)
780+
; CHECK-NEXT: call void @check1(i1 true)
789781
; CHECK-NEXT: ret void
790782
;
791783
entry:
@@ -854,10 +846,8 @@ define void @test_icmp_and_ugt(i32 %a, i32 %b) {
854846
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[AND]], 42
855847
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
856848
; CHECK: if.true:
857-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[A]], 42
858-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
859-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ugt i32 [[B]], 42
860-
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
849+
; CHECK-NEXT: call void @check1(i1 true)
850+
; CHECK-NEXT: call void @check1(i1 true)
861851
; CHECK-NEXT: ret void
862852
; CHECK: if.false:
863853
; CHECK-NEXT: [[CMP4:%.*]] = icmp ule i32 [[A]], 42
@@ -893,10 +883,8 @@ define void @test_icmp_and_uge(i32 %a, i32 %b) {
893883
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[AND]], 42
894884
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
895885
; CHECK: if.true:
896-
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[A]], 42
897-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
898-
; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[B]], 42
899-
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
886+
; CHECK-NEXT: call void @check1(i1 true)
887+
; CHECK-NEXT: call void @check1(i1 true)
900888
; CHECK-NEXT: ret void
901889
; CHECK: if.false:
902890
; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[A]], 42
@@ -938,10 +926,8 @@ define void @test_icmp_and_ult(i32 %a, i32 %b) {
938926
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
939927
; CHECK-NEXT: ret void
940928
; CHECK: if.false:
941-
; CHECK-NEXT: [[CMP4:%.*]] = icmp uge i32 [[A]], 42
942-
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
943-
; CHECK-NEXT: [[CMP5:%.*]] = icmp uge i32 [[B]], 42
944-
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
929+
; CHECK-NEXT: call void @check1(i1 true)
930+
; CHECK-NEXT: call void @check1(i1 true)
945931
; CHECK-NEXT: ret void
946932
;
947933
entry:

0 commit comments

Comments
 (0)