Skip to content

Commit a86ce06

Browse files
committed
[SCCP] Use conditional info with AND/OR branch conditions.
Currently SCCP does not combine the information of conditions joined by AND in the true branch or OR in the false branch. For branches on AND, 2 copies will be inserted for the true branch, with one being the operand of the other as in the code below. We can combine the information using intersection. Note that for the OR case, the copies are inserted in the false branch, where using intersection is safe as well. define void @foo(i32 %a) { entry: %lt = icmp ult i32 %a, 100 %gt = icmp ugt i32 %a, 20 %and = and i1 %lt, %gt ; Has predicate info ; branch predicate info { TrueEdge: 1 Comparison: %lt = icmp ult i32 %a, 100 Edge: [label %entry,label %true] } %a.0 = call i32 @llvm.ssa.copy.140247425954880(i32 %a) ; Has predicate info ; branch predicate info { TrueEdge: 1 Comparison: %gt = icmp ugt i32 %a, 20 Edge: [label %entry,label %false] } %a.1 = call i32 @llvm.ssa.copy.140247425954880(i32 %a.0) br i1 %and, label %true, label %false true: ; preds = %entry call void @use(i32 %a.1) %true.1 = icmp ne i32 %a.1, 20 call void @use.i1(i1 %true.1) ret void false: ; preds = %entry call void @use(i32 %a.1) ret void } Reviewers: efriedma, davide, mssimpso, nikic Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D77808
1 parent b444705 commit a86ce06

File tree

2 files changed

+32
-25
lines changed

2 files changed

+32
-25
lines changed

llvm/lib/Transforms/Scalar/SCCP.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
12581258
return;
12591259

12601260
Value *CopyOf = CB.getOperand(0);
1261-
ValueLatticeElement OriginalVal = getValueState(CopyOf);
1261+
ValueLatticeElement CopyOfVal = getValueState(CopyOf);
12621262
auto *PI = getPredicateInfoFor(&CB);
12631263
assert(PI && "Missing predicate info for ssa.copy");
12641264

@@ -1271,25 +1271,27 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
12711271
Cmp = dyn_cast<CmpInst>(PAssume->Condition);
12721272
TrueEdge = true;
12731273
} else {
1274-
mergeInValue(ValueState[&CB], &CB, OriginalVal);
1274+
mergeInValue(ValueState[&CB], &CB, CopyOfVal);
12751275
return;
12761276
}
12771277

12781278
// Everything below relies on the condition being a comparison.
12791279
if (!Cmp) {
1280-
mergeInValue(ValueState[&CB], &CB, OriginalVal);
1280+
mergeInValue(ValueState[&CB], &CB, CopyOfVal);
12811281
return;
12821282
}
12831283

1284+
Value *RenamedOp = PI->RenamedOp;
12841285
Value *CmpOp0 = Cmp->getOperand(0);
12851286
Value *CmpOp1 = Cmp->getOperand(1);
1286-
if (CopyOf != CmpOp0 && CopyOf != CmpOp1) {
1287-
mergeInValue(ValueState[&CB], &CB, OriginalVal);
1287+
// Bail out if neither of the operands matches RenamedOp.
1288+
if (CmpOp0 != RenamedOp && CmpOp1 != RenamedOp) {
1289+
mergeInValue(ValueState[&CB], &CB, getValueState(CopyOf));
12881290
return;
12891291
}
12901292

12911293
auto Pred = Cmp->getPredicate();
1292-
if (CmpOp0 != CopyOf) {
1294+
if (CmpOp1 == RenamedOp) {
12931295
std::swap(CmpOp0, CmpOp1);
12941296
Pred = Cmp->getSwappedPredicate();
12951297
}
@@ -1300,27 +1302,37 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
13001302
return;
13011303
}
13021304

1305+
// The code below relies on PredicateInfo only inserting copies for the
1306+
// true branch when the branch condition is an AND and only inserting
1307+
// copies for the false branch when the branch condition is an OR. This
1308+
// ensures we can intersect the range from the condition with the range of
1309+
// CopyOf.
13031310
if (!TrueEdge)
13041311
Pred = CmpInst::getInversePredicate(Pred);
13051312

13061313
ValueLatticeElement CondVal = getValueState(CmpOp1);
13071314
ValueLatticeElement &IV = ValueState[&CB];
1308-
if (CondVal.isConstantRange() || OriginalVal.isConstantRange()) {
1309-
auto NewCR =
1315+
if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
1316+
auto ImposedCR =
13101317
ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType()));
13111318

