[Mlir-commits] [mlir] [MLIR][LLVMIR] llvm.call_intrinsic: support operand/result attributes (PR #129640)
Bruno Cardoso Lopes
llvmlistbot at llvm.org
Tue Mar 4 17:42:23 PST 2025
https://github.com/bcardosolopes updated https://github.com/llvm/llvm-project/pull/129640
>From c58a7d0831e52d851ccd094e1d50f99bc90159dd Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Mon, 3 Mar 2025 11:24:59 -0800
Subject: [PATCH 01/11] [MLIR][LLVMIR][NFC] Change llvm.call_intrinsic to use
hasCustomAssemblyFormat
This is in prep for adding operand and result atritbues to llvm.call_intrinsic,
in the same fashion as llvm.call. While here, reuse
`parseCallTypeAndResolveOperands` and
`call_interface_impl::printFunctionSignature`.
There's more that can be refactored once the order of attribute and call type
are flipped to match llvm.call.
---
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 8 +-
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 94 +++++++++++++++++++++
2 files changed, 95 insertions(+), 7 deletions(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index eed3b2cdb91ea..2a86d2a186295 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2112,13 +2112,7 @@ def LLVM_CallIntrinsicOp
let llvmBuilder = [{
return convertCallLLVMIntrinsicOp(op, builder, moduleTranslation);
}];
- let assemblyFormat = [{
- $intrin `(` $args `)`
- ( custom<OpBundles>($op_bundle_operands, type($op_bundle_operands),
- $op_bundle_tags)^ )?
- `:` functional-type($args, $results)
- attr-dict
- }];
+ let hasCustomAssemblyFormat = 1;
let builders = [
OpBuilder<(ins "StringAttr":$intrin, "ValueRange":$args)>,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index fb9236fcc640d..792ebef85e3e8 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3573,6 +3573,100 @@ void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
/*op_bundle_operands=*/{}, /*op_bundle_tags=*/{});
}
+ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
+ OperationState &result) {
+ StringAttr intrinAttr;
+ SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
+ SmallVector<SmallVector<OpAsmParser::UnresolvedOperand>> opBundleOperands;
+ SmallVector<SmallVector<Type>> opBundleOperandTypes;
+ ArrayAttr opBundleTags;
+
+ // Parse intrinsic name
+ if (parser.parseCustomAttributeWithFallback(
+ intrinAttr, parser.getBuilder().getType<mlir::NoneType>())) {
+ return mlir::failure();
+ }
+ result.addAttribute(CallIntrinsicOp::getIntrinAttrName(result.name),
+ intrinAttr);
+
+ if (parser.parseLParen())
+ return mlir::failure();
+
+ // Parse the function arguments.
+ if (parser.parseOperandList(operands))
+ return mlir::failure();
+
+ if (parser.parseRParen())
+ return mlir::failure();
+
+ // Handle bundles.
+ SMLoc opBundlesLoc = parser.getCurrentLocation();
+ if (std::optional<ParseResult> result = parseOpBundles(
+ parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
+ result && failed(*result))
+ return failure();
+ if (opBundleTags && !opBundleTags.empty())
+ result.addAttribute(
+ CallIntrinsicOp::getOpBundleTagsAttrName(result.name).getValue(),
+ opBundleTags);
+
+ SmallVector<DictionaryAttr> argAttrs;
+ SmallVector<DictionaryAttr> resultAttrs;
+ // TODO: add argument/result attribute support
+ if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
+ operands, argAttrs, resultAttrs))
+ return failure();
+
+ // TODO: In CallOp, the attr dict happens *before* the call type.
+ // CallIntrinsicOp should mimic that, allowing most of this function to be
+ // shared between the two ops.
+ if (parser.parseOptionalAttrDict(result.attributes))
+ return mlir::failure();
+
+ if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
+ opBundleOperandTypes,
+ getOpBundleSizesAttrName(result.name)))
+ return failure();
+
+ int32_t numOpBundleOperands = 0;
+ for (const auto &operands : opBundleOperands)
+ numOpBundleOperands += operands.size();
+
+ result.addAttribute(
+ CallIntrinsicOp::getOperandSegmentSizeAttr(),
+ parser.getBuilder().getDenseI32ArrayAttr(
+ {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
+
+ return mlir::success();
+}
+
+void CallIntrinsicOp::print(OpAsmPrinter &p) {
+ p << ' ';
+ p.printAttributeWithoutType(getIntrinAttr());
+
+ OperandRange args = getArgs();
+ p << "(" << args << ")";
+
+ // Operand bundles.
+ if (!getOpBundleOperands().empty()) {
+ p << ' ';
+ printOpBundles(p, *this, getOpBundleOperands(),
+ getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
+ }
+ p << " : ";
+
+ // Reconstruct the MLIR function type from operand and result types.
+ ArrayAttr argAttrsAttr, resAttrsAttr; // TODO: add support for arg/ret attrs.
+ call_interface_impl::printFunctionSignature(p, args.getTypes(), argAttrsAttr,
+ /*isVariadic=*/false,
+ getResultTypes(), resAttrsAttr);
+
+ p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
+ {getOperandSegmentSizesAttrName(),
+ getOpBundleSizesAttrName(), getIntrinAttrName(),
+ getOpBundleTagsAttrName()});
+}
+
//===----------------------------------------------------------------------===//
// OpAsmDialectInterface
//===----------------------------------------------------------------------===//
>From 0cda12bb794c9488e51b539cd2a6dea4aea184e7 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Wed, 26 Feb 2025 17:07:43 -0800
Subject: [PATCH 02/11] [MLIR][LLVMIR] llvm.call_intrinsic: support
operand/result attributes
Basically catch up with llvm.call.
- Similar approach to llvm.call.
- Add support for translate and import to LLVM IR.
---
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 4 +-
.../include/mlir/Target/LLVMIR/ModuleImport.h | 8 +-
.../mlir/Target/LLVMIR/ModuleTranslation.h | 2 +-
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 25 +++---
.../LLVMIR/LLVMToLLVMIRTranslation.cpp | 79 +++++++++++--------
.../lib/Target/LLVMIR/LLVMImportInterface.cpp | 5 ++
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 16 +++-
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 3 +-
mlir/test/Dialect/LLVMIR/call-intrin.mlir | 9 +++
.../LLVMIR/Import/intrinsic-unregistered.ll | 11 +++
10 files changed, 112 insertions(+), 50 deletions(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 2a86d2a186295..121cf53393f15 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2107,7 +2107,9 @@ def LLVM_CallIntrinsicOp
VariadicOfVariadic<LLVM_Type,
"op_bundle_sizes">:$op_bundle_operands,
DenseI32ArrayAttr:$op_bundle_sizes,
- OptionalAttr<ArrayAttr>:$op_bundle_tags);
+ OptionalAttr<ArrayAttr>:$op_bundle_tags,
+ OptionalAttr<DictArrayAttr>:$arg_attrs,
+ OptionalAttr<DictArrayAttr>:$res_attrs);
let results = (outs Optional<LLVM_Type>:$results);
let llvmBuilder = [{
return convertCallLLVMIntrinsicOp(op, builder, moduleTranslation);
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 6c673295d8dcc..de1692982a310 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -272,6 +272,11 @@ class ModuleImport {
SmallVectorImpl<Value> &valuesOut,
SmallVectorImpl<NamedAttribute> &attrsOut);
+ /// Converts the parameter and result attributes attached to `call` and adds
+ /// them to the `callOp`.
+ void convertParameterAttributes(llvm::CallBase *call, ArrayAttr &argsAttr,
+ ArrayAttr &resAttr, OpBuilder &builder);
+
private:
/// Clears the accumulated state before processing a new region.
void clearRegionState() {
@@ -350,7 +355,8 @@ class ModuleImport {
DictionaryAttr convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
OpBuilder &builder);
/// Converts the parameter and result attributes attached to `call` and adds
- /// them to the `callOp`.
+ /// them to the `callOp`. Implemented in terms of the other definition of
+ /// the public definition of convertParameterAttributes.
void convertParameterAttributes(llvm::CallBase *call, CallOpInterface callOp,
OpBuilder &builder);
/// Converts the attributes attached to `inst` and adds them to the `op`.
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index eb59ef8c62266..4e984baa65f16 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -237,7 +237,7 @@ class ModuleTranslation {
/// Translates parameter attributes of a call and adds them to the returned
/// AttrBuilder. Returns failure if any of the translations failed.
- FailureOr<llvm::AttrBuilder> convertParameterAttrs(CallOpInterface callOp,
+ FailureOr<llvm::AttrBuilder> convertParameterAttrs(mlir::Location loc,
DictionaryAttr paramAttrs);
/// Gets the named metadata in the LLVM IR module being constructed, creating
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 792ebef85e3e8..b1964481f7272 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3547,7 +3547,8 @@ void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
mlir::StringAttr intrin, mlir::ValueRange args) {
build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
FastmathFlagsAttr{},
- /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{});
+ /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
+ /*res_attrs=*/{});
}
void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
@@ -3555,14 +3556,16 @@ void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
build(builder, state, /*resultTypes=*/TypeRange{}, intrin, args,
fastMathFlags,
- /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{});
+ /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
+ /*res_attrs=*/{});
}
void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
mlir::Type resultType, mlir::StringAttr intrin,
mlir::ValueRange args) {
build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
- /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{});
+ /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
+ /*res_attrs=*/{});
}
void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
@@ -3570,7 +3573,8 @@ void CallIntrinsicOp::build(OpBuilder &builder, OperationState &state,
mlir::StringAttr intrin, mlir::ValueRange args,
mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
build(builder, state, resultTypes, intrin, args, fastMathFlags,
- /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{});
+ /*op_bundle_operands=*/{}, /*op_bundle_tags=*/{}, /*arg_attrs=*/{},
+ /*res_attrs=*/{});
}
ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
@@ -3616,6 +3620,9 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
operands, argAttrs, resultAttrs))
return failure();
+ call_interface_impl::addArgAndResultAttrs(
+ parser.getBuilder(), result, argAttrs, resultAttrs,
+ getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
// TODO: In CallOp, the attr dict happens *before* the call type.
// CallIntrinsicOp should mimic that, allowing most of this function to be
@@ -3656,15 +3663,15 @@ void CallIntrinsicOp::print(OpAsmPrinter &p) {
p << " : ";
// Reconstruct the MLIR function type from operand and result types.
- ArrayAttr argAttrsAttr, resAttrsAttr; // TODO: add support for arg/ret attrs.
- call_interface_impl::printFunctionSignature(p, args.getTypes(), argAttrsAttr,
- /*isVariadic=*/false,
- getResultTypes(), resAttrsAttr);
+ call_interface_impl::printFunctionSignature(
+ p, args.getTypes(), getArgAttrsAttr(),
+ /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
{getOperandSegmentSizesAttrName(),
getOpBundleSizesAttrName(), getIntrinAttrName(),
- getOpBundleTagsAttrName()});
+ getOpBundleTagsAttrName(), getArgAttrsAttrName(),
+ getResAttrsAttrName()});
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 4f89ee703ebb9..25599efe64322 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -135,6 +135,46 @@ convertOperandBundles(OperandRangeRange bundleOperands,
return convertOperandBundles(bundleOperands, *bundleTags, moduleTranslation);
}
+static LogicalResult
+convertParameterAndResultAttrs(mlir::Location loc, ArrayAttr argAttrsArray,
+ ArrayAttr resAttrsArray, llvm::CallBase *call,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ if (argAttrsArray) {
+ for (auto [argIdx, argAttrsAttr] : llvm::enumerate(argAttrsArray)) {
+ if (auto argAttrs = cast<DictionaryAttr>(argAttrsAttr);
+ !argAttrs.empty()) {
+ FailureOr<llvm::AttrBuilder> attrBuilder =
+ moduleTranslation.convertParameterAttrs(loc, argAttrs);
+ if (failed(attrBuilder))
+ return failure();
+ call->addParamAttrs(argIdx, *attrBuilder);
+ }
+ }
+ }
+
+ if (resAttrsArray && resAttrsArray.size() > 0) {
+ if (resAttrsArray.size() != 1)
+ return mlir::emitError(loc, "llvm.func cannot have multiple results");
+ if (auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
+ !resAttrs.empty()) {
+ FailureOr<llvm::AttrBuilder> attrBuilder =
+ moduleTranslation.convertParameterAttrs(loc, resAttrs);
+ if (failed(attrBuilder))
+ return failure();
+ call->addRetAttrs(*attrBuilder);
+ }
+ }
+ return success();
+}
+
+static LogicalResult
+convertParameterAndResultAttrs(CallOpInterface callOp, llvm::CallBase *call,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ return convertParameterAndResultAttrs(
+ callOp.getLoc(), callOp.getArgAttrsAttr(), callOp.getResAttrsAttr(), call,
+ moduleTranslation);
+}
+
/// Builder for LLVM_CallIntrinsicOp
static LogicalResult
convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
@@ -201,6 +241,12 @@ convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
fn, moduleTranslation.lookupValues(op.getArgs()),
convertOperandBundles(op.getOpBundleOperands(), op.getOpBundleTags(),
moduleTranslation));
+
+ if (failed(convertParameterAndResultAttrs(op.getLoc(), op.getArgAttrsAttr(),
+ op.getResAttrsAttr(), inst,
+ moduleTranslation)))
+ return failure();
+
if (op.getNumResults() == 1)
moduleTranslation.mapValue(op->getResults().front()) = inst;
return success();
@@ -224,39 +270,6 @@ static void convertLinkerOptionsOp(ArrayAttr options,
linkerMDNode->addOperand(listMDNode);
}
-static LogicalResult
-convertParameterAndResultAttrs(CallOpInterface callOp, llvm::CallBase *call,
- LLVM::ModuleTranslation &moduleTranslation) {
- if (ArrayAttr argAttrsArray = callOp.getArgAttrsAttr()) {
- for (auto [argIdx, argAttrsAttr] : llvm::enumerate(argAttrsArray)) {
- if (auto argAttrs = cast<DictionaryAttr>(argAttrsAttr);
- !argAttrs.empty()) {
- FailureOr<llvm::AttrBuilder> attrBuilder =
- moduleTranslation.convertParameterAttrs(callOp, argAttrs);
- if (failed(attrBuilder))
- return failure();
- call->addParamAttrs(argIdx, *attrBuilder);
- }
- }
- }
-
- ArrayAttr resAttrsArray = callOp.getResAttrsAttr();
- if (resAttrsArray && resAttrsArray.size() > 0) {
- if (resAttrsArray.size() != 1)
- return mlir::emitError(callOp.getLoc(),
- "llvm.func cannot have multiple results");
- if (auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
- !resAttrs.empty()) {
- FailureOr<llvm::AttrBuilder> attrBuilder =
- moduleTranslation.convertParameterAttrs(callOp, resAttrs);
- if (failed(attrBuilder))
- return failure();
- call->addRetAttrs(*attrBuilder);
- }
- }
- return success();
-}
-
static LogicalResult
convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
diff --git a/mlir/lib/Target/LLVMIR/LLVMImportInterface.cpp b/mlir/lib/Target/LLVMIR/LLVMImportInterface.cpp
index 24f500557c6de..fbf2d709c240c 100644
--- a/mlir/lib/Target/LLVMIR/LLVMImportInterface.cpp
+++ b/mlir/lib/Target/LLVMIR/LLVMImportInterface.cpp
@@ -45,6 +45,11 @@ LogicalResult mlir::LLVMImportInterface::convertUnregisteredIntrinsic(
moduleImport.setFastmathFlagsAttr(inst, op);
+ ArrayAttr argsAttr, resAttr;
+ moduleImport.convertParameterAttributes(inst, argsAttr, resAttr, builder);
+ op.setArgAttrsAttr(argsAttr);
+ op.setResAttrsAttr(resAttr);
+
// Update importer tracking of results.
unsigned numRes = op.getNumResults();
if (numRes == 1)
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 7ea82f61fadbb..2d3c0efd9a972 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2213,7 +2213,8 @@ void ModuleImport::convertParameterAttributes(llvm::Function *func,
}
void ModuleImport::convertParameterAttributes(llvm::CallBase *call,
- CallOpInterface callOp,
+ ArrayAttr &argsAttr,
+ ArrayAttr &resAttr,
OpBuilder &builder) {
llvm::AttributeList llvmAttrs = call->getAttributes();
SmallVector<llvm::AttributeSet> llvmArgAttrsSet;
@@ -2233,14 +2234,23 @@ void ModuleImport::convertParameterAttributes(llvm::CallBase *call,
SmallVector<DictionaryAttr> argAttrs;
for (auto &llvmArgAttrs : llvmArgAttrsSet)
argAttrs.emplace_back(convertParameterAttribute(llvmArgAttrs, builder));
- callOp.setArgAttrsAttr(getArrayAttr(argAttrs));
+ argsAttr = getArrayAttr(argAttrs);
}
llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
if (!llvmResAttr.hasAttributes())
return;
DictionaryAttr resAttrs = convertParameterAttribute(llvmResAttr, builder);
- callOp.setResAttrsAttr(getArrayAttr({resAttrs}));
+ resAttr = getArrayAttr({resAttrs});
+}
+
+void ModuleImport::convertParameterAttributes(llvm::CallBase *call,
+ CallOpInterface callOp,
+ OpBuilder &builder) {
+ ArrayAttr argsAttr, resAttr;
+ convertParameterAttributes(call, argsAttr, resAttr, builder);
+ callOp.setArgAttrsAttr(argsAttr);
+ callOp.setResAttrsAttr(resAttr);
}
template <typename Op>
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index eda6b51ff45ea..46d73ded4ca9a 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1696,10 +1696,9 @@ ModuleTranslation::convertParameterAttrs(LLVMFuncOp func, int argIdx,
}
FailureOr<llvm::AttrBuilder>
-ModuleTranslation::convertParameterAttrs(CallOpInterface callOp,
+ModuleTranslation::convertParameterAttrs(Location loc,
DictionaryAttr paramAttrs) {
llvm::AttrBuilder attrBuilder(llvmModule->getContext());
- Location loc = callOp.getLoc();
auto attrNameToKindMapping = getAttrNameToKindMapping();
for (auto namedAttr : paramAttrs) {
diff --git a/mlir/test/Dialect/LLVMIR/call-intrin.mlir b/mlir/test/Dialect/LLVMIR/call-intrin.mlir
index 24aa38fca4a65..e41428bb40b58 100644
--- a/mlir/test/Dialect/LLVMIR/call-intrin.mlir
+++ b/mlir/test/Dialect/LLVMIR/call-intrin.mlir
@@ -105,3 +105,12 @@ llvm.func @bad_args() {
%res = llvm.call_intrinsic "llvm.x86.sse41.round.ss"(%1, %1, %0) : (vector<4xf32>, vector<4xf32>, i64) -> vector<4xf32> {fastmathFlags = #llvm.fastmath<reassoc>}
llvm.return
}
+
+// -----
+
+// CHECK-LABEL: intrinsic_call_arg_attrs
+llvm.func @intrinsic_call_arg_attrs(%arg0: i32) -> i32 {
+ // CHECK: call i32 @llvm.riscv.sha256sig0(i32 signext %{{.*}})
+ %0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) : (i32 {llvm.signext}) -> (i32)
+ llvm.return %0 : i32
+}
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index 554be8f797b75..80e45f3479e2c 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -66,3 +66,14 @@ define void @lround_test(float %0, double %1) {
%3 = call i32 @llvm.lround.i32.f32(float %0)
ret void
}
+
+; // -----
+
+declare i32 @llvm.riscv.sha256sig0(i32)
+
+; CHECK-LABEL: test_intrin_arg_attr
+define signext i32 @test_intrin_arg_attr(i32 signext %a) nounwind {
+ ; CHECK: llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) : (i32 {llvm.signext}) -> i32
+ %val = call i32 @llvm.riscv.sha256sig0(i32 signext %a)
+ ret i32 %val
+}
\ No newline at end of file
>From a3d11220e51efd361ea14995fbd88d197ac0d57c Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Mon, 3 Mar 2025 20:30:29 -0800
Subject: [PATCH 03/11] Update comment
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index b1964481f7272..10edd8e16e355 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3616,7 +3616,6 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
SmallVector<DictionaryAttr> argAttrs;
SmallVector<DictionaryAttr> resultAttrs;
- // TODO: add argument/result attribute support
if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
operands, argAttrs, resultAttrs))
return failure();
>From 9e172001113d2450c0585feebd07e1ec385a911f Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Mon, 3 Mar 2025 20:31:28 -0800
Subject: [PATCH 04/11] more comment updates
---
mlir/include/mlir/Target/LLVMIR/ModuleImport.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index de1692982a310..5301154410638 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -272,8 +272,8 @@ class ModuleImport {
SmallVectorImpl<Value> &valuesOut,
SmallVectorImpl<NamedAttribute> &attrsOut);
- /// Converts the parameter and result attributes attached to `call` and adds
- /// them to the `callOp`.
+ /// Converts the parameter and result attributes in `argsAttr` and `resAttr`
+ /// and add them to the `callOp`.
void convertParameterAttributes(llvm::CallBase *call, ArrayAttr &argsAttr,
ArrayAttr &resAttr, OpBuilder &builder);
>From 70b631dc02044322286ec2ed40a26b347039a698 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 10:36:36 -0800
Subject: [PATCH 05/11] Update mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 10edd8e16e355..206549556ab8e 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3585,7 +3585,7 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
SmallVector<SmallVector<Type>> opBundleOperandTypes;
ArrayAttr opBundleTags;
- // Parse intrinsic name
+ // Parse intrinsic name.
if (parser.parseCustomAttributeWithFallback(
intrinAttr, parser.getBuilder().getType<mlir::NoneType>())) {
return mlir::failure();
>From 4d6f68462744eb5b540fc7945d061ff9d46cf8ec Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 10:36:48 -0800
Subject: [PATCH 06/11] Update mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 206549556ab8e..e91d34abcab1a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3587,9 +3587,8 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
// Parse intrinsic name.
if (parser.parseCustomAttributeWithFallback(
- intrinAttr, parser.getBuilder().getType<mlir::NoneType>())) {
- return mlir::failure();
- }
+ intrinAttr, parser.getBuilder().getType<NoneType>()))
+ return failure();
result.addAttribute(CallIntrinsicOp::getIntrinAttrName(result.name),
intrinAttr);
>From d4745ed508320441b8465f26a841abdbfba08b0d Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 16:43:27 -0800
Subject: [PATCH 07/11] Add parse/print roundtrip test
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 2 +-
mlir/test/Dialect/LLVMIR/roundtrip.mlir | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index e91d34abcab1a..24751b7d49b73 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3587,7 +3587,7 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
// Parse intrinsic name.
if (parser.parseCustomAttributeWithFallback(
- intrinAttr, parser.getBuilder().getType<NoneType>()))
+ intrinAttr, parser.getBuilder().getType<NoneType>()))
return failure();
result.addAttribute(CallIntrinsicOp::getIntrinAttrName(result.name),
intrinAttr);
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index e0a17308af828..8dedaa12b74b6 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -988,3 +988,10 @@ llvm.func @test_invoke_arg_attrs_indirect(%arg0: i16, %arg1: !llvm.ptr) -> i16 a
^bb2:
llvm.return %0 : i16
}
+
+// CHECK-LABEL: intrinsic_call_arg_attrs
+llvm.func @intrinsic_call_arg_attrs(%arg0: i32) -> i32 {
+ // CHECK: %{{.*}} = llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) : (i32 {llvm.signext}) -> i32
+ %0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) : (i32 {llvm.signext}) -> (i32)
+ llvm.return %0 : i32
+}
>From 7c70731ef3c12d636306fa4b8345535140a1a4f6 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 16:56:33 -0800
Subject: [PATCH 08/11] Add bundle tests
---
mlir/test/Dialect/LLVMIR/roundtrip.mlir | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 8dedaa12b74b6..d97d54245bb4a 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -995,3 +995,10 @@ llvm.func @intrinsic_call_arg_attrs(%arg0: i32) -> i32 {
%0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) : (i32 {llvm.signext}) -> (i32)
llvm.return %0 : i32
}
+
+// CHECK-LABEL: intrinsic_call_arg_attrs_bundles
+llvm.func @intrinsic_call_arg_attrs_bundles(%arg0: i32) -> i32 {
+ // CHECK: %{{.*}} = llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) ["adazdazd"()] : (i32 {llvm.signext}) -> i32
+ %0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) ["adazdazd"()] : (i32 {llvm.signext}) -> (i32)
+ llvm.return %0 : i32
+}
\ No newline at end of file
>From bbc3b1ff71e82d4e1db8809409e2ab93dadaf52b Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 17:02:25 -0800
Subject: [PATCH 09/11] Add Dialect/LLVMIR/invalid.mlir suggestion
---
mlir/test/Dialect/LLVMIR/invalid.mlir | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index 0415ab00bdb05..fcb6ae07f4912 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -1693,6 +1693,15 @@ llvm.func @wrong_number_of_bundle_types() {
// -----
+llvm.func @wrong_number_of_bundle_types_intrin(%arg0: i32) -> i32 {
+ %0 = llvm.mlir.constant(0 : i32) : i32
+ // expected-error at +1 {{expected 1 types for operand bundle operands for operand bundle #0, but actually got 2}}
+ %1 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) ["tag"(%0 : i32, i32)] : (i32 {llvm.signext}) -> (i32)
+ llvm.return %1 : i32
+}
+
+// -----
+
llvm.func @foo()
llvm.func @wrong_number_of_bundle_tags() {
%0 = llvm.mlir.constant(0 : i32) : i32
>From 1f0af0135a5104c970d7bd2ab425beab0ac14a9b Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 17:36:26 -0800
Subject: [PATCH 10/11] Flip the order attributes appear, add more tests for
that in face of operand attrs
---
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 22 ++++++++++------------
mlir/test/Dialect/LLVMIR/call-intrin.mlir | 10 +++++-----
mlir/test/Dialect/LLVMIR/roundtrip.mlir | 4 ++--
3 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 24751b7d49b73..f9d12f0f8513d 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3613,6 +3613,9 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
CallIntrinsicOp::getOpBundleTagsAttrName(result.name).getValue(),
opBundleTags);
+ if (parser.parseOptionalAttrDict(result.attributes))
+ return mlir::failure();
+
SmallVector<DictionaryAttr> argAttrs;
SmallVector<DictionaryAttr> resultAttrs;
if (parseCallTypeAndResolveOperands(parser, result, /*isDirect=*/true,
@@ -3622,12 +3625,6 @@ ParseResult CallIntrinsicOp::parse(OpAsmParser &parser,
parser.getBuilder(), result, argAttrs, resultAttrs,
getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
- // TODO: In CallOp, the attr dict happens *before* the call type.
- // CallIntrinsicOp should mimic that, allowing most of this function to be
- // shared between the two ops.
- if (parser.parseOptionalAttrDict(result.attributes))
- return mlir::failure();
-
if (resolveOpBundleOperands(parser, opBundlesLoc, result, opBundleOperands,
opBundleOperandTypes,
getOpBundleSizesAttrName(result.name)))
@@ -3658,18 +3655,19 @@ void CallIntrinsicOp::print(OpAsmPrinter &p) {
printOpBundles(p, *this, getOpBundleOperands(),
getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
}
- p << " : ";
-
- // Reconstruct the MLIR function type from operand and result types.
- call_interface_impl::printFunctionSignature(
- p, args.getTypes(), getArgAttrsAttr(),
- /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
p.printOptionalAttrDict(processFMFAttr((*this)->getAttrs()),
{getOperandSegmentSizesAttrName(),
getOpBundleSizesAttrName(), getIntrinAttrName(),
getOpBundleTagsAttrName(), getArgAttrsAttrName(),
getResAttrsAttrName()});
+
+ p << " : ";
+
+ // Reconstruct the MLIR function type from operand and result types.
+ call_interface_impl::printFunctionSignature(
+ p, args.getTypes(), getArgAttrsAttr(),
+ /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/LLVMIR/call-intrin.mlir b/mlir/test/Dialect/LLVMIR/call-intrin.mlir
index e41428bb40b58..ea15ec2d5f654 100644
--- a/mlir/test/Dialect/LLVMIR/call-intrin.mlir
+++ b/mlir/test/Dialect/LLVMIR/call-intrin.mlir
@@ -7,7 +7,7 @@
llvm.func @round_sse41() -> vector<4xf32> {
%0 = llvm.mlir.constant(1 : i32) : i32
%1 = llvm.mlir.constant(dense<0.2> : vector<4xf32>) : vector<4xf32>
- %res = llvm.call_intrinsic "llvm.x86.sse41.round.ss"(%1, %1, %0) : (vector<4xf32>, vector<4xf32>, i32) -> vector<4xf32> {fastmathFlags = #llvm.fastmath<reassoc>}
+ %res = llvm.call_intrinsic "llvm.x86.sse41.round.ss"(%1, %1, %0) {fastmathFlags = #llvm.fastmath<reassoc>} : (vector<4xf32>, vector<4xf32>, i32) -> vector<4xf32>
llvm.return %res: vector<4xf32>
}
@@ -19,7 +19,7 @@ llvm.func @round_sse41() -> vector<4xf32> {
// CHECK: }
llvm.func @round_overloaded() -> f32 {
%0 = llvm.mlir.constant(1.0 : f32) : f32
- %res = llvm.call_intrinsic "llvm.round"(%0) : (f32) -> f32 {}
+ %res = llvm.call_intrinsic "llvm.round"(%0) {} : (f32) -> f32
llvm.return %res: f32
}
@@ -34,7 +34,7 @@ llvm.func @lifetime_start() {
%0 = llvm.mlir.constant(4 : i64) : i64
%1 = llvm.mlir.constant(1 : i8) : i8
%2 = llvm.alloca %1 x f32 : (i8) -> !llvm.ptr
- llvm.call_intrinsic "llvm.lifetime.start"(%0, %2) : (i64, !llvm.ptr) -> () {}
+ llvm.call_intrinsic "llvm.lifetime.start"(%0, %2) {} : (i64, !llvm.ptr) -> ()
llvm.return
}
@@ -64,7 +64,7 @@ llvm.func @bad_types() {
%0 = llvm.mlir.constant(1 : i8) : i8
// expected-error at below {{call intrinsic signature i8 (i8) to overloaded intrinsic "llvm.round" does not match any of the overloads}}
// expected-error at below {{LLVM Translation failed for operation: llvm.call_intrinsic}}
- llvm.call_intrinsic "llvm.round"(%0) : (i8) -> i8 {}
+ llvm.call_intrinsic "llvm.round"(%0) {} : (i8) -> i8
llvm.return
}
@@ -102,7 +102,7 @@ llvm.func @bad_args() {
%1 = llvm.mlir.constant(dense<0.2> : vector<4xf32>) : vector<4xf32>
// expected-error @below {{intrinsic call operand #2 has type i64 but "llvm.x86.sse41.round.ss" expects i32}}
// expected-error at below {{LLVM Translation failed for operation: llvm.call_intrinsic}}
- %res = llvm.call_intrinsic "llvm.x86.sse41.round.ss"(%1, %1, %0) : (vector<4xf32>, vector<4xf32>, i64) -> vector<4xf32> {fastmathFlags = #llvm.fastmath<reassoc>}
+ %res = llvm.call_intrinsic "llvm.x86.sse41.round.ss"(%1, %1, %0) {fastmathFlags = #llvm.fastmath<reassoc>} : (vector<4xf32>, vector<4xf32>, i64) -> vector<4xf32>
llvm.return
}
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index d97d54245bb4a..3a461328c04db 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -998,7 +998,7 @@ llvm.func @intrinsic_call_arg_attrs(%arg0: i32) -> i32 {
// CHECK-LABEL: intrinsic_call_arg_attrs_bundles
llvm.func @intrinsic_call_arg_attrs_bundles(%arg0: i32) -> i32 {
- // CHECK: %{{.*}} = llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) ["adazdazd"()] : (i32 {llvm.signext}) -> i32
- %0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) ["adazdazd"()] : (i32 {llvm.signext}) -> (i32)
+ // CHECK: %{{.*}} = llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) ["adazdazd"()] {constant} : (i32 {llvm.signext}) -> i32
+ %0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) ["adazdazd"()] {constant} : (i32 {llvm.signext}) -> (i32)
llvm.return %0 : i32
}
\ No newline at end of file
>From 5b93d4db8b31d350d25b9d7954860f431046b992 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 4 Mar 2025 17:42:05 -0800
Subject: [PATCH 11/11] Fix newlines
---
mlir/test/Dialect/LLVMIR/roundtrip.mlir | 2 +-
mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 3a461328c04db..d0aa65d14a176 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -1001,4 +1001,4 @@ llvm.func @intrinsic_call_arg_attrs_bundles(%arg0: i32) -> i32 {
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) ["adazdazd"()] {constant} : (i32 {llvm.signext}) -> i32
%0 = llvm.call_intrinsic "llvm.riscv.sha256sig0"(%arg0) ["adazdazd"()] {constant} : (i32 {llvm.signext}) -> (i32)
llvm.return %0 : i32
-}
\ No newline at end of file
+}
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index 80e45f3479e2c..5afc29a5642fc 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -76,4 +76,4 @@ define signext i32 @test_intrin_arg_attr(i32 signext %a) nounwind {
; CHECK: llvm.call_intrinsic "llvm.riscv.sha256sig0"({{.*}}) : (i32 {llvm.signext}) -> i32
%val = call i32 @llvm.riscv.sha256sig0(i32 signext %a)
ret i32 %val
-}
\ No newline at end of file
+}
More information about the Mlir-commits
mailing list