[Mlir-commits] [mlir] [mlir][affine] Implement PromotableRegionOpInterface for AffineIfOp (PR #225388)
Paul Berg
llvmlistbot at llvm.org
Tue Sep 22 05:59:46 PDT 2026
https://github.com/Pangoraw created https://github.com/llvm/llvm-project/pull/225388
Follow-up to #221123 to use the structured mem2reg pass on affine if operations.
>From 00e4812ed72dd2d0e43886abbf336a08b4720048 Mon Sep 17 00:00:00 2001
From: Paul Berg <9824244+Pangoraw at users.noreply.github.com>
Date: Tue, 22 Sep 2026 07:48:50 -0500
Subject: [PATCH] [mlir][affine] Implement PromotableRegionOpInterface for
AffineIfOp
---
.../mlir/Dialect/Affine/IR/AffineOps.td | 3 +-
mlir/lib/Dialect/Affine/IR/MemorySlot.cpp | 45 +++++++++++++++++++
mlir/test/Dialect/Affine/mem2reg.mlir | 38 ++++++++++++++++
3 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td b/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
index cf2848f55ea09..100eb9b5ce2b3 100644
--- a/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
+++ b/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
@@ -355,7 +355,8 @@ def AffineIfOp : Affine_Op<"if",
[ImplicitAffineTerminator, RecursivelySpeculatable,
RecursiveMemoryEffects, NoRegionArguments,
DeclareOpInterfaceMethods<RegionBranchOpInterface,
- ["getSuccessorInputs"]>
+ ["getSuccessorInputs"]>,
+ DeclareOpInterfaceMethods<PromotableRegionOpInterface>,
]> {
let summary = "if-then-else operation";
let description = [{
diff --git a/mlir/lib/Dialect/Affine/IR/MemorySlot.cpp b/mlir/lib/Dialect/Affine/IR/MemorySlot.cpp
index 7b74b7eb7bb6b..b98cb0d16f92d 100644
--- a/mlir/lib/Dialect/Affine/IR/MemorySlot.cpp
+++ b/mlir/lib/Dialect/Affine/IR/MemorySlot.cpp
@@ -54,3 +54,48 @@ Value AffineForOp::finalizePromotion(
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
return newOp->getResults().back();
}
+
+//===----------------------------------------------------------------------===//
+// AffineIfOp
+//===----------------------------------------------------------------------===//
+
+bool AffineIfOp::isRegionPromotable(const MemorySlot &slot, Region *region,
+ bool hasValueStores) {
+ return true;
+}
+
+void AffineIfOp::setupPromotion(
+ const MemorySlot &slot, Value reachingDef, bool hasValueStores,
+ llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
+ regionsToProcess.insert({&getThenRegion(), reachingDef});
+ regionsToProcess.insert({&getElseRegion(), reachingDef});
+}
+
+Value AffineIfOp::finalizePromotion(
+ const MemorySlot &slot, Value reachingDef, bool hasValueStores,
+ const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
+ OpBuilder &builder) {
+ if (!hasValueStores)
+ return reachingDef;
+
+ IRRewriter rewriter(builder);
+
+ memoryslot::updateTerminator(&getThenRegion().back(), reachingDef,
+ reachingAtBlockEnd);
+
+ if (getElseRegion().hasOneBlock()) {
+ memoryslot::updateTerminator(&getElseRegion().back(), reachingDef,
+ reachingAtBlockEnd);
+ } else {
+ OpBuilder::InsertionGuard guard(rewriter);
+ rewriter.createBlock(&getElseRegion());
+ AffineYieldOp::create(rewriter, getOperation()->getLoc(), reachingDef);
+ }
+
+ SmallVector<Type> resultTypes(getResultTypes());
+ resultTypes.push_back(slot.elemType);
+
+ Operation *newOp =
+ memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
+ return newOp->getResults().back();
+}
diff --git a/mlir/test/Dialect/Affine/mem2reg.mlir b/mlir/test/Dialect/Affine/mem2reg.mlir
index af890cdb7a7a0..5920fab45d3b6 100644
--- a/mlir/test/Dialect/Affine/mem2reg.mlir
+++ b/mlir/test/Dialect/Affine/mem2reg.mlir
@@ -114,3 +114,41 @@ func.func @for_nested_load_and_store(%lb: index, %ub: index) -> i32 {
%load2 = memref.load %alloca[] : memref<i32>
return %load2 : i32
}
+
+// -----
+
+#iseven = affine_set<(d0) : (d0 mod 2 == 0)>
+// CHECK-LABEL: func.func @affine_for_affine_if
+// CHECK-SAME: (%[[X:.*]]: f32)
+// CHECK-DAG: %[[CST:.*]] = arith.constant 2.000000e+00 : f32
+// CHECK: %[[RES:.*]] = affine.for %[[IV:.*]] = 0 to 128 iter_args(%[[ARG:.*]] = %[[X]]) -> (f32) {
+// CHECK: %[[IFRES:.*]] = affine.if #{{.*}}(%[[IV]]) -> f32 {
+// CHECK: %[[NEW:.*]] = arith.mulf %[[ARG]], %[[CST]] : f32
+// CHECK: affine.yield %[[NEW]] : f32
+// CHECK: } else {
+// CHECK: affine.yield %[[ARG]] : f32
+// CHECK: }
+// CHECK: arith.mulf %[[IFRES]], %[[CST]] : f32
+// CHECK: affine.yield %[[IFRES]] : f32
+// CHECK: }
+// CHECK: return %[[RES]] : f32
+func.func @affine_for_affine_if(%x: f32) -> (f32) {
+ %cst = arith.constant 2.0 : f32
+ %alloc = memref.alloca() : memref<f32>
+ memref.store %x, %alloc[] : memref<f32>
+
+ affine.for %iv = 0 to 128 {
+
+ affine.if #iseven(%iv) {
+ %val = memref.load %alloc[] : memref<f32>
+ %new_val = arith.mulf %val, %cst : f32
+ memref.store %new_val, %alloc[] : memref<f32>
+ }
+
+ %cur_val = memref.load %alloc[] : memref<f32>
+ %prod_next = arith.mulf %cur_val, %cst : f32
+ }
+
+ %prod = memref.load %alloc[] : memref<f32>
+ return %prod : f32
+}
More information about the Mlir-commits
mailing list