Skip to content

Commit 0561ff6

Browse files
authored
[LVI] Add support for trunc nuw range. (#154021)
Proof: https://alive2.llvm.org/ce/z/a5Yjb8
1 parent e1aa415 commit 0561ff6

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,8 +927,13 @@ LazyValueInfoImpl::solveBlockValueCast(CastInst *CI, BasicBlock *BB) {
927927
// NOTE: We're currently limited by the set of operations that ConstantRange
928928
// can evaluate symbolically. Enhancing that set will allows us to analyze
929929
// more definitions.
930-
return ValueLatticeElement::getRange(LHSRange.castOp(CI->getOpcode(),
931-
ResultBitWidth));
930+
ConstantRange Res = ConstantRange::getEmpty(ResultBitWidth);
931+
if (auto *Trunc = dyn_cast<TruncInst>(CI))
932+
Res = LHSRange.truncate(ResultBitWidth, Trunc->getNoWrapKind());
933+
else
934+
Res = LHSRange.castOp(CI->getOpcode(), ResultBitWidth);
935+
936+
return ValueLatticeElement::getRange(Res);
932937
}
933938

934939
std::optional<ValueLatticeElement>

llvm/test/Transforms/CorrelatedValuePropagation/trunc.ll

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,43 @@ define i1 @overdefined_range_negative(i8 %A, i8 %B) {
106106
%trunc = trunc i8 %xor to i1
107107
ret i1 %trunc
108108
}
109+
110+
define i1 @trunc_nuw_infere_false_for_icmp_ne_1(i8 %x) {
111+
; CHECK-LABEL: define i1 @trunc_nuw_infere_false_for_icmp_ne_1(
112+
; CHECK-SAME: i8 [[X:%.*]]) {
113+
; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i8 [[X]], 1
114+
; CHECK-NEXT: br i1 [[ICMP]], label %[[IFTRUE:.*]], label %[[IFFALSE:.*]]
115+
; CHECK: [[IFTRUE]]:
116+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
117+
; CHECK-NEXT: ret i1 false
118+
; CHECK: [[IFFALSE]]:
119+
; CHECK-NEXT: ret i1 true
120+
;
121+
%icmp = icmp ne i8 %x, 1
122+
br i1 %icmp, label %iftrue, label %iffalse
123+
iftrue:
124+
%trunc = trunc nuw i8 %x to i1
125+
ret i1 %trunc
126+
iffalse:
127+
ret i1 true
128+
}
129+
130+
define i1 @neg_trunc_do_not_infere_false_for_icmp_ne_1(i8 %x) {
131+
; CHECK-LABEL: define i1 @neg_trunc_do_not_infere_false_for_icmp_ne_1(
132+
; CHECK-SAME: i8 [[X:%.*]]) {
133+
; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i8 [[X]], 1
134+
; CHECK-NEXT: br i1 [[ICMP]], label %[[IFTRUE:.*]], label %[[IFFALSE:.*]]
135+
; CHECK: [[IFTRUE]]:
136+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[X]] to i1
137+
; CHECK-NEXT: ret i1 [[TRUNC]]
138+
; CHECK: [[IFFALSE]]:
139+
; CHECK-NEXT: ret i1 true
140+
;
141+
%icmp = icmp ne i8 %x, 1
142+
br i1 %icmp, label %iftrue, label %iffalse
143+
iftrue:
144+
%trunc = trunc i8 %x to i1
145+
ret i1 %trunc
146+
iffalse:
147+
ret i1 true
148+
}

0 commit comments

Comments
 (0)