Skip to content

Commit 445db89

Browse files
committed
[LVI] Get value range from mask comparison
InstCombine likes to canonicalize comparisons of the form X == C || X == C+1 into (X & -2) == C'. Make sure LVI can still recover the value range from this. Can of course also be useful for proper mask comparisons. For the sake of clarity, the implementation goes through KnownBits to compute the range.
1 parent 91af6a7 commit 445db89

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/InitializePasses.h"
3737
#include "llvm/Support/Debug.h"
3838
#include "llvm/Support/FormattedStream.h"
39+
#include "llvm/Support/KnownBits.h"
3940
#include "llvm/Support/raw_ostream.h"
4041
#include <map>
4142
using namespace llvm;
@@ -1145,6 +1146,19 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
11451146
if (matchICmpOperand(Offset, RHS, Val, SwappedPred))
11461147
return getValueFromSimpleICmpCondition(SwappedPred, LHS, Offset);
11471148

1149+
// If (Val & Mask) == C then all the masked bits are known and we can compute
1150+
// a value range based on that.
1151+
const APInt *Mask, *C;
1152+
if (EdgePred == ICmpInst::ICMP_EQ &&
1153+
match(LHS, m_And(m_Specific(Val), m_APInt(Mask))) &&
1154+
match(RHS, m_APInt(C))) {
1155+
KnownBits Known;
1156+
Known.Zero = ~*C & *Mask;
1157+
Known.One = *C & *Mask;
1158+
return ValueLatticeElement::getRange(
1159+
ConstantRange::fromKnownBits(Known, /*IsSigned*/ false));
1160+
}
1161+
11481162
return ValueLatticeElement::getOverdefined();
11491163
}
11501164

llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll

+6-12
Original file line numberDiff line numberDiff line change
@@ -995,14 +995,10 @@ define void @test_icmp_mask_two_values(i32 %a) {
995995
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 10
996996
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
997997
; CHECK: if.true:
998-
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[A]], 10
999-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
1000-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[A]], 11
1001-
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
1002-
; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[A]], 10
1003-
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
1004-
; CHECK-NEXT: [[CMP5:%.*]] = icmp ugt i32 [[A]], 11
1005-
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
998+
; CHECK-NEXT: call void @check1(i1 true)
999+
; CHECK-NEXT: call void @check1(i1 true)
1000+
; CHECK-NEXT: call void @check1(i1 false)
1001+
; CHECK-NEXT: call void @check1(i1 false)
10061002
; CHECK-NEXT: ret void
10071003
; CHECK: if.false:
10081004
; CHECK-NEXT: ret void
@@ -1032,8 +1028,7 @@ define void @test_icmp_mask_bit_set(i32 %a) {
10321028
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 32
10331029
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
10341030
; CHECK: if.true:
1035-
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[A]], 32
1036-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
1031+
; CHECK-NEXT: call void @check1(i1 true)
10371032
; CHECK-NEXT: [[CMP3:%.*]] = icmp uge i32 [[A]], 33
10381033
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
10391034
; CHECK-NEXT: ret void
@@ -1061,8 +1056,7 @@ define void @test_icmp_mask_bit_unset(i32 %a) {
10611056
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
10621057
; CHECK-NEXT: br i1 [[CMP]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
10631058
; CHECK: if.true:
1064-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[A]], -33
1065-
; CHECK-NEXT: call void @check1(i1 [[CMP2]])
1059+
; CHECK-NEXT: call void @check1(i1 true)
10661060
; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[A]], -34
10671061
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
10681062
; CHECK-NEXT: ret void

0 commit comments

Comments
 (0)