Skip to content

Commit 2701a22

Browse files
authored
[LVI] Support no constant range of cast value in getEdgeValueLocal. (#157614)
proof: https://alive2.llvm.org/ce/z/8emkHY
1 parent b44e6e0 commit 2701a22

File tree

3 files changed

+140
-2
lines changed

3 files changed

+140
-2
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,24 @@ LazyValueInfoImpl::getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
14931493
// br %Condition, label %then, label %else
14941494
APInt ConditionVal(1, isTrueDest ? 1 : 0);
14951495
Result = constantFoldUser(Usr, Condition, ConditionVal, DL);
1496+
} else if (isa<TruncInst, ZExtInst, SExtInst>(Usr)) {
1497+
ValueLatticeElement OpLatticeVal =
1498+
*getValueFromCondition(Usr->getOperand(0), Condition,
1499+
isTrueDest, /*UseBlockValue*/ false);
1500+
1501+
if (!OpLatticeVal.isConstantRange())
1502+
return OpLatticeVal;
1503+
1504+
const unsigned ResultBitWidth =
1505+
Usr->getType()->getScalarSizeInBits();
1506+
if (auto *Trunc = dyn_cast<TruncInst>(Usr))
1507+
return ValueLatticeElement::getRange(
1508+
OpLatticeVal.getConstantRange().truncate(
1509+
ResultBitWidth, Trunc->getNoWrapKind()));
1510+
1511+
return ValueLatticeElement::getRange(
1512+
OpLatticeVal.getConstantRange().castOp(
1513+
cast<CastInst>(Usr)->getOpcode(), ResultBitWidth));
14961514
} else {
14971515
// If one of Val's operand has an inferred value, we may be able to
14981516
// infer the value of Val.

llvm/test/Transforms/CorrelatedValuePropagation/range.ll

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,126 @@ define i1 @neg_icmp_eq_range_call() {
12351235
ret i1 %cmp
12361236
}
12371237

1238+
define i16 @return_range_for_edge_value_zext(i8 %a) {
1239+
; CHECK-LABEL: define range(i16 0, 98) i16 @return_range_for_edge_value_zext(
1240+
; CHECK-SAME: i8 [[A:%.*]]) {
1241+
; CHECK-NEXT: [[ENTRY:.*:]]
1242+
; CHECK-NEXT: [[B:%.*]] = zext i8 [[A]] to i16
1243+
; CHECK-NEXT: br label %[[DISPATCH:.*]]
1244+
; CHECK: [[DISPATCH]]:
1245+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A]], 98
1246+
; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]]
1247+
; CHECK: [[TARGET]]:
1248+
; CHECK-NEXT: ret i16 [[B]]
1249+
;
1250+
entry:
1251+
%b = zext i8 %a to i16
1252+
br label %dispatch
1253+
1254+
dispatch:
1255+
%cmp = icmp ult i8 %a, 98
1256+
br i1 %cmp, label %target, label %dispatch
1257+
1258+
target:
1259+
ret i16 %b
1260+
}
1261+
1262+
define i16 @return_range_for_edge_value_sext(i8 %a) {
1263+
; CHECK-LABEL: define range(i16 -55, 0) i16 @return_range_for_edge_value_sext(
1264+
; CHECK-SAME: i8 [[A:%.*]]) {
1265+
; CHECK-NEXT: [[ENTRY:.*:]]
1266+
; CHECK-NEXT: [[B:%.*]] = sext i8 [[A]] to i16
1267+
; CHECK-NEXT: br label %[[DISPATCH:.*]]
1268+
; CHECK: [[DISPATCH]]:
1269+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A]], -56
1270+
; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]]
1271+
; CHECK: [[TARGET]]:
1272+
; CHECK-NEXT: ret i16 [[B]]
1273+
;
1274+
entry:
1275+
%b = sext i8 %a to i16
1276+
br label %dispatch
1277+
1278+
dispatch:
1279+
%cmp = icmp ugt i8 %a, -56
1280+
br i1 %cmp, label %target, label %dispatch
1281+
1282+
target:
1283+
ret i16 %b
1284+
}
1285+
1286+
define i8 @return_range_for_edge_value_trunc(i16 %a) {
1287+
; CHECK-LABEL: define range(i8 0, 98) i8 @return_range_for_edge_value_trunc(
1288+
; CHECK-SAME: i16 [[A:%.*]]) {
1289+
; CHECK-NEXT: [[ENTRY:.*:]]
1290+
; CHECK-NEXT: [[B:%.*]] = trunc i16 [[A]] to i8
1291+
; CHECK-NEXT: br label %[[DISPATCH:.*]]
1292+
; CHECK: [[DISPATCH]]:
1293+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[A]], 98
1294+
; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]]
1295+
; CHECK: [[TARGET]]:
1296+
; CHECK-NEXT: ret i8 [[B]]
1297+
;
1298+
entry:
1299+
%b = trunc i16 %a to i8
1300+
br label %dispatch
1301+
1302+
dispatch:
1303+
%cmp = icmp ult i16 %a, 98
1304+
br i1 %cmp, label %target, label %dispatch
1305+
1306+
target:
1307+
ret i8 %b
1308+
}
1309+
1310+
define i8 @neg_return_range_for_edge_value_trunc(i16 %a) {
1311+
; CHECK-LABEL: define i8 @neg_return_range_for_edge_value_trunc(
1312+
; CHECK-SAME: i16 [[A:%.*]]) {
1313+
; CHECK-NEXT: [[ENTRY:.*:]]
1314+
; CHECK-NEXT: [[B:%.*]] = trunc i16 [[A]] to i8
1315+
; CHECK-NEXT: br label %[[DISPATCH:.*]]
1316+
; CHECK: [[DISPATCH]]:
1317+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[A]], 200
1318+
; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]]
1319+
; CHECK: [[TARGET]]:
1320+
; CHECK-NEXT: ret i8 [[B]]
1321+
;
1322+
entry:
1323+
%b = trunc i16 %a to i8
1324+
br label %dispatch
1325+
1326+
dispatch:
1327+
%cmp = icmp ugt i16 %a, 200
1328+
br i1 %cmp, label %target, label %dispatch
1329+
1330+
target:
1331+
ret i8 %b
1332+
}
1333+
1334+
define i8 @return_range_for_edge_value_trunc_nuw(i16 %a) {
1335+
; CHECK-LABEL: define range(i8 -55, 0) i8 @return_range_for_edge_value_trunc_nuw(
1336+
; CHECK-SAME: i16 [[A:%.*]]) {
1337+
; CHECK-NEXT: [[ENTRY:.*:]]
1338+
; CHECK-NEXT: [[B:%.*]] = trunc nuw i16 [[A]] to i8
1339+
; CHECK-NEXT: br label %[[DISPATCH:.*]]
1340+
; CHECK: [[DISPATCH]]:
1341+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[A]], 200
1342+
; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]]
1343+
; CHECK: [[TARGET]]:
1344+
; CHECK-NEXT: ret i8 [[B]]
1345+
;
1346+
entry:
1347+
%b = trunc nuw i16 %a to i8
1348+
br label %dispatch
1349+
1350+
dispatch:
1351+
%cmp = icmp ugt i16 %a, 200
1352+
br i1 %cmp, label %target, label %dispatch
1353+
1354+
target:
1355+
ret i8 %b
1356+
}
1357+
12381358
declare i16 @llvm.ctlz.i16(i16, i1)
12391359
declare i16 @llvm.cttz.i16(i16, i1)
12401360
declare i16 @llvm.ctpop.i16(i16)

llvm/test/Transforms/JumpThreading/branch-debug-info2.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ if.end.i60: ; preds = %shadow_to_ptr.exit
1818
%spec.select.i = select i1 %cmp3.i, i32 -1, i32 %conv7.i, !dbg !17
1919
; Jump threading is going to fold the select in to the branch. Ensure debug
2020
; info is not lost, and is merged from the select and the branch.
21-
; CHECK-NOT: br i1 %cmp3.i, label %for.inc, label %ptr_to_shadow.exit
22-
; CHECK: br i1 %cmp3.i, label %for.inc, label %ptr_to_shadow.exit, !dbg [[DBG:![0-9]+]]
21+
; CHECK-NOT: br i1 %cmp3.i, label %for.inc, label %if.end22
22+
; CHECK: br i1 %cmp3.i, label %for.inc, label %if.end22, !dbg [[DBG:![0-9]+]]
2323
; CHECK: [[DBG]] = !DILocation(line: 9, column: 1, scope: !{{.*}})
2424

2525
br label %ptr_to_shadow.exit, !dbg !17

0 commit comments

Comments
 (0)