Skip to content

Commit 1126fe2

Browse files
committed
fixup! [mlir][LLVMIR] Add IFuncOp to LLVM dialect
1 parent 2593954 commit 1126fe2

File tree

7 files changed

+30
-61
lines changed

7 files changed

+30
-61
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,7 +1629,7 @@ def LLVM_IFuncOp : LLVM_Op<"mlir.ifunc",
16291629
Examples:
16301630

16311631
```mlir
1632-
// IFuncs have @-identifier and use a resolver function.
1632+
// IFuncs resolve a symbol at runtime using a resovler function.
16331633
llvm.mlir.ifunc external @foo: !llvm.func<f32 (i64)>, !llvm.ptr @resolver
16341634

16351635
llvm.func @foo_1(i64) -> f32

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ class ModuleImport {
323323
/// Converts an LLVM global alias variable into an MLIR LLVM dialect alias
324324
/// operation if a conversion exists. Otherwise, returns failure.
325325
LogicalResult convertAlias(llvm::GlobalAlias *alias);
326-
// Converts an LLVM global ifunc into an MLIR LLVM dialect ifunc operation
326+
// Converts an LLVM global ifunc into an MLIR LLVM dialect ifunc operation.
327327
LogicalResult convertIFunc(llvm::GlobalIFunc *ifunc);
328328
/// Returns personality of `func` as a FlatSymbolRefAttr.
329329
FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func);

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,14 +2709,24 @@ void IFuncOp::build(OpBuilder &builder, OperationState &result, StringRef name,
27092709
LogicalResult IFuncOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
27102710
Operation *symbol =
27112711
symbolTable.lookupSymbolIn(parentLLVMModule(*this), getResolverAttr());
2712+
// This matches LLVM IR verification logic, see llvm/lib/IR/Verifier.cpp
27122713
auto resolver = dyn_cast<LLVMFuncOp>(symbol);
2713-
if (!resolver) {
2714-
// FIXME: Strip aliases to find the called function
2715-
if (isa<AliasOp>(symbol))
2714+
auto alias = dyn_cast<AliasOp>(symbol);
2715+
while (alias) {
2716+
Block &initBlock = alias.getInitializerBlock();
2717+
auto returnOp = cast<ReturnOp>(initBlock.getTerminator());
2718+
auto addrOp = dyn_cast<AddressOfOp>(returnOp.getArg().getDefiningOp());
2719+
// FIXME: This is a best effort solution. The AliasOp body might be more
2720+
// complex and in that case we bail out with success. To completely match
2721+
// the LLVM IR logic it would be necessary to implement proper alias and
2722+
// cast stripping.
2723+
if (!addrOp)
27162724
return success();
2717-
return emitOpError("must have a function resolver");
2725+
resolver = addrOp.getFunction(symbolTable);
2726+
alias = addrOp.getAlias(symbolTable);
27182727
}
2719-
// This matches LLVM IR verification logic, see from llvm/lib/IR/Verifier.cpp
2728+
if (!resolver)
2729+
return emitOpError("must have a function resolver");
27202730
Linkage linkage = resolver.getLinkage();
27212731
if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
27222732
return emitOpError("resolver must be a definition");

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,11 +1877,11 @@ LogicalResult ModuleTranslation::convertIFuncs() {
18771877
convertLinkageToLLVM(op.getLinkage());
18781878
llvm::Constant *resolver;
18791879
if (auto *resolverFn = lookupFunction(op.getResolver())) {
1880-
resolver = dyn_cast<llvm::Constant>(resolverFn);
1880+
resolver = cast<llvm::Constant>(resolverFn);
18811881
} else {
1882-
Operation *aliasTrg = symbolTable().lookupSymbolIn(parentLLVMModule(op),
1883-
op.getResolverAttr());
1884-
resolver = cast<llvm::Constant>(lookupAlias(aliasTrg));
1882+
Operation *aliasOp = symbolTable().lookupSymbolIn(parentLLVMModule(op),
1883+
op.getResolverAttr());
1884+
resolver = cast<llvm::Constant>(lookupAlias(aliasOp));
18851885
}
18861886

18871887
auto *ifunc =

mlir/test/Dialect/LLVMIR/ifunc.mlir

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ llvm.func @resolver() -> !llvm.ptr {
3131
// -----
3232

3333
// CHECK: llvm.mlir.ifunc weak @ifunc : !llvm.func<f32 (i64)>, !llvm.ptr @resolver
34-
3534
llvm.mlir.ifunc weak @ifunc : !llvm.func<f32 (i64)>, !llvm.ptr @resolver
3635
llvm.func @resolver() -> !llvm.ptr {
3736
%0 = llvm.mlir.constant(333 : i64) : i64

mlir/test/Target/LLVMIR/Import/ifunc.ll

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,15 @@
44
@foo = dso_local ifunc void (ptr, i32), ptr @resolve_foo
55

66
define dso_local void @call_foo(ptr noundef %0, i32 noundef %1) {
7-
%3 = alloca ptr, align 8
8-
%4 = alloca i32, align 4
9-
store ptr %0, ptr %3, align 8
10-
store i32 %1, ptr %4, align 4
11-
%5 = load ptr, ptr %3, align 8
12-
%6 = load i32, ptr %4, align 4
137
; CHECK: llvm.call @foo
14-
call void @foo(ptr noundef %5, i32 noundef %6)
8+
call void @foo(ptr noundef %0, i32 noundef %1)
159
ret void
1610
}
1711

18-
define dso_local void @call_indirect_foo(ptr noundef %0, i32 noundef %1) {
19-
%3 = alloca ptr, align 8
20-
%4 = alloca i32, align 4
21-
%5 = alloca ptr, align 8
22-
; CHECK: [[CALLEE:%[0-9]+]] = llvm.mlir.addressof @foo
23-
; CHECK: llvm.store [[CALLEE]], [[STORED:%[0-9]+]]
24-
; CHECK: [[LOADED_CALLEE:%[0-9]+]] = llvm.load [[STORED]]
25-
store ptr %0, ptr %3, align 8
26-
store i32 %1, ptr %4, align 4
27-
store ptr @foo, ptr %5, align 8
28-
%6 = load ptr, ptr %5, align 8
29-
%7 = load ptr, ptr %3, align 8
30-
%8 = load i32, ptr %4, align 4
31-
call void %6(ptr noundef %7, i32 noundef %8)
32-
ret void
12+
define dso_local ptr @foo_fptr() {
13+
; CHECK: [[FPTR:%[0-9]+]] = llvm.mlir.addressof @foo
14+
; CHECK: llvm.return [[FPTR]]
15+
ret ptr @foo
3316
}
3417

3518
define internal ptr @resolve_foo() {

mlir/test/Target/LLVMIR/ifunc.mlir

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,14 @@
33
// CHECK: @foo = dso_local ifunc void (ptr, i32), ptr @resolve_foo
44
llvm.mlir.ifunc external @foo : !llvm.func<void (ptr, i32)>, !llvm.ptr @resolve_foo {dso_local}
55
llvm.func @call_foo(%arg0: !llvm.ptr {llvm.noundef}, %arg1: i32 {llvm.noundef}) attributes {dso_local} {
6-
%0 = llvm.mlir.constant(1 : i32) : i32
7-
%1 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr
8-
%2 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr
9-
llvm.store %arg0, %1 {alignment = 8 : i64} : !llvm.ptr, !llvm.ptr
10-
llvm.store %arg1, %2 {alignment = 4 : i64} : i32, !llvm.ptr
11-
%3 = llvm.load %1 {alignment = 8 : i64} : !llvm.ptr -> !llvm.ptr
12-
%4 = llvm.load %2 {alignment = 4 : i64} : !llvm.ptr -> i32
136
// CHECK: call void @foo
14-
llvm.call @foo(%3, %4) : (!llvm.ptr {llvm.noundef}, i32 {llvm.noundef}) -> ()
7+
llvm.call @foo(%arg0, %arg1) : (!llvm.ptr {llvm.noundef}, i32 {llvm.noundef}) -> ()
158
llvm.return
169
}
17-
llvm.func @call_indirect_foo(%arg0: !llvm.ptr {llvm.noundef}, %arg1: i32 {llvm.noundef}) attributes {dso_local} {
18-
%0 = llvm.mlir.constant(1 : i32) : i32
10+
llvm.func @foo_fptr() -> !llvm.ptr attributes {dso_local} {
1911
%1 = llvm.mlir.addressof @foo : !llvm.ptr
20-
%2 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr
21-
%3 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr
22-
%4 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr
23-
llvm.store %arg0, %2 {alignment = 8 : i64} : !llvm.ptr, !llvm.ptr
24-
llvm.store %arg1, %3 {alignment = 4 : i64} : i32, !llvm.ptr
25-
// CHECK: store ptr @foo, ptr [[STORED:%[0-9]+]]
26-
llvm.store %1, %4 {alignment = 8 : i64} : !llvm.ptr, !llvm.ptr
27-
// CHECK: [[LOADED:%[0-9]+]] = load ptr, ptr [[STORED]]
28-
%5 = llvm.load %4 {alignment = 8 : i64} : !llvm.ptr -> !llvm.ptr
29-
%6 = llvm.load %2 {alignment = 8 : i64} : !llvm.ptr -> !llvm.ptr
30-
%7 = llvm.load %3 {alignment = 4 : i64} : !llvm.ptr -> i32
31-
// CHECK: call void [[LOADED]]
32-
llvm.call %5(%6, %7) : !llvm.ptr, (!llvm.ptr {llvm.noundef}, i32 {llvm.noundef}) -> ()
33-
llvm.return
12+
// CHECK: ret ptr @foo
13+
llvm.return %1 : !llvm.ptr
3414
}
3515
llvm.func internal @resolve_foo() -> !llvm.ptr attributes {dso_local} {
3616
%0 = llvm.mlir.addressof @foo_1 : !llvm.ptr
@@ -62,7 +42,6 @@ llvm.func @resolver() -> !llvm.ptr {
6242
// -----
6343

6444
// CHECK: @ifunc = linkonce_odr hidden ifunc
65-
6645
llvm.mlir.ifunc linkonce_odr hidden @ifunc : !llvm.func<f32 (i64)>, !llvm.ptr @resolver {dso_local}
6746
llvm.func @resolver() -> !llvm.ptr {
6847
%0 = llvm.mlir.constant(333 : i64) : i64
@@ -73,7 +52,6 @@ llvm.func @resolver() -> !llvm.ptr {
7352
// -----
7453

7554
// CHECK: @ifunc = private ifunc
76-
7755
llvm.mlir.ifunc private @ifunc : !llvm.func<f32 (i64)>, !llvm.ptr @resolver {dso_local}
7856
llvm.func @resolver() -> !llvm.ptr {
7957
%0 = llvm.mlir.constant(333 : i64) : i64
@@ -84,7 +62,6 @@ llvm.func @resolver() -> !llvm.ptr {
8462
// -----
8563

8664
// CHECK: @ifunc = weak ifunc
87-
8865
llvm.mlir.ifunc weak @ifunc : !llvm.func<f32 (i64)>, !llvm.ptr @resolver
8966
llvm.func @resolver() -> !llvm.ptr {
9067
%0 = llvm.mlir.constant(333 : i64) : i64

0 commit comments

Comments
 (0)