[Mlir-commits] [mlir] [mlir][acc] Add utilities for converting acc.loop to scf (PR #172953)
Valentin Clement バレンタイン クレメン
llvmlistbot at llvm.org
Thu Dec 18 21:44:58 PST 2025
================
@@ -0,0 +1,323 @@
+//===- OpenACCUtilsLoop.cpp - OpenACC Loop Utilities ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions for converting OpenACC loops to SCF.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACCUtilsLoop.h"
+
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/Arith/Utils/Utils.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/Dialect/SCF/Utils/Utils.h"
+#include "mlir/IR/IRMapping.h"
+
+using namespace mlir;
+
+namespace {
+
+/// Calculate trip count for a loop: max(0, (ub - lb + step) / step)
+/// If inclusiveUpperbound is true, uses ub as-is; otherwise subtracts 1.
+/// The result is clamped to 0 to handle cases where lb > ub for positive step
+/// (or lb < ub for negative step), which would result in a negative trip count.
+static Value calculateTripCount(OpBuilder &b, Location loc, Value lb, Value ub,
+ Value step, bool inclusiveUpperbound) {
+ Type type = b.getIndexType();
+
+ // Convert original loop arguments to index type
+ lb = getValueOrCreateCastToIndexLike(b, loc, type, lb);
+ ub = getValueOrCreateCastToIndexLike(b, loc, type, ub);
+ step = getValueOrCreateCastToIndexLike(b, loc, type, step);
+
+ if (!inclusiveUpperbound) {
+ Value one = arith::ConstantIndexOp::create(b, loc, 1);
+ ub = b.createOrFold<arith::SubIOp>(loc, ub, one);
+ }
+
+ Value sub = b.createOrFold<arith::SubIOp>(loc, ub, lb);
+ Value add = b.createOrFold<arith::AddIOp>(loc, sub, step);
+ Value unclampedTrips = b.createOrFold<arith::DivSIOp>(loc, add, step);
+
+ // Clamp negative trip counts to 0
+ Value zero = arith::ConstantIndexOp::create(b, loc, 0);
+ Value isNegative = b.createOrFold<arith::CmpIOp>(
+ loc, arith::CmpIPredicate::slt, unclampedTrips, zero);
+ Value trips =
+ b.createOrFold<arith::SelectOp>(loc, isNegative, zero, unclampedTrips);
+ return trips;
+}
+
+/// Get exclusive upper bound from acc.loop (add 1 if inclusive).
+static Value getExclusiveUpperBound(acc::LoopOp loopOp, size_t ivPos,
+ OpBuilder &b) {
+ bool isInclusive = false;
+ if (loopOp.getInclusiveUpperbound().has_value())
+ isInclusive = loopOp.getInclusiveUpperboundAttr().asArrayRef()[ivPos];
+
+ Value origUB = loopOp.getUpperbound()[ivPos];
+ if (isInclusive) {
+ Location loc = origUB.getLoc();
+ Value one;
+ Type ubType = origUB.getType();
+ if (ubType.isIndex())
+ one = arith::ConstantIndexOp::create(b, loc, 1);
+ else
+ one = arith::ConstantIntOp::create(b, loc, ubType, 1);
+ return b.createOrFold<arith::AddIOp>(loc, origUB, one);
+ }
+ return origUB;
+}
+
+/// Handle differing types between SCF (index) and ACC loops.
+/// Creates casts from the new SCF IVs to the original ACC IV types and updates
+/// the mapping. The newIVs should correspond 1:1 with the ACC loop's IVs.
+static void mapACCLoopIVsToSCFIVs(acc::LoopOp accLoop, ValueRange newIVs,
+ OpBuilder &b, IRMapping &mapping) {
+ for (auto [origIV, newIV] :
+ llvm::zip(accLoop.getBody().getArguments(), newIVs)) {
+ Value replacementIV = getValueOrCreateCastToIndexLike(
+ b, accLoop->getLoc(), origIV.getType(), newIV);
+ mapping.map(origIV, replacementIV);
+ }
+}
+
+/// Normalize IV uses after converting to normalized loop form.
+/// For normalized loops (lb=0, step=1), we need to denormalize the IV:
+/// original_iv = new_iv * orig_step + orig_lb
+static void normalizeIVUses(OpBuilder &b, Location loc, Value iv, Value origLB,
+ Value origStep) {
+ Type indexType = b.getIndexType();
+ Value lb = getValueOrCreateCastToIndexLike(b, loc, indexType, origLB);
+ Value step = getValueOrCreateCastToIndexLike(b, loc, indexType, origStep);
+
+ // new_iv * step + lb
+ Value scaled = arith::MulIOp::create(b, loc, iv, step);
+ Value denormalized = arith::AddIOp::create(b, loc, scaled, lb);
+
+ // Replace uses of iv with denormalized value, except for the ops that
+ // compute the denormalized value itself (muli and addi)
+ llvm::SmallPtrSet<Operation *, 2> exceptions;
+ exceptions.insert(scaled.getDefiningOp());
+ exceptions.insert(denormalized.getDefiningOp());
+ iv.replaceAllUsesExcept(denormalized, exceptions);
+}
+
+/// Clone an ACC region into a destination block, handling the ACC terminators.
+/// Returns the insertion point after the cloned operations.
+static Block::iterator cloneACCRegionInto(Region *src, Block *dest,
+ Block::iterator insertionPoint,
+ IRMapping &mapping) {
+ assert(src->hasOneBlock() && "expected single-block region");
+
+ Region *insertRegion = dest->getParent();
+ Block *postInsertBlock = dest->splitBlock(insertionPoint);
+ src->cloneInto(insertRegion, postInsertBlock->getIterator(), mapping);
+
+ auto lastNewBlock = std::prev(postInsertBlock->getIterator());
+
+ Block::iterator ip;
----------------
clementval wrote:
```suggestion
Block::iterator it;
```
?
https://github.com/llvm/llvm-project/pull/172953
More information about the Mlir-commits
mailing list