Skip to content

Commit ae8002c

Browse files
committedJul 31, 2018
[X86] Preserve more liveness information in emitStackProbeInline
This commit fixes two issues with the liveness information after the call: 1) The code always spills RCX and RDX if InProlog == true, which results in an use of undefined phys reg. 2) FinalReg, JoinReg, RoundedReg, SizeReg are not added as live-ins to the basic blocks that use them, therefore they are seen undefined. https://llvm.org/PR38376 Differential Revision: https://reviews.llvm.org/D50020 llvm-svn: 338400
1 parent 3823514 commit ae8002c

File tree

3 files changed

+61
-25
lines changed

3 files changed

+61
-25
lines changed
 

‎llvm/lib/Target/X86/X86FrameLowering.cpp

+37-18
Original file line numberDiff line numberDiff line change
@@ -608,23 +608,37 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
608608
int64_t RDXShadowSlot = 0;
609609

610610
// If inlining in the prolog, save RCX and RDX.
611-
// Future optimization: don't save or restore if not live in.
612611
if (InProlog) {
613612
// Compute the offsets. We need to account for things already
614613
// pushed onto the stack at this point: return address, frame
615614
// pointer (if used), and callee saves.
616615
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
617616
const int64_t CalleeSaveSize = X86FI->getCalleeSavedFrameSize();
618617
const bool HasFP = hasFP(MF);
619-
RCXShadowSlot = 8 + CalleeSaveSize + (HasFP ? 8 : 0);
620-
RDXShadowSlot = RCXShadowSlot + 8;
621-
// Emit the saves.
622-
addRegOffset(BuildMI(&MBB, DL, TII.get(X86::MOV64mr)), X86::RSP, false,
623-
RCXShadowSlot)
624-
.addReg(X86::RCX);
625-
addRegOffset(BuildMI(&MBB, DL, TII.get(X86::MOV64mr)), X86::RSP, false,
626-
RDXShadowSlot)
627-
.addReg(X86::RDX);
618+
619+
// Check if we need to spill RCX and/or RDX.
620+
// Here we assume that no earlier prologue instruction changes RCX and/or
621+
// RDX, so checking the block live-ins is enough.
622+
const bool IsRCXLiveIn = MBB.isLiveIn(X86::RCX);
623+
const bool IsRDXLiveIn = MBB.isLiveIn(X86::RDX);
624+
int64_t InitSlot = 8 + CalleeSaveSize + (HasFP ? 8 : 0);
625+
// Assign the initial slot to both registers, then change RDX's slot if both
626+
// need to be spilled.
627+
if (IsRCXLiveIn)
628+
RCXShadowSlot = InitSlot;
629+
if (IsRDXLiveIn)
630+
RDXShadowSlot = InitSlot;
631+
if (IsRDXLiveIn && IsRCXLiveIn)
632+
RDXShadowSlot += 8;
633+
// Emit the saves if needed.
634+
if (IsRCXLiveIn)
635+
addRegOffset(BuildMI(&MBB, DL, TII.get(X86::MOV64mr)), X86::RSP, false,
636+
RCXShadowSlot)
637+
.addReg(X86::RCX);
638+
if (IsRDXLiveIn)
639+
addRegOffset(BuildMI(&MBB, DL, TII.get(X86::MOV64mr)), X86::RSP, false,
640+
RDXShadowSlot)
641+
.addReg(X86::RDX);
628642
} else {
629643
// Not in the prolog. Copy RAX to a virtual reg.
630644
BuildMI(&MBB, DL, TII.get(X86::MOV64rr), SizeReg).addReg(X86::RAX);
@@ -661,6 +675,7 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
661675
BuildMI(&MBB, DL, TII.get(X86::JAE_1)).addMBB(ContinueMBB);
662676

663677
// Add code to roundMBB to round the final stack pointer to a page boundary.
678+
RoundMBB->addLiveIn(FinalReg);
664679
BuildMI(RoundMBB, DL, TII.get(X86::AND64ri32), RoundedReg)
665680
.addReg(FinalReg)
666681
.addImm(PageMask);
@@ -677,6 +692,7 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
677692
.addMBB(LoopMBB);
678693
}
679694

695+
LoopMBB->addLiveIn(JoinReg);
680696
addRegOffset(BuildMI(LoopMBB, DL, TII.get(X86::LEA64r), ProbeReg), JoinReg,
681697
false, -PageSize);
682698

@@ -688,6 +704,8 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
688704
.addImm(0)
689705
.addReg(0)
690706
.addImm(0);
707+
708+
LoopMBB->addLiveIn(RoundedReg);
691709
BuildMI(LoopMBB, DL, TII.get(X86::CMP64rr))
692710
.addReg(RoundedReg)
693711
.addReg(ProbeReg);
@@ -697,16 +715,19 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
697715

