Index: llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1564,7 +1564,9 @@ Args.push_back(getOrCreateVRegs(*Arg)); } - MF->getFrameInfo().setHasCalls(true); + // We don't set HasCalls on MFI here yet because call lowering may decide to + // optimize into tail calls. Instead, we defer that to selection where a final + // scan is done to check if any instructions are calls. bool Success = CLI->lowerCall(MIRBuilder, CS, Res, Args, SwiftErrorVReg, [&]() { return getOrCreateVReg(*CS.getCalledValue()); }); Index: llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -17,7 +17,9 @@ #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -223,6 +225,22 @@ auto &TLI = *MF.getSubtarget().getTargetLowering(); TLI.finalizeLowering(MF); + // Determine if there are any calls in this machine function. Ported from + // SelectionDAG. + MachineFrameInfo &MFI = MF.getFrameInfo(); + for (const auto &MBB : MF) { + if (MFI.hasCalls() && MF.hasInlineAsm()) + break; + + for (const auto &MI : MBB) { + if ((MI.isCall() && !MI.isReturn()) || MI.isStackAligningInlineAsm()) + MFI.setHasCalls(true); + if (MI.isInlineAsm()) + MF.setHasInlineAsm(true); + } + } + + LLVM_DEBUG({ dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo.covered()) Index: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -364,8 +364,6 @@ auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); const char *Name = TLI.getLibcallName(Libcall); - MIRBuilder.getMF().getFrameInfo().setHasCalls(true); - CallLowering::CallLoweringInfo Info; Info.CallConv = TLI.getLibcallCallingConv(Libcall); Info.Callee = MachineOperand::CreateES(Name); @@ -430,7 +428,6 @@ const char *Name = TLI.getLibcallName(RTLibcall); MIRBuilder.setInstr(MI); - MIRBuilder.getMF().getFrameInfo().setHasCalls(true); CallLowering::CallLoweringInfo Info; Info.CallConv = TLI.getLibcallCallingConv(RTLibcall); Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -100,7 +100,6 @@ } ; CHECK-LABEL: name: test_arr_call -; CHECK: hasCalls: true ; CHECK: %0:_(p0) = COPY $x0 ; CHECK: [[LD1:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.addr) ; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/tail-call-no-save-fp-lr.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/tail-call-no-save-fp-lr.ll +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/tail-call-no-save-fp-lr.ll @@ -0,0 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc %s -verify-machineinstrs -mtriple aarch64-apple-darwin -global-isel -global-isel-abort=1 -o - 2>&1 | FileCheck %s + +; Check that we get a tail call to foo without saving fp/lr. +define void @bar(i32 %a) #1 { +; CHECK-LABEL: bar: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: b _zoo +entry: + tail call void @zoo(i32 undef) + ret void +} + +define void @zoo(i32 %a) { +entry: + ret void +} + +attributes #1 = { "frame-pointer"="all" } +