Skip to content

Commit fba06d9

Browse files
bcardosolopes2over12
authored andcommitted
[MLIR][LLVM] Implement LLVM dialect support for global aliases (llvm#125294)
This includes support for module translation, module import and add tests for both. Fix llvm#115390 ClangIR cannot currently lower global aliases to LLVM because of missing support for this.
1 parent e5ba872 commit fba06d9

File tree

11 files changed

+807
-41
lines changed

11 files changed

+807
-41
lines changed

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

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,12 +1164,12 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
11641164
let arguments = (ins FlatSymbolRefAttr:$global_name);
11651165
let results = (outs LLVM_AnyPointer:$res);
11661166

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

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

11751175
Examples:
@@ -1187,10 +1187,19 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
11871187

11881188
// The function address can be used for indirect calls.
11891189
llvm.call %2() : !llvm.ptr, () -> ()
1190+
1191+
// Get the address of an aliased global.
1192+
%3 = llvm.mlir.addressof @const_alias : !llvm.ptr
11901193
}
11911194

11921195
// Define the global.
11931196
llvm.mlir.global @const(42 : i32) : i32
1197+
1198+
// Define an alias.
1199+
llvm.mlir.alias @const_alias : i32 {
1200+
%0 = llvm.mlir.addressof @const : !llvm.ptr
1201+
llvm.return %0 : !llvm.ptr
1202+
}
11941203
```
11951204
}];
11961205

@@ -1209,6 +1218,14 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
12091218
build($_builder, $_state,
12101219
LLVM::LLVMPointerType::get($_builder.getContext()), func.getName());
12111220
$_state.addAttributes(attrs);
1221+
}]>,
1222+
OpBuilder<(ins "AliasOp":$alias,
1223+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs),
1224+
[{
1225+
build($_builder, $_state,
1226+
LLVM::LLVMPointerType::get($_builder.getContext(), alias.getAddrSpace()),
1227+
alias.getSymName());
1228+
$_state.addAttributes(attrs);
12121229
}]>
12131230
];
12141231

@@ -1220,6 +1237,11 @@ def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof",
12201237
/// Return the llvm.func operation that is referenced here.
12211238
LLVMFuncOp getFunction(SymbolTableCollection &symbolTable);
12221239

1240+
/// Return the llvm.mlir.alias operation that defined the value referenced
1241+
/// here.
1242+
AliasOp getAlias(SymbolTableCollection &symbolTable);
1243+
}];
1244+
12231245
}];
12241246
let assemblyFormat = "$global_name attr-dict `:` qualified(type($res))";
12251247

@@ -1450,6 +1472,85 @@ def LLVM_GlobalDtorsOp : LLVM_Op<"mlir.global_dtors", [
14501472
let hasVerifier = 1;
14511473
}
14521474

1475+
def LLVM_AliasOp : LLVM_Op<"mlir.alias",
1476+
[IsolatedFromAbove, SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> {
1477+
let arguments = (ins
1478+
TypeAttr:$alias_type,
1479+
StrAttr:$sym_name,
1480+
Linkage:$linkage,
1481+
UnitAttr:$dso_local,
1482+
UnitAttr:$thread_local_,
1483+
OptionalAttr<UnnamedAddr>:$unnamed_addr,
1484+
DefaultValuedAttr<Visibility, "mlir::LLVM::Visibility::Default">:$visibility_
1485+
);
1486+
let summary = "LLVM dialect alias.";
1487+
let description = [{
1488+
`llvm.mlir.alias` is a top level operation that defines a global alias for
1489+
global variables and functions. The operation is always initialized by
1490+
using a initializer region which could be a direct map to another global
1491+
value or contain some address computation on top of it.
1492+
1493+
It uses a symbol for its value, which will be uniqued by the module
1494+
with respect to other symbols in it.
1495+
1496+
Similarly to functions and globals, they can also have a linkage attribute.
1497+
This attribute is placed between `llvm.mlir.alias` and the symbol name. If
1498+
the attribute is omitted, `external` linkage is assumed by default.
1499+
1500+
Examples:
1501+
1502+
```mlir
1503+
// Global alias use @-identifiers.
1504+
llvm.mlir.alias external @foo_alias {addr_space = 0 : i32} : !llvm.ptr {
1505+
%0 = llvm.mlir.addressof @some_function : !llvm.ptr
1506+
llvm.return %0 : !llvm.ptr
1507+
}
1508+
1509+
// More complex initialization.
1510+
llvm.mlir.alias linkonce_odr hidden @glob
1511+
{addr_space = 0 : i32, dso_local} : !llvm.array<32 x i32> {
1512+
%0 = llvm.mlir.constant(1234 : i64) : i64
1513+
%1 = llvm.mlir.addressof @glob.private : !llvm.ptr
1514+
%2 = llvm.ptrtoint %1 : !llvm.ptr to i64
1515+
%3 = llvm.add %2, %0 : i64
1516+
%4 = llvm.inttoptr %3 : i64 to !llvm.ptr
1517+
llvm.return %4 : !llvm.ptr
1518+
}
1519+
```
1520+
}];
1521+
let regions = (region SizedRegion<1>:$initializer);
1522+
1523+
let builders = [
1524+
OpBuilder<(ins "Type":$type, "Linkage":$linkage,
1525+
"StringRef":$name,
1526+
CArg<"bool", "false">:$dsoLocal,
1527+
CArg<"bool", "false">:$thread_local_,
1528+
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
1529+
];
1530+
1531+
let extraClassDeclaration = [{
1532+
/// Return the LLVM type of the global alias.
1533+
Type getType() {
1534+
return getAliasType();
1535+
}
1536+
/// Return the initializer region. It's always present and terminates
1537+
/// with an `llvm.return` op with the initializer value.
1538+
Region &getInitializerRegion() {
1539+
return getOperation()->getRegion(0);
1540+
}
1541+
Block &getInitializerBlock() {
1542+
return getInitializerRegion().front();
1543+
}
1544+
// Retrieve address space information from the initializer block
1545+
// result.
1546+
unsigned getAddrSpace();
1547+
}];
1548+
1549+
let hasCustomAssemblyFormat = 1;
1550+
let hasVerifier = 1;
1551+
let hasRegionVerifier = 1;
1552+
}
1553+
14531554
def LLVM_ComdatSelectorOp : LLVM_Op<"comdat_selector", [Symbol]> {
14541555
let arguments = (ins
14551556
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();
@@ -284,6 +287,9 @@ class ModuleImport {
284287
LogicalResult convertGlobal(llvm::GlobalVariable *globalVar);
285288
/// Imports the magic globals "global_ctors" and "global_dtors".
286289
LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar);
290+
/// Converts an LLVM global alias variable into an MLIR LLVM dialect alias
291+
/// operation if a conversion exists. Otherwise, returns failure.
292+
LogicalResult convertAlias(llvm::GlobalAlias *alias);
287293
/// Returns personality of `func` as a FlatSymbolRefAttr.
288294
FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func);
289295
/// Imports `bb` into `block`, which must be initially empty.
@@ -393,6 +399,8 @@ class ModuleImport {
393399
Operation *constantInsertionOp = nullptr;
394400
/// Operation to insert the next global after.
395401
Operation *globalInsertionOp = nullptr;
402+
/// Operation to insert the next alias after.
403+
Operation *aliasInsertionOp = nullptr;
396404
/// Operation to insert comdat selector operations into.
397405
ComdatOp globalComdatOp = nullptr;
398406
/// 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)