Skip to content

Commit 3b9ce55

Browse files
nikicmemfrob
authored andcommitted
[SCCP] Propagate inequalities
Teach SCCP to create notconstant lattice values from inequality assumes and nonnull metadata, and update getConstant() to make use of them. Additionally isOverdefined() needs to be changed to consider notconstant an overdefined value. Handling inequality branches is delayed until our branch on undef story in other passes has been improved. Differential Revision: https://reviews.llvm.org/D83643
1 parent a151621 commit 3b9ce55

File tree

4 files changed

+42
-29
lines changed

4 files changed

+42
-29
lines changed

llvm/include/llvm/Analysis/ValueLattice.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "llvm/IR/ConstantRange.h"
1313
#include "llvm/IR/Constants.h"
14+
#include "llvm/IR/Instructions.h"
1415
//
1516
//===----------------------------------------------------------------------===//
1617
// ValueLatticeElement
@@ -456,6 +457,16 @@ class ValueLatticeElement {
456457
if (isConstant() && Other.isConstant())
457458
return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
458459

460+
if (ICmpInst::isEquality(Pred)) {
461+
// not(C) != C => true, not(C) == C => false.
462+
if ((isNotConstant() && Other.isConstant() &&
463+
getNotConstant() == Other.getConstant()) ||
464+
(isConstant() && Other.isNotConstant() &&
465+
getConstant() == Other.getNotConstant()))
466+
return Pred == ICmpInst::ICMP_NE
467+
? ConstantInt::getTrue(Ty) : ConstantInt::getFalse(Ty);
468+
}
469+
459470
// Integer constants are represented as ConstantRanges with single
460471
// elements.
461472
if (!isConstantRange() || !Other.isConstantRange())

llvm/lib/Transforms/Scalar/SCCP.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ bool isConstant(const ValueLatticeElement &LV) {
104104
// ValueLatticeElement::isOverdefined() and is intended to be used in the
105105
// transition to ValueLatticeElement.
106106
bool isOverdefined(const ValueLatticeElement &LV) {
107-
return LV.isOverdefined() ||
108-
(LV.isConstantRange() && !LV.getConstantRange().isSingleElement());
107+
return !LV.isUnknownOrUndef() && !isConstant(LV);
109108
}
110109

111110
//===----------------------------------------------------------------------===//
@@ -1123,7 +1122,9 @@ static ValueLatticeElement getValueFromMetadata(const Instruction *I) {
11231122
if (I->getType()->isIntegerTy())
11241123
return ValueLatticeElement::getRange(
11251124
getConstantRangeFromMetadata(*Ranges));
1126-
// TODO: Also handle MD_nonnull.
1125+
if (I->hasMetadata(LLVMContext::MD_nonnull))
1126+
return ValueLatticeElement::getNot(
1127+
ConstantPointerNull::get(cast<PointerType>(I->getType())));
11271128
return ValueLatticeElement::getOverdefined();
11281129
}
11291130

@@ -1291,6 +1292,17 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
12911292
return;
12921293
}
12931294

1295+
// TODO: Actually filp MayIncludeUndef for the created range to false,
1296+
// once most places in the optimizer respect the branches on
1297+
// undef/poison are UB rule. The reason why the new range cannot be
1298+
// undef is as follows below:
1299+
// The new range is based on a branch condition. That guarantees that
1300+
// neither of the compare operands can be undef in the branch targets,
1301+
// unless we have conditions that are always true/false (e.g. icmp ule
1302+
// i32, %a, i32_max). For the latter overdefined/empty range will be
1303+
// inferred, but the branch will get folded accordingly anyways.
1304+
bool MayIncludeUndef = !isa<PredicateAssume>(PI);
1305+
12941306
ValueLatticeElement CondVal = getValueState(OtherOp);
12951307
ValueLatticeElement &IV = ValueState[&CB];
12961308
if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
@@ -1316,25 +1328,23 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
13161328
NewCR = CopyOfCR;
13171329

13181330
addAdditionalUser(OtherOp, &CB);
1319-
// TODO: Actually filp MayIncludeUndef for the created range to false,
1320-
// once most places in the optimizer respect the branches on
1321-
// undef/poison are UB rule. The reason why the new range cannot be
1322-
// undef is as follows below:
1323-
// The new range is based on a branch condition. That guarantees that
1324-
// neither of the compare operands can be undef in the branch targets,
1325-
// unless we have conditions that are always true/false (e.g. icmp ule
1326-
// i32, %a, i32_max). For the latter overdefined/empty range will be
1327-
// inferred, but the branch will get folded accordingly anyways.
13281331
mergeInValue(
13291332
IV, &CB,
1330-
ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef=*/true));
1333+
ValueLatticeElement::getRange(NewCR, MayIncludeUndef));
13311334
return;
13321335
} else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) {
13331336
// For non-integer values or integer constant expressions, only
13341337
// propagate equal constants.
13351338
addAdditionalUser(OtherOp, &CB);
13361339
mergeInValue(IV, &CB, CondVal);
13371340
return;
1341+
} else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant() &&
1342+
!MayIncludeUndef) {
1343+
// Propagate inequalities.
1344+
addAdditionalUser(OtherOp, &CB);
1345+
mergeInValue(IV, &CB,
1346+
ValueLatticeElement::getNot(CondVal.getConstant()));
1347+
return;
13381348
}
13391349

