Skip to content

Commit 3896bb9

Browse files
committed
[MLIR][LLVMIR] Import unregistered intrinsics via llvm.intrinsic_call
Currently, the llvm importer can only cover intrinsics that have a first class representation in an MLIR dialect (arm-neon, etc). This PR introduces a fallback mechanism that allow "unregistered" intrinsics to be imported by using the generic `llvm.intrinsic_call` operation. This is useful in several ways: 1. Allows round-trip the LLVM dialect output lowered from other dialects (example: ClangIR) 2. Enables MLIR-linking tools to operate on imported LLVM IR without requiring adding new operations to dozen of different targets (cc @xlauko @smeenai). Implemented: - Cover intrinsics across all current supported LLVM targets and generic ones. - Use existing LLVM tablegen files to populate intrinsic matching. - Matches with lower priority against dialect supported intrinsic conversion. Open question: how to add the proper include path for tablegen to find Intrinsics.td?
1 parent 2c7780a commit 3896bb9

File tree

7 files changed

+302
-13
lines changed

7 files changed

+302
-13
lines changed

mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,29 @@ mlir_tablegen(VCIXConversions.inc -gen-llvmir-conversions)
8181
mlir_tablegen(VCIXOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=vcix)
8282
mlir_tablegen(VCIXOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=vcix)
8383
add_public_tablegen_target(MLIRVCIXConversionsIncGen)
84+
85+
# FIXME: Should emit extra file with intrinsics_gen if MLIR is enabled? Or maybe find
86+
# a better way to get the path for Intrinsics.td?
87+
set(LLVM_TARGET_DEFINITIONS ../../../../../llvm/include/llvm/IR/Intrinsics.td)
88+
89+
mlir_tablegen(LLVMUnregisteredLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics)
90+
mlir_tablegen(LLVMUnregisteredAArch64LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=aarch64)
91+
mlir_tablegen(LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=amdgcn)
92+
mlir_tablegen(LLVMUnregisteredARMLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=arm)
93+
mlir_tablegen(LLVMUnregisteredBPFLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=bpf)
94+
mlir_tablegen(LLVMUnregisteredDirectXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=dx)
95+
mlir_tablegen(LLVMUnregisteredHexagonLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=hexagon)
96+
mlir_tablegen(LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=loongarch)
97+
mlir_tablegen(LLVMUnregisteredMipsLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=mips)
98+
mlir_tablegen(LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=nvvm)
99+
mlir_tablegen(LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ppc)
100+
mlir_tablegen(LLVMUnregisteredR600LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=r600)
101+
mlir_tablegen(LLVMUnregisteredRISCVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=riscv)
102+
mlir_tablegen(LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=spv)
103+
mlir_tablegen(LLVMUnregisteredS390LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=s390)
104+
mlir_tablegen(LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=wasm)
105+
mlir_tablegen(LLVMUnregisteredX86LLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=x86)
106+
mlir_tablegen(LLVMUnregisteredXCoreLLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=xcore)
107+
mlir_tablegen(LLVMUnregisteredVELLVMIRIntrinsics.inc -gen-unregistered-llvmir-intrinsics -intrinsic-prefix=ve)
108+
109+
add_public_tablegen_target(MLIRLLVMIntrinsicUnregisteredIncGen)

mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class LLVMImportDialectInterface
7474
/// returns the list of supported intrinsic identifiers.
7575
virtual ArrayRef<unsigned> getSupportedIntrinsics() const { return {}; }
7676

