Skip to content

Commit e745d6d

Browse files
committed
Merging r354756:
------------------------------------------------------------------------ r354756 | ctopper | 2019-02-24 20:33:37 +0100 (Sun, 24 Feb 2019) | 36 lines [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 ------------------------------------------------------------------------ llvm-svn: 354857
1 parent ee57e9e commit e745d6d

File tree

2 files changed

+79
-5
lines changed

2 files changed

+79
-5
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,15 +1138,23 @@ bool X86DAGToDAGISel::matchWrapper(SDValue N, X86ISelAddressMode &AM) {
11381138
if (AM.hasSymbolicDisplacement())
11391139
return true;
11401140

1141+
bool IsRIPRelTLS = false;
11411142
bool IsRIPRel = N.getOpcode() == X86ISD::WrapperRIP;
1143+
if (IsRIPRel) {
1144+
SDValue Val = N.getOperand(0);
1145+
if (Val.getOpcode() == ISD::TargetGlobalTLSAddress)
1146+
IsRIPRelTLS = true;
1147+
}
11421148

1143-
// We can't use an addressing mode in the 64-bit large code model. In the
1144-
// medium code model, we use can use an mode when RIP wrappers are present.
1145-
// That signifies access to globals that are known to be "near", such as the
1146-
// GOT itself.
1149+
// We can't use an addressing mode in the 64-bit large code model.
1150+
// Global TLS addressing is an exception. In the medium code model,
1151+
// we use can use a mode when RIP wrappers are present.
1152+
// That signifies access to globals that are known to be "near",
1153+
// such as the GOT itself.
11471154
CodeModel::Model M = TM.getCodeModel();
11481155
if (Subtarget->is64Bit() &&
1149-
(M == CodeModel::Large || (M == CodeModel::Medium && !IsRIPRel)))
1156+
((M == CodeModel::Large && !IsRIPRelTLS) ||
1157+
(M == CodeModel::Medium && !IsRIPRel)))
11501158
return true;
11511159

11521160
// Base and index reg must be 0 in order to use %rip as base.

llvm/test/CodeGen/X86/code-model-elf.ll

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ target triple = "x86_64--linux"
3737
@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
3838
@static_data = internal global [10 x i32] zeroinitializer, align 16
3939
@extern_data = external global [10 x i32], align 16
40+
@thread_data = external thread_local global i32, align 4
41+
4042

4143
define dso_local i32* @lea_static_data() #0 {
4244
; SMALL-STATIC-LABEL: lea_static_data:
@@ -373,6 +375,70 @@ define dso_local void ()* @lea_extern_fn() #0 {
373375
ret void ()* @extern_fn
374376
}
375377

378+
; FIXME: The result is same for small, medium and large model, because we
379+
; specify pie option in the test case. And the type of tls is initial exec tls.
380+
; For pic code. The large model code for pic tls should be emitted as below.
381+
382+
; .L3:
383+
; leaq .L3(%rip), %rbx
384+
; movabsq $_GLOBAL_OFFSET_TABLE_-.L3, %r11
385+
; addq %r11, %rbx
386+
; leaq thread_data@TLSGD(%rip), %rdi
387+
; movabsq $__tls_get_addr@PLTOFF, %rax
388+
; addq %rbx, %rax
389+
; call *%rax
390+
; movl (%rax), %eax
391+
392+
; The medium and small model code for pic tls should be emitted as below.
393+
; data16
394+
; leaq thread_data@TLSGD(%rip), %rdi
395+
; data16
396+
; data16
397+
; rex64
398+
; callq __tls_get_addr@PLT
399+
; movl (%rax), %eax
400+
401+
define dso_local i32 @load_thread_data() #0 {
402+
; SMALL-STATIC-LABEL: load_thread_data:
403+
; SMALL-STATIC: # %bb.0:
404+
; SMALL-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
405+
; SMALL-STATIC-NEXT: movl %fs:(%rax), %eax
406+
; SMALL-STATIC-NEXT: retq
407+
;
408+
; MEDIUM-STATIC-LABEL: load_thread_data:
409+
; MEDIUM-STATIC: # %bb.0:
410+
; MEDIUM-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
411+
; MEDIUM-STATIC-NEXT: movl %fs:(%rax), %eax
412+
; MEDIUM-STATIC-NEXT: retq
413+
;
414+
; LARGE-STATIC-LABEL: load_thread_data:
415+
; LARGE-STATIC: # %bb.0:
416+
; LARGE-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
417+
; LARGE-STATIC-NEXT: movl %fs:(%rax), %eax
418+
; LARGE-STATIC-NEXT: retq
419+
;
420+
; SMALL-PIC-LABEL: load_thread_data:
421+
; SMALL-PIC: # %bb.0:
422+
; SMALL-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
423+
; SMALL-PIC-NEXT: movl %fs:(%rax), %eax
424+
; SMALL-PIC-NEXT: retq
425+
;
426+
; MEDIUM-PIC-LABEL: load_thread_data:
427+
; MEDIUM-PIC: # %bb.0:
428+
; MEDIUM-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
429+
; MEDIUM-PIC-NEXT: movl %fs:(%rax), %eax
430+
; MEDIUM-PIC-NEXT: retq
431+
;
432+
; LARGE-PIC-LABEL: load_thread_data:
433+
; LARGE-PIC: # %bb.0:
434+
; LARGE-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax
435+
; LARGE-PIC-NEXT: movl %fs:(%rax), %eax
436+
; LARGE-PIC-NEXT: retq
437+
;
438+
%1 = load i32, i32* @thread_data, align 4
439+
ret i32 %1
440+
}
441+
376442
attributes #0 = { noinline nounwind uwtable }
377443

378444
!llvm.module.flags = !{!0, !1, !2}

0 commit comments

Comments
 (0)