diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -950,9 +950,13 @@ isOSBinFormatDXContainer()); } + /// Tests whether the target supports emulated tls + bool supportsEmulatedTLS() const { return !isRISCV(); } + /// Tests whether the target uses emulated TLS as default. bool hasDefaultEmulatedTLS() const { - return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); + return supportsEmulatedTLS() && + (isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment()); } /// Tests whether the target uses -data-sections as default. diff --git a/llvm/test/LTO/RISCV/riscv-no-emutls.ll b/llvm/test/LTO/RISCV/riscv-no-emutls.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/RISCV/riscv-no-emutls.ll @@ -0,0 +1,39 @@ +; Ensure targets that normally enable emulated TLS by default, don't run the +; LowerEmuTLSPass under LTO when targeting RISCV. Under LTO the backend options +; for emulated TLS won't be propagated unless passed explicitly as part of the +; linker invocation. Since LLVM doesn't support emulated TLS on RISCV, we want +; to be sure related transforms don't take place. + +; RUN: opt < %s -o %t.bc --mtriple=riscv64-unknown-linux-android10000 + +; RUN: llvm-lto2 run %t.bc -o %t.out.o \ +; RUN: -r=%t.bc,baz,pxl \ +; RUN: -debug-pass=Structure 2>&1 | FileCheck %s --allow-empty +; RUN: llvm-readelf -s %t.out.o.0 | FileCheck %s --check-prefix=NOUNDEF + +; Ensure the backend pass we want to avoid doesn't run: LowerEmuTLSPass +; so we check for its output under pass structure +; CHECK-NOT: Add __emutls_ + +; Also check that we don't end up creating internal thread_locals that are +; undefined in the final link. This used to happen because the LowerEmuTLSPass +; would be added when targeting platforms with default emulated TLS. +; NOUNDEF : TLS LOCAL DEFAULT {[0-9]+} Mem +; NOUNDEF-NOT: TLS GLOBAL DEFAULT UND Mem + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" + +%struct.Memory = type { i32, i32 } + +@Mem = internal thread_local global ptr null, align 8 + +define void @baz(i32 noundef signext %n) { +entry: + %loc = inttoptr i64 66 to ptr + %threadlocal = call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @Mem) + store ptr %loc, ptr %threadlocal, align 8 + + ret void +} + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)