summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Cheptsov <vit9696@avp.su>2023-03-29 20:55:51 +0100
committerTom Stellard <tstellar@redhat.com>2023-04-04 10:47:15 -0700
commit555e0e732d48d10e6ea77ab51418edf4ff3066fe (patch)
tree303781648affda84bcb765b94fb3cb63037f06a4
parent356cb7e0d01681ed4f1e7cdd494267c5b3b81ab1 (diff)
downloadllvm-555e0e732d48d10e6ea77ab51418edf4ff3066fe.tar.gz
[RISCV] Support emulated TLS
As discussed earlier in the [GitHub issue](https://github.com/llvm/llvm-project/issues/59500), currently LLVM generates invalid code when emulated TLS is used. There were attempts to resolve this previously (D102527), but they were not merged because the component owners raised concerns about emulated TLS efficiency. The current state of the art is that: - OpenBSD team, which raised the initial issue, simply has [patches downstream](https://github.com/openbsd/src/blob/a0747c9/gnu/llvm/llvm/lib/Target/RISCV/RISCVISelLowering.cpp#L2850-L2852). - Our team, which raised the GH issue, has patches downstream as well. We also do not use `malloc` or any [dynamic allocations](https://github.com/llvm/llvm-project/issues/59500#issuecomment-1349046835) with emulated TLS, so the concerns raised in the original issue does not apply to us. - GCC compatibility is broken, because GCC supports emulated TLS. - RISC-V is the only architecture in LLVM that does not support emulated TLS, and work is being done to at least warn the users about it (D143619). With all these in mind I believe it is important to address the consumers' needs especially given that there is little to no maintenance downsides. Differential Revision: https://reviews.llvm.org/D143708 (cherry picked from commit f5e63f8fc9f492944b8432d80c1c49051a7d600a)
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp3
-rw-r--r--llvm/test/CodeGen/RISCV/emutls.ll139
2 files changed, 142 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6eea169f8919..a1dc6a0cd2c1 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -4540,6 +4540,9 @@ SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
assert(N->getOffset() == 0 && "unexpected offset in global node");
+ if (DAG.getTarget().useEmulatedTLS())
+ return LowerToTLSEmulatedModel(N, DAG);
+
TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
if (DAG.getMachineFunction().getFunction().getCallingConv() ==
diff --git a/llvm/test/CodeGen/RISCV/emutls.ll b/llvm/test/CodeGen/RISCV/emutls.ll
new file mode 100644
index 000000000000..9ce985ba4242
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/emutls.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -emulated-tls -relocation-model=pic < %s \
+; RUN: | FileCheck -check-prefix=RV32 %s
+; RUN: llc -mtriple=riscv64 -emulated-tls -relocation-model=pic < %s \
+; RUN: | FileCheck -check-prefix=RV64 %s
+
+@external_x = external thread_local global i32, align 8
+@y = thread_local global i8 7, align 2
+@internal_z = internal thread_local global i64 9, align 16
+
+define ptr @get_external_x() nounwind {
+; RV32-LABEL: get_external_x:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .Lpcrel_hi0:
+; RV32-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_x)
+; RV32-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi0)(a0)
+; RV32-NEXT: call __emutls_get_address@plt
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: get_external_x:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .Lpcrel_hi0:
+; RV64-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_x)
+; RV64-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi0)(a0)
+; RV64-NEXT: call __emutls_get_address@plt
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ ret ptr @external_x
+}
+
+define ptr @get_y() nounwind {
+; RV32-LABEL: get_y:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .Lpcrel_hi1:
+; RV32-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.y)
+; RV32-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi1)(a0)
+; RV32-NEXT: call __emutls_get_address@plt
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: get_y:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .Lpcrel_hi1:
+; RV64-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.y)
+; RV64-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi1)(a0)
+; RV64-NEXT: call __emutls_get_address@plt
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ ret ptr @y
+}
+
+define ptr @get_internal_z() nounwind {
+; RV32-LABEL: get_internal_z:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .Lpcrel_hi2:
+; RV32-NEXT: auipc a0, %pcrel_hi(__emutls_v.internal_z)
+; RV32-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi2)
+; RV32-NEXT: call __emutls_get_address@plt
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: get_internal_z:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .Lpcrel_hi2:
+; RV64-NEXT: auipc a0, %pcrel_hi(__emutls_v.internal_z)
+; RV64-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi2)
+; RV64-NEXT: call __emutls_get_address@plt
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ ret ptr @internal_z
+}
+
+; UTC_ARGS: --disable
+
+; RV32: .data
+; RV32: .globl __emutls_v.y
+; RV32: .p2align 2
+; RV32-LABEL: __emutls_v.y:
+; RV32-NEXT: .word 1
+; RV32-NEXT: .word 2
+; RV32-NEXT: .word 0
+; RV32-NEXT: .word __emutls_t.y
+; RV32: .section .rodata,
+; RV32-LABEL: __emutls_t.y:
+; RV32-NEXT: .byte 7
+; RV32: .data
+; RV32: .p2align 2
+; RV32-LABEL: __emutls_v.internal_z:
+; RV32-NEXT: .word 8
+; RV32-NEXT: .word 16
+; RV32-NEXT: .word 0
+; RV32-NEXT: .word __emutls_t.internal_z
+; RV32: .section .rodata,
+; RV32-LABEL: __emutls_t.internal_z:
+; RV32-NEXT: .quad 9
+
+; RV64: .data
+; RV64: .globl __emutls_v.y
+; RV64: .p2align 3
+; RV64-LABEL: __emutls_v.y:
+; RV64-NEXT: .quad 1
+; RV64-NEXT: .quad 2
+; RV64-NEXT: .quad 0
+; RV64-NEXT: .quad __emutls_t.y
+; RV64: .section .rodata,
+; RV64-LABEL: __emutls_t.y:
+; RV64-NEXT: .byte 7
+; RV64: .data
+; RV64: .p2align 3
+; RV64-LABEL: __emutls_v.internal_z:
+; RV64-NEXT: .quad 8
+; RV64-NEXT: .quad 16
+; RV64-NEXT: .quad 0
+; RV64-NEXT: .quad __emutls_t.internal_z
+; RV64: .section .rodata,
+; RV64-LABEL: __emutls_t.internal_z:
+; RV64-NEXT: .quad 9