Skip to content

Commit d62776d

Browse files
authored
[LVI] Handle constant value lattice in getEdgeValueLocal (#161410)
Closes #161367. In #157614, we ignored cases where OpLatticeVal might be a constant or notconstant. Directly returning the result causes a type mismatch. I apologize for the oversight in the previous code review. This patch applies the cast op to constants. For notconstant value lattices, I'd leave it as a todo (it is similar to the constant case, except for trunc without nsw/nuw).
1 parent 6e0d519 commit d62776d

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,19 +1632,25 @@ LazyValueInfoImpl::getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
16321632
*getValueFromCondition(Usr->getOperand(0), Condition,
16331633
isTrueDest, /*UseBlockValue*/ false);
16341634

1635-
if (!OpLatticeVal.isConstantRange())
1636-
return OpLatticeVal;
1635+
if (OpLatticeVal.isConstantRange()) {
1636+
const unsigned ResultBitWidth =
1637+
Usr->getType()->getScalarSizeInBits();
1638+
if (auto *Trunc = dyn_cast<TruncInst>(Usr))
1639+
return ValueLatticeElement::getRange(
1640+
OpLatticeVal.getConstantRange().truncate(
1641+
ResultBitWidth, Trunc->getNoWrapKind()));
16371642

1638-
const unsigned ResultBitWidth =
1639-
Usr->getType()->getScalarSizeInBits();
1640-
if (auto *Trunc = dyn_cast<TruncInst>(Usr))
16411643
return ValueLatticeElement::getRange(
1642-
OpLatticeVal.getConstantRange().truncate(
1643-
ResultBitWidth, Trunc->getNoWrapKind()));
1644-
1645-
return ValueLatticeElement::getRange(
1646-
OpLatticeVal.getConstantRange().castOp(
1647-
cast<CastInst>(Usr)->getOpcode(), ResultBitWidth));
1644+
OpLatticeVal.getConstantRange().castOp(
1645+
cast<CastInst>(Usr)->getOpcode(), ResultBitWidth));
1646+
}
1647+
if (OpLatticeVal.isConstant()) {
1648+
Constant *C = OpLatticeVal.getConstant();
1649+
if (auto *CastC = ConstantFoldCastOperand(
1650+
cast<CastInst>(Usr)->getOpcode(), C, Usr->getType(), DL))
1651+
return ValueLatticeElement::get(CastC);
1652+
}
1653+
return ValueLatticeElement::getOverdefined();
16481654
} else {
16491655
// If one of Val's operand has an inferred value, we may be able to
16501656
// infer the value of Val.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
3+
4+
; Make sure that we apply trunc to the edge value of %x.
5+
@g = external global i8
6+
7+
define i16 @pr161367(i64 %x) {
8+
; CHECK-LABEL: define i16 @pr161367(
9+
; CHECK-SAME: i64 [[X:%.*]]) {
10+
; CHECK-NEXT: [[ENTRY:.*]]:
11+
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[X]] to i16
12+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[X]], sub (i64 0, i64 ptrtoint (ptr @g to i64))
13+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[ELSE:.*]]
14+
; CHECK: [[ELSE]]:
15+
; CHECK-NEXT: br label %[[EXIT]]
16+
; CHECK: [[EXIT]]:
17+
; CHECK-NEXT: [[RET:%.*]] = phi i16 [ trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g to i64)) to i16), %[[ENTRY]] ], [ 0, %[[ELSE]] ]
18+
; CHECK-NEXT: ret i16 [[RET]]
19+
;
20+
entry:
21+
%trunc = trunc i64 %x to i16
22+
%exitcond = icmp eq i64 %x, sub (i64 0, i64 ptrtoint (ptr @g to i64))
23+
br i1 %exitcond, label %exit, label %else
24+
25+
else:
26+
br label %exit
27+
28+
exit:
29+
%ret = phi i16 [ %trunc, %entry ], [ 0, %else ]
30+
ret i16 %ret
31+
}

0 commit comments

Comments
 (0)