[PATCH] D84737: [AArch64][SVE] Preserve SVE regs when callee may throw an exception.

Sander de Smalen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 08:01:21 PDT 2020


sdesmalen created this revision.
sdesmalen added reviewers: rsandifo-arm, efriedma.
Herald added subscribers: danielkiss, psnobl, hiraditya, kristof.beyls, tschuett.
Herald added a project: LLVM.
Harbormaster failed remote builds in B65982: Diff 281159!
Harbormaster returned this revision to the author for changes because remote builds failed.
sdesmalen updated this revision to Diff 281237.
sdesmalen added a comment.
sdesmalen requested review of this revision.

Fixed patch to look at call instruction and callee.


Unwinders may only preserve the base ABI over the exception edge, so the
caller needs to preserve additional registers for when the call throws
an exception and the unwinder has tried to recover state.

For  e.g.

  svint32_t bar(svint32_t);
  svint32_t foo(svint32_t x, bool *err) {
    try { bar(x); } catch (...) { *err = true; }
      return x;
    }

z0 needs to be spilled before the call to `bar(x)` and reloaded before
returning from foo, as the exception handler may have clobbered z0.

That registers are clobbered by the unwinder shouldn't necessarily be
tied to calls, but rather to the context that invokes the call, but
without -fnon-call-exceptions being implemented, that distinction is
not made.


https://reviews.llvm.org/D84737

Files:
  llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
  llvm/test/CodeGen/AArch64/sve-calling-convention.ll


Index: llvm/test/CodeGen/AArch64/sve-calling-convention.ll
===================================================================
--- llvm/test/CodeGen/AArch64/sve-calling-convention.ll
+++ llvm/test/CodeGen/AArch64/sve-calling-convention.ll
@@ -146,3 +146,44 @@
   call void asm sideeffect "nop", "~{z8},~{p4}"()
   ret void
 }
+
+; Unwinders may only preserve the base ABI over the exception edge,
+; so the caller needs to ensure all SVE registers are preserved.
+; This test checks that the right set of callee-saved-registers is used
+; for the call.
+
+; CHECKCSR-LABEL: name: invoke_callee_may_throw
+; CHECK: BL @may_throw, csr_aarch64_aapcs
+; CHECK: RET_ReallyLR
+define i32 @invoke_callee_may_throw(<vscale x 4 x i32> %v) personality i8 0 {
+  invoke void @may_throw(<vscale x 4 x i32> %v) to label %.Lcontinue unwind label %.Lunwind
+.Lcontinue:
+  ret i32 0
+.Lunwind:
+  %lp = landingpad { i8*, i32 } cleanup
+  ret i32 42;
+}
+
+; CHECKCSR-LABEL: name: call_callee_may_throw
+; CHECK: BL @may_throw, csr_aarch64_sve_aapcs
+; CHECK: RET_ReallyLR
+define void @call_callee_may_throw(<vscale x 4 x i32> %v) {
+  call void @may_throw(<vscale x 4 x i32> %v)
+  ret void
+}
+
+declare void @may_throw(<vscale x 4 x i32> %v);
+
+; CHECKCSR-LABEL: name: invoke_callee_does_not_throw
+; CHECK: BL @does_not_throw, csr_aarch64_sve_aapcs
+; CHECK: RET_ReallyLR
+define i32 @invoke_callee_does_not_throw(<vscale x 4 x i32> %v) personality i8 0 {
+  invoke void @does_not_throw(<vscale x 4 x i32> %v) to label %.Lcontinue unwind label %.Lunwind
+.Lcontinue:
+  ret i32 0
+.Lunwind:
+  %lp = landingpad { i8*, i32 } cleanup
+  ret i32 42;
+}
+
+declare void @does_not_throw(<vscale x 4 x i32> %v) nounwind
Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
===================================================================
--- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -4700,7 +4700,15 @@
       return In.VT.isScalableVector();
     });
 
-    if (CalleeInSVE || CalleeOutSVE)
+    // We check if the instruction is an invoke, because unwinders may only
+    // preserve the callee-saved registers as specified in the base ABI over the
+    // exception edge. This means that the caller needs to preserve additional
+    // registers for when the call throws an exception and the unwinder has
+    // tried to recover state.
+    bool CallNeedsUnwinding = false;
+    if (const CallBase *CB = CLI.CB)
+      CallNeedsUnwinding = isa<InvokeInst>(CB) && !CB->doesNotThrow();
+    if (!CallNeedsUnwinding && (CalleeInSVE || CalleeOutSVE))
       CallConv = CallingConv::AArch64_SVE_VectorCall;
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84737.281237.patch
Type: text/x-patch
Size: 2664 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200728/396044e6/attachment.bin>


More information about the llvm-commits mailing list