Skip to content

[MLIR][LLVM] Implement LLVM dialect support for global aliases #125295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cff1cd3
[MLIR][LLVM] Implement LLVM dialect support for global aliases
bcardosolopes Jan 24, 2025
8ccafc9
Fix comments
bcardosolopes Jan 31, 2025
e36ff90
Remove undef from testcase
bcardosolopes Jan 31, 2025
f12825e
Address Tobias review
bcardosolopes Feb 3, 2025
1186559
Add addrspace related tests
bcardosolopes Feb 3, 2025
1927cb5
Reorganize tests a bit, use -split-input-file
bcardosolopes Feb 3, 2025
7b27f3a
More verification love
bcardosolopes Feb 3, 2025
82ca97a
Refactor common parsing bits for GlobalOp and AliasOp
bcardosolopes Feb 3, 2025
8711298
Add roundtrip tests for the parsing/printing
bcardosolopes Feb 3, 2025
3eb7a53
Fix more nits and align linkage verification with LLVM
bcardosolopes Feb 4, 2025
f159dcc
Fix one more comment
bcardosolopes Feb 4, 2025
cf984ad
Update parse comment
bcardosolopes Feb 4, 2025
77661e7
Handle conversion for globals/aliases together since they can referen…
bcardosolopes Feb 4, 2025
b669463
Teach LLVM_AddressOfOp to work with alias symbols, fix remaining bugs…
bcardosolopes Feb 4, 2025
644424d
Improve LLVM_AddressOfOp description doc
bcardosolopes Feb 4, 2025
0d181ee
More tablegen fixes, new test file in Dialect
bcardosolopes Feb 4, 2025
3932b16
Address more review comments
bcardosolopes Feb 4, 2025
d8bd0ab
More split-input-file love
bcardosolopes Feb 4, 2025
8683355
Fix multiple printing of addressofs in init bodies
bcardosolopes Feb 4, 2025
d69436c
Get rid of address space as top level AliasOp attribute
bcardosolopes Feb 5, 2025
f0755a4
Fix test, removed too much from globals
bcardosolopes Feb 5, 2025
e4346f6
Add one more verifier check to addressof
bcardosolopes Feb 5, 2025
334d643
address more reviews
bcardosolopes Feb 5, 2025
bd0b538
Remove addr_space from globals to clean it up a bit
bcardosolopes Feb 5, 2025
7c293b2
Fix newline
bcardosolopes Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 104 additions & 4 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1163,12 +1163,12 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
let arguments = (ins FlatSymbolRefAttr:$global_name);
let results = (outs LLVM_AnyPointer:$res);

let summary = "Creates a pointer pointing to a global or a function";
let summary = "Creates a pointer pointing to a global, alias or a function";

