diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -6107,6 +6107,14 @@ // stack, then we need a different frame. unsigned NumBytesNoStackCalls = 0; std::vector CandidatesWithoutStackFixups; + + // We need to tell if we have a call or a noreturn in a candidate that will + // require a stack fixup because there is a chance that there might be more + // than one fixup required. The code to handle this asserts currently + // because it has not been sufficiently tested for this fixup behavior and + // still needs better checks for legal codegen. + bool DoCandidatesHaveCallsOrNoReturn = + FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls; // Check if we have to save LR. for (outliner::Candidate &C : RepeatedSequenceLocs) { @@ -6120,6 +6128,7 @@ // noreturn functions by fixing up the liveness info. bool IsNoReturn = C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn); + DoCandidatesHaveCallsOrNoReturn |= IsNoReturn; // Is LR available? If so, we don't need a save. if (C.LRU.available(AArch64::LR) && !IsNoReturn) { @@ -6159,6 +6168,11 @@ RepeatedSequenceLocs = CandidatesWithoutStackFixups; FrameID = MachineOutlinerNoLRSave; } else { + if (DoCandidatesHaveCallsOrNoReturn) { + RepeatedSequenceLocs.clear(); + return outliner::OutlinedFunction(); + } + SetCandidateCallInfo(MachineOutlinerDefault, 12); } diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-no-stack.mir b/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-no-stack.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/machine-outliner-noreturn-no-stack.mir @@ -0,0 +1,69 @@ +# RUN: llc -mtriple=arm64-apple-ios -run-pass=prologepilog -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# Noreturn functions conservatively need to save and restore lr. +# When there is no available register, the stack is used at call site. +# If the stack also needs to be set up for a call in the outlined function, +# bail-out this case since we do not handle adjusting the stack twice. + +# CHECK-NOT: OUTLINED_FUNCTION + +--- | + @g = external global i32 + define void @stack_1() #0 { ret void } + define void @stack_2() #0 { ret void } + define void @baz() { + ret void + } + attributes #0 = { noredzone noreturn } +... +--- +name: stack_1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x4, $x0, $x1, $x2, $x3 + $w8 = MOVZWi 259, 0 + $x9 = ADRP target-flags(aarch64-page) @g + $x9 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-nc) @g, 0 + STRXui $x9, $x1, 0 + STRHHui $w8, $x1, 8 + $w8 = ORRWrs $wzr, $w4, 0, implicit-def $x8 + STRXui $x8, $x3, 0 + STPXi $x3, $xzr, $x2, 0 + $w8 = MOVZWi 271, 0 + STRHHui $w8, $x2, 8 + $x8 = ORRXrs $xzr, $x0, 0 + $x0 = ORRXrs $xzr, $x1, 0 + $x1 = ORRXrs $xzr, $x2, 0 + BL @baz, implicit-def dead $lr, implicit $sp, implicit $x8, implicit $x0, implicit $x1, implicit $x3, implicit $x4, implicit-def $sp, implicit-def $x5, implicit-def $x6, implicit-def $x7, implicit-def $x8, implicit-def $x9, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit-def $x13, implicit-def $x14, implicit-def $x15, implicit-def $x18 + BRK 1 +... +--- +name: stack_2 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x4, $x0, $x1, $x2, $x3 + $w8 = MOVZWi 259, 0 + $x9 = ADRP target-flags(aarch64-page) @g + $x9 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-nc) @g, 0 + STRXui $x9, $x1, 0 + STRHHui $w8, $x1, 8 + $w8 = ORRWrs $wzr, $w4, 0, implicit-def $x8 + STRXui $x8, $x3, 0 + STPXi $x3, $xzr, $x2, 0 + $w8 = MOVZWi 271, 0 + STRHHui $w8, $x2, 8 + $x8 = ORRXrs $xzr, $x0, 0 + $x0 = ORRXrs $xzr, $x1, 0 + $x1 = ORRXrs $xzr, $x2, 0 + BL @baz, implicit-def dead $lr, implicit $sp, implicit $x8, implicit $x0, implicit $x1, implicit $x3, implicit $x4, implicit-def $sp, implicit-def $x5, implicit-def $x6, implicit-def $x7, implicit-def $x8, implicit-def $x9, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit-def $x13, implicit-def $x14, implicit-def $x15, implicit-def $x18 + BRK 1 +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $lr, $w8 + RET undef $lr