[Mlir-commits] [mlir] [flang][acc] Prune the acc.loop zero-trip edge when the body is proven to run (PR #219287)
Razvan Lupusoru
llvmlistbot at llvm.org
Fri Aug 28 09:05:02 PDT 2026
================
@@ -593,6 +594,67 @@ ValueRange HostDataOp::getSuccessorInputs(RegionSuccessor successor) {
return getSingleRegionSuccessorInputs(getOperation(), successor);
}
+/// Whether the body of a structured `acc.loop` is proven to run. This decides
+/// which edges out of the parent are feasible; the edges out of the region are
+/// unaffected.
+enum class BodyExecution {
+ /// The body runs at least once, so the parent cannot bypass the region.
+ Always,
+ /// The body never runs, so the parent cannot enter the region.
+ Never,
+ /// Neither could be proven, so the parent may do either.
+ Maybe
+};
+
+/// Prove whether the body of `loopOp` runs. A counted dimension whose entry
+/// test already fails at its lower bound runs exactly zero times, so a single
+/// comparison decides both `Always` and `Never`. Bounds that are not constant
+/// prove nothing.
+static BodyExecution getBodyExecution(LoopOp loopOp) {
+ // A container-like loop describes its iteration space inside the region.
+ if (loopOp.isContainerLike())
+ return BodyExecution::Maybe;
+
+ // The verifier guarantees one lower bound, upper bound and step per
+ // dimension.
+ ValueRange lbs = loopOp.getLowerbound();
+ ValueRange ubs = loopOp.getUpperbound();
+ ValueRange steps = loopOp.getStep();
+
+ BodyExecution result = BodyExecution::Always;
+ for (unsigned i = 0, e = lbs.size(); i < e; ++i) {
+ std::optional<int64_t> lb = getConstantIntValue(lbs[i]);
+ std::optional<int64_t> ub = getConstantIntValue(ubs[i]);
+ std::optional<int64_t> step = getConstantIntValue(steps[i]);
+ // An unknown bound cannot be tested, and a zero step either spins forever
+ // or never starts. Neither proves `Always`, but a later dimension may
+ // still prove the nest empty: `(0 to %n)` collapsed with `(0 to 0)`.
+ if (!lb || !ub || !step || *step == 0) {
+ result = BodyExecution::Maybe;
+ continue;
+ }
+
+ // The entry test at the lower bound. A descending dimension compares
+ // against its bound the other way round. The attribute is absent when
+ // every dimension is exclusive as in `scf.for`, and the verifier otherwise
+ // guarantees one entry per dimension.
+ std::optional<ArrayRef<bool>> inclusiveUbs =
+ loopOp.getInclusiveUpperbound();
+ bool inclusiveUb = inclusiveUbs && (*inclusiveUbs)[i];
+ bool runsOnce = *step > 0 ? (inclusiveUb ? *lb <= *ub : *lb < *ub)
----------------
razvanlupusoru wrote:
Thank you.
https://github.com/llvm/llvm-project/pull/219287
More information about the Mlir-commits
mailing list