13401350
return (void)mergeInValue(IV, &CB, CopyOfVal);

llvm/test/Transforms/SCCP/assume.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,10 @@ define void @nonnull(i32* %v) {
5151
; CHECK-LABEL: @nonnull(
5252
; CHECK-NEXT: [[A:%.*]] = icmp ne i32* [[V:%.*]], null
5353
; CHECK-NEXT: call void @llvm.assume(i1 [[A]])
54-
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32* [[V]], null
55-
; CHECK-NEXT: call void @use(i1 [[C1]])
56-
; CHECK-NEXT: [[C2:%.*]] = icmp ne i32* [[V]], null
57-
; CHECK-NEXT: call void @use(i1 [[C2]])
58-
; CHECK-NEXT: [[C3:%.*]] = icmp eq i32* null, [[V]]
59-
; CHECK-NEXT: call void @use(i1 [[C3]])
60-
; CHECK-NEXT: [[C4:%.*]] = icmp ne i32* null, [[V]]
61-
; CHECK-NEXT: call void @use(i1 [[C4]])
54+
; CHECK-NEXT: call void @use(i1 false)
55+
; CHECK-NEXT: call void @use(i1 true)
56+
; CHECK-NEXT: call void @use(i1 false)
57+
; CHECK-NEXT: call void @use(i1 true)
6258
; CHECK-NEXT: ret void
6359
;
6460
%a = icmp ne i32* %v, null

llvm/test/Transforms/SCCP/metadata.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,10 @@ define void @load_nonnull(i32** %p, i32** %p2) {
4848
; CHECK-LABEL: @load_nonnull(
4949
; CHECK-NEXT: [[V:%.*]] = load i32*, i32** [[P:%.*]], align 8, !nonnull !2
5050
; CHECK-NEXT: [[V2:%.*]] = load i32*, i32** [[P2:%.*]], align 8, !nonnull !2
51-
; CHECK-NEXT: [[C1:%.*]] = icmp ne i32* [[V]], null
52-
; CHECK-NEXT: call void @use(i1 [[C1]])
53-
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32* [[V]], null
54-
; CHECK-NEXT: call void @use(i1 [[C2]])
55-
; CHECK-NEXT: [[C3:%.*]] = icmp ne i32* null, [[V]]
56-
; CHECK-NEXT: call void @use(i1 [[C3]])
57-
; CHECK-NEXT: [[C4:%.*]] = icmp eq i32* null, [[V]]
58-
; CHECK-NEXT: call void @use(i1 [[C4]])
51+
; CHECK-NEXT: call void @use(i1 true)
52+
; CHECK-NEXT: call void @use(i1 false)
53+
; CHECK-NEXT: call void @use(i1 true)
54+
; CHECK-NEXT: call void @use(i1 false)
5955
; CHECK-NEXT: [[C5:%.*]] = icmp eq i32* [[V]], [[V2]]
6056
; CHECK-NEXT: call void @use(i1 [[C5]])
6157
; CHECK-NEXT: [[C6:%.*]] = icmp ne i32* [[V]], [[V2]]

0 commit comments

Comments
 (0)