[llvm] [LoopVectorize] Teach LoopVectorizationLegality about more early exits (PR #107004)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 17 05:51:52 PDT 2024
================
@@ -1442,6 +1442,157 @@ bool LoopVectorizationLegality::canVectorizeLoopNestCFG(
return Result;
}
+bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
+ BasicBlock *LatchBB = TheLoop->getLoopLatch();
+ if (!LatchBB) {
+ reportVectorizationFailure("Loop does not have a latch",
+ "Cannot vectorize early exit loop",
+ "NoLatchEarlyExit", ORE, TheLoop);
+ return false;
+ }
+
+ if (Reductions.size() || FixedOrderRecurrences.size()) {
+ reportVectorizationFailure(
+ "Found reductions or recurrences in early-exit loop",
+ "Cannot vectorize early exit loop with reductions or recurrences",
+ "RecurrencesInEarlyExitLoop", ORE, TheLoop);
+ return false;
+ }
+
+ SmallVector<BasicBlock *, 8> ExitingBlocks;
+ TheLoop->getExitingBlocks(ExitingBlocks);
+
+ // Keep a record of all the exiting blocks.
+ SmallVector<const SCEVPredicate *, 4> Predicates;
+ for (BasicBlock *BB1 : ExitingBlocks) {
+ const SCEV *EC =
+ PSE.getSE()->getPredicatedExitCount(TheLoop, BB1, &Predicates);
+ if (isa<SCEVCouldNotCompute>(EC)) {
+ UncountableExitingBlocks.push_back(BB1);
+
+ SmallVector<BasicBlock *, 2> Succs(successors(BB1));
+ if (Succs.size() != 2) {
+ reportVectorizationFailure(
+ "Early exiting block does not have exactly two successors",
+ "Incorrect number of successors from early exiting block",
+ "EarlyExitTooManySuccessors", ORE, TheLoop);
+ return false;
+ }
+
+ BasicBlock *BB2;
+ if (!TheLoop->contains(Succs[0]))
+ BB2 = Succs[0];
+ else {
+ assert(!TheLoop->contains(Succs[1]));
+ BB2 = Succs[1];
+ }
+ UncountableExitBlocks.push_back(BB2);
+ } else
+ CountableExitingBlocks.push_back(BB1);
+ }
+ Predicates.clear();
+
+ // We only support one uncountable early exit.
+ if (getUncountableExitingBlocks().size() != 1) {
+ reportVectorizationFailure(
+ "Loop has too many uncountable exits",
+ "Cannot vectorize early exit loop with more than one early exit",
+ "TooManyUncountableEarlyExits", ORE, TheLoop);
+ return false;
+ }
+
+ // The only supported early exit loops so far are ones where the early
+ // exiting block is a unique predecessor of the latch block.
+ BasicBlock *LatchPredBB = LatchBB->getUniquePredecessor();
+ if (LatchPredBB != getSpeculativeEarlyExitingBlock()) {
+ reportVectorizationFailure("Early exit is not the latch predecessor",
+ "Cannot vectorize early exit loop",
+ "EarlyExitNotLatchPredecessor", ORE, TheLoop);
+ return false;
+ }
+
+ // Check to see if there are instructions that could potentially generate
+ // exceptions or have side-effects.
+ auto IsSafeOperation = [](Instruction *I) -> bool {
+ switch (I->getOpcode()) {
+ case Instruction::Load:
+ case Instruction::Store:
+ case Instruction::PHI:
+ case Instruction::Br:
+ // These are checked separately.
+ return true;
+ default:
+ return isSafeToSpeculativelyExecute(I);
+ }
+ };
+
+ for (auto *BB : TheLoop->blocks())
+ for (auto &I : *BB) {
+ if (I.mayWriteToMemory()) {
+ // We don't support writes to memory.
+ reportVectorizationFailure(
+ "Writes to memory unsupported in early exit loops",
+ "Cannot vectorize early exit loop with writes to memory",
+ "WritesInEarlyExitLoop", ORE, TheLoop);
+ return false;
+ } else if (!IsSafeOperation(&I)) {
+ reportVectorizationFailure("Early exit loop contains operations that "
+ "cannot be speculatively executed",
+ "Early exit loop contains operations that "
+ "cannot be speculatively executed",
+ "UnsafeOperationsEarlyExitLoop", ORE,
+ TheLoop);
+ return false;
+ }
+ }
+
+ // At least one of the exiting blocks must be the latch.
----------------
paulwalker-arm wrote:
This comment does not seem to match the code.
https://github.com/llvm/llvm-project/pull/107004
More information about the llvm-commits
mailing list