<div dir="ltr">This patch breaks UBSAN tests on Android<div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-android/builds/9353/steps/run%20lit%20tests%20%5Barm%2Faosp_marlin-userdebug%2FOPR4.170623.016%5D/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-android/builds/9353/steps/run%20lit%20tests%20%5Barm%2Faosp_marlin-userdebug%2FOPR4.170623.016%5D/logs/stdio</a><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Apr 5, 2018 at 7:29 AM Tim Northover via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tnorthover<br>
Date: Thu Apr  5 07:26:06 2018<br>
New Revision: 329287<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=329287&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=329287&view=rev</a><br>
Log:<br>
ARM: Do not spill CSR to stack on entry to noreturn functions<br>
<br>
A noreturn nounwind function can be expected to never return in any way, and by<br>
never returning it will also never have to restore any callee-saved registers<br>
for its caller. This makes it possible to skip spills of those registers during<br>
function entry, saving some stack space and time in the process. This is rather<br>
useful for embedded targets with limited stack space.<br>
<br>
Should fix PR9970.<br>
<br>
Patch by myeisha (pmb).<br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir<br>
Modified:<br>
    llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h<br>
    llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp<br>
    llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp<br>
    llvm/trunk/lib/Target/ARM/ARMFrameLowering.h<br>
    llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll<br>
    llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll<br>
    llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll<br>
    llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll<br>
    llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll<br>
    llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/TargetFrameLowering.h Thu Apr  5 07:26:06 2018<br>
@@ -158,6 +158,10 @@ public:<br>
     return false;<br>
   }<br>
<br>
+  /// Returns true if the target can safely skip saving callee-saved registers<br>
+  /// for noreturn nounwind functions.<br>
+  virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const;<br>
+<br>
   /// emitProlog/emitEpilog - These methods insert prolog and epilog code into<br>
   /// the function.<br>
   virtual void emitPrologue(MachineFunction &MF,<br>
<br>
Modified: llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp Thu Apr  5 07:26:06 2018<br>
@@ -36,6 +36,12 @@ bool TargetFrameLowering::noFramePointer<br>
   return Attr.getValueAsString() == "true";<br>
 }<br>
<br>
+bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {<br>
+  assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&<br>
+      MF.getFunction().hasFnAttribute(Attribute::NoUnwind));<br>
+  return false;<br>
+}<br>
+<br>
 /// Returns the displacement from the frame register to the stack<br>
 /// frame of the specified index, along with the frame register used<br>
 /// (in output arg FrameReg). This is the default implementation which<br>
@@ -85,6 +91,18 @@ void TargetFrameLowering::determineCalle<br>
   if (MF.getFunction().hasFnAttribute(Attribute::Naked))<br>
     return;<br>
<br>
+  // Noreturn+nounwind functions never restore CSR, so no saves are needed.<br>
+  // Purely noreturn functions may still return through throws, so those must<br>
+  // save CSR for caller exception handlers.<br>
+  //<br>
+  // If the function uses longjmp to break out of its current path of<br>
+  // execution we do not need the CSR spills either: setjmp stores all CSRs<br>
+  // it was called with into the jmp_buf, which longjmp then restores.<br>
+  if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&<br>
+        MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&<br>
+        enableCalleeSaveSkip(MF))<br>
+    return;<br>
+<br>
   // Functions which call __builtin_unwind_init get all their registers saved.<br>
   bool CallsUnwindInit = MF.callsUnwindInit();<br>
   const MachineRegisterInfo &MRI = MF.getRegInfo();<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMFrameLowering.cpp Thu Apr  5 07:26:06 2018<br>
@@ -87,6 +87,17 @@ bool ARMFrameLowering::noFramePointerEli<br>
          MF.getSubtarget<ARMSubtarget>().useFastISel();<br>
 }<br>
