Skip to content

Commit

Permalink
[SimpleLoopUnswitch][NFC] Separate legality checks from cost computation
Browse files Browse the repository at this point in the history
These are semantically two different stages, but were entwined in the
old implementation. Now cost computation does not do legality checks,
and they all are done beforehead.
  • Loading branch information
xortator committed Oct 12, 2022
1 parent 421728b commit 6bfcac6
Showing 1 changed file with 30 additions and 25 deletions.
55 changes: 30 additions & 25 deletions llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
Expand Up @@ -2827,8 +2827,23 @@ struct NonTrivialUnswitchCandidate {
};
} // end anonymous namespace.

static Optional<NonTrivialUnswitchCandidate>
findBestNonTrivialUnswitchCandidate(
static bool isSafeToClone(const Loop &L) {
if (!L.isSafeToClone())
return false;
for (auto *BB : L.blocks())
for (auto &I : *BB) {
if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
return false;
if (auto *CB = dyn_cast<CallBase>(&I)) {
assert(!CB->cannotDuplicate() && "Checked by L.isSafeToClone().");
if (CB->isConvergent())
return false;
}
}
return true;
}

static NonTrivialUnswitchCandidate findBestNonTrivialUnswitchCandidate(
ArrayRef<std::pair<Instruction *, TinyPtrVector<Value *> > >
UnswitchCandidates, const Loop &L, const DominatorTree &DT,
const LoopInfo &LI, AssumptionCache &AC, const TargetTransformInfo &TTI,
Expand Down Expand Up @@ -2857,13 +2872,6 @@ findBestNonTrivialUnswitchCandidate(
for (auto &I : *BB) {
if (EphValues.count(&I))
continue;

if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
return None;
if (auto *CB = dyn_cast<CallBase>(&I))
if (CB->isConvergent() || CB->cannotDuplicate())
return None;

Cost += TTI.getInstructionCost(&I, CostKind);
}
assert(Cost >= 0 && "Must not have negative costs!");
Expand Down Expand Up @@ -3030,31 +3038,28 @@ static bool unswitchBestCondition(
dbgs() << "Considering " << UnswitchCandidates.size()
<< " non-trivial loop invariant conditions for unswitching.\n");

Optional<NonTrivialUnswitchCandidate> Best =
findBestNonTrivialUnswitchCandidate(UnswitchCandidates, L, DT, LI, AC,
TTI, PartialIVInfo);
if (!Best)
return false;
NonTrivialUnswitchCandidate Best = findBestNonTrivialUnswitchCandidate(
UnswitchCandidates, L, DT, LI, AC, TTI, PartialIVInfo);

assert(Best->TI && "Failed to find loop unswitch candidate");
assert(Best.TI && "Failed to find loop unswitch candidate");

if (Best->Cost >= UnswitchThreshold) {
LLVM_DEBUG(dbgs() << "Cannot unswitch, lowest cost found: " << Best->Cost
if (Best.Cost >= UnswitchThreshold) {
LLVM_DEBUG(dbgs() << "Cannot unswitch, lowest cost found: " << Best.Cost
<< "\n");
return false;
}

if (Best->TI != PartialIVCondBranch)
if (Best.TI != PartialIVCondBranch)
PartialIVInfo.InstToDuplicate.clear();

// If the best candidate is a guard, turn it into a branch.
if (isGuard(Best->TI))
Best->TI = turnGuardIntoBranch(cast<IntrinsicInst>(Best->TI), L, ExitBlocks,
DT, LI, MSSAU);
if (isGuard(Best.TI))
Best.TI = turnGuardIntoBranch(cast<IntrinsicInst>(Best.TI), L, ExitBlocks,
DT, LI, MSSAU);

LLVM_DEBUG(dbgs() << " Unswitching non-trivial (cost = " << Best->Cost
<< ") terminator: " << *Best->TI << "\n");
unswitchNontrivialInvariants(L, *Best->TI, Best->Invariants, ExitBlocks,
LLVM_DEBUG(dbgs() << " Unswitching non-trivial (cost = " << Best.Cost
<< ") terminator: " << *Best.TI << "\n");
unswitchNontrivialInvariants(L, *Best.TI, Best.Invariants, ExitBlocks,
PartialIVInfo, DT, LI, AC, UnswitchCB, SE, MSSAU,
DestroyLoopCB);
return true;
Expand Down Expand Up @@ -3133,7 +3138,7 @@ unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
}

// Skip non-trivial unswitching for loops that cannot be cloned.
if (!L.isSafeToClone())
if (!isSafeToClone(L))
return false;

// For non-trivial unswitching, because it often creates new loops, we rely on
Expand Down

0 comments on commit 6bfcac6

Please sign in to comment.