Skip to content

Commit 1bd72c4

Browse files
committed
[X86] Avoid generating nested CALLSEQ for TLS pointer function arguments
When a pointer to thread-local storage is passed in a function call, ISel first lowers the call and wraps the resulting code in CALLSEQ markers. Afterwards, to compute the pointer to TLS, a call to retrieve the TLS base address is generated and then wrapped in a set of CALLSEQ markers. If the latter call is inserted into the call sequence of the former call, this leads to nested call frames, which are illegal and lead to errors in the machine verifier. This patch avoids surrounding the call to compute the TLS base address in CALLSEQ markers if it is already surrounded by such markers. It relies on zero-sized call frames being represented in the call frame size info stored in the MachineBBs. Fixes #45574 and #98042.
1 parent 9cad0b2 commit 1bd72c4

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

llvm/lib/CodeGen/FinalizeISel.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ static std::pair<bool, bool> runImpl(MachineFunction &MF) {
4747
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
4848
const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
4949

50+
// Pseudo-Lowering might require the sizes of call frames, so compute them
51+
// (lazily). The MachineFrameSizeInfo registers itself in MF's
52+
// MachineFrameInfo for the SizeInfo's lifetime and does not need to be passed
53+
// explicitly.
54+
const MachineFrameSizeInfo MFSI(MF);
55+
5056
// Iterate through each instruction in the function, looking for pseudos.
5157
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
5258
MachineBasicBlock *MBB = &*I;

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35588,6 +35588,15 @@ X86TargetLowering::EmitLoweredTLSAddr(MachineInstr &MI,
3558835588
// inside MC, therefore without the two markers shrink-wrapping
3558935589
// may push the prologue/epilogue pass them.
3559035590
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
35591+
35592+
// Do not introduce CALLSEQ markers if we are already in a call sequence.
35593+
// Nested call sequences are not allowed and cause errors in the machine
35594+
// verifier.
35595+
MachineFrameSizeInfo *MFSI = MI.getMF()->getFrameInfo().getSizeInfo();
35596+
assert(MFSI && "Call frame size information needs to be available!");
35597+
if (MFSI->getCallFrameSizeAt(MI).has_value())
35598+
return BB;
35599+
3559135600
const MIMetadata MIMD(MI);
3559235601
MachineFunction &MF = *BB->getParent();
3559335602

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=x86_64 -verify-machineinstrs -relocation-model=pic < %s | FileCheck %s
3+
4+
; Passing a pointer to thread-local storage to a function can be problematic
5+
; since computing such addresses requires a function call that is introduced
6+
; very late in instruction selection. We need to ensure that we don't introduce
7+
; nested call sequence markers if this function call happens in a call sequence.
8+
9+
@TLS = internal thread_local global i64 zeroinitializer, align 8
10+
declare void @bar(ptr)
11+
define internal void @foo() {
12+
; CHECK-LABEL: foo:
13+
; CHECK: # %bb.0:
14+
; CHECK-NEXT: pushq %rbx
15+
; CHECK-NEXT: .cfi_def_cfa_offset 16
16+
; CHECK-NEXT: .cfi_offset %rbx, -16
17+
; CHECK-NEXT: leaq TLS@TLSLD(%rip), %rdi
18+
; CHECK-NEXT: callq __tls_get_addr@PLT
19+
; CHECK-NEXT: leaq TLS@DTPOFF(%rax), %rbx
20+
; CHECK-NEXT: movq %rbx, %rdi
21+
; CHECK-NEXT: callq bar@PLT
22+
; CHECK-NEXT: movq %rbx, %rdi
23+
; CHECK-NEXT: callq bar@PLT
24+
; CHECK-NEXT: popq %rbx
25+
; CHECK-NEXT: .cfi_def_cfa_offset 8
26+
; CHECK-NEXT: retq
27+
call void @bar(ptr @TLS)
28+
call void @bar(ptr @TLS)
29+
ret void
30+
}

0 commit comments

Comments
 (0)