77+
/// Returns the list of LLVM IR intrinsic identifiers that are unsupported
78+
/// but dialects might have a generic way to represent them.
79+
virtual ArrayRef<unsigned> getUnregisteredIntrinsics() const { return {}; }
80+
7781
/// Hook for derived dialect interfaces to publish the supported instructions.
7882
/// As every LLVM IR instruction has a unique integer identifier, the function
7983
/// returns the list of supported instruction identifiers. These identifiers
@@ -139,6 +143,9 @@ class LLVMImportInterface
139143
// Add a mapping for all supported intrinsic identifiers.
140144
for (unsigned id : iface.getSupportedIntrinsics())
141145
intrinsicToDialect[id] = iface.getDialect();
146+
// Add a mapping for all unregistered intrinsic identifiers.
147+
for (unsigned id : iface.getUnregisteredIntrinsics())
148+
unregisteredIntrinscToDialect[id] = iface.getDialect();
142149
// Add a mapping for all supported instruction identifiers.
143150
for (unsigned id : iface.getSupportedInstructions())
144151
instructionToDialect[id] = &iface;
@@ -155,7 +162,19 @@ class LLVMImportInterface
155162
LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
156163
LLVM::ModuleImport &moduleImport) const {
157164
// Lookup the dialect interface for the given intrinsic.
158-
Dialect *dialect = intrinsicToDialect.lookup(inst->getIntrinsicID());
165+
llvm::Intrinsic::ID intrinId = inst->getIntrinsicID();
166+
if (intrinId == llvm::Intrinsic::not_intrinsic)
167+
return failure();
168+
169+
// First lookup intrinsic across different dialects for known
170+
// supported converstions, examples include arm-neon, nvm-sve, etc
171+
Dialect *dialect = intrinsicToDialect.lookup(intrinId);
172+
173+
// No specialized (supported) intrinsics, attempt to generate a generic
174+
// version via llvm.call_intrinsic (if available).
175+
if (!dialect)
176+
dialect = unregisteredIntrinscToDialect.lookup(intrinId);
177+
159178
if (!dialect)
160179
return failure();
161180

@@ -227,6 +246,9 @@ class LLVMImportInterface
227246
DenseMap<unsigned, Dialect *> intrinsicToDialect;
228247
DenseMap<unsigned, const LLVMImportDialectInterface *> instructionToDialect;
229248
DenseMap<unsigned, SmallVector<Dialect *, 1>> metadataToDialect;
249+
250+
/// Unregistered generic and target independent intrinsics.
251+
DenseMap<unsigned, Dialect *> unregisteredIntrinscToDialect;
230252
};
231253

232254
} // namespace mlir

