diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -780,6 +780,17 @@ let cppNamespace = "::mlir::LLVM"; } +def UnnamedAddrNone : LLVM_EnumAttrCase<"None", "", "None", 0>; +def UnnamedAddrLocal : LLVM_EnumAttrCase<"Local", "local_unnamed_addr", "Local", 1>; +def UnnamedAddrGlobal : LLVM_EnumAttrCase<"Global", "unnamed_addr", "Global", 2>; + +def UnnamedAddr : LLVM_EnumAttr< + "UnnamedAddr", + "::llvm::GlobalValue::UnnamedAddr", + "LLVM GlobalValue UnnamedAddr", + [UnnamedAddrNone, UnnamedAddrLocal, UnnamedAddrGlobal]> { + let cppNamespace = "::mlir::LLVM"; +} def LLVM_AddressOfOp : LLVM_Op<"mlir.addressof"> { let arguments = (ins FlatSymbolRefAttr:$global_name); @@ -896,7 +907,8 @@ StrAttr:$sym_name, Linkage:$linkage, OptionalAttr:$value, - DefaultValuedAttr, "0">:$addr_space + DefaultValuedAttr, "0">:$addr_space, + OptionalAttr:$unnamed_addr ); let summary = "LLVM dialect global."; let description = [{ diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1244,6 +1244,10 @@ /// the name of the attribute in ODS. static StringRef getLinkageAttrName() { return "linkage"; } +/// Returns the name used for the unnamed_addr attribute. This *must* correspond +/// to the name of the attribute in ODS. +static StringRef getUnnamedAddrAttrName() { return "unnamed_addr"; } + void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type, bool isConstant, Linkage linkage, StringRef name, Attribute value, unsigned addrSpace, @@ -1265,6 +1269,8 @@ static void printGlobalOp(OpAsmPrinter &p, GlobalOp op) { p << op.getOperationName() << ' ' << stringifyLinkage(op.linkage()) << ' '; + if (op.unnamed_addr()) + p << stringifyUnnamedAddr(*op.unnamed_addr()) << ' '; if (op.constant()) p << "constant "; p.printSymbolName(op.sym_name()); @@ -1274,7 +1280,8 @@ p << ')'; p.printOptionalAttrDict(op->getAttrs(), {SymbolTable::getSymbolAttrName(), "type", "constant", - "value", getLinkageAttrName()}); + "value", getLinkageAttrName(), + getUnnamedAddrAttrName()}); // Print the trailing type unless it's a string global. if (op.getValueOrNull().dyn_cast_or_null()) @@ -1495,6 +1502,7 @@ } REGISTER_ENUM_TYPE(Linkage); +REGISTER_ENUM_TYPE(UnnamedAddr); } // end namespace template @@ -1524,6 +1532,12 @@ parser.getBuilder().getI64IntegerAttr( static_cast(LLVM::Linkage::External))); + if (failed(parseOptionalLLVMKeyword(parser, result, + getUnnamedAddrAttrName()))) + result.addAttribute(getUnnamedAddrAttrName(), + parser.getBuilder().getI64IntegerAttr( + static_cast(LLVM::UnnamedAddr::None))); + if (succeeded(parser.parseOptionalKeyword("constant"))) result.addAttribute("constant", parser.getBuilder().getUnitAttr()); diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -487,6 +487,9 @@ return nullptr; b.create(op.getLoc(), ArrayRef({v})); } + if (GV->hasAtLeastLocalUnnamedAddr()) + op.unnamed_addrAttr(UnnamedAddrAttr::get( + context, convertUnnamedAddrFromLLVM(GV->getUnnamedAddr()))); return globals[GV] = op; } diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -407,6 +407,9 @@ op.sym_name(), /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, addrSpace); + if (op.unnamed_addr().hasValue()) + var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.unnamed_addr())); + globalsMapping.try_emplace(op, var); } diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir --- a/mlir/test/Dialect/LLVMIR/global.mlir +++ b/mlir/test/Dialect/LLVMIR/global.mlir @@ -63,6 +63,12 @@ llvm.return } +// CHECK: llvm.mlir.global private local_unnamed_addr constant @local(42 : i64) : i64 +llvm.mlir.global private local_unnamed_addr constant @local(42 : i64) : i64 + +// CHECK: llvm.mlir.global private unnamed_addr constant @foo(42 : i64) : i64 +llvm.mlir.global private unnamed_addr constant @foo(42 : i64) : i64 + // ----- // expected-error @+1 {{requires string attribute 'sym_name'}} diff --git a/mlir/test/Target/LLVMIR/import.ll b/mlir/test/Target/LLVMIR/import.ll --- a/mlir/test/Target/LLVMIR/import.ll +++ b/mlir/test/Target/LLVMIR/import.ll @@ -49,6 +49,18 @@ ; CHECK: llvm.mlir.global external @external() : i32 @external = external global i32 +; +; UnnamedAddr attribute. +; + + +; CHECK: llvm.mlir.global private constant @no_unnamed_addr(42 : i64) : i64 +@no_unnamed_addr = private constant i64 42 +; CHECK: llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i64) : i64 +@local_unnamed_addr = private local_unnamed_addr constant i64 42 +; CHECK: llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) : i64 +@unnamed_addr = private unnamed_addr constant i64 42 + ; ; Sequential constants. ; @@ -109,7 +121,7 @@ if.then: ; CHECK: llvm.return %[[c42]] : i32 ret i32 42 - + ; CHECK: ^bb2: if.end: ; CHECK: %[[orcond:[0-9]+]] = llvm.or %[[e]], %[[c1]] : i1 diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -59,6 +59,16 @@ // CHECK: @external = external global i32 llvm.mlir.global external @external() : i32 +// +// UnnamedAddr attribute. +// + +// CHECK: @no_unnamed_addr = private constant i64 42 +llvm.mlir.global private constant @no_unnamed_addr(42 : i64) : i64 +// CHECK: @local_unnamed_addr = private local_unnamed_addr constant i64 42 +llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i64) : i64 +// CHECK: @unnamed_addr = private unnamed_addr constant i64 42 +llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) : i64 // // Declarations of the allocation functions to be linked against. These are