Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -681,6 +681,9 @@ /// This method emits the header for the current function. virtual void emitFunctionHeader(); + /// This method emits a comment next to header for the current function. + 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 @@ -6408,9 +6408,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) { @@ -6424,6 +6429,8 @@ .addImm(0); MBB.insert(MBB.end(), TC); Call->eraseFromParent(); + + FI->setOutliningStyle("Thunk"); } bool IsLeafFunction = true; @@ -6529,6 +6536,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 @@ -131,6 +131,10 @@ // stack slot. unsigned TaggedBasePointerOffset = 0; + /// OutliningStyle denotes, if a function was outined, how it was outlined, + /// e.g. Tail Call, Thunk, or Function if none apply. + Optional OutliningStyle; + public: AArch64FunctionInfo() = default; @@ -179,6 +183,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; 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