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 @@ -1001,6 +1001,7 @@ StrAttr:$sym_name, Linkage:$linkage, UnitAttr:$dso_local, + UnitAttr:$thr_local, OptionalAttr:$value, OptionalAttr:$alignment, DefaultValuedAttr, "0">:$addr_space, @@ -1112,6 +1113,7 @@ CArg<"uint64_t", "0">:$alignment, CArg<"unsigned", "0">:$addrSpace, CArg<"bool", "false">:$dsoLocal, + CArg<"bool", "false">:$threadLocal, CArg<"ArrayRef", "{}">:$attrs)> ]; 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 @@ -1590,7 +1590,8 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type, bool isConstant, Linkage linkage, StringRef name, Attribute value, uint64_t alignment, unsigned addrSpace, - bool dsoLocal, ArrayRef attrs) { + bool dsoLocal, bool threadLocal, + ArrayRef attrs) { result.addAttribute(SymbolTable::getSymbolAttrName(), builder.getStringAttr(name)); result.addAttribute("global_type", TypeAttr::get(type)); @@ -1600,6 +1601,8 @@ result.addAttribute("value", value); if (dsoLocal) result.addAttribute("dso_local", builder.getUnitAttr()); + if (threadLocal) + result.addAttribute("thr_local", builder.getUnitAttr()); // Only add an alignment attribute if the "alignment" input // is different from 0. The value must also be a power of two, but 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 @@ -432,10 +432,11 @@ alignment = align.value(); } - GlobalOp op = - b.create(UnknownLoc::get(context), type, gv->isConstant(), - convertLinkageFromLLVM(gv->getLinkage()), - gv->getName(), valueAttr, alignment); + GlobalOp op = b.create( + UnknownLoc::get(context), type, gv->isConstant(), + convertLinkageFromLLVM(gv->getLinkage()), gv->getName(), valueAttr, + alignment, /*addr_space=*/0, /*dsoLocal=*/gv->isDSOLocal(), + /*thr_local=*/gv->isThreadLocal()); if (gv->hasInitializer() && !valueAttr) { Region &r = op.getInitializerRegion(); 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 @@ -661,7 +661,10 @@ auto *var = new llvm::GlobalVariable( *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(), - /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, addrSpace); + /*InsertBefore=*/nullptr, + op.getThrLocal() ? llvm::GlobalValue::GeneralDynamicTLSModel + : llvm::GlobalValue::NotThreadLocal, + addrSpace); if (op.getUnnamedAddr().hasValue()) var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr())); 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 @@ -57,6 +57,10 @@ llvm.mlir.global linkonce_odr @linkonce_odr() : i64 // CHECK: llvm.mlir.global weak_odr llvm.mlir.global weak_odr @weak_odr() : i64 +// CHECK: llvm.mlir.global external @has_thr_local(42 : i64) {thr_local} : i64 +llvm.mlir.global external @has_thr_local(42 : i64) {thr_local} : i64 +// CHECK: llvm.mlir.global external @has_dso_local(42 : i64) {dso_local} : i64 +llvm.mlir.global external @has_dso_local(42 : i64) {dso_local} : i64 // CHECK-LABEL: references func @references() { 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 @@ -13,14 +13,14 @@ ; CHECK: llvm.mlir.global external @g5() : vector<8xi32> @g5 = external global <8 x i32> -; CHECK: llvm.mlir.global private @alig32(42 : i64) {alignment = 32 : i64} : i64 +; CHECK: llvm.mlir.global private @alig32(42 : i64) {alignment = 32 : i64, dso_local} : i64 @alig32 = private global i64 42, align 32 -; CHECK: llvm.mlir.global private @alig64(42 : i64) {alignment = 64 : i64} : i64 +; CHECK: llvm.mlir.global private @alig64(42 : i64) {alignment = 64 : i64, dso_local} : i64 @alig64 = private global i64 42, align 64 @g4 = external global i32, align 8 -; CHECK: llvm.mlir.global internal constant @int_gep() : !llvm.ptr { +; CHECK: llvm.mlir.global internal constant @int_gep() {dso_local} : !llvm.ptr { ; CHECK-DAG: %[[addr:[0-9]+]] = llvm.mlir.addressof @g4 : !llvm.ptr ; CHECK-DAG: %[[c2:[0-9]+]] = llvm.mlir.constant(2 : i32) : i32 ; CHECK-NEXT: %[[gepinit:[0-9]+]] = llvm.getelementptr %[[addr]][%[[c2]]] : (!llvm.ptr, i32) -> !llvm.ptr @@ -28,13 +28,27 @@ ; CHECK-NEXT: } @int_gep = internal constant i32* getelementptr (i32, i32* @g4, i32 2) +; +; dso_local attribute +; + +; CHECK: llvm.mlir.global external @dso_local_var() {dso_local} : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)> +@dso_local_var = external dso_local global %struct.s + +; +; thread_local attribute +; + +; CHECK: llvm.mlir.global external @thread_local_var() {thr_local} : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)> +@thread_local_var = external thread_local global %struct.s + ; ; Linkage attribute. ; -; CHECK: llvm.mlir.global private @private(42 : i32) : i32 +; CHECK: llvm.mlir.global private @private(42 : i32) {dso_local} : i32 @private = private global i32 42 -; CHECK: llvm.mlir.global internal @internal(42 : i32) : i32 +; CHECK: llvm.mlir.global internal @internal(42 : i32) {dso_local} : i32 @internal = internal global i32 42 ; CHECK: llvm.mlir.global available_externally @available_externally(42 : i32) : i32 @available_externally = available_externally global i32 42 @@ -60,33 +74,33 @@ ; -; CHECK: llvm.mlir.global private constant @no_unnamed_addr(42 : i64) : i64 +; CHECK: llvm.mlir.global private constant @no_unnamed_addr(42 : i64) {dso_local} : i64 @no_unnamed_addr = private constant i64 42 -; CHECK: llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i64) : i64 +; CHECK: llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i64) {dso_local} : i64 @local_unnamed_addr = private local_unnamed_addr constant i64 42 -; CHECK: llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) : i64 +; CHECK: llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) {dso_local} : i64 @unnamed_addr = private unnamed_addr constant i64 42 ; ; Section attribute ; -; CHECK: llvm.mlir.global internal constant @sectionvar("teststring") {section = ".mysection"} +; CHECK: llvm.mlir.global internal constant @sectionvar("teststring") {dso_local, section = ".mysection"} @sectionvar = internal constant [10 x i8] c"teststring", section ".mysection" ; ; Sequential constants. ; -; CHECK: llvm.mlir.global internal constant @vector_constant(dense<[1, 2]> : vector<2xi32>) : vector<2xi32> +; CHECK: llvm.mlir.global internal constant @vector_constant(dense<[1, 2]> : vector<2xi32>) {dso_local} : vector<2xi32> @vector_constant = internal constant <2 x i32> -; CHECK: llvm.mlir.global internal constant @array_constant(dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf32>) : !llvm.array<2 x f32> +; CHECK: llvm.mlir.global internal constant @array_constant(dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf32>) {dso_local} : !llvm.array<2 x f32> @array_constant = internal constant [2 x float] [float 1., float 2.] -; CHECK: llvm.mlir.global internal constant @nested_array_constant(dense<[{{\[}}1, 2], [3, 4]]> : tensor<2x2xi32>) : !llvm.array<2 x array<2 x i32>> +; CHECK: llvm.mlir.global internal constant @nested_array_constant(dense<[{{\[}}1, 2], [3, 4]]> : tensor<2x2xi32>) {dso_local} : !llvm.array<2 x array<2 x i32>> @nested_array_constant = internal constant [2 x [2 x i32]] [[2 x i32] [i32 1, i32 2], [2 x i32] [i32 3, i32 4]] -; CHECK: llvm.mlir.global internal constant @nested_array_constant3(dense<[{{\[}}[1, 2], [3, 4]]]> : tensor<1x2x2xi32>) : !llvm.array<1 x array<2 x array<2 x i32>>> +; CHECK: llvm.mlir.global internal constant @nested_array_constant3(dense<[{{\[}}[1, 2], [3, 4]]]> : tensor<1x2x2xi32>) {dso_local} : !llvm.array<1 x array<2 x array<2 x i32>>> @nested_array_constant3 = internal constant [1 x [2 x [2 x i32]]] [[2 x [2 x i32]] [[2 x i32] [i32 1, i32 2], [2 x i32] [i32 3, i32 4]]] -; CHECK: llvm.mlir.global internal constant @nested_array_vector(dense<[{{\[}}[1, 2], [3, 4]]]> : vector<1x2x2xi32>) : !llvm.array<1 x array<2 x vector<2xi32>>> +; CHECK: llvm.mlir.global internal constant @nested_array_vector(dense<[{{\[}}[1, 2], [3, 4]]]> : vector<1x2x2xi32>) {dso_local} : !llvm.array<1 x array<2 x vector<2xi32>>> @nested_array_vector = internal constant [1 x [2 x <2 x i32>]] [[2 x <2 x i32>] [<2 x i32> , <2 x i32> ]] ; 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 @@ -128,6 +128,13 @@ llvm.mlir.global @has_dso_local(42 : i64) {dso_local} : i64 // CHECK: @has_dso_local = dso_local global i64 42 +// +// thr_local attribute. +// + +llvm.mlir.global @has_thr_local(42 : i64) {thr_local} : i64 +// CHECK: @has_thr_local = thread_local global i64 42 + // // Section attribute. //