mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[SCCP] Use ranges for predicate info conditions.
This patch updates the code that deals with conditions from predicate info to make use of constant ranges. For ssa_copy instructions inserted by PredicateInfo, we have 2 ranges: 1. The range of the original value. 2. The range imposed by the linked condition. 1. is known, 2. can be determined using makeAllowedICmpRegion. The intersection of those ranges is the range for the copy. With this patch, we get a nice increase in the number of instructions eliminated by both SCCP and IPSCCP for some benchmarks: For MultiSource, SPEC2000 & SPEC2006: Tests: 237 Same hash: 170 (filtered out) Remaining: 67 Metric: sccp.NumInstRemoved Program base patch diff test-suite...Source/Benchmarks/sim/sim.test 10.00 71.00 610.0% test-suite...CFP2000/177.mesa/177.mesa.test 361.00 1626.00 350.4% test-suite...encode/alacconvert-encode.test 141.00 602.00 327.0% test-suite...decode/alacconvert-decode.test 141.00 602.00 327.0% test-suite...CI_Purple/SMG2000/smg2000.test 1639.00 4093.00 149.7% test-suite...peg2/mpeg2dec/mpeg2decode.test 75.00 163.00 117.3% test-suite...T2006/401.bzip2/401.bzip2.test 358.00 513.00 43.3% test-suite...rks/FreeBench/pifft/pifft.test 11.00 15.00 36.4% test-suite...langs-C/unix-tbl/unix-tbl.test 4.00 5.00 25.0% test-suite...lications/sqlite3/sqlite3.test 541.00 667.00 23.3% test-suite.../CINT2000/254.gap/254.gap.test 243.00 299.00 23.0% test-suite...ks/Prolangs-C/agrep/agrep.test 25.00 29.00 16.0% test-suite...marks/7zip/7zip-benchmark.test 1135.00 1304.00 14.9% test-suite...lications/ClamAV/clamscan.test 1105.00 1268.00 14.8% test-suite...urce/Applications/lua/lua.test 398.00 436.00 9.5% Metric: sccp.IPNumInstRemoved Program base patch diff test-suite...C/CFP2000/179.art/179.art.test 1.00 3.00 200.0% test-suite...006/447.dealII/447.dealII.test 429.00 1056.00 146.2% test-suite...nch/fourinarow/fourinarow.test 3.00 7.00 133.3% test-suite...CI_Purple/SMG2000/smg2000.test 818.00 1748.00 113.7% test-suite...ks/McCat/04-bisect/bisect.test 3.00 5.00 66.7% test-suite...CFP2000/177.mesa/177.mesa.test 165.00 255.00 54.5% test-suite...ediabench/gsm/toast/toast.test 18.00 27.00 50.0% test-suite...telecomm-gsm/telecomm-gsm.test 18.00 27.00 50.0% test-suite...ks/Prolangs-C/agrep/agrep.test 24.00 35.00 45.8% test-suite...TimberWolfMC/timberwolfmc.test 43.00 62.00 44.2% test-suite...encode/alacconvert-encode.test 46.00 66.00 43.5% test-suite...decode/alacconvert-decode.test 46.00 66.00 43.5% test-suite...langs-C/unix-tbl/unix-tbl.test 12.00 17.00 41.7% test-suite...peg2/mpeg2dec/mpeg2decode.test 31.00 41.00 32.3% test-suite.../CINT2000/254.gap/254.gap.test 117.00 154.00 31.6% Reviewers: efriedma, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D76611
This commit is contained in:
parent
3bbec7c664
commit
0e532fb177
@ -1219,24 +1219,19 @@ void SCCPSolver::handleCallResult(CallSite CS) {
|
||||
|
||||
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
|
||||
if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
|
||||
if (isOverdefined(ValueState[I]))
|
||||
return (void)markOverdefined(I);
|
||||
|
||||
auto *PI = getPredicateInfoFor(I);
|
||||
if (!PI)
|
||||
if (ValueState[I].isOverdefined())
|
||||
return;
|
||||
|
||||
Value *CopyOf = I->getOperand(0);
|
||||
auto *PBranch = dyn_cast<PredicateBranch>(PI);
|
||||
if (!PBranch) {
|
||||
auto *PI = getPredicateInfoFor(I);
|
||||
auto *PBranch = dyn_cast_or_null<PredicateBranch>(PI);
|
||||
if (!PI || !PBranch) {
|
||||
mergeInValue(ValueState[I], I, getValueState(CopyOf));
|
||||
return;
|
||||
}
|
||||
|
||||
Value *Cond = PBranch->Condition;
|
||||
|
||||
// Everything below relies on the condition being a comparison.
|
||||
auto *Cmp = dyn_cast<CmpInst>(Cond);
|
||||
auto *Cmp = dyn_cast<CmpInst>(PBranch->Condition);
|
||||
if (!Cmp) {
|
||||
mergeInValue(ValueState[I], I, getValueState(CopyOf));
|
||||
return;
|
||||
@ -1249,26 +1244,60 @@ void SCCPSolver::handleCallResult(CallSite CS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CmpOp0 != CopyOf)
|
||||
auto Pred = Cmp->getPredicate();
|
||||
if (CmpOp0 != CopyOf) {
|
||||
std::swap(CmpOp0, CmpOp1);
|
||||
Pred = Cmp->getSwappedPredicate();
|
||||
}
|
||||
|
||||
ValueLatticeElement OriginalVal = getValueState(CopyOf);
|
||||
ValueLatticeElement EqVal = getValueState(CmpOp1);
|
||||
ValueLatticeElement &IV = ValueState[I];
|
||||
if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) {
|
||||
// Wait until CmpOp1 is resolved.
|
||||
if (getValueState(CmpOp1).isUnknown()) {
|
||||
addAdditionalUser(CmpOp1, I);
|
||||
if (isConstant(OriginalVal))
|
||||
mergeInValue(IV, I, OriginalVal);
|
||||
else
|
||||
mergeInValue(IV, I, EqVal);
|
||||
return;
|
||||
}
|
||||
if (!PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_NE) {
|
||||
|
||||
if (!PBranch->TrueEdge)
|
||||
Pred = CmpInst::getInversePredicate(Pred);
|
||||
|
||||
ValueLatticeElement CondVal = getValueState(CmpOp1);
|
||||
ValueLatticeElement &IV = ValueState[I];
|
||||
ValueLatticeElement OriginalVal = getValueState(CopyOf);
|
||||
if (CondVal.isConstantRange() || OriginalVal.isConstantRange()) {
|
||||
auto NewCR =
|
||||
ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType()));
|
||||
|
||||
// Get the range imposed by the condition.
|
||||
if (CondVal.isConstantRange())
|
||||
NewCR = ConstantRange::makeAllowedICmpRegion(
|
||||
Pred, CondVal.getConstantRange());
|
||||
|
||||
// Combine range info for the original value with the new range from the
|
||||
// condition.
|
||||
auto OriginalCR = OriginalVal.isConstantRange()
|
||||
? OriginalVal.getConstantRange()
|
||||
: ConstantRange::getFull(
|
||||
DL.getTypeSizeInBits(CopyOf->getType()));
|
||||
NewCR = NewCR.intersectWith(OriginalCR);
|
||||
|
||||
addAdditionalUser(CmpOp1, I);
|
||||
if (isConstant(OriginalVal))
|
||||
mergeInValue(IV, I, OriginalVal);
|
||||
else
|
||||
mergeInValue(IV, I, EqVal);
|
||||
// TODO: Actually filp MayIncludeUndef for the created range to false,
|
||||
// once most places in the optimizer respect the branches on
|
||||
// undef/poison are UB rule. The reason why the new range cannot be
|
||||
// undef is as follows below:
|
||||
// The new range is based on a branch condition. That guarantees that
|
||||
// neither of the compare operands can be undef in the branch targets,
|
||||
// unless we have conditions that are always true/false (e.g. icmp ule
|
||||
// i32, %a, i32_max). For the latter overdefined/empty range will be
|
||||
// inferred, but the branch will get folded accordingly anyways.
|
||||
mergeInValue(
|
||||
IV, I,
|
||||
ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef=*/true));
|
||||
return;
|
||||
} else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) {
|
||||
// For non-integer values or integer constant expressions, only
|
||||
// propagate equal constants.
|
||||
addAdditionalUser(CmpOp1, I);
|
||||
mergeInValue(IV, I, CondVal);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,7 @@ define void @val_undef_range() {
|
||||
; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[A]], 127
|
||||
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 128
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
|
||||
; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
|
||||
; CHECK-NEXT: ret void
|
||||
@ -83,7 +82,8 @@ define void @val_singlecrfromundef_range(i1 %cond) {
|
||||
; CHECK-NEXT: br label [[TRUE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use.i32(i32 10)
|
||||
; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127
|
||||
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
@ -130,8 +130,7 @@ define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
|
||||
; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[P]], 100
|
||||
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[P]], 128
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
|
||||
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
|
||||
; CHECK-NEXT: ret void
|
||||
@ -179,10 +178,8 @@ define void @bound_singlecrfromundef(i32 %a, i1 %cond) {
|
||||
; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A:%.*]], 10
|
||||
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ne i32 [[A]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
|
||||
; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
|
||||
; CHECK-NEXT: ret void
|
||||
|
@ -11,16 +11,11 @@ define void @f1(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: [[BC:%.*]] = icmp ugt i32 [[B:%.*]], [[A_2]]
|
||||
; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[B]], 0
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
||||
; CHECK-NEXT: [[F_3:%.*]] = icmp ult i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[F_3]])
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i32 [[B]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[C_1]])
|
||||
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 21
|
||||
@ -29,14 +24,10 @@ define void @f1(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: false:
|
||||
; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[B]], 276
|
||||
; CHECK-NEXT: call void @use(i1 [[F_4]])
|
||||
; CHECK-NEXT: [[F_5:%.*]] = icmp ugt i32 [[B]], 275
|
||||
; CHECK-NEXT: call void @use(i1 [[F_5]])
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[B]], 276
|
||||
; CHECK-NEXT: call void @use(i1 [[T_3]])
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i32 [[B]], 275
|
||||
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B]], 275
|
||||
@ -279,24 +270,15 @@ define void @f8_nested_conds(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: [[BC_2:%.*]] = icmp ult i32 [[B]], 255
|
||||
; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE_2:%.*]]
|
||||
; CHECK: true.2:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[B]], 0
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
||||
; CHECK-NEXT: [[F_3:%.*]] = icmp ult i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[F_3]])
|
||||
; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[F_4]])
|
||||
; CHECK-NEXT: [[F_5:%.*]] = icmp ugt i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[F_5]])
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i32 [[B]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ult i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[T_3]])
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ne i32 [[B]], 300
|
||||
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[C_1]])
|
||||
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 21
|
||||
@ -305,14 +287,10 @@ define void @f8_nested_conds(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: false.2:
|
||||
; CHECK-NEXT: [[F_6:%.*]] = icmp eq i32 [[B]], 254
|
||||
; CHECK-NEXT: call void @use(i1 [[F_6]])
|
||||
; CHECK-NEXT: [[F_7:%.*]] = icmp ult i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[F_7]])
|
||||
; CHECK-NEXT: [[T_5:%.*]] = icmp ne i32 [[B]], 254
|
||||
; CHECK-NEXT: call void @use(i1 [[T_5]])
|
||||
; CHECK-NEXT: [[T_6:%.*]] = icmp uge i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[T_6]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 255
|
||||
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp ne i32 [[B]], 275
|
||||
@ -395,14 +373,10 @@ define void @f9_nested_conds(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[B:%.*]], 10
|
||||
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[B]], 0
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[B]], 10
|
||||
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i32 [[B]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[B]], 10
|
||||
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 11
|
||||
; CHECK-NEXT: call void @use(i1 [[C_1]])
|
||||
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 11
|
||||
@ -410,14 +384,10 @@ define void @f9_nested_conds(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: [[BC_2:%.*]] = icmp ugt i32 [[B]], 20
|
||||
; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE_2:%.*]]
|
||||
; CHECK: true.2:
|
||||
; CHECK-NEXT: [[F_3:%.*]] = icmp eq i32 [[B]], 11
|
||||
; CHECK-NEXT: call void @use(i1 [[F_3]])
|
||||
; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[F_4]])
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ugt i32 [[B]], 11
|
||||
; CHECK-NEXT: call void @use(i1 [[T_3]])
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ne i32 [[B]], 20
|
||||
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_3:%.*]] = icmp eq i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
||||
; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[B]], 21
|
||||
@ -426,18 +396,12 @@ define void @f9_nested_conds(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: false.2:
|
||||
; CHECK-NEXT: [[F_5:%.*]] = icmp eq i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[F_5]])
|
||||
; CHECK-NEXT: [[F_6:%.*]] = icmp ugt i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[F_6]])
|
||||
; CHECK-NEXT: [[F_7:%.*]] = icmp ne i32 [[B]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[F_7]])
|
||||
; CHECK-NEXT: [[T_5:%.*]] = icmp ne i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[T_5]])
|
||||
; CHECK-NEXT: [[T_6:%.*]] = icmp ult i32 [[B]], 21
|
||||
; CHECK-NEXT: call void @use(i1 [[T_6]])
|
||||
; CHECK-NEXT: [[T_7:%.*]] = icmp ne i32 [[B]], 5
|
||||
; CHECK-NEXT: call void @use(i1 [[T_7]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_6:%.*]] = icmp eq i32 [[B]], 11
|
||||
; CHECK-NEXT: call void @use(i1 [[C_6]])
|
||||
; CHECK-NEXT: [[C_7:%.*]] = icmp ne i32 [[B]], 15
|
||||
@ -530,18 +494,12 @@ define void @f10_cond_does_not_restrict_range(i32 %a, i32 %b) {
|
||||
; CHECK-NEXT: [[B_255:%.*]] = and i32 [[B:%.*]], 255
|
||||
; CHECK-NEXT: br label [[TRUE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[B_255]], 256
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[B_255]], 300
|
||||
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[B_255]], 256
|
||||
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[B_255]], 300
|
||||
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[B_255]], 256
|
||||
; CHECK-NEXT: call void @use(i1 [[T_3]])
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ne i32 [[B_255]], 300
|
||||
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B_255]], 11
|
||||
; CHECK-NEXT: call void @use(i1 [[C_1]])
|
||||
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B_255]], 30
|
||||
@ -649,10 +607,8 @@ define void @f13_constexpr1() {
|
||||
; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 55
|
||||
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 10
|
||||
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||||
; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 add (i32 ptrtoint (i32* @A to i32), i32 10), 55
|
||||
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
||||
; CHECK-NEXT: call void @use(i1 false)
|
||||
; CHECK-NEXT: call void @use(i1 true)
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: false:
|
||||
; CHECK-NEXT: ret void
|
||||
@ -680,8 +636,8 @@ define void @f14_constexpr2() {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32)), label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32)))
|
||||
; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (i32* @A to i32), i32 ptrtoint (i32* @B to i32)))
|
||||
; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (i32* @B to i32), i32 ptrtoint (i32* @A to i32)))
|
||||
; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (i32* @B to i32), i32 ptrtoint (i32* @A to i32)))
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: false:
|
||||
; CHECK-NEXT: ret void
|
||||
@ -830,10 +786,9 @@ define i32 @udiv_2(i64 %sz) {
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SZ:%.*]], 4088
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
|
||||
; CHECK: cond.true:
|
||||
; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]]
|
||||
; CHECK-NEXT: br label [[COND_END]]
|
||||
; CHECK: cond.end:
|
||||
; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[COND:%.*]] = phi i64 [ 0, [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32
|
||||
; CHECK-NEXT: ret i32 [[CONV]]
|
||||
;
|
||||
|
@ -84,9 +84,7 @@ end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f4
|
||||
; CHECK: %cmp = icmp sgt i32 %x, 300
|
||||
; CHECK: %res = select i1 %cmp, i32 1, i32 2
|
||||
; CHECK: ret i32 %res
|
||||
; CHECK: ret i32 undef
|
||||
define internal i32 @f4(i32 %x) {
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %x, 300
|
||||
@ -94,8 +92,13 @@ entry:
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
; ICmp could introduce bounds on ConstantRanges.
|
||||
; ICmp introduces bounds on ConstantRanges.
|
||||
define i32 @caller3(i32 %x) {
|
||||
; CHECK-LABEL: define i32 @caller3(i32 %x)
|
||||
; CHECK-LABEL: end:
|
||||
; CHECK-NEXT: %res = phi i32 [ 0, %entry ], [ 1, %if.true ]
|
||||
; CHECK-NEXT: ret i32 %res
|
||||
;
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %x, 300
|
||||
br i1 %cmp, label %if.true, label %end
|
||||
|
Loading…
x
Reference in New Issue
Block a user