<br>
+/// Returns true if the target can safely skip saving callee-saved registers<br>
+/// for noreturn nounwind functions.<br>
+bool ARMFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {<br>
+  assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&<br>
+      MF.getFunction().hasFnAttribute(Attribute::NoUnwind));<br>
+<br>
+  // Frame pointer and link register are not treated as normal CSR, thus we<br>
+  // can always skip CSR saves for nonreturning functions.<br>
+  return true;<br>
+}<br>
+<br>
 /// hasFP - Return true if the specified function should have a dedicated frame<br>
 /// pointer register.  This is true if the function has variable sized allocas<br>
 /// or if frame pointer elimination is disabled.<br>
<br>
Modified: llvm/trunk/lib/Target/ARM/ARMFrameLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFrameLowering.h?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFrameLowering.h?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/ARM/ARMFrameLowering.h (original)<br>
+++ llvm/trunk/lib/Target/ARM/ARMFrameLowering.h Thu Apr  5 07:26:06 2018<br>
@@ -44,6 +44,8 @@ public:<br>
<br>
   bool noFramePointerElim(const MachineFunction &MF) const override;<br>
<br>
+  bool enableCalleeSaveSkip(const MachineFunction &MF) const override;<br>
+<br>
   bool hasFP(const MachineFunction &MF) const override;<br>
   bool hasReservedCallFrame(const MachineFunction &MF) const override;<br>
   bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override;<br>
<br>
Modified: llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll (original)<br>
+++ llvm/trunk/test/CodeGen/AArch64/arm64-shrink-wrapping.ll Thu Apr  5 07:26:06 2018<br>
@@ -281,7 +281,7 @@ declare void @somethingElse(...)<br>
 ; Shift second argument by one and store into returned register.<br>
 ; ENABLE: lsl w0, w1, #1<br>
 ; ENABLE: ret<br>