13121319
// Get the range imposed by the condition.
13131320
if (CondVal.isConstantRange())
1314-
NewCR = ConstantRange::makeAllowedICmpRegion(
1321+
ImposedCR = ConstantRange::makeAllowedICmpRegion(
13151322
Pred, CondVal.getConstantRange());
13161323

13171324
// Combine range info for the original value with the new range from the
13181325
// condition.
1319-
auto OriginalCR = OriginalVal.isConstantRange()
1320-
? OriginalVal.getConstantRange()
1321-
: ConstantRange::getFull(
1322-
DL.getTypeSizeInBits(CopyOf->getType()));
1323-
NewCR = NewCR.intersectWith(OriginalCR);
1326+
auto CopyOfCR = CopyOfVal.isConstantRange()
1327+
? CopyOfVal.getConstantRange()
1328+
: ConstantRange::getFull(
1329+
DL.getTypeSizeInBits(CopyOf->getType()));
1330+
auto NewCR = ImposedCR.intersectWith(CopyOfCR);
1331+
// If the existing information is != x, do not use the information from
1332+
// a chained predicate, as the != x information is more likely to be
1333+
// helpful in practice.
1334+
if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement())
1335+
NewCR = CopyOfCR;
13241336

13251337
addAdditionalUser(CmpOp1, &CB);
13261338
// TODO: Actually filp MayIncludeUndef for the created range to false,
@@ -1344,7 +1356,7 @@ void SCCPSolver::handleCallResult(CallBase &CB) {
13441356
return;
13451357
}
13461358

1347-
return (void)mergeInValue(IV, &CB, OriginalVal);
1359+
return (void)mergeInValue(IV, &CB, CopyOfVal);
13481360
}
13491361
}
13501362

llvm/test/Transforms/SCCP/conditions-ranges.ll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -814,14 +814,11 @@ define void @f16_conditions_and(i32 %a, i32 %b) {
814814
; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT]], [[GT]]
815815
; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]]
816816
; CHECK: true:
817-
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 0
818-
; CHECK-NEXT: call void @use(i1 [[F_1]])
819-
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[A]], 20
820-
; CHECK-NEXT: call void @use(i1 [[F_2]])
817+
; CHECK-NEXT: call void @use(i1 false)
818+
; CHECK-NEXT: call void @use(i1 false)
821819
; CHECK-NEXT: call void @use(i1 false)
822820
; CHECK-NEXT: call void @use(i1 true)
823-
; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[A]], 20
824-
; CHECK-NEXT: call void @use(i1 [[T_2]])
821+
; CHECK-NEXT: call void @use(i1 true)
825822
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21
826823
; CHECK-NEXT: call void @use(i1 [[C_1]])
827824
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21
@@ -899,10 +896,8 @@ define void @f17_conditions_or(i32 %a, i32 %b) {
899896
; CHECK: false:
900897
; CHECK-NEXT: call void @use(i1 false)
901898
; CHECK-NEXT: call void @use(i1 false)
902-
; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i32 [[A]], 100
903-
; CHECK-NEXT: call void @use(i1 [[F_3]])
904-
; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 100
905-
; CHECK-NEXT: call void @use(i1 [[T_1]])
899+
; CHECK-NEXT: call void @use(i1 false)
900+
; CHECK-NEXT: call void @use(i1 true)
906901
; CHECK-NEXT: call void @use(i1 true)
907902
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21
908903
; CHECK-NEXT: call void @use(i1 [[C_1]])

0 commit comments

Comments
 (0)