[Mlir-commits] [mlir] [WIP][mlir][EmitC] Model lvalues as a type in EmitC (PR #91475)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Jun 11 07:07:44 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-emitc

Author: Simon Camphausen (simon-camp)

<details>
<summary>Changes</summary>

This is an early unpolished version of what has been previously discussed on [discourse](https://discourse.llvm.org/t/rfc-separate-variables-from-ssa-values-in-emitc/75224/9). See this as a starting point for further discussions.

---

Patch is 94.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/91475.diff


25 Files Affected:

- (modified) mlir/include/mlir/Dialect/EmitC/IR/EmitC.td (+38-9) 
- (modified) mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td (+18) 
- (modified) mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp (+1-6) 
- (modified) mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp (+27-4) 
- (modified) mlir/lib/Dialect/EmitC/IR/EmitC.cpp (+83-24) 
- (modified) mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp (+2-1) 
- (modified) mlir/lib/Target/Cpp/TranslateToCpp.cpp (+82-43) 
- (modified) mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir (+12-12) 
- (modified) mlir/test/Conversion/SCFToEmitC/for.mlir (+27-19) 
- (modified) mlir/test/Conversion/SCFToEmitC/if.mlir (+12-10) 
- (modified) mlir/test/Dialect/EmitC/invalid_ops.mlir (+31-30) 
- (modified) mlir/test/Dialect/EmitC/invalid_types.mlir (+53-13) 
- (modified) mlir/test/Dialect/EmitC/ops.mlir (+11-10) 
- (modified) mlir/test/Dialect/EmitC/transforms.mlir (+11-37) 
- (modified) mlir/test/Dialect/EmitC/types.mlir (+17-2) 
- (modified) mlir/test/Target/Cpp/common-cpp.mlir (+13-5) 
- (modified) mlir/test/Target/Cpp/expressions.mlir (+52-32) 
- (modified) mlir/test/Target/Cpp/for.mlir (+60-22) 
- (modified) mlir/test/Target/Cpp/global.mlir (+79-17) 
- (modified) mlir/test/Target/Cpp/if.mlir (+6-6) 
- (modified) mlir/test/Target/Cpp/invalid.mlir (+1-1) 
- (modified) mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir (+13-2) 
- (added) mlir/test/Target/Cpp/lvalue.mlir (+37) 
- (modified) mlir/test/Target/Cpp/subscript.mlir (+76-30) 
- (modified) mlir/test/Target/Cpp/variable.mlir (+9-7) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 5da8593f59563..f5d82bc41642e 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -97,9 +97,9 @@ def EmitC_ApplyOp : EmitC_Op<"apply", [CExpression]> {
   }];
   let arguments = (ins
     Arg<StrAttr, "the operator to apply">:$applicableOperator,
-    EmitCType:$operand
+    AnyTypeOf<[EmitCType, EmitC_LValueType]>:$operand
   );
-  let results = (outs EmitCType:$result);
+  let results = (outs AnyTypeOf<[EmitCType, EmitC_LValueType]>:$result);
   let assemblyFormat = [{
     $applicableOperator `(` $operand `)` attr-dict `:` functional-type($operand, results)
   }];
@@ -835,6 +835,21 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
   let assemblyFormat = "operands attr-dict `:` type(operands)";
 }
 
+def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
+  TypesMatchWith<"result type matches value type of 'operand'",
+                  "operand", "result",
+                  "::llvm::cast<LValueType>($_self).getValue()">
+]> {
+  let summary = "load an lvalue by assigning it to a local variable";
+  let description = [{}];
+
+  let arguments = (ins 
+      Res<EmitC_LValueType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$operand);
+  let results = (outs AnyType:$result);
+
+  let assemblyFormat = "$operand attr-dict `:` type($operand)"; 
+}
+
 def EmitC_MulOp : EmitC_BinaryOp<"mul", [CExpression]> {
   let summary = "Multiplication operation";
   let description = [{
@@ -1009,7 +1024,8 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
   }];
 
   let arguments = (ins EmitC_OpaqueOrTypedAttr:$value);
-  let results = (outs EmitCType);
+  let results = (outs Res<AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>, "",
+                          [MemAlloc<DefaultResource, 0, FullEffect>]>:$memref);
 
   let hasVerifier = 1;
 }
