[llvm] r354756 - [X86] Fix tls variable lowering issue with large code model

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 26 02:20:31 PST 2019


Merged to release_80 in r354857.

On Sun, Feb 24, 2019 at 8:32 PM Craig Topper via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: ctopper
> Date: Sun Feb 24 11:33:37 2019
> New Revision: 354756
>
> URL: http://llvm.org/viewvc/llvm-project?rev=354756&view=rev
> Log:
> [X86] Fix tls variable lowering issue with large code model
>
> Summary:
> The problem here is the lowering for tls variable. Below is the DAG for the code.
> SelectionDAG has 11 nodes:
>
> t0: ch = EntryToken
>       t8: i64,ch = load<(load 8 from `i8 addrspace(257)* null`, addrspace 257)> t0, Constant:i64<0>, undef:i64
>         t10: i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i32* @x> 0 [TF=10]
>       t11: i64,ch = load<(load 8 from got)> t0, t10, undef:i64
>     t12: i64 = add t8, t11
>   t4: i32,ch = load<(dereferenceable load 4 from @x)> t0, t12, undef:i64
> t6: ch = CopyToReg t0, Register:i32 %0, t4
> And when mcmodel is large, below instruction can NOT be folded.
>
>   t10: i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i32* @x> 0 [TF=10]
> t11: i64,ch = load<(load 8 from got)> t0, t10, undef:i64
> So "t11: i64,ch = load<(load 8 from got)> t0, t10, undef:i64" is lowered to " Morphed node: t11: i64,ch = MOV64rm<Mem:(load 8 from got)> t10, TargetConstant:i8<1>, Register:i64 $noreg, TargetConstant:i32<0>, Register:i32 $noreg, t0"
>
> When llvm start to lower "t10: i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i32* @x> 0 [TF=10]", it fails.
>
> The patch is to fold the load and X86ISD::WrapperRIP.
>
> Fixes PR26906
>
> Patch by LuoYuanke
>
> Reviewers: craig.topper, rnk, annita.zhang, wxiao3
>
> Reviewed By: rnk
>
> Subscribers: llvm-commits
>
> Tags: #llvm
>
> Differential Revision: https://reviews.llvm.org/D58336
>
> Modified:
>     llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
>     llvm/trunk/test/CodeGen/X86/code-model-elf.ll
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=354756&r1=354755&r2=354756&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Sun Feb 24 11:33:37 2019
> @@ -1137,15 +1137,23 @@ bool X86DAGToDAGISel::matchWrapper(SDVal
>    if (AM.hasSymbolicDisplacement())
>      return true;
>
> +  bool IsRIPRelTLS = false;
>    bool IsRIPRel = N.getOpcode() == X86ISD::WrapperRIP;
> +  if (IsRIPRel) {
> +    SDValue Val = N.getOperand(0);
> +    if (Val.getOpcode() == ISD::TargetGlobalTLSAddress)
> +      IsRIPRelTLS = true;
> +  }
>
> -  // We can't use an addressing mode in the 64-bit large code model. In the
> -  // medium code model, we use can use an mode when RIP wrappers are present.
> -  // That signifies access to globals that are known to be "near", such as the
> -  // GOT itself.
> +  // We can't use an addressing mode in the 64-bit large code model.
> +  // Global TLS addressing is an exception. In the medium code model,
> +  // we use can use a mode when RIP wrappers are present.
> +  // That signifies access to globals that are known to be "near",
> +  // such as the GOT itself.
>    CodeModel::Model M = TM.getCodeModel();
>    if (Subtarget->is64Bit() &&
> -      (M == CodeModel::Large || (M == CodeModel::Medium && !IsRIPRel)))
> +      ((M == CodeModel::Large && !IsRIPRelTLS) ||
> +       (M == CodeModel::Medium && !IsRIPRel)))
>      return true;
>
>    // Base and index reg must be 0 in order to use %rip as base.
>
> Modified: llvm/trunk/test/CodeGen/X86/code-model-elf.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/code-model-elf.ll?rev=354756&r1=354755&r2=354756&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/code-model-elf.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/code-model-elf.ll Sun Feb 24 11:33:37 2019
> @@ -37,6 +37,8 @@ target triple = "x86_64--linux"
>  @global_data = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16
>  @static_data = internal global [10 x i32] zeroinitializer, align 16
>  @extern_data = external global [10 x i32], align 16
> + at thread_data = external thread_local global i32, align 4
> +
>
>  define dso_local i32* @lea_static_data() #0 {
>  ; SMALL-STATIC-LABEL: lea_static_data:
> @@ -373,6 +375,70 @@ define dso_local void ()* @lea_extern_fn
>    ret void ()* @extern_fn
>  }
>
> +; FIXME: The result is same for small, medium and large model, because we
> +; specify pie option in the test case. And the type of tls is initial exec tls.
> +; For pic code. The large model code for pic tls should be emitted as below.
> +
> +; .L3:
> +; leaq .L3(%rip), %rbx
> +; movabsq      $_GLOBAL_OFFSET_TABLE_-.L3, %r11
> +; addq %r11, %rbx
> +; leaq thread_data at TLSGD(%rip), %rdi
> +; movabsq      $__tls_get_addr at PLTOFF, %rax
> +; addq %rbx, %rax
> +; call *%rax
> +; movl (%rax), %eax
> +
> +; The medium and small model code for pic tls should be emitted as below.
> +; data16
> +; leaq thread_data at TLSGD(%rip), %rdi
> +; data16
> +; data16
> +; rex64
> +; callq        __tls_get_addr at PLT
> +; movl (%rax), %eax
> +
> +define dso_local i32 @load_thread_data() #0 {
> +; SMALL-STATIC-LABEL: load_thread_data:
> +; SMALL-STATIC:       # %bb.0:
> +; SMALL-STATIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; SMALL-STATIC-NEXT:    movl    %fs:(%rax), %eax
> +; SMALL-STATIC-NEXT:    retq
> +;
> +; MEDIUM-STATIC-LABEL: load_thread_data:
> +; MEDIUM-STATIC:       # %bb.0:
> +; MEDIUM-STATIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; MEDIUM-STATIC-NEXT:    movl    %fs:(%rax), %eax
> +; MEDIUM-STATIC-NEXT:    retq
> +;
> +; LARGE-STATIC-LABEL: load_thread_data:
> +; LARGE-STATIC:       # %bb.0:
> +; LARGE-STATIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; LARGE-STATIC-NEXT:    movl    %fs:(%rax), %eax
> +; LARGE-STATIC-NEXT:    retq
> +;
> +; SMALL-PIC-LABEL: load_thread_data:
> +; SMALL-PIC:       # %bb.0:
> +; SMALL-PIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; SMALL-PIC-NEXT:    movl    %fs:(%rax), %eax
> +; SMALL-PIC-NEXT:    retq
> +;
> +; MEDIUM-PIC-LABEL: load_thread_data:
> +; MEDIUM-PIC:       # %bb.0:
> +; MEDIUM-PIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; MEDIUM-PIC-NEXT:    movl    %fs:(%rax), %eax
> +; MEDIUM-PIC-NEXT:    retq
> +;
> +; LARGE-PIC-LABEL: load_thread_data:
> +; LARGE-PIC:       # %bb.0:
> +; LARGE-PIC-NEXT:    movq    thread_data at GOTTPOFF(%rip), %rax
> +; LARGE-PIC-NEXT:    movl    %fs:(%rax), %eax
> +; LARGE-PIC-NEXT:    retq
> +;
> +  %1 = load i32, i32* @thread_data, align 4
> +  ret i32 %1
> +}
> +
>  attributes #0 = { noinline nounwind uwtable }
>
>  !llvm.module.flags = !{!0, !1, !2}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list