[ARM CodeGen] @llvm.debugtrap call may be removed when restoring callee saved registers
authorOleg Ranevskyy <oranevskyy@accesssoftek.com>
Fri, 23 Oct 2015 17:17:59 +0000 (17:17 +0000)
committerOleg Ranevskyy <oranevskyy@accesssoftek.com>
Fri, 23 Oct 2015 17:17:59 +0000 (17:17 +0000)
Summary:
When ARMFrameLowering::emitPopInst generates a "pop" instruction to restore the callee saved registers, it checks if the LR register is among them. If so, the function may decide to remove the basic block's terminator and replace it with a "pop" to the PC register instead of LR.

This leads to a problem when the block's terminator is preceded by a "llvm.debugtrap" call. The MI iterator points to the trap in such a case, which is also a terminator. If the function decides to restore LR to PC, it erroneously removes the trap.

Reviewers: asl, rengolin

Subscribers: aemerson, jfb, rengolin, dschuff, llvm-commits

Differential Revision: http://reviews.llvm.org/D13672

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

lib/Target/ARM/ARMFrameLowering.cpp
test/CodeGen/ARM/debugtrap.ll [new file with mode: 0644]

index d6542637c3b7580d0e0e209205912730057ebd7d..28e866e8cb3f7e402dcaba27fd138fbd9b9d16e1 100644 (file)
@@ -968,12 +968,16 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
   DebugLoc DL;
   bool isTailCall = false;
   bool isInterrupt = false;
+  bool isTrap = false;
   if (MBB.end() != MI) {
     DL = MI->getDebugLoc();
     unsigned RetOpcode = MI->getOpcode();
     isTailCall = (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri);
     isInterrupt =
         RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
+    isTrap =
+        RetOpcode == ARM::TRAP || RetOpcode == ARM::TRAPNaCl ||
+        RetOpcode == ARM::tTRAP;
   }
 
   SmallVector<unsigned, 4> Regs;
@@ -990,7 +994,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
         continue;
 
       if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
-          STI.hasV5TOps()) {
+          !isTrap && STI.hasV5TOps()) {
         if (MBB.succ_empty()) {
           Reg = ARM::PC;
           DeleteRet = true;
diff --git a/test/CodeGen/ARM/debugtrap.ll b/test/CodeGen/ARM/debugtrap.ll
new file mode 100644 (file)
index 0000000..9ce7393
--- /dev/null
@@ -0,0 +1,17 @@
+; This test ensures the @llvm.debugtrap() call is not removed when generating\r
+; the 'pop' instruction to restore the callee saved registers on ARM.\r
+\r
+; RUN: llc < %s -mtriple=armv7 -O0 -filetype=asm | FileCheck %s \r
+\r
+declare void @llvm.debugtrap() nounwind\r
+declare void @foo() nounwind\r
+\r
+define void @test() nounwind {\r
+entry:\r
+  ; CHECK: bl foo\r
+  ; CHECK-NEXT: pop\r
+  ; CHECK-NEXT: trap\r
+  call void @foo()\r
+  call void @llvm.debugtrap()\r
+  ret void\r
+}\r