[llvm] r329287 - ARM: Do not spill CSR to stack on entry to noreturn functions

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 5 17:38:26 PDT 2018


This patch breaks UBSAN tests on Android
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

On Thu, Apr 5, 2018 at 7:29 AM Tim Northover via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

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


More information about the llvm-commits mailing list