diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -4570,6 +4570,9 @@ SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { GlobalAddressSDNode *N = cast(Op); + if (DAG.getTarget().useEmulatedTLS()) + return LowerToTLSEmulatedModel(N, DAG); + assert(N->getOffset() == 0 && "unexpected offset in global node"); TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal()); diff --git a/llvm/test/CodeGen/RISCV/emutls.ll b/llvm/test/CodeGen/RISCV/emutls.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/emutls.ll @@ -0,0 +1,161 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -emulated-tls -mtriple=riscv32 -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=RV32 %s +; RUN: llc < %s -emulated-tls -mtriple=riscv64 -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=RV64 %s + +; Make sure that TLS symbols are emitted in expected order. + +@external_x = external thread_local global i32, align 8 +@external_y = thread_local global i8 7, align 2 +@internal_y = internal thread_local global i64 9, align 16 + +define ptr @get_external_x() { +; RV32-LABEL: get_external_x: +; RV32: # %bb.0: # %entry +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .LBB0_1: # %entry +; RV32-NEXT: # Label of block must be emitted +; RV32-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_x) +; RV32-NEXT: lw a0, %pcrel_lo(.LBB0_1)(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: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .LBB0_1: # %entry +; RV64-NEXT: # Label of block must be emitted +; RV64-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_x) +; RV64-NEXT: ld a0, %pcrel_lo(.LBB0_1)(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_external_y() { +; RV32-LABEL: get_external_y: +; RV32: # %bb.0: # %entry +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .LBB1_1: # %entry +; RV32-NEXT: # Label of block must be emitted +; RV32-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_y) +; RV32-NEXT: lw a0, %pcrel_lo(.LBB1_1)(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_y: +; RV64: # %bb.0: # %entry +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .LBB1_1: # %entry +; RV64-NEXT: # Label of block must be emitted +; RV64-NEXT: auipc a0, %got_pcrel_hi(__emutls_v.external_y) +; RV64-NEXT: ld a0, %pcrel_lo(.LBB1_1)(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_y +} + +define ptr @get_internal_y() { +; RV32-LABEL: get_internal_y: +; RV32: # %bb.0: # %entry +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: .LBB2_1: # %entry +; RV32-NEXT: # Label of block must be emitted +; RV32-NEXT: auipc a0, %pcrel_hi(__emutls_v.internal_y) +; RV32-NEXT: addi a0, a0, %pcrel_lo(.LBB2_1) +; 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_y: +; RV64: # %bb.0: # %entry +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: .LBB2_1: # %entry +; RV64-NEXT: # Label of block must be emitted +; RV64-NEXT: auipc a0, %pcrel_hi(__emutls_v.internal_y) +; RV64-NEXT: addi a0, a0, %pcrel_lo(.LBB2_1) +; 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_y +} + +; RV32: .data +; RV32: .globl __emutls_v.external_y +; RV32: .p2align 2 +; RV32-LABEL: __emutls_v.external_y: +; RV32-NEXT: .word 1 +; RV32-NEXT: .word 2 +; RV32-NEXT: .word 0 +; RV32-NEXT: .word __emutls_t.external_y +; RV32-NOT: __emutls_v.external_x: +; RV32: .section .rodata, +; RV32-LABEL: __emutls_t.external_y: +; RV32-NEXT: .byte 7 +; RV32: .data +; RV32-NOT: .globl __emutls_v +; RV32: .p2align 2 +; RV32-LABEL: __emutls_v.internal_y: +; RV32-NEXT: .word 8 +; RV32-NEXT: .word 16 +; RV32-NEXT: .word 0 +; RV32-NEXT: .word __emutls_t.internal_y +; RV32: .section .rodata, +; RV32-LABEL: __emutls_t.internal_y: +; RV32-NEXT: .quad 9 + +; RV64: .data +; RV64: .globl __emutls_v.external_y +; RV64: .p2align 3 +; RV64-LABEL: __emutls_v.external_y: +; RV64-NEXT: .quad 1 +; RV64-NEXT: .quad 2 +; RV64-NEXT: .quad 0 +; RV64-NEXT: .quad __emutls_t.external_y +; RV64-NOT: __emutls_v.external_x: +; RV64: .section .rodata, +; RV64-LABEL: __emutls_t.external_y: +; RV64-NEXT: .byte 7 +; RV64: .data +; RV64-NOT: .globl __emutls_v +; RV64: .p2align 3 +; RV64-LABEL: __emutls_v.internal_y: +; RV64-NEXT: .quad 8 +; RV64-NEXT: .quad 16 +; RV64-NEXT: .quad 0 +; RV64-NEXT: .quad __emutls_t.internal_y +; RV64: .section .rodata, +; RV64-LABEL: __emutls_t.internal_y: +; RV64-NEXT: .quad 9