@@ -1079,7 +1095,7 @@ def EmitC_GetGlobalOp : EmitC_Op<"get_global",
   }];
 
   let arguments = (ins FlatSymbolRefAttr:$name);
-  let results = (outs EmitCType:$result);
+  let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>:$result);
   let assemblyFormat = "$name `:` type($result) attr-dict";
 }
 
@@ -1137,7 +1153,9 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
     ```
   }];
 
-  let arguments = (ins EmitCType:$var, EmitCType:$value);
+  let arguments = (ins 
+      Res<EmitC_LValueType, "", [MemWrite<DefaultResource, 1, FullEffect>]>:$var,
+      Res<EmitCType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$value);
   let results = (outs);
 
   let hasVerifier = 1;
@@ -1243,15 +1261,26 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
       EmitC_PointerType]>,
     "the value to subscript">:$value,
     Variadic<EmitCType>:$indices);
-  let results = (outs EmitCType:$result);
+  let results = (outs EmitC_LValueType:$result);
 
   let builders = [
     OpBuilder<(ins "TypedValue<ArrayType>":$array, "ValueRange":$indices), [{
-      build($_builder, $_state, array.getType().getElementType(), array, indices);
+      build(
+        $_builder,
+        $_state,
+        emitc::LValueType::get(array.getType().getElementType()),
+        array,
+        indices
+      );
     }]>,
     OpBuilder<(ins "TypedValue<PointerType>":$pointer, "Value":$index), [{
-      build($_builder, $_state, pointer.getType().getPointee(), pointer,
-            ValueRange{index});
+      build(
+        $_builder,
+        $_state,
+        emitc::LValueType::get(pointer.getType().getPointee()),
+        pointer,
+        ValueRange{index}
+      );
     }]>
   ];
 
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
index 444395b915e25..fc795962a3e5b 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -83,6 +83,23 @@ def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> {
   let hasCustomAssemblyFormat = 1;
 }
 
+def EmitC_LValueType : EmitC_Type<"LValue", "lvalue"> {
+  let summary = "EmitC lvalue type";
+
+  let description = [{
+    Values of this type can be assigned to and their address can be taken.
+  }];
+
+  let parameters = (ins "Type":$value);
+  let builders = [
+    TypeBuilderWithInferredContext<(ins "Type":$value), [{
+      return $_get(value.getContext(), value);
+    }]>
+  ];
+  let assemblyFormat = "`<` qualified($value) `>`";
+  let genVerifyDecl = 1;
+}
+
 def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
   let summary = "EmitC opaque type";
 
@@ -128,6 +145,7 @@ def EmitC_PointerType : EmitC_Type<"Pointer", "ptr"> {
     }]>
   ];
   let assemblyFormat = "`<` qualified($pointee) `>`";
+  let genVerifyDecl = 1;
 }
 
 #endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index e0c421741b305..2e8fbbad14d40 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -137,12 +137,7 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
     auto subscript = rewriter.create<emitc::SubscriptOp>(
         op.getLoc(), arrayValue, operands.getIndices());
 
-    auto noInit = emitc::OpaqueAttr::get(getContext(), "");
-    auto var =
-        rewriter.create<emitc::VariableOp>(op.getLoc(), resultTy, noInit);
-
-    rewriter.create<emitc::AssignOp>(op.getLoc(), var, subscript);
-    rewriter.replaceOp(op, var);
+    rewriter.replaceOpWithNewOp<emitc::LValueLoadOp>(op, resultTy, subscript);
     return success();
   }
 };
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 0a89242225255..59a090a5fc65f 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -63,9 +63,10 @@ static SmallVector<Value> createVariablesForResults(T op,
 
   for (OpResult result : op.getResults()) {
     Type resultType = result.getType();
+    Type varType = emitc::LValueType::get(resultType);
     emitc::OpaqueAttr noInit = emitc::OpaqueAttr::get(context, "");
     emitc::VariableOp var =
-        rewriter.create<emitc::VariableOp>(loc, resultType, noInit);
+        rewriter.create<emitc::VariableOp>(loc, varType, noInit);
     resultVariables.push_back(var);
   }
 
@@ -80,6 +81,14 @@ static void assignValues(ValueRange values, SmallVector<Value> &variables,
     rewriter.create<emitc::AssignOp>(loc, var, value);
 }
 
+SmallVector<Value> loadValues(const SmallVector<Value> &variables,
+                              PatternRewriter &rewriter, Location loc) {
+  return llvm::map_to_vector<>(variables, [&](Value var) {
+    Type type = cast<emitc::LValueType>(var.getType()).getValue();
+    return rewriter.create<emitc::LValueLoadOp>(loc, type, var).getResult();
+  });
+}
+
 static void lowerYield(SmallVector<Value> &resultVariables,
                        PatternRewriter &rewriter, scf::YieldOp yield) {
   Location loc = yield.getLoc();
@@ -113,15 +122,26 @@ LogicalResult ForLowering::matchAndRewrite(ForOp forOp,
   // Erase the auto-generated terminator for the lowered for op.
   rewriter.eraseOp(loweredBody->getTerminator());
 
+  IRRewriter::InsertPoint ip = rewriter.saveInsertionPoint();
+  rewriter.setInsertionPointToEnd(loweredBody);
+
+  SmallVector<Value> iterArgsValues =
+      loadValues(resultVariables, rewriter, loc);
+
+  rewriter.restoreInsertionPoint(ip);
+
   SmallVector<Value> replacingValues;
   replacingValues.push_back(loweredFor.getInductionVar());
-  replacingValues.append(resultVariables.begin(), resultVariables.end());
+  replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
 
   rewriter.mergeBlocks(forOp.getBody(), loweredBody, replacingValues);
   lowerYield(resultVariables, rewriter,
              cast<scf::YieldOp>(loweredBody->getTerminator()));
 
-  rewriter.replaceOp(forOp, resultVariables);
+  // Copy iterArgs into results after the for loop.
+  SmallVector<Value> resultValues = loadValues(resultVariables, rewriter, loc);
+
+  rewriter.replaceOp(forOp, resultValues);
   return success();
 }
 
@@ -173,7 +193,10 @@ LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
     lowerRegion(elseRegion, loweredElseRegion);
   }
 
-  rewriter.replaceOp(ifOp, resultVariables);
+  rewriter.setInsertionPointAfter(ifOp);
+  SmallVector<Value> results = loadValues(resultVariables, rewriter, loc);
+
+  rewriter.replaceOp(ifOp, results);
   return success();
 }
 
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 20f47574b25ad..43cf410e8889c 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -61,6 +61,9 @@ void mlir::emitc::buildTerminatedBody(OpBuilder &builder, Location loc) {
 bool mlir::emitc::isSupportedEmitCType(Type type) {
   if (llvm::isa<emitc::OpaqueType>(type))
     return true;
+  if (auto lType = llvm::dyn_cast<emitc::LValueType>(type))
+    // lvalue types are only allowed in a few places.
+    return false;
   if (auto ptrType = llvm::dyn_cast<emitc::PointerType>(type))
     return isSupportedEmitCType(ptrType.getPointee());
   if (auto arrayType = llvm::dyn_cast<emitc::ArrayType>(type)) {
@@ -140,6 +143,8 @@ static LogicalResult verifyInitializationAttribute(Operation *op,
            << "string attributes are not supported, use #emitc.opaque instead";
 
   Type resultType = op->getResult(0).getType();
+  if (auto lType = dyn_cast<LValueType>(resultType))
+    resultType = lType.getValue();
   Type attrType = cast<TypedAttr>(value).getType();
 
   if (resultType != attrType)
@@ -188,9 +193,19 @@ LogicalResult ApplyOp::verify() {
   if (applicableOperatorStr != "&" && applicableOperatorStr != "*")
     return emitOpError("applicable operator is illegal");
 
-  Operation *op = getOperand().getDefiningOp();
-  if (op && dyn_cast<ConstantOp>(op))
-    return emitOpError("cannot apply to constant");
+  Type operandType = getOperand().getType();
+  Type resultType = getResult().getType();
+  if (applicableOperatorStr == "&") {
+    if (!llvm::isa<emitc::LValueType>(operandType))
+      return emitOpError("operand type must be an lvalue when applying `&`");
+    if (!llvm::isa<emitc::PointerType>(resultType))
+      return emitOpError("result type must be a pointer when applying `&`");
+  } else {
+    if (!llvm::isa<emitc::PointerType>(operandType))
+      return emitOpError("operand type must be a pointer when applying `*`");
+    if (!llvm::isa<emitc::LValueType>(resultType))
+      return emitOpError("result type must be an lvalue when applying `*`");
+  }
 
   return success();
 }
@@ -202,20 +217,18 @@ LogicalResult ApplyOp::verify() {
 /// The assign op requires that the assigned value's type matches the
 /// assigned-to variable type.
 LogicalResult emitc::AssignOp::verify() {
-  Value variable = getVar();
-  Operation *variableDef = variable.getDefiningOp();
-  if (!variableDef ||
-      !llvm::isa<emitc::VariableOp, emitc::SubscriptOp>(variableDef))
-    return emitOpError() << "requires first operand (" << variable
-                         << ") to be a Variable or subscript";
-
-  Value value = getValue();
-  if (variable.getType() != value.getType())
-    return emitOpError() << "requires value's type (" << value.getType()
-                         << ") to match variable's type (" << variable.getType()
-                         << ")";
-  if (isa<ArrayType>(variable.getType()))
-    return emitOpError() << "cannot assign to array type";
+  TypedValue<emitc::LValueType> variable = getVar();
+
+  if (!variable.getDefiningOp())
+    return emitOpError() << "cannot assign to block argument";
+
+  Type valueType = getValue().getType();
+  Type variableType = variable.getType().getValue();
+  if (variableType != valueType)
+    return emitOpError() << "requires value's type (" << valueType
+                         << ") to match variable's type (" << variableType
+                         << ")\n  variable: " << variable
+                         << "\n  value: " << getValue() << "\n";
   return success();
 }
 
@@ -842,9 +855,10 @@ LogicalResult emitc::SubscriptOp::verify() {
     }
     // Check element type.
     Type elementType = arrayType.getElementType();
-    if (elementType != getType()) {
+    Type resultType = getType().getValue();
+    if (elementType != resultType) {
       return emitOpError() << "on array operand requires element type ("
-                           << elementType << ") and result type (" << getType()
+                           << elementType << ") and result type (" << resultType
                            << ") to match";
     }
     return success();
@@ -868,9 +882,10 @@ LogicalResult emitc::SubscriptOp::verify() {
     }
     // Check pointee type.
     Type pointeeType = pointerType.getPointee();
-    if (pointeeType != getType()) {
+    Type resultType = getType().getValue();
+    if (pointeeType != resultType) {
       return emitOpError() << "on pointer operand requires pointee type ("
-                           << pointeeType << ") and result type (" << getType()
+                           << pointeeType << ") and result type (" << resultType
                            << ") to match";
     }
     return success();
@@ -964,6 +979,25 @@ emitc::ArrayType::cloneWith(std::optional<ArrayRef<int64_t>> shape,
   return emitc::ArrayType::get(*shape, elementType);
 }
 
+//===----------------------------------------------------------------------===//
+// LValueType
+//===----------------------------------------------------------------------===//
+
+LogicalResult mlir::emitc::LValueType::verify(
+    llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+    mlir::Type value) {
+  // Check that the wrapped type is valid. This especially forbids nested lvalue
+  // types.
+  if (!isSupportedEmitCType(value))
+    return emitError()
+           << "!emitc.lvalue must wrap supported emitc type, but got " << value;
+
+  if (llvm::isa<emitc::ArrayType>(value))
+    return emitError() << "!emitc.lvalue cannot wrap !emitc.array type";
+
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // OpaqueType
 //===----------------------------------------------------------------------===//
@@ -981,6 +1015,18 @@ LogicalResult mlir::emitc::OpaqueType::verify(
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// PointerType
+//===----------------------------------------------------------------------===//
+
+LogicalResult mlir::emitc::PointerType::verify(
+    llvm::function_ref<mlir::InFlightDiagnostic()> emitError, Type value) {
+  if (llvm::isa<emitc::LValueType>(value))
+    return emitError() << "pointers to lvalues are not allowed";
+
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // GlobalOp
 //===----------------------------------------------------------------------===//
@@ -1078,9 +1124,22 @@ GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
            << getName() << "' does not reference a valid emitc.global";
 
   Type resultType = getResult().getType();
-  if (global.getType() != resultType)
-    return emitOpError("result type ")
-           << resultType << " does not match type " << global.getType()
+  Type globalType = global.getType();
+
+  // global has array type
+  if (llvm::isa<ArrayType>(globalType)) {
+    if (globalType != resultType)
+      return emitOpError("on array type expects result type ")
+             << resultType << " to match type " << globalType
+             << " of the global @" << getName();
+    return success();
+  }
+
+  // global has non-array type
+  auto lvalueType = dyn_cast<LValueType>(resultType);
+  if (!lvalueType || lvalueType.getValue() != globalType)
+    return emitOpError("on non-array type expects result inner type ")
+           << lvalueType.getValue() << " to match type " << globalType
            << " of the global @" << getName();
   return success();
 }
diff --git a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
index 82bd031430d36..758b8527c2fa5 100644
--- a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
+++ b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
@@ -38,7 +38,8 @@ struct FormExpressionsPass
     auto matchFun = [&](Operation *op) {
       if (op->hasTrait<OpTrait::emitc::CExpression>() &&
           !op->getParentOfType<emitc::ExpressionOp>() &&
-          op->getNumResults() == 1)
+          op->getNumResults() == 1 &&
+          isSupportedEmitCType(op->getResult(0).getType()))
         createExpression(op, builder);
     };
     rootOp->walk(matchFun);
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 202df89025f26..79e433cbe4612 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -174,6 +174,9 @@ struct CppEmitter {
   /// Emit an expression as a C expression.
   LogicalResult emitExpression(ExpressionOp expressionOp);
 
+  /// Insert the expression representing the operation into the value cache.
+  LogicalResult cacheDeferredOpResult(Operation *op);
+
   /// Return the existing or a new name for a Value.
   StringRef getOrCreateName(Value val);
 
@@ -273,6 +276,18 @@ struct CppEmitter {
 };
 } // namespace
 
+/// Determine whether expression \p op should be emitted in a deferred way.
+static bool hasDeferredEmission(Operation *op) {
+  if (isa_and_nonnull<emitc::GetGlobalOp, emitc::LiteralOp, emitc::SubscriptOp>(
+          op))
+    return true;
+
+  if (auto applyOp = dyn_cast_or_null<emitc::ApplyOp>(op))
+    return applyOp.getApplicableOperator() == "*";
+
+  return false;
+}
+
 /// Determine whether expression \p expressionOp should be emitted inline, i.e.
 /// as part of its user. This function recommends inlining of any expressions
 /// that can be inlined unless it is used by another expression, under the
@@ -295,10 +310,10 @@ static bool shouldBeInlined(ExpressionOp expressionOp) {
 
   Operation *user = *result.getUsers().begin();
 
-  // Do not inline expressions used by subscript operations, since the
-  // way the subscript operation translation is implemented requires that
-  // variables be materialized.
-  if (isa<emitc::SubscriptOp>(user))
+  // Do not inline expressions used by operations with deferred emission, since
+  // the way their translation is implemented requires that variables be
+  // materialized.
+  if (hasDeferredEmission(user))
     return false;
 
   // Do not inline expressions used by ops with the CExpression trait. If this
@@ -371,17 +386,11 @@ static LogicalResult printOperation(CppEmitter &emitter,
 }
 
 static LogicalResult printOperation(CppEmitter &emitter,
-                                    emitc::GetGlobalOp op) {
-  // Add name to cache so that `hasValueInScope` works.
-  emitter.getOrCreateName(op.getResult());
-  return success();
-}
+                                    emitc::LValueLoadOp lValueLoadOp) {
+  if (failed(emitter.emitAssignPrefix(*lValueLoadOp)))
+    return failure();
 
-static LogicalResult printOperation(CppEmitter &emitter,
-                                    emitc::SubscriptOp subscriptOp) {
-  // Add name to cache so that `hasValueInScope` works.
-  emitter.getOrCreateName(subscriptOp.getResult());
-  return success();
+  return emitter.emitOperand(lValueLoadOp.getOperand());
 }
 
 static LogicalResult printBinaryOperation(CppEmitter &emitter,
@@ -621,9 +630,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
       if (t.getType().isIndex()) {
         int64_t idx = t.getInt();
         Value operand = op.getOperand(idx);
-        auto literalDef =
-            dyn_cast_if_present<LiteralOp>(operand.getDefiningOp());
-        if (!literalDef && !emitter.hasValueInScope(operand))
+        if (!emitter.hasValueInScope(operand))
           return op.emitOpError("operand ")
                  << idx << "'s value not defined in scope";
         os << emitter.getOrCreateName(operand);
@@ -660,6 +667,10 @@ static LogicalResult printOperation(CppEmitter &emitter,
                                     emitc::ApplyOp applyOp) {
   raw_ostream &os = emitter.ostre...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/91475


More information about the Mlir-commits mailing list