let description = [{
Creates an SSA value containing a pointer to a global variable or constant
defined by `llvm.mlir.global`. The global value can be defined after its
first referenced. If the global value is a constant, storing into it is not
Creates an SSA value containing a pointer to a global value (function,
variable or alias). The global value can be defined after its first
referenced. If the global value is a constant, storing into it is not
allowed.

Examples:
Expand All @@ -1186,10 +1186,19 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",

// The function address can be used for indirect calls.
llvm.call %2() : !llvm.ptr, () -> ()

// Get the address of an aliased global.
%3 = llvm.mlir.addressof @const_alias : !llvm.ptr
}

// Define the global.
llvm.mlir.global @const(42 : i32) : i32

// Define an alias.
llvm.mlir.alias @const_alias : i32 {
%0 = llvm.mlir.addressof @const : !llvm.ptr
llvm.return %0 : !llvm.ptr
}
```
}];

Expand All @@ -1208,6 +1217,14 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
build($_builder, $_state,
LLVM::LLVMPointerType::get($_builder.getContext()), func.getName());
$_state.addAttributes(attrs);
}]>,
OpBuilder<(ins "AliasOp":$alias,
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs),
[{
build($_builder, $_state,
LLVM::LLVMPointerType::get($_builder.getContext(), alias.getAddrSpace()),
alias.getSymName());
$_state.addAttributes(attrs);
}]>
];

Expand All @@ -1218,6 +1235,10 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",

/// Return the llvm.func operation that is referenced here.
LLVMFuncOp getFunction(SymbolTableCollection &symbolTable);

/// Return the llvm.mlir.alias operation that defined the value referenced
/// here.
AliasOp getAlias(SymbolTableCollection &symbolTable);
}];

let assemblyFormat = "$global_name attr-dict `:` qualified(type($res))";
Expand Down Expand Up @@ -1443,6 +1464,85 @@ def LLVM_GlobalDtorsOp : LLVM_Op<"mlir.global_dtors", [
let hasVerifier = 1;
}

def LLVM_AliasOp : LLVM_Op<"mlir.alias",
[IsolatedFromAbove, SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> {
let arguments = (ins
TypeAttr:$alias_type,
StrAttr:$sym_name,
Linkage:$linkage,
UnitAttr:$dso_local,
UnitAttr:$thread_local_,
OptionalAttr<UnnamedAddr>:$unnamed_addr,
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_
);
let summary = "LLVM dialect alias.";
let description = [{
`llvm.mlir.alias` is a top level operation that defines a global alias for
global variables and functions. The operation is always initialized by
using a initializer region which could be a direct map to another global
value or contain some address computation on top of it.

It uses a symbol for its value, which will be uniqued by the module
with respect to other symbols in it.

Similarly to functions and globals, they can also have a linkage attribute.
This attribute is placed between `llvm.mlir.alias` and the symbol name. If
the attribute is omitted, `external` linkage is assumed by default.

Examples:

```mlir
// Global alias use @-identifiers.
llvm.mlir.alias external @foo_alias {addr_space = 0 : i32} : !llvm.ptr {
%0 = llvm.mlir.addressof @some_function : !llvm.ptr
llvm.return %0 : !llvm.ptr
}

// More complex initialization.
llvm.mlir.alias linkonce_odr hidden @glob
{addr_space = 0 : i32, dso_local} : !llvm.array<32 x i32> {
%0 = llvm.mlir.constant(1234 : i64) : i64
%1 = llvm.mlir.addressof @glob.private : !llvm.ptr
%2 = llvm.ptrtoint %1 : !llvm.ptr to i64
%3 = llvm.add %2, %0 : i64
%4 = llvm.inttoptr %3 : i64 to !llvm.ptr
llvm.return %4 : !llvm.ptr
}
```
}];
let regions = (region SizedRegion<1>:$initializer);

let builders = [
OpBuilder<(ins "Type":$type, "Linkage":$linkage,
"StringRef":$name,
CArg<"bool", "false">:$dsoLocal,
CArg<"bool", "false">:$thread_local_,
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
];

let extraClassDeclaration = [{
/// Return the LLVM type of the global alias.
Type getType() {
return getAliasType();
}
/// Return the initializer region. It's always present and terminates
/// with an `llvm.return` op with the initializer value.
Region &getInitializerRegion() {
return getOperation()->getRegion(0);
}
Block &getInitializerBlock() {
return getInitializerRegion().front();
}
// Retrieve address space information from the initializer block
// result.
unsigned getAddrSpace();
}];

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
let hasRegionVerifier = 1;
}

def LLVM_ComdatSelectorOp : LLVM_Op<"comdat_selector", [Symbol]> {
let arguments = (ins
SymbolNameAttr:$sym_name,
Expand Down
8 changes: 8 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/ModuleImport.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class ModuleImport {
/// Converts all global variables of the LLVM module to MLIR global variables.
LogicalResult convertGlobals();

/// Converts all aliases of the LLVM module to MLIR variables.
LogicalResult convertAliases();

/// Converts the data layout of the LLVM module to an MLIR data layout
/// specification.
LogicalResult convertDataLayout();
Expand Down Expand Up @@ -288,6 +291,9 @@ class ModuleImport {
LogicalResult convertGlobal(llvm::GlobalVariable *globalVar);
/// Imports the magic globals "global_ctors" and "global_dtors".
LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar);
/// Converts an LLVM global alias variable into an MLIR LLVM dialect alias
/// operation if a conversion exists. Otherwise, returns failure.
LogicalResult convertAlias(llvm::GlobalAlias *alias);
/// Returns personality of `func` as a FlatSymbolRefAttr.
FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func);
/// Imports `bb` into `block`, which must be initially empty.
Expand Down Expand Up @@ -406,6 +412,8 @@ class ModuleImport {
Operation *constantInsertionOp = nullptr;
/// Operation to insert the next global after.
Operation *globalInsertionOp = nullptr;
/// Operation to insert the next alias after.
Operation *aliasInsertionOp = nullptr;
/// Operation to insert comdat selector operations into.
ComdatOp globalComdatOp = nullptr;
/// The current context.
Expand Down
18 changes: 17 additions & 1 deletion mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ class ModuleTranslation {
return globalsMapping.lookup(op);
}

/// Finds an LLVM IR global value that corresponds to the given MLIR operation
/// defining a global alias value.
llvm::GlobalValue *lookupAlias(Operation *op) {
return aliasesMapping.lookup(op);
}

/// Returns the OpenMP IR builder associated with the LLVM IR module being
/// constructed.
llvm::OpenMPIRBuilder *getOpenMPBuilder();
Expand Down Expand Up @@ -321,7 +327,13 @@ class ModuleTranslation {
LogicalResult convertFunctionSignatures();
LogicalResult convertFunctions();
LogicalResult convertComdats();
LogicalResult convertGlobals();

/// Handle conversion for both globals and global aliases.
///
/// - Create named global variables that correspond to llvm.mlir.global
/// definitions, similarly Convert llvm.global_ctors and global_dtors ops.
/// - Create global alias that correspond to llvm.mlir.alias.
LogicalResult convertGlobalsAndAliases();
LogicalResult convertOneFunction(LLVMFuncOp func);
LogicalResult convertBlockImpl(Block &bb, bool ignoreArguments,
llvm::IRBuilderBase &builder,
Expand Down Expand Up @@ -366,6 +378,10 @@ class ModuleTranslation {
/// Mappings between llvm.mlir.global definitions and corresponding globals.
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;

/// Mappings between llvm.mlir.alias definitions and corresponding global
/// aliases.
DenseMap<Operation *, llvm::GlobalValue *> aliasesMapping;

/// A stateful object used to translate types.
TypeToLLVMIRTranslator typeTranslator;

Expand Down
Loading