698716
// If in prolog, restore RDX and RCX.
699717
if (InProlog) {
700-
addRegOffset(BuildMI(*ContinueMBB, ContinueMBBI, DL, TII.get(X86::MOV64rm),
701-
X86::RCX),
702-
X86::RSP, false, RCXShadowSlot);
703-
addRegOffset(BuildMI(*ContinueMBB, ContinueMBBI, DL, TII.get(X86::MOV64rm),
704-
X86::RDX),
705-
X86::RSP, false, RDXShadowSlot);
718+
if (RCXShadowSlot) // It means we spilled RCX in the prologue.
719+
addRegOffset(BuildMI(*ContinueMBB, ContinueMBBI, DL,
720+
TII.get(X86::MOV64rm), X86::RCX),
721+
X86::RSP, false, RCXShadowSlot);
722+
if (RDXShadowSlot) // It means we spilled RDX in the prologue.
723+
addRegOffset(BuildMI(*ContinueMBB, ContinueMBBI, DL,
724+
TII.get(X86::MOV64rm), X86::RDX),
725+
X86::RSP, false, RDXShadowSlot);
706726
}
707727

708728
// Now that the probing is done, add code to continueMBB to update
709729
// the stack pointer for real.
730+
ContinueMBB->addLiveIn(SizeReg);
710731
BuildMI(*ContinueMBB, ContinueMBBI, DL, TII.get(X86::SUB64rr), X86::RSP)
711732
.addReg(X86::RSP)
712733
.addReg(SizeReg);
@@ -734,8 +755,6 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
734755
CMBBI->setFlag(MachineInstr::FrameSetup);
735756
}
736757
}
737-
738-
// Possible TODO: physreg liveness for InProlog case.
739758
}
740759

741760
void X86FrameLowering::emitStackProbeCall(MachineFunction &MF,

‎llvm/test/CodeGen/X86/win_coreclr_chkstk.ll

-7
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ entry:
1010
; WIN_X64-LABEL:main4k:
1111
; WIN_X64: # %bb.0:
1212
; WIN_X64: movl $4096, %eax
13-
; WIN_X64: movq %rcx, 8(%rsp)
14-
; WIN_X64: movq %rdx, 16(%rsp)
1513
; WIN_X64: xorq %rcx, %rcx
1614
; WIN_X64: movq %rsp, %rdx
1715
; WIN_X64: subq %rax, %rdx
@@ -27,8 +25,6 @@ entry:
2725
; WIN_X64: cmpq %rcx, %rdx
2826
; WIN_X64: jne .LBB0_2
2927
; WIN_X64:.LBB0_3:
30-
; WIN_X64: movq 8(%rsp), %rcx
31-
; WIN_X64: movq 16(%rsp), %rdx
3228
; WIN_X64: subq %rax, %rsp
3329
; WIN_X64: xorl %eax, %eax
3430
; WIN_X64: addq $4096, %rsp
@@ -45,7 +41,6 @@ entry:
4541
define i32 @main4k_frame() nounwind "no-frame-pointer-elim"="true" {
4642
entry:
4743
; WIN_X64-LABEL:main4k_frame:
48-
; WIN_X64: movq %rcx, 16(%rsp)
4944
; WIN_X64: movq %gs:16, %rcx
5045
; LINUX-LABEL:main4k_frame:
5146
; LINUX-NOT: movq %gs:16, %rcx
@@ -58,7 +53,6 @@ entry:
5853
; Case with INT args
5954
define i32 @main4k_intargs(i32 %x, i32 %y) nounwind {
6055
entry:
61-
; WIN_X64: movq %rcx, 8(%rsp)
6256
; WIN_X64: movq %gs:16, %rcx
6357
; LINUX-NOT: movq %gs:16, %rcx
6458
; LINUX: retq
@@ -71,7 +65,6 @@ entry:
7165
; Case with FP regs
7266
define i32 @main4k_fpargs(double %x, double %y) nounwind {
7367
entry:
74-
; WIN_X64: movq %rcx, 8(%rsp)
7568
; WIN_X64: movq %gs:16, %rcx
7669
; LINUX-NOT: movq %gs:16, %rcx
7770
; LINUX: retq
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# RUN: llc -verify-machineinstrs %s -run-pass prologepilog -mtriple=x86_64-pc-win32-coreclr -o - | FileCheck %s
2+
...
3+
---
4+
name: main4k
5+
# CHECK-LABEL: name: main4k
6+
7+
alignment: 4
8+
tracksRegLiveness: true
9+
frameInfo:
10+
maxAlignment: 8
11+
stack:
12+
- { id: 0, size: 4096, alignment: 1, stack-id: 0 }
13+
body: |
14+
bb.0.entry:
15+
$eax = IMPLICIT_DEF
16+
RET 0, killed $eax
17+
18+
; CHECK: bb.1.entry:
19+
; CHECK: liveins: $rdx
20+
; CHECK: bb.2.entry:
21+
; CHECK: liveins: $rcx, $rdx
22+
; CHECK: bb.3.entry:
23+
; CHECK: liveins: $rax
24+
...

0 commit comments

Comments
 (0)
Please sign in to comment.