-define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {<br>
+define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {<br>
 entry:<br>
   %tobool = icmp eq i32 %cond, 0<br>
   br i1 %tobool, label %if.else, label %if.then<br>
@@ -355,7 +355,7 @@ entry:<br>
 ; CHECK-NEXT: lsl w0, w1, #1<br>
 ; DISABLE-NEXT: add sp, sp, #16<br>
 ; CHECK-NEXT: ret<br>
-define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 {<br>
+define i32 @variadicFunc(i32 %cond, i32 %count, ...) nounwind {<br>
 entry:<br>
   %ap = alloca i8*, align 8<br>
   %tobool = icmp eq i32 %cond, 0<br>
<br>
Modified: llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll (original)<br>
+++ llvm/trunk/test/CodeGen/ARM/arm-shrink-wrapping.ll Thu Apr  5 07:26:06 2018<br>
@@ -327,7 +327,7 @@ declare void @somethingElse(...)<br>
 ; DISABLE-NEXT: pop {r4, r7, pc}<br>
 ;<br>
 ; ENABLE-NEXT: bx lr<br>
-define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" #0 {<br>
+define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) "no-frame-pointer-elim"="true" nounwind {<br>
 entry:<br>
   %tobool = icmp eq i32 %cond, 0<br>
   br i1 %tobool, label %if.else, label %if.then<br>
<br>
Added: llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir?rev=329287&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir?rev=329287&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir (added)<br>
+++ llvm/trunk/test/CodeGen/ARM/noreturn-csr-skip.mir Thu Apr  5 07:26:06 2018<br>
@@ -0,0 +1,51 @@<br>
+# RUN: llc -mtriple thumbv7m-none-eabi -run-pass prologepilog %s -o - | FileCheck %s<br>
+<br>
+--- |<br>
+  define void @throw() noreturn { unreachable }<br>
+<br>
+  define void @ret() nounwind { ret void }<br>
+<br>
+  define void @noret() noreturn nounwind {<br>
+  start:<br>
+    %p = alloca i32<br>
+    store i32 42, i32* %p<br>
+    unreachable<br>
+  }<br>
+...<br>
+---<br>
+# This function may return by exception. Check that $r4 is saved and restored.<br>
+# CHECK-LABEL: name: throw<br>
+# CHECK: killed $r4<br>
+# CHECK: def $r4<br>
+name: throw<br>
+body: |<br>
+  bb.0:<br>
+    $r4 = IMPLICIT_DEF<br>
+    tBX_RET 14, $noreg<br>
+---<br>
+---<br>
+# This function may return. Check that $r4 is saved and restored.<br>
+# CHECK-LABEL: name: ret<br>
+# CHECK: killed $r4<br>
+# CHECK: def $r4<br>
+name: ret<br>
+body: |<br>
+  bb.0:<br>
+    $r4 = IMPLICIT_DEF<br>
+    tBX_RET 14, $noreg<br>
+---<br>
+---<br>
+# This function does not return. We need not save any CSR, but<br>
+# other stack adjustments in the prologue are still necessary.<br>
+# CHECK-LABEL: name: noret<br>
+# CHECK-NOT: killed $r4<br>
+# CHECK-NOT: def $r4<br>
+# CHECK: $sp = frame-setup<br>
+name: noret<br>
+stack:<br>
+  - { id: 0, name: p, offset: 0, size: 4, alignment: 4, local-offset: -4 }<br>
+body: |<br>
+  bb.0:<br>
+    $r4 = IMPLICIT_DEF<br>
+    tBX_RET 14, $noreg<br>
+---<br>
<br>
Modified: llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll (original)<br>
+++ llvm/trunk/test/CodeGen/PowerPC/ppc-shrink-wrapping.ll Thu Apr  5 07:26:06 2018<br>
@@ -328,7 +328,7 @@ declare void @somethingElse(...)<br>
 ; Shift second argument by one and store into returned register.<br>
 ; ENABLE: slwi 3, 4, 1<br>
 ; ENABLE-NEXT: blr<br>
-define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {<br>
+define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {<br>
 entry:<br>
   %tobool = icmp eq i32 %cond, 0<br>
   br i1 %tobool, label %if.else, label %if.then<br>
<br>
Modified: llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll (original)<br>
+++ llvm/trunk/test/CodeGen/Thumb/thumb-shrink-wrapping.ll Thu Apr  5 07:26:06 2018<br>
@@ -374,7 +374,7 @@ declare void @somethingElse(...)<br>
 ;<br>
 ; ENABLE-V5T-NEXT: {{LBB[0-9_]+}}: @ %if.end<br>
 ; ENABLE-NEXT: bx lr<br>
-define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {<br>
+define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {<br>
 entry:<br>
   %tobool = icmp eq i32 %cond, 0<br>
   br i1 %tobool, label %if.else, label %if.then<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll Thu Apr  5 07:26:06 2018<br>
@@ -17,10 +17,10 @@<br>
<br>
 %tupl = type [9 x i32]<br>
<br>
-declare fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) noreturn nounwind<br>
-declare fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) noreturn nounwind<br>
+declare fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) nounwind<br>
+declare fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) nounwind<br>
<br>
-define fastcc void @l186(%tupl* %r1) noreturn nounwind {<br>
+define fastcc void @l186(%tupl* %r1) nounwind {<br>
 entry:<br>
   %ptr1 = getelementptr %tupl, %tupl* %r1, i32 0, i32 0<br>
   %r2 = load i32, i32* %ptr1<br>
@@ -44,10 +44,10 @@ entry:<br>
   br i1 %cond, label %true, label %false<br>
<br>
 true:<br>
-  tail call fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) noreturn nounwind<br>
+  tail call fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) nounwind<br>
   ret void<br>
<br>
 false:<br>
-  tail call fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) noreturn nounwind<br>
+  tail call fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) nounwind<br>
   ret void<br>
 }<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll?rev=329287&r1=329286&r2=329287&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/x86-shrink-wrapping.ll Thu Apr  5 07:26:06 2018<br>
@@ -314,7 +314,7 @@ if.end:<br>
 ; ENABLE: addl %esi, %esi<br>
 ; ENABLE-NEXT: movl %esi, %eax<br>
 ; ENABLE-NEXT: retq<br>
-define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {<br>
+define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind {<br>
 entry:<br>
   %tobool = icmp eq i32 %cond, 0<br>
   br i1 %tobool, label %if.else, label %if.then<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>