Index: llvm/include/llvm/CodeGen/MachineOutliner.h =================================================================== --- llvm/include/llvm/CodeGen/MachineOutliner.h +++ llvm/include/llvm/CodeGen/MachineOutliner.h @@ -23,6 +23,14 @@ namespace llvm { namespace outliner { +enum MachineOutlinerClass { + MachineOutlinerDefault, /// Emit a save, restore, call, and return. + MachineOutlinerTailCall, /// Only emit a branch. + MachineOutlinerNoLRSave, /// Emit a call and return. + MachineOutlinerThunk, /// Emit a call and tail-call. + MachineOutlinerRegSave /// Same as default, but save to a register. +}; + /// Represents how an instruction should be mapped by the outliner. /// \p Legal instructions are those which are safe to outline. /// \p LegalTerminator instructions are safe to outline, but only as the Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -704,6 +704,10 @@ if (isVerbose()) { F.printAsOperand(OutStreamer->GetCommentOS(), /*PrintType=*/false, F.getParent()); + MDNode *OutlinedMetaData = F.getMetadata("outlined.kind"); + if (OutlinedMetaData) + if(MDString *OutlinedMetaString = dyn_cast(OutlinedMetaData->getOperand(0))) + OutStreamer->GetCommentOS() << ' ' << OutlinedMetaString->getString(); OutStreamer->GetCommentOS() << '\n'; } Index: llvm/lib/CodeGen/MachineOutliner.cpp =================================================================== --- llvm/lib/CodeGen/MachineOutliner.cpp +++ llvm/lib/CodeGen/MachineOutliner.cpp @@ -75,6 +75,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include +#include #include #include @@ -1147,6 +1148,18 @@ if (ParentFn.hasFnAttribute("target-features")) F->addFnAttr(ParentFn.getFnAttribute("target-features")); + std::string OutlineKindString = "; "; + if (FirstCand.CallConstructionID == MachineOutlinerTailCall) + OutlineKindString += "Tail Call"; + else if (FirstCand.CallConstructionID == MachineOutlinerThunk) + OutlineKindString += "Thunk"; + else if (FirstCand.CallConstructionID == MachineOutlinerNoLRSave) + OutlineKindString += "Function with no Save and Restore"; + else if (FirstCand.CallConstructionID == MachineOutlinerRegSave) + OutlineKindString += "Function saving to register"; + else + OutlineKindString += "Function"; + BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); IRBuilder<> Builder(EntryBB); Builder.CreateRetVoid(); @@ -1157,6 +1170,9 @@ const TargetSubtargetInfo &STI = MF.getSubtarget(); const TargetInstrInfo &TII = *STI.getInstrInfo(); + MDNode* N = MDNode::get(C, MDString::get(C, OutlineKindString)); + F->addMetadata("outlined.kind", *N); + // Insert the new function into the module. MF.insert(MF.begin(), &MBB); Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -5556,13 +5556,13 @@ /// * Call construction overhead: 3 (save + BL + restore) /// * Frame construction overhead: 1 (ret) /// * Requires stack fixups? No -enum MachineOutlinerClass { +/*enum MachineOutlinerClass { MachineOutlinerDefault, /// Emit a save, restore, call, and return. MachineOutlinerTailCall, /// Only emit a branch. MachineOutlinerNoLRSave, /// Emit a call and return. MachineOutlinerThunk, /// Emit a call and tail-call. MachineOutlinerRegSave /// Same as default, but save to a register. -}; +};*/ enum MachineOutlinerMBBFlags { LRUnavailableSomewhere = 0x2, @@ -5855,7 +5855,7 @@ C.setCallInfo(CallID, NumBytesForCall); }; - unsigned FrameID = MachineOutlinerDefault; + unsigned FrameID = outliner::MachineOutlinerDefault; NumBytesToCreateFrame += 4; bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) { @@ -5925,17 +5925,17 @@ // If the last instruction in any candidate is a terminator, then we should // tail call all of the candidates. if (RepeatedSequenceLocs[0].back()->isTerminator()) { - FrameID = MachineOutlinerTailCall; + FrameID = outliner::MachineOutlinerTailCall; NumBytesToCreateFrame = 0; - SetCandidateCallInfo(MachineOutlinerTailCall, 4); + SetCandidateCallInfo(outliner::MachineOutlinerTailCall, 4); } else if (LastInstrOpcode == AArch64::BL || (LastInstrOpcode == AArch64::BLR && !HasBTI)) { // FIXME: Do we need to check if the code after this uses the value of LR? - FrameID = MachineOutlinerThunk; + FrameID = outliner::MachineOutlinerThunk; NumBytesToCreateFrame = 0; - SetCandidateCallInfo(MachineOutlinerThunk, 4); + SetCandidateCallInfo(outliner::MachineOutlinerThunk, 4); } else { @@ -5961,7 +5961,7 @@ // Is LR available? If so, we don't need a save. if (C.LRU.available(AArch64::LR) && !IsNoReturn) { NumBytesNoStackCalls += 4; - C.setCallInfo(MachineOutlinerNoLRSave, 4); + C.setCallInfo(outliner::MachineOutlinerNoLRSave, 4); CandidatesWithoutStackFixups.push_back(C); } @@ -5969,7 +5969,7 @@ // we can outline with the same frame type as those that don't save LR. else if (findRegisterToSaveLRTo(C)) { NumBytesNoStackCalls += 12; - C.setCallInfo(MachineOutlinerRegSave, 12); + C.setCallInfo(outliner::MachineOutlinerRegSave, 12); CandidatesWithoutStackFixups.push_back(C); } @@ -5977,7 +5977,7 @@ // the stack, so we are guaranteed to get the same frame. else if (C.UsedInSequence.available(AArch64::SP)) { NumBytesNoStackCalls += 12; - C.setCallInfo(MachineOutlinerDefault, 12); + C.setCallInfo(outliner::MachineOutlinerDefault, 12); CandidatesWithoutStackFixups.push_back(C); } @@ -5994,9 +5994,9 @@ if (!AllStackInstrsSafe || NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) { RepeatedSequenceLocs = CandidatesWithoutStackFixups; - FrameID = MachineOutlinerNoLRSave; + FrameID = outliner::MachineOutlinerNoLRSave; } else { - SetCandidateCallInfo(MachineOutlinerDefault, 12); + SetCandidateCallInfo(outliner::MachineOutlinerDefault, 12); } // If we dropped all of the candidates, bail out here. @@ -6021,8 +6021,9 @@ // However, it could be possible that the last instruction is a call without // it being valid to tail call this sequence. We should consider this as // well. - else if (FrameID != MachineOutlinerThunk && - FrameID != MachineOutlinerTailCall && FirstCand.back()->isCall()) + else if (FrameID != outliner::MachineOutlinerThunk && + FrameID != outliner::MachineOutlinerTailCall && + FirstCand.back()->isCall()) ModStackToSaveLR = true; if (ModStackToSaveLR) { @@ -6375,7 +6376,7 @@ const outliner::OutlinedFunction &OF) const { // For thunk outlining, rewrite the last instruction from a call to a // tail-call. - if (OF.FrameConstructionID == MachineOutlinerThunk) { + if (OF.FrameConstructionID == outliner::MachineOutlinerThunk) { MachineInstr *Call = &*--MBB.instr_end(); unsigned TailOpcode; if (Call->getOpcode() == AArch64::BL) { @@ -6401,7 +6402,7 @@ if (std::any_of(MBB.instr_begin(), MBB.instr_end(), IsNonTailCall)) { // Fix up the instructions in the range, since we're going to modify the // stack. - assert(OF.FrameConstructionID != MachineOutlinerDefault && + assert(OF.FrameConstructionID != outliner::MachineOutlinerDefault && "Can only fix up stack references once"); fixupPostOutline(MBB); @@ -6413,8 +6414,8 @@ MachineBasicBlock::iterator It = MBB.begin(); MachineBasicBlock::iterator Et = MBB.end(); - if (OF.FrameConstructionID == MachineOutlinerTailCall || - OF.FrameConstructionID == MachineOutlinerThunk) + if (OF.FrameConstructionID == outliner::MachineOutlinerTailCall || + OF.FrameConstructionID == outliner::MachineOutlinerThunk) Et = std::prev(MBB.end()); // Insert a save before the outlined region @@ -6479,8 +6480,8 @@ } // If this is a tail call outlined function, then there's already a return. - if (OF.FrameConstructionID == MachineOutlinerTailCall || - OF.FrameConstructionID == MachineOutlinerThunk) { + if (OF.FrameConstructionID == outliner::MachineOutlinerTailCall || + OF.FrameConstructionID == outliner::MachineOutlinerThunk) { signOutlinedFunction(MF, MBB, ShouldSignReturnAddr, ShouldSignReturnAddrWithAKey); return; @@ -6495,7 +6496,7 @@ ShouldSignReturnAddrWithAKey); // Did we have to modify the stack by saving the link register? - if (OF.FrameConstructionID != MachineOutlinerDefault) + if (OF.FrameConstructionID != outliner::MachineOutlinerDefault) return; // We modified the stack. @@ -6508,7 +6509,7 @@ MachineFunction &MF, const outliner::Candidate &C) const { // Are we tail calling? - if (C.CallConstructionID == MachineOutlinerTailCall) { + if (C.CallConstructionID == outliner::MachineOutlinerTailCall) { // If yes, then we can just branch to the label. It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi)) .addGlobalAddress(M.getNamedValue(MF.getName())) @@ -6517,8 +6518,8 @@ } // Are we saving the link register? - if (C.CallConstructionID == MachineOutlinerNoLRSave || - C.CallConstructionID == MachineOutlinerThunk) { + if (C.CallConstructionID == outliner::MachineOutlinerNoLRSave || + C.CallConstructionID == outliner::MachineOutlinerThunk) { // No, so just insert the call. It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL)) .addGlobalAddress(M.getNamedValue(MF.getName()))); @@ -6533,7 +6534,7 @@ MachineInstr *Save; MachineInstr *Restore; // Can we save to a register? - if (C.CallConstructionID == MachineOutlinerRegSave) { + if (C.CallConstructionID == outliner::MachineOutlinerRegSave) { // FIXME: This logic should be sunk into a target-specific interface so that // we don't have to recompute the register. unsigned Reg = findRegisterToSaveLRTo(C); Index: llvm/lib/Target/X86/X86InstrInfo.cpp =================================================================== --- llvm/lib/Target/X86/X86InstrInfo.cpp +++ llvm/lib/Target/X86/X86InstrInfo.cpp @@ -8663,10 +8663,10 @@ /// * Call construction overhead: 1 (jump instruction) /// * Frame construction overhead: 0 (don't need to return) /// -enum MachineOutlinerClass { +/*enum MachineOutlinerClass { MachineOutlinerDefault, MachineOutlinerTailCall -}; +};*/ outliner::OutlinedFunction X86InstrInfo::getOutliningCandidateInfo( std::vector &RepeatedSequenceLocs) const { @@ -8685,19 +8685,20 @@ // FIXME: Use real size in bytes for call and ret instructions. if (RepeatedSequenceLocs[0].back()->isTerminator()) { for (outliner::Candidate &C : RepeatedSequenceLocs) - C.setCallInfo(MachineOutlinerTailCall, 1); + C.setCallInfo(outliner::MachineOutlinerTailCall, 1); - return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, - 0, // Number of bytes to emit frame. - MachineOutlinerTailCall // Type of frame. + return outliner::OutlinedFunction( + RepeatedSequenceLocs, SequenceSize, + 0, // Number of bytes to emit frame. + outliner::MachineOutlinerTailCall // Type of frame. ); } for (outliner::Candidate &C : RepeatedSequenceLocs) - C.setCallInfo(MachineOutlinerDefault, 1); + C.setCallInfo(outliner::MachineOutlinerDefault, 1); return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, 1, - MachineOutlinerDefault); + outliner::MachineOutlinerDefault); } bool X86InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF, @@ -8787,7 +8788,7 @@ const outliner::OutlinedFunction &OF) const { // If we're a tail call, we already have a return, so don't do anything. - if (OF.FrameConstructionID == MachineOutlinerTailCall) + if (OF.FrameConstructionID == outliner::MachineOutlinerTailCall) return; // We're a normal call, so our sequence doesn't have a return instruction. @@ -8802,7 +8803,7 @@ MachineFunction &MF, const outliner::Candidate &C) const { // Is it a tail call? - if (C.CallConstructionID == MachineOutlinerTailCall) { + if (C.CallConstructionID == outliner::MachineOutlinerTailCall) { // Yes, just insert a JMP. It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(X86::TAILJMPd64))