]> granicus.if.org Git - llvm/commitdiff
[X86] Don't clobber reserved registers with stack adjustments
authorBjorn Steinbrink <bsteinbr@gmail.com>
Tue, 7 Nov 2017 08:50:21 +0000 (08:50 +0000)
committerBjorn Steinbrink <bsteinbr@gmail.com>
Tue, 7 Nov 2017 08:50:21 +0000 (08:50 +0000)
Summary:
Calls using invoke in funclet based functions are assumed to clobber
all registers, which causes the stack adjustment using pops to consider
all registers not defined by the call to be undefined, which can
unfortunately include the base pointer, if one is needed.

To prevent this (and possibly other hazards), skip reserved registers
when looking for candidate registers.

This fixes issue #45034 in the Rust compiler.

Reviewers: mkuper

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D39636

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317551 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FrameLowering.cpp
test/CodeGen/X86/pop-stack-cleanup-msvc.ll [new file with mode: 0644]

index 988f2967401b02de042589bb246b40da194f766e..c7af0ae43d2abadd8bbe53a94c16c5b7e1d5db02 100644 (file)
@@ -2577,6 +2577,7 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB,
   unsigned Regs[2];
   unsigned FoundRegs = 0;
 
+  auto &MRI = MBB.getParent()->getRegInfo();
   auto RegMask = Prev->getOperand(1);
 
   auto &RegClass =
@@ -2590,6 +2591,10 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB,
     if (!RegMask.clobbersPhysReg(Candidate))
       continue;
 
+    // Don't clobber reserved registers
+    if (MRI.isReserved(Candidate))
+      continue;
+
     bool IsDef = false;
     for (const MachineOperand &MO : Prev->implicit_operands()) {
       if (MO.isReg() && MO.isDef() &&
diff --git a/test/CodeGen/X86/pop-stack-cleanup-msvc.ll b/test/CodeGen/X86/pop-stack-cleanup-msvc.ll
new file mode 100644 (file)
index 0000000..6330d3d
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: llc < %s | FileCheck %s
+
+target triple = "i686--windows-msvc"
+
+declare { i8*, i32 } @param2_ret2(i32, i32)
+declare i32 @__CxxFrameHandler3(...)
+
+
+define void @test_reserved_regs() minsize optsize personality i32 (...)* @__CxxFrameHandler3 {
+; CHECK-LABEL: test_reserved_regs:
+; CHECK: calll _param2_ret2
+; CHECK-NEXT: popl %ecx
+; CHECK-NEXT: popl %edi
+start:
+  %s = alloca i64
+  store i64 4, i64* %s
+  %0 = invoke { i8*, i32 } @param2_ret2(i32 0, i32 1)
+          to label %out unwind label %cleanup
+
+out:
+  ret void
+
+cleanup:
+  %cp = cleanuppad within none []
+  cleanupret from %cp unwind to caller
+}