mlir/lib/Dialect/LLVMIR/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ add_mlir_dialect_library(MLIRLLVMDialect
1717
MLIRLLVMTypesIncGen
1818
MLIRLLVMIntrinsicOpsIncGen
1919
MLIRLLVMInterfacesIncGen
20+
MLIRLLVMConversionsIncGen
21+
MLIRLLVMIntrinsicConversionsIncGen
22+
MLIRLLVMIntrinsicUnregisteredIncGen
2023
MLIROpenMPOpsIncGen
2124
intrinsics_gen
2225

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@
2424
#include "llvm/IR/InlineAsm.h"
2525
#include "llvm/IR/Instructions.h"
2626
#include "llvm/IR/IntrinsicInst.h"
27+
#include "llvm/IR/IntrinsicsAArch64.h"
28+
#include "llvm/IR/IntrinsicsAMDGPU.h"
29+
#include "llvm/IR/IntrinsicsARM.h"
30+
#include "llvm/IR/IntrinsicsBPF.h"
31+
#include "llvm/IR/IntrinsicsDirectX.h"
32+
#include "llvm/IR/IntrinsicsHexagon.h"
33+
#include "llvm/IR/IntrinsicsLoongArch.h"
34+
#include "llvm/IR/IntrinsicsMips.h"
35+
#include "llvm/IR/IntrinsicsNVPTX.h"
36+
#include "llvm/IR/IntrinsicsPowerPC.h"
37+
#include "llvm/IR/IntrinsicsR600.h"
38+
#include "llvm/IR/IntrinsicsRISCV.h"
39+
#include "llvm/IR/IntrinsicsS390.h"
40+
#include "llvm/IR/IntrinsicsSPIRV.h"
41+
#include "llvm/IR/IntrinsicsVE.h"
42+
#include "llvm/IR/IntrinsicsWebAssembly.h"
43+
#include "llvm/IR/IntrinsicsX86.h"
44+
#include "llvm/IR/IntrinsicsXCore.h"
2745
#include "llvm/Support/ModRef.h"
2846

2947
using namespace mlir;
@@ -56,6 +74,105 @@ static ArrayRef<unsigned> getSupportedIntrinsicsImpl() {
5674
return convertibleIntrinsics;
5775
}
5876

77+
/// Returns true if the LLVM IR intrinsic is convertible to llvm.intrinsic_call
78+
/// Returns false otherwise.
79+
static bool isConvertibleUnregisteredIntrinsic(llvm::Intrinsic::ID id) {
80+
static const DenseSet<unsigned> convertibleTargetIntrinsics = {
81+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
82+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
83+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
84+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
85+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
86+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
87+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
88+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
89+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
90+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
91+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
92+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
93+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
94+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
95+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
96+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
97+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
98+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
99+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
100+
};
101+
return convertibleTargetIntrinsics.contains(id);
102+
}
103+
104+
/// Returns the list of LLVM IR intrinsic identifiers that are not registered
105+
/// by any dialect but can be convertible to llvm.intrinsic_call operation.
106+
static ArrayRef<unsigned> getUnregisteredIntrinsicsImpl() {
107+
static const SmallVector<unsigned> convertibleTargetIntrinsics = {
108+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAArch64LLVMIRIntrinsics.inc"
109+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredAMDGPULLVMIRIntrinsics.inc"
110+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredARMLLVMIRIntrinsics.inc"
111+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredBPFLLVMIRIntrinsics.inc"
112+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredDirectXLLVMIRIntrinsics.inc"
113+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredHexagonLLVMIRIntrinsics.inc"
114+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLLVMIRIntrinsics.inc"
115+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredLoongArchLLVMIRIntrinsics.inc"
116+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredMipsLLVMIRIntrinsics.inc"
117+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredNVPTXLLVMIRIntrinsics.inc"
118+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredPowerPCLLVMIRIntrinsics.inc"
119+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredR600LLVMIRIntrinsics.inc"
120+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredRISCVLLVMIRIntrinsics.inc"
121+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredS390LLVMIRIntrinsics.inc"
122+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredSPIRVLLVMIRIntrinsics.inc"
123+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredVELLVMIRIntrinsics.inc"
124+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredWebAssemblyLLVMIRIntrinsics.inc"
125+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredX86LLVMIRIntrinsics.inc"
126+
#include "mlir/Dialect/LLVMIR/LLVMUnregisteredXCoreLLVMIRIntrinsics.inc"
127+
};
128+
return convertibleTargetIntrinsics;
129+
}
130+
131+
/// Converts the LLVM intrinsic to a generic LLVM intrinsic call using
132+
/// llvm.intrinsic_call. Returns failure otherwise.
133+
static LogicalResult
134+
convertUnregisteredIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst,
135+
LLVM::ModuleImport &moduleImport) {
136+
llvm::Intrinsic::ID intrinsicID = inst->getIntrinsicID();
137+
StringRef intrinName = inst->getCalledFunction()->getName();
138+
139+
// Sanity check the intrinsic ID.
140+
assert(isConvertibleUnregisteredIntrinsic(intrinsicID));
141+
SmallVector<llvm::Value *> args(inst->args());
142+
ArrayRef<llvm::Value *> llvmOperands(args);
143+
144+
SmallVector<llvm::OperandBundleUse> llvmOpBundles;
145+
llvmOpBundles.reserve(inst->getNumOperandBundles());
146+
for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i)
147+
llvmOpBundles.push_back(inst->getOperandBundleAt(i));
148+
149+
SmallVector<Value> mlirOperands;
150+
SmallVector<NamedAttribute> mlirAttrs;
151+
if (failed(moduleImport.convertIntrinsicArguments(
152+
llvmOperands, llvmOpBundles, false, {}, {}, mlirOperands, mlirAttrs)))
153+
return failure();
154+
155+
mlir::Type results = moduleImport.convertType(inst->getType());
156+
auto op = odsBuilder.create<::mlir::LLVM::CallIntrinsicOp>(
157+
moduleImport.translateLoc(inst->getDebugLoc()), results,
158+
StringAttr::get(odsBuilder.getContext(), intrinName),
159+
ValueRange{mlirOperands}, FastmathFlagsAttr{});
160+
161+
moduleImport.setFastmathFlagsAttr(inst, op);
162+
163+
// Update importer tracking of results.
164+
unsigned numRes = op.getNumResults();
165+
if (numRes == 1)
166+
moduleImport.mapValue(inst) = op.getResult(0);
167+
else if (numRes == 0)
168+
moduleImport.mapNoResultOp(inst);
169+
else
170+
return op.emitError(
171+
"expected at most one result from target intrinsic call");
172+
173+
return success();
174+
}
175+
59176
/// Converts the LLVM intrinsic to an MLIR LLVM dialect operation if a
60177
/// conversion exits. Returns failure otherwise.
61178
static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
@@ -75,6 +192,8 @@ static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
75192
llvmOpBundles.push_back(inst->getOperandBundleAt(i));
76193

77194
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicFromLLVMIRConversions.inc"
195+
} else if (isConvertibleUnregisteredIntrinsic(intrinsicID)) {
196+
return convertUnregisteredIntrinsicImpl(odsBuilder, inst, moduleImport);
78197
}
79198

80199
return failure();
@@ -422,6 +541,12 @@ class LLVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
422541
return getSupportedIntrinsicsImpl();
423542
}
424543

