[Mlir-commits] [mlir] [mlir][emitc] Add 'emitc.while' and 'emitc.do' ops to the dialect (PR #143008)
Gil Rapaport
llvmlistbot at llvm.org
Tue Sep 9 01:03:59 PDT 2025
================
@@ -336,11 +336,205 @@ LogicalResult IndexSwitchOpLowering::matchAndRewrite(
return success();
}
+// Lower scf::while to emitc::do using mutable variables to maintain loop state
+// across iterations. The do-while structure ensures the condition is evaluated
+// after each iteration, matching SCF while semantics.
+struct WhileLowering : public OpConversionPattern<WhileOp> {
+ using OpConversionPattern::OpConversionPattern;
+
+ LogicalResult
+ matchAndRewrite(WhileOp whileOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ Location loc = whileOp.getLoc();
+ MLIRContext *context = loc.getContext();
+
+ // Create variable storage for loop-carried values to enable imperative
+ // updates while maintaining SSA semantics at conversion boundaries.
+ SmallVector<Value> variables;
+ if (failed(createInitVariables(whileOp, rewriter, variables, loc, context)))
+ return failure();
+
+ if (failed(lowerDoWhile(whileOp, variables, context, rewriter, loc)))
+ return failure();
+
+ // Create an emitc::variable op for each result. These variables will be
+ // assigned to by emitc::assign ops within the loop body.
+ SmallVector<Value> resultVariables;
+ if (failed(createVariablesForResults(whileOp, getTypeConverter(), rewriter,
+ resultVariables))) {
+ return rewriter.notifyMatchFailure(whileOp,
+ "Failed to create result variables");
+ }
+
+ rewriter.setInsertionPointAfter(whileOp);
+
+ // Transfer final loop state to result variables and get final SSA results.
+ SmallVector<Value> finalResults =
+ finalizeLoopResults(resultVariables, variables, rewriter, loc);
+
+ rewriter.replaceOp(whileOp, finalResults);
+ return success();
+ }
+
+private:
+ // Initialize variables for loop-carried values to enable state updates
+ // across iterations without SSA argument passing.
+ static LogicalResult createInitVariables(WhileOp whileOp,
+ ConversionPatternRewriter &rewriter,
+ SmallVectorImpl<Value> &outVars,
+ Location loc, MLIRContext *context) {
+ emitc::OpaqueAttr noInit = emitc::OpaqueAttr::get(context, "");
+
+ for (Value init : whileOp.getInits()) {
+ emitc::VariableOp var = rewriter.create<emitc::VariableOp>(
+ loc, emitc::LValueType::get(init.getType()), noInit);
+ rewriter.create<emitc::AssignOp>(loc, var.getResult(), init);
+ outVars.push_back(var.getResult());
+ }
+
+ return success();
+ }
+
+ // Transition from SSA block arguments to variable-based state management by
+ // replacing argument uses with variable loads and cleaning up block
+ // interface.
+ void replaceBlockArgsWithVarLoads(Block *block, ArrayRef<Value> vars,
+ ConversionPatternRewriter &rewriter,
+ Location loc) const {
+ rewriter.setInsertionPointToStart(block);
+
+ for (auto [arg, var] : llvm::zip(block->getArguments(), vars)) {
+ Type loadedType = cast<emitc::LValueType>(var.getType()).getValueType();
+ Value load = rewriter.create<emitc::LoadOp>(loc, loadedType, var);
+ arg.replaceAllUsesWith(load);
+ }
+
+ // Remove arguments after replacement to simplify block structure.
+ block->eraseArguments(0, block->getNumArguments());
+ }
+
+ // Convert SCF yield terminators to imperative assignments to update loop
+ // variables, maintaining loop semantics while transitioning to emitc model.
+ void processYieldTerminator(Operation *terminator, ArrayRef<Value> vars,
+ ConversionPatternRewriter &rewriter,
+ Location loc) const {
+ auto yieldOp = cast<scf::YieldOp>(terminator);
+ SmallVector<Value> yields(yieldOp.getOperands());
----------------
aniragil wrote:
Yield handling in other ops (among other things in this file) seems to have been fixed in https://github.com/llvm/llvm-project/pull/121476, @mgehre-amd could you take a look at this patch w.r.t. those changes you made there?
https://github.com/llvm/llvm-project/pull/143008
More information about the Mlir-commits
mailing list