Skip to content

Commit 4fb96f2

Browse files
[MLIR][LLVM] Implement LLVM dialect support for global aliases (#125295)
This includes support for module translation, module import and add tests for both. Fix #115390 ClangIR cannot currently lower global aliases to LLVM because of missing support for this.
1 parent fc10ad1 commit 4fb96f2

File tree

11 files changed

+805
-40
lines changed

11 files changed

+805
-40
lines changed

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

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,12 +1167,12 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
11671167
let arguments = (ins FlatSymbolRefAttr:$global_name);
11681168
let results = (outs LLVM_AnyPointer:$res);
11691169

1170-
let summary = "Creates a pointer pointing to a global or a function";
1170+
let summary = "Creates a pointer pointing to a global, alias or a function";
11711171

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

11781178
Examples:
@@ -1190,10 +1190,19 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
11901190

11911191
// The function address can be used for indirect calls.
11921192
llvm.call %2() : !llvm.ptr, () -> ()
1193+
1194+
// Get the address of an aliased global.
1195+
%3 = llvm.mlir.addressof @const_alias : !llvm.ptr
11931196
}
11941197

11951198
// Define the global.
11961199
llvm.mlir.global @const(42 : i32) : i32
1200+
1201+
// Define an alias.
1202+
llvm.mlir.alias @const_alias : i32 {
1203+
%0 = llvm.mlir.addressof @const : !llvm.ptr
1204+
llvm.return %0 : !llvm.ptr
1205+
}
11971206
```
11981207
}];
11991208

@@ -1212,6 +1221,14 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
12121221
build($_builder, $_state,
12131222
LLVM::LLVMPointerType::get($_builder.getContext()), func.getName());
12141223
$_state.addAttributes(attrs);
1224+
}]>,
1225+
OpBuilder<(ins "AliasOp":$alias,
1226+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs),
1227+
[{
1228+
build($_builder, $_state,
1229+
LLVM::LLVMPointerType::get($_builder.getContext(), alias.getAddrSpace()),
1230+
alias.getSymName());
1231+
$_state.addAttributes(attrs);
12151232
}]>
12161233
];
12171234

@@ -1222,6 +1239,10 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
12221239

12231240
/// Return the llvm.func operation that is referenced here.
12241241
LLVMFuncOp getFunction(SymbolTableCollection &symbolTable);
1242+
1243+
/// Return the llvm.mlir.alias operation that defined the value referenced
1244+
/// here.
1245+
AliasOp getAlias(SymbolTableCollection &symbolTable);
12251246
}];
12261247

12271248
let assemblyFormat = "$global_name attr-dict `:` qualified(type($res))";
@@ -1447,6 +1468,85 @@ def LLVM_GlobalDtorsOp : LLVM_Op<"mlir.global_dtors", [
14471468
let hasVerifier = 1;
14481469
}
14491470

1471+
def LLVM_AliasOp : LLVM_Op<"mlir.alias",
1472+
[IsolatedFromAbove, SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> {
1473+
let arguments = (ins
1474+
TypeAttr:$alias_type,
1475+
StrAttr:$sym_name,
1476+
Linkage:$linkage,
1477+
UnitAttr:$dso_local,
1478+
UnitAttr:$thread_local_,
1479+
OptionalAttr<UnnamedAddr>:$unnamed_addr,
1480+
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_
1481+
);
1482+
let summary = "LLVM dialect alias.";
1483+
let description = [{
1484+
`llvm.mlir.alias` is a top level operation that defines a global alias for
1485+
global variables and functions. The operation is always initialized by
1486+
using a initializer region which could be a direct map to another global
1487+
value or contain some address computation on top of it.
1488+
1489+
It uses a symbol for its value, which will be uniqued by the module
1490+
with respect to other symbols in it.
1491+
1492+
Similarly to functions and globals, they can also have a linkage attribute.
1493+
This attribute is placed between `llvm.mlir.alias` and the symbol name. If
1494+
the attribute is omitted, `external` linkage is assumed by default.
1495+
1496+
Examples:
1497+
1498+
```mlir
1499+
// Global alias use @-identifiers.
1500+
llvm.mlir.alias external @foo_alias {addr_space = 0 : i32} : !llvm.ptr {
1501+
%0 = llvm.mlir.addressof @some_function : !llvm.ptr
1502+
llvm.return %0 : !llvm.ptr
1503+
}
1504+
1505+
// More complex initialization.
1506+
llvm.mlir.alias linkonce_odr hidden @glob
1507+
{addr_space = 0 : i32, dso_local} : !llvm.array<32 x i32> {
1508+
%0 = llvm.mlir.constant(1234 : i64) : i64
1509+
%1 = llvm.mlir.addressof @glob.private : !llvm.ptr
1510+
%2 = llvm.ptrtoint %1 : !llvm.ptr to i64
1511+
%3 = llvm.add %2, %0 : i64
1512+
%4 = llvm.inttoptr %3 : i64 to !llvm.ptr
1513+
llvm.return %4 : !llvm.ptr
1514+
}
1515+
```
1516+
}];
1517+
let regions = (region SizedRegion<1>:$initializer);
1518+
1519+
let builders = [
1520+
OpBuilder<(ins "Type":$type, "Linkage":$linkage,
1521+
"StringRef":$name,
1522+
CArg<"bool", "false">:$dsoLocal,
1523+
CArg<"bool", "false">:$thread_local_,
1524+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
1525+
];
1526+
1527+
let extraClassDeclaration = [{
1528+
/// Return the LLVM type of the global alias.
1529+
Type getType() {
1530+
return getAliasType();
1531+
}
1532+
/// Return the initializer region. It's always present and terminates
1533+
/// with an `llvm.return` op with the initializer value.
1534+
Region &getInitializerRegion() {
1535+
return getOperation()->getRegion(0);
1536+
}
1537+
Block &getInitializerBlock() {
1538+
return getInitializerRegion().front();
1539+
}
1540+
// Retrieve address space information from the initializer block
1541+
// result.
1542+
unsigned getAddrSpace();
1543+
}];
1544+
1545+
let hasCustomAssemblyFormat = 1;
1546+
let hasVerifier = 1;
1547+
let hasRegionVerifier = 1;
1548+
}
1549+
14501550
def LLVM_ComdatSelectorOp : LLVM_Op<"comdat_selector", [Symbol]> {
14511551
let arguments = (ins
14521552
SymbolNameAttr:$sym_name,

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class ModuleImport {
6767
/// Converts all global variables of the LLVM module to MLIR global variables.
6868
LogicalResult convertGlobals();
6969

70+
/// Converts all aliases of the LLVM module to MLIR variables.
71+
LogicalResult convertAliases();
72+
7073
/// Converts the data layout of the LLVM module to an MLIR data layout
7174
/// specification.
7275
LogicalResult convertDataLayout();
@@ -288,6 +291,9 @@ class ModuleImport {
288291
LogicalResult convertGlobal(llvm::GlobalVariable *globalVar);
289292
/// Imports the magic globals "global_ctors" and "global_dtors".
290293
LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar);
294+
/// Converts an LLVM global alias variable into an MLIR LLVM dialect alias
295+
/// operation if a conversion exists. Otherwise, returns failure.
296+
LogicalResult convertAlias(llvm::GlobalAlias *alias);
291297
/// Returns personality of `func` as a FlatSymbolRefAttr.
292298
FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func);
293299
/// Imports `bb` into `block`, which must be initially empty.
@@ -406,6 +412,8 @@ class ModuleImport {
406412
Operation *constantInsertionOp = nullptr;
407413
/// Operation to insert the next global after.
408414
Operation *globalInsertionOp = nullptr;
415+
/// Operation to insert the next alias after.
416+
Operation *aliasInsertionOp = nullptr;
409417
/// Operation to insert comdat selector operations into.
410418
ComdatOp globalComdatOp = nullptr;
411419
/// The current context.

mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ class ModuleTranslation {
188188
return globalsMapping.lookup(op);
189189
}
190190

191+
/// Finds an LLVM IR global value that corresponds to the given MLIR operation
192+
/// defining a global alias value.
193+
llvm::GlobalValue *lookupAlias(Operation *op) {
194+
return aliasesMapping.lookup(op);
195+
}
196+
191197
/// Returns the OpenMP IR builder associated with the LLVM IR module being
192198
/// constructed.
193199
llvm::OpenMPIRBuilder *getOpenMPBuilder();
@@ -321,7 +327,13 @@ class ModuleTranslation {
321327
LogicalResult convertFunctionSignatures();
322328
LogicalResult convertFunctions();
323329
LogicalResult convertComdats();
324-
LogicalResult convertGlobals();
330+
331+
/// Handle conversion for both globals and global aliases.
332+
///
333+
/// - Create named global variables that correspond to llvm.mlir.global
334+
/// definitions, similarly Convert llvm.global_ctors and global_dtors ops.
335+
/// - Create global alias that correspond to llvm.mlir.alias.
336+
LogicalResult convertGlobalsAndAliases();
325337
LogicalResult convertOneFunction(LLVMFuncOp func);
326338
LogicalResult convertBlockImpl(Block &bb, bool ignoreArguments,
327339
llvm::IRBuilderBase &builder,
@@ -366,6 +378,10 @@ class ModuleTranslation {
366378
/// Mappings between llvm.mlir.global definitions and corresponding globals.
367379
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
368380

381+
/// Mappings between llvm.mlir.alias definitions and corresponding global
382+
/// aliases.
383+
DenseMap<Operation *, llvm::GlobalValue *> aliasesMapping;
384+
369385
/// A stateful object used to translate types.
370386
TypeToLLVMIRTranslator typeTranslator;
371387

0 commit comments

Comments
 (0)