544+
/// Returns the list of LLVM IR intrinsic identifiers that are unsupported
545+
/// by existing dialects by are convertible to generic llvm.call_intrinsic.
546+
ArrayRef<unsigned> getUnregisteredIntrinsics() const final {
547+
return getUnregisteredIntrinsicsImpl();
548+
}
549+
425550
/// Returns the list of LLVM IR metadata kinds that are convertible to MLIR
426551
/// LLVM dialect attributes.
427552
ArrayRef<unsigned>

mlir/test/Target/LLVMIR/Import/import-failure.ll

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@ bb1:
3838

3939
; // -----
4040

41-
declare void @llvm.gcroot(ptr %arg1, ptr %arg2)
42-
43-
; CHECK: <unknown>
44-
; CHECK-SAME: error: unhandled intrinsic: call void @llvm.gcroot(ptr %arg1, ptr null)
45-
define void @unhandled_intrinsic() gc "example" {
46-
%arg1 = alloca ptr
47-
call void @llvm.gcroot(ptr %arg1, ptr null)
48-
ret void
49-
}
50-
51-
; // -----
52-
5341
; Check that debug intrinsics with an unsupported argument are dropped.
5442

5543
declare void @llvm.dbg.value(metadata, metadata, metadata)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
; RUN: mlir-translate -import-llvm %s -split-input-file | FileCheck %s
2+
3+
declare i64 @llvm.aarch64.ldxr.p0(ptr)
4+
5+
define dso_local void @t0(ptr %a) {
6+
%x = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i8) %a)
7+
ret void
8+
}
9+
10+
; CHECK-LABEL: llvm.func @llvm.aarch64.ldxr.p0(!llvm.ptr)
11+
; CHECK-LABEL: llvm.func @t0
12+
; CHECK: llvm.call_intrinsic "llvm.aarch64.ldxr.p0"({{.*}}) : (!llvm.ptr) -> i64
13+
; CHECK: llvm.return
14+
; CHECK: }
15+
16+
; -----
17+
18+
declare <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8>, <8 x i8>)
19+
20+
define dso_local <8 x i8> @t1(<8 x i8> %lhs, <8 x i8> %rhs) {
21+
%r = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %lhs, <8 x i8> %rhs)
22+
ret <8 x i8> %r
23+
}
24+
25+
; CHECK: llvm.func @t1(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>) -> vector<8xi8> {{.*}} {
26+
; CHECK: %[[R:.*]] = llvm.call_intrinsic "llvm.aarch64.neon.uabd.v8i8"(%[[A0]], %[[A1]]) : (vector<8xi8>, vector<8xi8>) -> vector<8xi8>
27+
; CHECK: llvm.return %[[R]] : vector<8xi8>
28+
; CHECK: }
29+
30+
; -----
31+
32+
declare void @llvm.aarch64.neon.st2.v8i8.p0(<8 x i8>, <8 x i8>, ptr)
33+
34+
define dso_local void @t2(<8 x i8> %lhs, <8 x i8> %rhs, ptr %a) {
35+
call void @llvm.aarch64.neon.st2.v8i8.p0(<8 x i8> %lhs, <8 x i8> %rhs, ptr %a)
36+
ret void
37+
}
38+
39+
; CHECK: llvm.func @t2(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>, %[[A2:.*]]: !llvm.ptr) {{.*}} {
40+
; CHECK: llvm.call_intrinsic "llvm.aarch64.neon.st2.v8i8.p0"(%[[A0]], %[[A1]], %[[A2]]) : (vector<8xi8>, vector<8xi8>, !llvm.ptr) -> !llvm.void
41+
; CHECK: llvm.return
42+
; CHECK: }
43+
44+
; -----
45+
46+
declare void @llvm.gcroot(ptr %arg1, ptr %arg2)
47+
define void @gctest() gc "example" {
48+
%arg1 = alloca ptr
49+
call void @llvm.gcroot(ptr %arg1, ptr null)
50+
ret void
51+
}
52+
53+
; CHECK-LABEL: @gctest
54+
; CHECK: llvm.call_intrinsic "llvm.gcroot"({{.*}}, {{.*}}) : (!llvm.ptr, !llvm.ptr) -> !llvm.void
55+
56+
; -----
57+
58+
; Test we get the supported version, not the unregistered one.
59+
60+
declare i32 @llvm.lround.i32.f32(float)
61+
62+
; CHECK-LABEL: llvm.func @lround_test
63+
define void @lround_test(float %0, double %1) {
64+
; CHECK-NOT: llvm.call_intrinsic "llvm.lround
65+
; CHECK: llvm.intr.lround(%{{.*}}) : (f32) -> i32
66+
%3 = call i32 @llvm.lround.i32.f32(float %0)
67+
ret void
68+
}

0 commit comments

Comments
 (0)