Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -677,6 +677,8 @@ /// This method emits the header for the current function. virtual void emitFunctionHeader(); + virtual void emitFunctionHeaderComment(); + /// Emit a blob of inline asm to the output streamer. void emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -668,6 +668,8 @@ OutStreamer->emitValue(Value, Size); } +void AsmPrinter::emitFunctionHeaderComment() {} + /// EmitFunctionHeader - This method emits the header for the current /// function. void AsmPrinter::emitFunctionHeader() { @@ -704,6 +706,7 @@ if (isVerbose()) { F.printAsOperand(OutStreamer->GetCommentOS(), /*PrintType=*/false, F.getParent()); + emitFunctionHeaderComment(); OutStreamer->GetCommentOS() << '\n'; } Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -114,6 +114,8 @@ void emitInstruction(const MachineInstr *MI) override; + void emitFunctionHeaderComment() override; + void getAnalysisUsage(AnalysisUsage &AU) const override { AsmPrinter::getAnalysisUsage(AU); AU.setPreservesAll(); @@ -241,6 +243,13 @@ OutStreamer->SwitchSection(Cur); } +void AArch64AsmPrinter::emitFunctionHeaderComment() { + const AArch64FunctionInfo *FI = MF->getInfo(); + Optional OutlinerString = FI->getOutliningStyle(); + if (OutlinerString != None) + OutStreamer->GetCommentOS() << ' ' << OutlinerString; +} + void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { const Function &F = MF->getFunction(); Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -6373,9 +6373,14 @@ void AArch64InstrInfo::buildOutlinedFrame( MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const { - // For thunk outlining, rewrite the last instruction from a call to a - // tail-call. - if (OF.FrameConstructionID == MachineOutlinerThunk) { + + AArch64FunctionInfo *FI = MF.getInfo(); + + if (OF.FrameConstructionID == MachineOutlinerTailCall) + FI->setOutliningStyle("Tail Call"); + else if (OF.FrameConstructionID == MachineOutlinerThunk) { + // For thunk outlining, rewrite the last instruction from a call to a + // tail-call. MachineInstr *Call = &*--MBB.instr_end(); unsigned TailOpcode; if (Call->getOpcode() == AArch64::BL) { @@ -6389,6 +6394,8 @@ .addImm(0); MBB.insert(MBB.end(), TC); Call->eraseFromParent(); + + FI->setOutliningStyle("Thunk"); } bool IsLeafFunction = true; @@ -6494,6 +6501,8 @@ signOutlinedFunction(MF, MBB, ShouldSignReturnAddr, ShouldSignReturnAddrWithAKey); + FI->setOutliningStyle("Function"); + // Did we have to modify the stack by saving the link register? if (OF.FrameConstructionID != MachineOutlinerDefault) return; Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/IR/Function.h" @@ -26,6 +27,10 @@ namespace llvm { +namespace yaml { +struct AArch64FunctionInfo; +} + class MachineInstr; /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and @@ -126,6 +131,8 @@ // stack slot. unsigned TaggedBasePointerOffset = 0; + Optional OutliningStyle; + public: AArch64FunctionInfo() = default; @@ -137,6 +144,7 @@ if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) HasRedZone = false; } + void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI); unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } @@ -173,6 +181,9 @@ void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; } uint64_t getLocalStackSize() const { return LocalStackSize; } + void setOutliningStyle(std::string Style) { OutliningStyle = Style; } + Optional getOutliningStyle() const { return OutliningStyle; } + void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; HasCalleeSavedStackSize = true; @@ -333,6 +344,25 @@ DenseMap> JumpTableEntryInfo; }; +namespace yaml { +struct AArch64FunctionInfo final : public yaml::MachineFunctionInfo { + Optional HasRedZone; + + AArch64FunctionInfo() = default; + AArch64FunctionInfo(const llvm::AArch64FunctionInfo &MFI); + + void mappingImpl(yaml::IO &YamlIO) override; + ~AArch64FunctionInfo() = default; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, AArch64FunctionInfo &MFI) { + YamlIO.mapOptional("hasRedZone", MFI.HasRedZone); + } +}; + +} // end namespace yaml + } // end namespace llvm #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -0,0 +1,32 @@ +//=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=// + +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements AArch64-specific per-machine-function +/// information. +/// +//===----------------------------------------------------------------------===// + +#include "AArch64MachineFunctionInfo.h" + +using namespace llvm; + +yaml::AArch64FunctionInfo::AArch64FunctionInfo( + const llvm::AArch64FunctionInfo &MFI) + : HasRedZone(MFI.hasRedZone()) {} + +void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) { + MappingTraits::mapping(YamlIO, *this); +} + +void AArch64FunctionInfo::initializeBaseYamlFields( + const yaml::AArch64FunctionInfo &YamlMFI) { + if (YamlMFI.HasRedZone.hasValue()) + HasRedZone = YamlMFI.HasRedZone; +} Index: llvm/lib/Target/AArch64/AArch64TargetMachine.h =================================================================== --- llvm/lib/Target/AArch64/AArch64TargetMachine.h +++ llvm/lib/Target/AArch64/AArch64TargetMachine.h @@ -49,6 +49,14 @@ return TLOF.get(); } + yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override; + yaml::MachineFunctionInfo * + convertFuncInfoToYAML(const MachineFunction &MF) const override; + bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, + PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, + SMRange &SourceRange) const override; + private: bool isLittle; }; Index: llvm/lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -11,6 +11,7 @@ #include "AArch64TargetMachine.h" #include "AArch64.h" +#include "AArch64MachineFunctionInfo.h" #include "AArch64MacroFusion.h" #include "AArch64Subtarget.h" #include "AArch64TargetObjectFile.h" @@ -26,6 +27,7 @@ #include "llvm/CodeGen/GlobalISel/Legalizer.h" #include "llvm/CodeGen/GlobalISel/Localizer.h" #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" +#include "llvm/CodeGen/MIRParser/MIParser.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -651,3 +653,24 @@ // SVE bundles move prefixes with destructive operations. addPass(createUnpackMachineBundles(nullptr)); } + +yaml::MachineFunctionInfo * +AArch64TargetMachine::createDefaultFuncInfoYAML() const { + return new yaml::AArch64FunctionInfo(); +} + +yaml::MachineFunctionInfo * +AArch64TargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { + const auto *MFI = MF.getInfo(); + return new yaml::AArch64FunctionInfo(*MFI); +} + +bool AArch64TargetMachine::parseMachineFunctionInfo( + const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, SMRange &SourceRange) const { + const auto &YamlMFI = + reinterpret_cast(MFI); + MachineFunction &MF = PFS.MF; + MF.getInfo()->initializeBaseYamlFields(YamlMFI); + return false; +} Index: llvm/lib/Target/AArch64/CMakeLists.txt =================================================================== --- llvm/lib/Target/AArch64/CMakeLists.txt +++ llvm/lib/Target/AArch64/CMakeLists.txt @@ -48,6 +48,7 @@ AArch64InstructionSelector.cpp AArch64LegalizerInfo.cpp AArch64LoadStoreOptimizer.cpp + AArch64MachineFunctionInfo.cpp AArch64MacroFusion.cpp AArch64MCInstLower.cpp AArch64PreLegalizerCombiner.cpp Index: llvm/test/CodeGen/AArch64/machine-outliner-function-annotate.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/machine-outliner-function-annotate.mir @@ -0,0 +1,119 @@ +# RUN: llc -mtriple=aarch64--- -start-before=machine-outliner -enable-machine-outliner %s -o - | FileCheck %s + +# Check that a non tail called or thunk function is annotated properly with +# only "Function" + +# CHECK-LABEL: OUTLINED_FUNCTION_0: +# CHECK-SAME: // @OUTLINED_FUNCTION_0 Function +# CHECK: mov w0, #1 +# CHECK-NEXT: mov w1, #2 +# CHECK-NEXT: mov w2, #3 +# CHECK-NEXT: mov w3, #4 +# CHECK-NEXT: ret + +--- | + ; ModuleID = '' + source_filename = "" + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-unknown-linux-gnu" + + define void @a() { + entry: + call void @z(i32 1, i32 2, i32 3, i32 4) + %ptr = alloca i32, align 4 + store i32 2, i32* %ptr, align 4 + ret void + } + + declare void @z(i32, i32, i32, i32) + + define dso_local void @b(i32* nocapture readnone %p) { + entry: + call void @z(i32 1, i32 2, i32 3, i32 4) + %ptr = alloca i32, align 4 + store i32 1, i32* %ptr, align 4 + ret void + } + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #0 + + attributes #0 = { nounwind } + +... +--- +name: a +alignment: 4 +tracksRegLiveness: true +frameInfo: + stackSize: 32 + maxAlignment: 8 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + localFrameSize: 4 +stack: + - { id: 0, name: ptr, offset: -20, size: 4, alignment: 4, local-offset: -4 } + - { id: 1, type: spill-slot, offset: -8, size: 8, alignment: 8, callee-saved-register: '$x19' } + - { id: 2, type: spill-slot, offset: -16, size: 8, alignment: 8, callee-saved-register: '$lr' } +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.entry: + liveins: $x19, $lr + + $sp = frame-setup SUBXri $sp, 32, 0 + frame-setup STPXi killed $lr, killed $x19, $sp, 2 :: (store 8 into %stack.2), (store 8 into %stack.1) + frame-setup CFI_INSTRUCTION def_cfa_offset 32 + frame-setup CFI_INSTRUCTION offset $w19, -8 + frame-setup CFI_INSTRUCTION offset $w30, -16 + $w0 = MOVZWi 1, 0 + $w1 = MOVZWi 2, 0 + $w2 = MOVZWi 3, 0 + $w3 = MOVZWi 4, 0 + renamable $w19 = MOVZWi 2, 0 + BL @z, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit killed $w2, implicit killed $w3, implicit-def $sp + STRWui killed renamable $w19, $sp, 3 :: (store 4 into %ir.ptr) + $lr, $x19 = frame-destroy LDPXi $sp, 2 :: (load 8 from %stack.2), (load 8 from %stack.1) + $sp = frame-destroy ADDXri $sp, 32, 0 + RET undef $lr + +... +--- +name: b +alignment: 4 +tracksRegLiveness: true +frameInfo: + stackSize: 32 + maxAlignment: 8 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + localFrameSize: 4 +stack: + - { id: 0, name: ptr, offset: -20, size: 4, alignment: 4, local-offset: -4 } + - { id: 1, type: spill-slot, offset: -8, size: 8, alignment: 8, callee-saved-register: '$x19' } + - { id: 2, type: spill-slot, offset: -16, size: 8, alignment: 8, callee-saved-register: '$lr' } +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.entry: + liveins: $x19, $lr + + $sp = frame-setup SUBXri $sp, 32, 0 + frame-setup STPXi killed $lr, killed $x19, $sp, 2 :: (store 8 into %stack.2), (store 8 into %stack.1) + frame-setup CFI_INSTRUCTION def_cfa_offset 32 + frame-setup CFI_INSTRUCTION offset $w19, -8 + frame-setup CFI_INSTRUCTION offset $w30, -16 + $w0 = MOVZWi 1, 0 + $w1 = MOVZWi 2, 0 + $w2 = MOVZWi 3, 0 + $w3 = MOVZWi 4, 0 + renamable $w19 = MOVZWi 1, 0 + BL @z, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit killed $w2, implicit killed $w3, implicit-def $sp + STRWui killed renamable $w19, $sp, 3 :: (store 4 into %ir.ptr) + $lr, $x19 = frame-destroy LDPXi $sp, 2 :: (load 8 from %stack.2), (load 8 from %stack.1) + $sp = frame-destroy ADDXri $sp, 32, 0 + RET undef $lr + +... Index: llvm/test/CodeGen/AArch64/machine-outliner-tail.ll =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-tail.ll +++ llvm/test/CodeGen/AArch64/machine-outliner-tail.ll @@ -1,6 +1,7 @@ ; RUN: llc -verify-machineinstrs -enable-machine-outliner -mtriple=aarch64-linux-gnu < %s | FileCheck %s -; CHECK: OUTLINED_FUNCTION_0: +; CHECK-LABEL: OUTLINED_FUNCTION_0: +; CHECK-SAME: // @OUTLINED_FUNCTION_0 Tail Call ; CHECK: mov w0, #1 ; CHECK-NEXT: mov w1, #2 ; CHECK-NEXT: mov w2, #3 Index: llvm/test/CodeGen/AArch64/machine-outliner-thunk.ll =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-thunk.ll +++ llvm/test/CodeGen/AArch64/machine-outliner-thunk.ll @@ -71,6 +71,7 @@ } ; CHECK: [[OUTLINED_INDIRECT]]: +; CHECK-SAME: // @[[OUTLINED_INDIRECT]] Thunk ; CHECK: // %bb.0: ; CHECK-NEXT: mov x8, x0 ; CHECK-NEXT: mov w0, #1 @@ -80,6 +81,7 @@ ; CHECK-NEXT: br x8 ; CHECK: [[OUTLINED_DIRECT]]: +; CHECK-SAME: // @[[OUTLINED_DIRECT]] Thunk ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, #1 ; CHECK-NEXT: mov w1, #2