Index: llvm/include/llvm/CodeGen/AsmPrinterHandler.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinterHandler.h +++ llvm/include/llvm/CodeGen/AsmPrinterHandler.h @@ -67,6 +67,10 @@ /// Process end of an instruction. virtual void endInstruction() = 0; + + // Process beginning and end of a basic block, with basic block sections. + virtual void beginBasicBlock(const MachineBasicBlock &MBB) { } + virtual void endBasicBlock(const MachineBasicBlock &MBB) { } }; } // End of namespace llvm Index: llvm/include/llvm/CodeGen/CommandFlags.inc =================================================================== --- llvm/include/llvm/CodeGen/CommandFlags.inc +++ llvm/include/llvm/CodeGen/CommandFlags.inc @@ -238,6 +238,15 @@ cl::desc("Emit functions into separate sections"), cl::init(false)); +static cl::opt BasicBlockSections( + "basicblock-sections", + cl::desc("Emit basic blocks into separate sections"), + cl::init(BasicBlockSection::None), + cl::values( + clEnumValN(BasicBlockSection::None, "none", "Off"), + clEnumValN(BasicBlockSection::All, "all", "All Basic Blocks"), + clEnumValN(BasicBlockSection::Labels, "labels", "Labelled Basic Blocks"))); + static cl::opt EmulatedTLS("emulated-tls", cl::desc("Use emulated TLS model"), cl::init(false)); @@ -247,6 +256,11 @@ cl::desc("Give unique names to every section"), cl::init(true)); +static cl::opt UniqueBBSectionNames( + "unique-bb-section-names", + cl::desc("Give unique names to every basic block section"), + cl::init(false)); + static cl::opt EABIVersion("meabi", cl::desc("Set EABI type (default depends on triple):"), cl::init(EABI::Default), @@ -299,7 +313,9 @@ Options.RelaxELFRelocations = RelaxELFRelocations; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.BasicBlockSections = BasicBlockSections; Options.UniqueSectionNames = UniqueSectionNames; + Options.UniqueBBSectionNames = UniqueBBSectionNames; Options.EmulatedTLS = EmulatedTLS; Options.ExplicitEmulatedTLS = EmulatedTLS.getNumOccurrences() > 0; Options.ExceptionModel = ExceptionModel; @@ -308,6 +324,7 @@ Options.EnableDebugEntryValues = EnableDebugEntryValues; Options.MCOptions = InitMCTargetOptionsFromFlags(); + Options.MCOptions.MCRelocateWithSymbols = (BasicBlockSections == BasicBlockSection::All); Options.ThreadModel = TMModel; Options.EABIVersion = EABIVersion; Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h =================================================================== --- llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -129,10 +129,15 @@ /// Indicate that this basic block is the entry block of a cleanup funclet. bool IsCleanupFuncletEntry = false; + /// Indicate that this basic block needs a unqiue section. + bool IsUniqueSection = false; + /// since getSymbol is a relatively heavy-weight operation, the symbol /// is only computed once and is cached. mutable MCSymbol *CachedMCSymbol = nullptr; + MCSymbol *EndMCSymbol = nullptr; + // Intrusive list support MachineBasicBlock() = default; @@ -408,6 +413,11 @@ /// Indicates if this is the entry block of a cleanup funclet. void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; } + /// Indicate that this basic block needs a unqiue section. + bool isUniqueSection() const { return IsUniqueSection; } + + void setIsUniqueSection(bool V = true) { IsUniqueSection = V; } + /// Returns true if it is legal to hoist instructions into this block. bool isLegalToHoistInto() const; @@ -419,6 +429,9 @@ void moveBefore(MachineBasicBlock *NewAfter); void moveAfter(MachineBasicBlock *NewBefore); + /// Insert an unconditional jump to a fallthrough block if any. + void insertUnconditionalFallthroughBranch(); + /// Update the terminator instructions in block to account for changes to the /// layout. If the block previously used a fallthrough, it may now need a /// branch, and if it previously used branching it may now be able to use a @@ -803,6 +816,13 @@ /// Return the MCSymbol for this basic block. MCSymbol *getSymbol() const; + void setEndMCSymbol(MCSymbol *Sym) + { EndMCSymbol = Sym; } + + MCSymbol *getEndMCSymbol() const { + return EndMCSymbol; + } + Optional getIrrLoopHeaderWeight() const { return IrrLoopHeaderWeight; } Index: llvm/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/include/llvm/CodeGen/MachineFunction.h +++ llvm/include/llvm/CodeGen/MachineFunction.h @@ -63,6 +63,7 @@ class MCContext; class MCInstrDesc; class MCSymbol; +class MCSection; class Pass; class PseudoSourceValueManager; class raw_ostream; @@ -242,6 +243,9 @@ // Keep track of jump tables for switch instructions MachineJumpTableInfo *JumpTableInfo; + // Keep track of the function section. + MCSection *Section = nullptr; + // Keeps track of Wasm exception handling related data. This will be null for // functions that aren't using a wasm EH personality. WasmEHFuncInfo *WasmEHInfo = nullptr; @@ -330,6 +334,13 @@ bool HasEHScopes = false; bool HasEHFunclets = false; + // True if basic block sections that are generated have been sorted. + bool BBSectionsSorted = false; + // True if sections must be generated for all basic blocks. + bool BasicBlockSections = false; + // True if labels must be generated for all basic blocks. + bool BasicBlockLabels = false; + /// List of C++ TypeInfo used. std::vector TypeInfos; @@ -441,6 +452,8 @@ MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } + MCSection *getSection() const { return Section; } + void setSection(MCSection *S) { Section = S; } PseudoSourceValueManager &getPSVManager() const { return *PSVManager; } @@ -456,6 +469,10 @@ /// getFunctionNumber - Return a unique ID for the current function. unsigned getFunctionNumber() const { return FunctionNumber; } + bool getBasicBlockSections() const { return BasicBlockSections; } + bool sortBasicBlockSections(); + bool getBasicBlockLabels() const { return BasicBlockLabels; } + /// getTarget - Return the target machine this machine code is compiled with const LLVMTargetMachine &getTarget() const { return Target; } Index: llvm/include/llvm/CodeGen/TargetFrameLowering.h =================================================================== --- llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -177,6 +177,9 @@ virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; + virtual void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI) const { } + /// Replace a StackProbe stub (if any) with the actual probe code inline virtual void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologueMBB) const {} Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -65,6 +65,11 @@ MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const override; + MCSection *getSectionForMachineBasicBlock(const Function &F, + const MachineBasicBlock &MBB, + const TargetMachine &TM) + const override; + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, const Function &F) const override; Index: llvm/include/llvm/IR/BasicBlock.h =================================================================== --- llvm/include/llvm/IR/BasicBlock.h +++ llvm/include/llvm/IR/BasicBlock.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/GlobalObject.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/Value.h" @@ -428,6 +429,12 @@ Optional getIrrLoopHeaderWeight() const; + /// Set the section prefix for this function. + void setSectionPrefix(StringRef Prefix); + + /// Get the section prefix for this function. + Optional getSectionPrefix() const; + private: /// Increment the internal refcount of the number of BlockAddresses /// referencing this BasicBlock by \p Amt. Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1797,6 +1797,11 @@ return cast_or_null(getRawUnit()); } void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } + + void replaceLinkageName(StringRef NewName) { + replaceOperandWith(3, MDString::get(getContext(), NewName)); + } + DITemplateParameterArray getTemplateParams() const { return cast_or_null(getRawTemplateParams()); } Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -96,6 +96,9 @@ friend class SymbolTableListTraits; + bool BasicBlockSections = false; + bool BasicBlockLabels = false; + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is /// built on demand, so that the list isn't allocated until the first client /// needs it. The hasLazyArguments predicate returns true if the arg list @@ -159,6 +162,22 @@ /// within this function. unsigned getInstructionCount() const; + bool getBasicBlockSections() const { + return BasicBlockSections; + } + + void setBasicBlockSections(bool value) { + BasicBlockSections = value; + } + + bool getBasicBlockLabels() const { + return BasicBlockLabels; + } + + void setBasicBlockLabels(bool value) { + BasicBlockLabels = value; + } + /// Returns the FunctionType for me. FunctionType *getFunctionType() const { return cast(getValueType()); Index: llvm/include/llvm/MC/MCAsmInfo.h =================================================================== --- llvm/include/llvm/MC/MCAsmInfo.h +++ llvm/include/llvm/MC/MCAsmInfo.h @@ -392,6 +392,12 @@ // %hi(), and similar unary operators. bool HasMipsExpressions = false; + // If true, then use symbols instead of sections for relocations. This is + // true with basic block sections, as the basic block is relaxed by the + // linker. + bool RelocateWithSymbols = false; + bool RelocateWithSizeRelocs = false; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -647,6 +653,15 @@ bool canRelaxRelocations() const { return RelaxELFRelocations; } void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; } bool hasMipsExpressions() const { return HasMipsExpressions; } + bool shouldRelocateWithSymbols() const { return RelocateWithSymbols; } + bool shouldRelocateWithSizeRelocs() const { return RelocateWithSizeRelocs; } + void setRelocateWithSymbols(bool V = true) { + // Relocate with symbols and size relocs. This is currently active + // during basic block sections. If the target does not support size + // relocs, this must be split. + RelocateWithSymbols = V; + RelocateWithSizeRelocs = V; + } }; } // end namespace llvm Index: llvm/include/llvm/MC/MCDwarf.h =================================================================== --- llvm/include/llvm/MC/MCDwarf.h +++ llvm/include/llvm/MC/MCDwarf.h @@ -474,6 +474,12 @@ assert(Op == OpRegister); } + long long GetOffsetOrRegister2() const { + if (Operation == OpRegister) + return Register2; + return Offset; + } + public: /// .cfi_def_cfa defines a rule for computing CFA as: take address from /// Register and add Offset to it. @@ -601,6 +607,27 @@ assert(Operation == OpEscape); return StringRef(&Values[0], Values.size()); } + + friend hash_code hash_value(const MCCFIInstruction &Arg) { + return hash_combine(Arg.Label, Arg.Operation, Arg.Register, + Arg.GetOffsetOrRegister2()); + } + + bool operator<(const MCCFIInstruction &Other) const { + return std::make_tuple(Label, Operation, Register, GetOffsetOrRegister2()) < + std::make_tuple(Other.Label, Other.Operation, Other.Register, + Other.GetOffsetOrRegister2()); + } + + bool operator==(const MCCFIInstruction &Other) const { + return !(*this < Other) && !(Other < *this); + } + + MCCFIInstruction StripLabel() const { + MCCFIInstruction Copy = *this; + Copy.Label = nullptr; + return Copy; + } }; struct MCDwarfFrameInfo { Index: llvm/include/llvm/MC/MCTargetOptions.h =================================================================== --- llvm/include/llvm/MC/MCTargetOptions.h +++ llvm/include/llvm/MC/MCTargetOptions.h @@ -47,6 +47,7 @@ bool MCUseDwarfDirectory : 1; bool MCIncrementalLinkerCompatible : 1; bool MCPIECopyRelocations : 1; + bool MCRelocateWithSymbols : 1; bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; Index: llvm/include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -24,6 +24,7 @@ namespace llvm { class GlobalValue; +class MachineBasicBlock; class MachineModuleInfo; class Mangler; class MCContext; @@ -90,6 +91,9 @@ const Constant *C, unsigned &Align) const; + virtual MCSection *getSectionForMachineBasicBlock(const Function &F, + const MachineBasicBlock &MBB, const TargetMachine &TM) const; + /// Classify the specified global variable into a set of target independent /// categories embodied in SectionKind. static SectionKind getKindForGlobal(const GlobalObject *GO, Index: llvm/include/llvm/Target/TargetMachine.h =================================================================== --- llvm/include/llvm/Target/TargetMachine.h +++ llvm/include/llvm/Target/TargetMachine.h @@ -242,6 +242,8 @@ bool getUniqueSectionNames() const { return Options.UniqueSectionNames; } + bool getUniqueBBSectionNames() const { return Options.UniqueBBSectionNames; } + /// Return true if data objects should be emitted into their own section, /// corresponds to -fdata-sections. bool getDataSections() const { @@ -254,6 +256,16 @@ return Options.FunctionSections; } + /// If basic blocks should be emitted into their own section, + /// corresponding to -fbasicblock-sections. + llvm::BasicBlockSection::SectionMode getBasicBlockSections() const { + return Options.BasicBlockSections; + } + + bool isFunctionInBasicBlockSectionsList(const StringRef &name) const { + return Options.BasicBlockSectionsList.lookup(name); + } + /// Get a \c TargetIRAnalysis appropriate for the target. /// /// This is used to construct the new pass manager's target IR analysis pass, Index: llvm/include/llvm/Target/TargetOptions.h =================================================================== --- llvm/include/llvm/Target/TargetOptions.h +++ llvm/include/llvm/Target/TargetOptions.h @@ -15,6 +15,7 @@ #define LLVM_TARGET_TARGETOPTIONS_H #include "llvm/MC/MCTargetOptions.h" +#include "llvm/ADT/StringMap.h" namespace llvm { class MachineFunction; @@ -63,6 +64,15 @@ }; } + namespace BasicBlockSection { + enum SectionMode { + None, // Do not use Basic Block Sections. + All, // Use Basic Block Sections for all functions. + Labels, // Do not use Basic Block Sections but label basic blocks. + List // Get list of functions from a file/ + }; + } + enum class EABI { Unknown, Default, // Default means not specified @@ -114,7 +124,8 @@ EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), DisableIntegratedAS(false), RelaxELFRelocations(false), FunctionSections(false), DataSections(false), - UniqueSectionNames(true), TrapUnreachable(false), + UniqueSectionNames(true), + UniqueBBSectionNames(false), TrapUnreachable(false), NoTrapAfterNoreturn(false), EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), @@ -224,6 +235,8 @@ unsigned UniqueSectionNames : 1; + unsigned UniqueBBSectionNames : 1; + /// Emit target-specific trap instruction for 'unreachable' IR instructions. unsigned TrapUnreachable : 1; @@ -253,6 +266,11 @@ /// Emit address-significance table. unsigned EmitAddrsig : 1; + /// Emit basic blocks into separate sections. + BasicBlockSection::SectionMode BasicBlockSections = BasicBlockSection::None; + + StringMap BasicBlockSectionsList; + /// Emit debug info about parameter's entry values. unsigned EnableDebugEntryValues : 1; Index: llvm/include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -106,7 +106,10 @@ /// If the module has no strong external symbols (such a module may still have a /// semantic effect if it performs global initialization), we cannot produce a /// unique identifier for this module, so we return the empty string. -std::string getUniqueModuleId(Module *M); +/// +/// If UseModuleId is true, we include the ModuleIdentifier string. This is +/// however not guaranteed to be unique. +std::string getUniqueModuleId(Module *M, bool UseModuleId = false); } // End llvm namespace Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -659,7 +659,9 @@ EmitConstantPool(); // Print the 'header' of function. - OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(&F, TM)); + MF->setSection(getObjFileLowering().SectionForGlobal(&F, TM)); + OutStreamer->SwitchSection(MF->getSection()); + EmitVisibility(CurrentFnSym, F.getVisibility()); EmitLinkage(&F, CurrentFnSym); @@ -1040,6 +1042,10 @@ // Print out code for the function. bool HasAnyRealCode = false; int NumInstsInFunction = 0; + bool emitBasicBlockSections = MF->getBasicBlockSections(); + if (emitBasicBlockSections) + MF->sortBasicBlockSections(); + for (auto &MBB : *MF) { // Print a label for the basic block. EmitBasicBlockStart(MBB); @@ -1119,7 +1125,17 @@ } } } - + if (MF->getBasicBlockLabels() || MBB.isUniqueSection()) { + // Emit size directive for the size of this basic block. Create a symbol + // for the end of the basic block. + MCSymbol *CurrentBBEnd = OutContext.createTempSymbol(); + const MCExpr *SizeExp = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(CurrentBBEnd, OutContext), + MCSymbolRefExpr::create(MBB.getSymbol(), OutContext), OutContext); + OutStreamer->EmitLabel(CurrentBBEnd); + MBB.setEndMCSymbol(CurrentBBEnd); + OutStreamer->emitELFSize(MBB.getSymbol(), SizeExp); + } EmitBasicBlockEnd(MBB); } @@ -1153,6 +1169,10 @@ } } + // Switch to the original section if basic block sections was used. + if (emitBasicBlockSections) + OutStreamer->SwitchSection(MF->getSection()); + const Function &F = MF->getFunction(); for (const auto &BB : F) { if (!BB.hasAddressTaken()) @@ -2894,6 +2914,7 @@ /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { + bool BasicBlockSections = MF->getBasicBlockSections(); // End the previous funclet and start a new one. if (MBB.isEHFuncletEntry()) { for (const HandlerInfo &HI : Handlers) { @@ -2903,9 +2924,11 @@ } // Emit an alignment directive for this block, if needed. - const llvm::Align Align = MBB.getAlignment(); - if (Align != llvm::Align::None()) - EmitAlignment(Align); + if (MBB.pred_empty() || !BasicBlockSections) { + const llvm::Align Align = MBB.getAlignment(); + if (Align != llvm::Align::None()) + EmitAlignment(Align); + } MCCodePaddingContext Context; setupCodePaddingContext(MBB, Context); OutStreamer->EmitCodePaddingBasicBlockStart(Context); @@ -2940,19 +2963,39 @@ emitBasicBlockLoopComments(MBB, MLI, *this); } - // Print the main label for the block. + bool emitBBLabels = BasicBlockSections || MF->getBasicBlockLabels(); if (MBB.pred_empty() || - (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() && - !MBB.hasLabelMustBeEmitted())) { + (!emitBBLabels && isBlockOnlyReachableByFallthrough(&MBB) && + !MBB.isEHFuncletEntry() && !MBB.hasLabelMustBeEmitted())) { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":", false); } } else { - if (isVerbose() && MBB.hasLabelMustBeEmitted()) + if (isVerbose() && MBB.hasLabelMustBeEmitted()) { OutStreamer->AddComment("Label of block must be emitted"); + } + // For -fbasicblock-sections, switch to another section. + if (MBB.isUniqueSection()) { + OutStreamer->SwitchSection( + getObjFileLowering().getSectionForMachineBasicBlock(MF->getFunction(), + MBB, TM)); + } else if (BasicBlockSections) { + OutStreamer->SwitchSection(MF->getSection()); + } + // Emit alignment after section is created for basic block sections. + // if (MBB.isUniqueSection()) { + // if (unsigned LogAlign = MBB.getLogAlignment()) + // EmitAlignment(LogAlign); + // } OutStreamer->EmitLabel(MBB.getSymbol()); + // With BasicBlockSections, each Basic Block must handle CFI information on its own. + if (MBB.isUniqueSection()) { + for (const HandlerInfo &HI : Handlers) { + HI.Handler->beginBasicBlock(MBB); + } + } } } @@ -2960,6 +3003,18 @@ MCCodePaddingContext Context; setupCodePaddingContext(MBB, Context); OutStreamer->EmitCodePaddingBasicBlockEnd(Context); + // Check if CFI information needs to be updated for this MBB with basic block + // sections. + if (MF->getBasicBlockSections()) { + auto I = std::next(MBB.getIterator()); + const MachineBasicBlock *nextBB = (I != MF->end()) ? &*I : nullptr; + if (MBB.isUniqueSection() || + !nextBB || nextBB->isUniqueSection()) { + for (const HandlerInfo &HI : Handlers) { + HI.Handler->endBasicBlock(MBB); + } + } + } } void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, @@ -2988,6 +3043,10 @@ /// the predecessor and this block is a fall-through. bool AsmPrinter:: isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // With BasicBlock Sections, no block is a fall through. + if (MBB->isUniqueSection()) + return false; + // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isEHPad() || MBB->pred_empty()) Index: llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -46,7 +46,8 @@ } void DwarfCFIExceptionBase::endFragment() { - if (shouldEmitCFI) + // With -fbasicblock-sections, this is handled at each basic block. + if (shouldEmitCFI && !Asm->MF->getBasicBlockSections()) Asm->OutStreamer->EmitCFIEndProc(); } @@ -169,3 +170,13 @@ emitExceptionTable(); } + +void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) { + if (shouldEmitCFI) + Asm->OutStreamer->EmitCFIStartProc(/*IsSimple=*/false); +} + +void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) { + if (shouldEmitCFI) + Asm->OutStreamer->EmitCFIEndProc(); +} Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -384,7 +384,24 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); - attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + if (!Asm->MF->getBasicBlockSections()) + attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd()); + else { + SmallVector BB_List; + BB_List.push_back(RangeSpan(Asm->getFunctionBegin(), + Asm->getFunctionEnd())); + // If basic block sections are on, only the entry BB and exception + // handling BBs will be in the [getFunctionBegin(), getFunctionEnd()] + // range. Ranges for the other BBs have to be emitted separately. + for (auto &MBB : *Asm->MF) { + if (!MBB.pred_empty() && MBB.isUniqueSection()) { + BB_List.push_back( + RangeSpan(MBB.getSymbol(), + MBB.getEndMCSymbol())); + } + } + attachRangesOrLowHighPC(*SPDie, BB_List); + } if (DD->useAppleExtensionAttributes() && !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( *DD->getCurrentFunction())) @@ -504,7 +521,10 @@ void DwarfCompileUnit::attachRangesOrLowHighPC( DIE &Die, SmallVector Ranges) { - if (Ranges.size() == 1 || !DD->useRangesSection()) { + // With basic block sections, if the range spans multiple sections then this + // cannot be emitted as (low pc, high pc). + if ((Asm->TM.getBasicBlockSections() == llvm::BasicBlockSection::None) && + (Ranges.size() == 1 || !DD->useRangesSection())) { const RangeSpan &Front = Ranges.front(); const RangeSpan &Back = Ranges.back(); attachLowHighPC(Die, Front.getStart(), Back.getEnd()); @@ -516,9 +536,49 @@ DIE &Die, const SmallVectorImpl &Ranges) { SmallVector List; List.reserve(Ranges.size()); - for (const InsnRange &R : Ranges) - List.push_back(RangeSpan(DD->getLabelBeforeInsn(R.first), - DD->getLabelAfterInsn(R.second))); + for (const InsnRange &R : Ranges) { + auto *BeginLabel = DD->getLabelBeforeInsn(R.first); + auto *EndLabel = DD->getLabelAfterInsn(R.second); + + const auto *BeginMBB = R.first->getParent(); + const auto *EndBB = R.second->getParent(); + + if (BeginMBB == EndBB || !EndBB->isUniqueSection() || + Asm->MF->getBasicBlockSections() == llvm::BasicBlockSection::None) { + // Without basic block sections, there is just one continuous range. + // The same holds if EndBB is in the initial non-unique-section BB range. + List.push_back(RangeSpan(BeginLabel, EndLabel)); + continue; + } + + const auto *LastMBBInSection = BeginMBB; + + if (BeginMBB->isUniqueSection()) { + // BeginLabel lies in a unique section ending at the BeginMBB's end + // symbol. + assert(BeginMBB->getEndMCSymbol() && + "Unique BB sections should have end symbols."); + List.push_back(RangeSpan(BeginLabel, BeginMBB->getEndMCSymbol())); + } else { + // BeginLabel lies in a non-unique section, but EndLabel does not. The + // section for non-unique-section BBs ends at Asm->getFunctionEnd(). + List.push_back(RangeSpan(BeginLabel, Asm->getFunctionEnd())); + while (!std::next(LastMBBInSection)->isUniqueSection()) + ++LastMBBInSection; + } + + for (auto *MBB = std::next(LastMBBInSection); MBB != EndBB; ++MBB) { + assert(MBB->isUniqueSection() && "All non-unique-section BBs should be" + " before the unique-section ones."); + assert(MBB->getSymbol() && "Unique BB sections should have symbols."); + assert(MBB->getEndMCSymbol() && + "Unique BB sections should have end symbols."); + List.push_back(RangeSpan(MBB->getSymbol(), MBB->getEndMCSymbol())); + } + + assert(EndBB->getSymbol() && "Unique BB sections should have symbols."); + List.push_back(RangeSpan(EndBB->getSymbol(), EndLabel)); + } attachRangesOrLowHighPC(Die, std::move(List)); } Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1806,6 +1806,16 @@ // Add the range of this function to the list of ranges for the CU. TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd())); + // With basic block sections, add all basic block ranges with unique + // sections. + if (MF->getBasicBlockSections()) { + for (auto &MBB : *MF) { + if (MBB.isUniqueSection() && !MBB.pred_empty()) { + TheCU.addRange(RangeSpan(MBB.getSymbol(), MBB.getEndMCSymbol())); + } + } + } + // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram // is still needed as we need its source location. @@ -2381,11 +2391,19 @@ // * as of October 2018, at least // Ideally/in v5, this could use SectionLabels to reuse existing addresses // in the address pool to minimize object size/relocations. - Asm->emitInt8(dwarf::DW_LLE_startx_length); - unsigned idx = AddrPool.getIndex(Entry.BeginSym); - Asm->EmitULEB128(idx); - Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4); - + if (Asm->TM.getBasicBlockSections() != llvm::BasicBlockSection::None && + Asm->TM.getBasicBlockSections() != llvm::BasicBlockSection::Labels) { + // With basic block sections, symbol difference cannot be emitted as + // the can span sections. + Asm->emitInt8(dwarf::DW_LLE_startx_endx); + Asm->EmitULEB128(AddrPool.getIndex(Entry.BeginSym)); + Asm->EmitULEB128(AddrPool.getIndex(Entry.EndSym)); + } else { + Asm->emitInt8(dwarf::DW_LLE_startx_length); + unsigned idx = AddrPool.getIndex(Entry.BeginSym); + Asm->EmitULEB128(idx); + Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4); + } emitDebugLocEntryLocation(Entry, List.CU); } Asm->emitInt8(dwarf::DW_LLE_end_of_list); Index: llvm/lib/CodeGen/AsmPrinter/DwarfException.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -66,6 +66,9 @@ void beginFragment(const MachineBasicBlock *MBB, ExceptionSymbolProvider ESP) override; + + void beginBasicBlock(const MachineBasicBlock &MBB) override; + void endBasicBlock(const MachineBasicBlock &MBB) override; }; class LLVM_LIBRARY_VISIBILITY ARMException : public DwarfCFIExceptionBase { Index: llvm/lib/CodeGen/CFIInstrInserter.cpp =================================================================== --- llvm/lib/CodeGen/CFIInstrInserter.cpp +++ llvm/lib/CodeGen/CFIInstrInserter.cpp @@ -247,6 +247,8 @@ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); bool InsertedCFIInstr = false; + MF.sortBasicBlockSections(); + for (MachineBasicBlock &MBB : MF) { // Skip the first MBB in a function if (MBB.getNumber() == MF.front().getNumber()) continue; @@ -255,11 +257,17 @@ auto MBBI = MBBInfo.MBB->begin(); DebugLoc DL = MBBInfo.MBB->findDebugLoc(MBBI); - if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) { + // If the current MBB will be placed in a unique section, a full DefCfa + // must be emitted. + const bool ForceFullCFA = MBB.isUniqueSection(); + + if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset || + ForceFullCFA) { // If both outgoing offset and register of a previous block don't match // incoming offset and register of this block, add a def_cfa instruction // with the correct offset and register for this block. - if (PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) { + if (PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister || + ForceFullCFA) { unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa( nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&MBB))); BuildMI(*MBBInfo.MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) @@ -287,6 +295,13 @@ .addCFIIndex(CFIIndex); InsertedCFIInstr = true; } + + if (ForceFullCFA) { + MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMoves( + *MBBInfo.MBB, MBBI); + InsertedCFIInstr = true; + } + PrevMBBInfo = &MBBInfo; } return InsertedCFIInstr; Index: llvm/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -433,6 +433,17 @@ ProfileSummaryInfo *PSI = &getAnalysis().getPSI(); + + if (TM && TM->getBasicBlockSections() == llvm::BasicBlockSection::All) + F.setBasicBlockSections(true); + + if (TM && TM->getBasicBlockSections() == llvm::BasicBlockSection::List && + TM->isFunctionInBasicBlockSectionsList(F.getName())) + F.setBasicBlockSections(true); + + if (TM && TM->getBasicBlockSections() == llvm::BasicBlockSection::Labels) + F.setBasicBlockLabels(true); + if (ProfileGuidedSectionPrefix) { if (PSI->isFunctionHotInCallGraph(&F, *BFI)) F.setSectionPrefix(".hot"); Index: llvm/lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -66,6 +66,7 @@ TmpAsmInfo->setCompressDebugSections(Options.CompressDebugSections); TmpAsmInfo->setRelaxELFRelocations(Options.RelaxELFRelocations); + TmpAsmInfo->setRelocateWithSymbols(Options.MCOptions.MCRelocateWithSymbols); if (Options.ExceptionModel != ExceptionHandling::None) TmpAsmInfo->setExceptionsType(Options.ExceptionModel); Index: llvm/lib/CodeGen/MachineBasicBlock.cpp =================================================================== --- llvm/lib/CodeGen/MachineBasicBlock.cpp +++ llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -61,12 +61,32 @@ const MachineFunction *MF = getParent(); MCContext &Ctx = MF->getContext(); auto Prefix = Ctx.getAsmInfo()->getPrivateLabelPrefix(); + + bool BasicBlockSymbols = MF->getBasicBlockSections() || + MF->getBasicBlockLabels(); + auto Delimiter = BasicBlockSymbols ? "." : "_"; assert(getNumber() >= 0 && "cannot get label for unreachable MBB"); - CachedMCSymbol = Ctx.getOrCreateSymbol(Twine(Prefix) + "BB" + - Twine(MF->getFunctionNumber()) + - "_" + Twine(getNumber())); - } + // With Basic Block Sections, we emit a symbol for every basic block. To + // keep the size of strtab small, we choose a unary encoding which can + // compress the symbol names significantly. The basic blocks for function + // foo are named a.BB.foo, aa.BB.foo, and so on. + if (BasicBlockSymbols) { + std::function Unary = [&Unary](unsigned num) { + if (num == 0) return std::string(""); + if (num == 1) return std::string("a"); + std::string s = Unary(num / 2); + return s + s + Unary(num % 2); + }; + CachedMCSymbol = Ctx.getOrCreateSymbol(Unary(getNumber()) + + Twine(Delimiter) + "BB" + Twine(Delimiter) + + Twine(MF->getName())); + } else { + CachedMCSymbol = Ctx.getOrCreateSymbol(Twine(Prefix) + "BB" + + Twine(MF->getFunctionNumber()) + Twine(Delimiter) + + Twine(getNumber())); + } + } return CachedMCSymbol; } @@ -529,6 +549,34 @@ getParent()->splice(++NewBefore->getIterator(), getIterator()); } +// Insert unconditional jumps to the basic block to which there is +// a fall through. +void MachineBasicBlock::insertUnconditionalFallthroughBranch() { + MachineBasicBlock *Fallthrough = getFallThrough(); + + if (Fallthrough == nullptr) + return; + + // If this basic block and the Fallthrough basic block are in the same + // section then do not insert the jump. + if (!this->isUniqueSection() && !Fallthrough->isUniqueSection()) + return; + + const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo(); + SmallVector Cond; + MachineBasicBlock *TBB = nullptr, *FBB = nullptr; + + // If a branch to the fall through block already exists, return. + if (!TII->analyzeBranch(*this, TBB, FBB, Cond) && + (TBB == Fallthrough || FBB == Fallthrough)) { + return; + } + + Cond.clear(); + DebugLoc DL = findBranchDebugLoc(); + TII->insertBranch(*this, Fallthrough, nullptr, Cond, DL); +} + void MachineBasicBlock::updateTerminator() { const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo(); // A block with no successors has no concerns with fall-through edges. Index: llvm/lib/CodeGen/MachineBlockPlacement.cpp =================================================================== --- llvm/lib/CodeGen/MachineBlockPlacement.cpp +++ llvm/lib/CodeGen/MachineBlockPlacement.cpp @@ -3125,7 +3125,6 @@ MBFI->view("MBP." + MF.getName(), false); } - // We always return true as we have no way to track whether the final order // differs from the original order. return true; Index: llvm/lib/CodeGen/MachineFunction.cpp =================================================================== --- llvm/lib/CodeGen/MachineFunction.cpp +++ llvm/lib/CodeGen/MachineFunction.cpp @@ -181,6 +181,16 @@ Alignment = std::max(Alignment, STI->getTargetLowering()->getPrefFunctionAlignment()); + if (Target.getBasicBlockSections() == llvm::BasicBlockSection::All || + F.getBasicBlockSections() || + (Target.getBasicBlockSections() == llvm::BasicBlockSection::List && + Target.isFunctionInBasicBlockSectionsList(F.getName()))) + BasicBlockSections = true; + + if (Target.getBasicBlockSections() == llvm::BasicBlockSection::Labels || + F.getBasicBlockLabels()) + BasicBlockLabels = true; + if (AlignAllFunctions) Alignment = llvm::Align(1ULL << AlignAllFunctions); @@ -322,6 +332,50 @@ MBBNumbering.resize(BlockNo); } +/// HasEHInfo - Return true is this Machine Basic Block is a landing pad or +/// it has EHLabels used in exception tables. +static bool HasEHInfo(const MachineBasicBlock &MBB) { + if (MBB.isEHPad() || MBB.isEHFuncletEntry()) + return true; + for (auto &MI : MBB) { + if (MI.isEHLabel()) + return true; + } + return false; +} + +bool MachineFunction::sortBasicBlockSections() { + // This should only be done once no matter how many times it is called. + if (this->BBSectionsSorted || !this->getBasicBlockSections()) + return false; + + DenseMap MBBOrder; + unsigned MBBOrderN = 0; + + for (auto &MBB : *this) { + // A unique BB section can only be created if this basic block is not + // used for exception table computations. + if (!MBB.pred_empty() && !HasEHInfo(MBB)) + MBB.setIsUniqueSection(); + MBBOrder[&MBB] = MBBOrderN++; + } + + // With -fbasicblock-sections, fall through blocks must be made + // explicitly reachable. Do this after unique sections is set as + // unnecessary fallthroughs can be avoided. + for (auto &MBB : *this) { + MBB.insertUnconditionalFallthroughBranch(); + } + + this->sort(([&](MachineBasicBlock &X, MachineBasicBlock &Y) { + return (X.isUniqueSection() == Y.isUniqueSection()) ? + (MBBOrder[&X] < MBBOrder[&Y]) : !X.isUniqueSection(); + })); + + this->BBSectionsSorted = true; + return true; +} + /// Allocate a new MachineInstr. Use this instead of `new MachineInstr'. MachineInstr *MachineFunction::CreateMachineInstr(const MCInstrDesc &MCID, const DebugLoc &DL, Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -21,6 +21,8 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/IR/Comdat.h" @@ -749,6 +751,26 @@ return DataRelROSection; } +MCSection *TargetLoweringObjectFileELF::getSectionForMachineBasicBlock( + const Function &F, const MachineBasicBlock &MBB, const TargetMachine &TM) + const { + SmallString<128> Name; + Name = (static_cast(MBB.getParent()->getSection()))->getSectionName(); + if (TM.getUniqueBBSectionNames()) { + Name += "."; + Name += MBB.getSymbol()->getName(); + } + unsigned UniqueID = NextUniqueID++; + unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_EXECINSTR; + std::string GroupName = ""; + if (F.hasComdat()) { + Flags |= ELF::SHF_GROUP; + GroupName = F.getComdat()->getName(); + } + return getContext().getELFSection(Name, ELF::SHT_PROGBITS, + Flags, 0, GroupName, UniqueID); +} + static MCSectionELF *getStaticStructorSection(MCContext &Ctx, bool UseInitArray, bool IsCtor, unsigned Priority, const MCSymbol *KeySym) { Index: llvm/lib/IR/BasicBlock.cpp =================================================================== --- llvm/lib/IR/BasicBlock.cpp +++ llvm/lib/IR/BasicBlock.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Type.h" #include Index: llvm/lib/IR/Globals.cpp =================================================================== --- llvm/lib/IR/Globals.cpp +++ llvm/lib/IR/Globals.cpp @@ -237,6 +237,10 @@ if (const Function *F = dyn_cast(this)) return F->empty() && !F->isMaterializable(); + // A basic block is always defined. + if (dyn_cast(this)) + return false; + // Aliases and ifuncs are always definitions. assert(isa(this)); return false; Index: llvm/lib/IR/Mangler.cpp =================================================================== --- llvm/lib/IR/Mangler.cpp +++ llvm/lib/IR/Mangler.cpp @@ -118,7 +118,10 @@ PrefixTy = Private; } - const DataLayout &DL = GV->getParent()->getDataLayout(); + const DataLayout &DL = (isa(GV) ? + dyn_cast(GV)->getParent()->getParent()->getDataLayout() : + GV->getParent()->getDataLayout()); + if (!GV->hasName()) { // Get the ID for the global, assigning a new one if we haven't got one // already. Index: llvm/lib/MC/ELFObjectWriter.cpp =================================================================== --- llvm/lib/MC/ELFObjectWriter.cpp +++ llvm/lib/MC/ELFObjectWriter.cpp @@ -39,6 +39,7 @@ #include "llvm/Support/Alignment.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -1344,6 +1345,7 @@ if (!RefA) return false; + const auto &MAI = Asm.getContext().getAsmInfo(); MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); switch (Kind) { default: @@ -1368,6 +1370,12 @@ case MCSymbolRefExpr::VK_PPC_GOT_HI: case MCSymbolRefExpr::VK_PPC_GOT_HA: return true; + + case MCSymbolRefExpr::VK_SIZE: + if (MAI->shouldRelocateWithSymbols()) + return true; + else + break; } // An undefined symbol is not in any section, so the relocation has to point @@ -1436,7 +1444,7 @@ if (TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type)) return true; - return false; + return MAI->shouldRelocateWithSymbols(); } void ELFObjectWriter::recordRelocation(MCAssembler &Asm, Index: llvm/lib/MC/MCDwarf.cpp =================================================================== --- llvm/lib/MC/MCDwarf.cpp +++ llvm/lib/MC/MCDwarf.cpp @@ -29,6 +29,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" @@ -39,12 +40,18 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include #include #include #include using namespace llvm; +static cl::opt NoDedupFDEToCIE( + "no-dedup-fde-to-cie", + cl::desc("Moves FDE instructions at the beginning of an FDE to CIE"), + cl::init(false), cl::Hidden); + /// Manage the .debug_line_str section contents, if we use it. class llvm::MCDwarfLineStr { MCSymbol *LineStrLabel = nullptr; @@ -847,6 +854,20 @@ MCOS->EmitIntValue(0, 1); } +static const MCExpr *MakeSizeExpr(MCStreamer &MCOS, MCSymbol &Start, + const MCSymbol &End) { + const MCExpr *Range = MakeStartMinusEndExpr(MCOS, Start, End, 0); + + auto MAI = MCOS.getContext().getAsmInfo(); + if (!MAI->shouldRelocateWithSizeRelocs()) + return forceExpAbs(MCOS, Range); + + MCOS.emitELFSize(&Start, Range); + const MCExpr *RelocatableRange = MCSymbolRefExpr::create( + &Start, MCSymbolRefExpr::VK_SIZE, MCOS.getContext()); + return RelocatableRange; +} + // When generating dwarf for assembly source files this emits the data for // .debug_aranges section. This section contains a header and a table of pairs // of PointerSize'ed values for the address and size of section(s) with line @@ -901,17 +922,16 @@ // Now emit the table of pairs of PointerSize'ed values for the section // addresses and sizes. for (MCSection *Sec : Sections) { - const MCSymbol *StartSymbol = Sec->getBeginSymbol(); + MCSymbol *StartSymbol = Sec->getBeginSymbol(); MCSymbol *EndSymbol = Sec->getEndSymbol(context); assert(StartSymbol && "StartSymbol must not be NULL"); assert(EndSymbol && "EndSymbol must not be NULL"); const MCExpr *Addr = MCSymbolRefExpr::create( StartSymbol, MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, - *StartSymbol, *EndSymbol, 0); + const MCExpr *Size = MakeSizeExpr(*MCOS, *StartSymbol, *EndSymbol); MCOS->EmitValue(Addr, AddrSize); - emitAbsValue(*MCOS, Size, AddrSize); + MCOS->EmitValue(Size, AddrSize); } // And finally the pair of terminating zeros. @@ -1106,7 +1126,7 @@ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); for (MCSection *Sec : Sections) { - const MCSymbol *StartSymbol = Sec->getBeginSymbol(); + MCSymbol *StartSymbol = Sec->getBeginSymbol(); MCSymbol *EndSymbol = Sec->getEndSymbol(context); assert(StartSymbol && "StartSymbol must not be NULL"); assert(EndSymbol && "EndSymbol must not be NULL"); @@ -1118,10 +1138,10 @@ MCOS->EmitValue(SectionStartAddr, AddrSize); // Emit a range list entry spanning this section - const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, - *StartSymbol, *EndSymbol, 0); + const MCExpr *SectionSize = MakeSizeExpr(*MCOS, *StartSymbol, *EndSymbol); + MCOS->EmitIntValue(0, AddrSize); - emitAbsValue(*MCOS, SectionSize, AddrSize); + MCOS->EmitValue(SectionSize, AddrSize); } // Emit end of list entry @@ -1316,7 +1336,8 @@ void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame, bool LastInSection, const MCSymbol &SectionStart); void EmitCFIInstructions(ArrayRef Instrs, - MCSymbol *BaseLabel); + MCSymbol *BaseLabel, bool EmitDeduped, + bool EmitNotDeduped); void EmitCFIInstruction(const MCCFIInstruction &Instr); }; @@ -1457,14 +1478,41 @@ llvm_unreachable("Unhandled case in switch"); } +static bool ShouldBeDeduped(const MCCFIInstruction &Instr, + const MCSymbol *BaseLabel, + const MCObjectStreamer &Streamer) { + if (NoDedupFDEToCIE || + !Streamer.getContext().getAsmInfo()->shouldRelocateWithSymbols()) + return false; + + if (!BaseLabel || !BaseLabel->isDefined() || !BaseLabel->isInSection()) + return false; + + MCSymbol *Label = Instr.getLabel(); + + if (!Label || !Label->isDefined() || !Label->isInSection()) + return false; + + return &Label->getSection() == &BaseLabel->getSection() && + Label->getOffset() == BaseLabel->getOffset(); +} + /// Emit frame instructions to describe the layout of the frame. void FrameEmitterImpl::EmitCFIInstructions(ArrayRef Instrs, - MCSymbol *BaseLabel) { + MCSymbol *BaseLabel, + bool EmitDeduped = true, + bool EmitNotDeduped = true) { + bool InDedupedRange = true; for (const MCCFIInstruction &Instr : Instrs) { MCSymbol *Label = Instr.getLabel(); // Throw out move if the label is invalid. if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + InDedupedRange &= ShouldBeDeduped(Instr, BaseLabel, Streamer); + if ((InDedupedRange && !EmitDeduped) || + (!InDedupedRange && !EmitNotDeduped)) + continue; + // Advance row if new location. if (BaseLabel && Label) { MCSymbol *ThisSym = Label; @@ -1519,9 +1567,8 @@ Streamer.EmitSymbolValue(Frame.Begin, Size); // Range Length - const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, - *Frame.End, 0); - emitAbsValue(Streamer, Range, 4); + const MCExpr *Range = MakeSizeExpr(Streamer, *Frame.Begin, *Frame.End); + Streamer.EmitValue(Range, 4); // Compact Encoding Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); @@ -1661,7 +1708,8 @@ if (!Frame.IsSimple) { const std::vector &Instructions = MAI->getInitialFrameState(); - EmitCFIInstructions(Instructions, nullptr); + EmitCFIInstructions(Instructions, nullptr, true, true); + EmitCFIInstructions(Frame.Instructions, Frame.Begin, true, false); } InitialCFAOffset = CFAOffset; @@ -1711,9 +1759,8 @@ emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH); // PC Range - const MCExpr *Range = - MakeStartMinusEndExpr(Streamer, *frame.Begin, *frame.End, 0); - emitAbsValue(Streamer, Range, PCSize); + const MCExpr *Range = MakeSizeExpr(Streamer, *frame.Begin, *frame.End); + Streamer.EmitValue(Range, PCSize); if (IsEH) { // Augmentation Data Length @@ -1730,7 +1777,7 @@ } // Call Frame Instructions - EmitCFIInstructions(frame.Instructions, frame.Begin); + EmitCFIInstructions(frame.Instructions, frame.Begin, false, true); // Padding // The size of a .eh_frame section has to be a multiple of the alignment @@ -1747,27 +1794,50 @@ struct CIEKey { static const CIEKey getEmptyKey() { return CIEKey(nullptr, 0, -1, false, false, static_cast(INT_MAX), - false); + false, nullptr); } static const CIEKey getTombstoneKey() { return CIEKey(nullptr, -1, 0, false, false, static_cast(INT_MAX), - false); + false, nullptr); + } + + static std::vector + getDedupedInstructions(const std::vector &Instructions, + const MCSymbol *BaseSymbol, + const MCObjectStreamer &Streamer) { + std::vector DedupedInstructions; + for (const auto &Instr : Instructions) { + MCSymbol *Label = Instr.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) + continue; // Not emitted, in dead code. + + if (!ShouldBeDeduped(Instr, BaseSymbol, Streamer)) + break; + + DedupedInstructions.push_back(Instr.StripLabel()); + } + return DedupedInstructions; } CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding, unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple, - unsigned RAReg, bool IsBKeyFrame) + unsigned RAReg, bool IsBKeyFrame, + const std::vector *DedupedInstructions) : Personality(Personality), PersonalityEncoding(PersonalityEncoding), LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame), - IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame) {} + IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame), + DedupedInstructions(DedupedInstructions) {} - explicit CIEKey(const MCDwarfFrameInfo &Frame) + explicit CIEKey(const MCDwarfFrameInfo &Frame, + const std::vector *DedupedInstructions) : Personality(Frame.Personality), PersonalityEncoding(Frame.PersonalityEncoding), LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame), IsSimple(Frame.IsSimple), RAReg(Frame.RAReg), - IsBKeyFrame(Frame.IsBKeyFrame) {} + IsBKeyFrame(Frame.IsBKeyFrame), + DedupedInstructions(DedupedInstructions) {} StringRef PersonalityName() const { if (!Personality) @@ -1775,12 +1845,20 @@ return Personality->getName(); } + const std::vector GetDedupedInstructions() const { + if (!DedupedInstructions) + return {}; + return *DedupedInstructions; + } + bool operator<(const CIEKey &Other) const { return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding, - IsSignalFrame, IsSimple, RAReg) < + IsSignalFrame, IsSimple, RAReg, + GetDedupedInstructions()) < std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding, Other.LsdaEncoding, Other.IsSignalFrame, - Other.IsSimple, Other.RAReg); + Other.IsSimple, Other.RAReg, + Other.GetDedupedInstructions()); } const MCSymbol *Personality; @@ -1790,6 +1868,7 @@ bool IsSimple; unsigned RAReg; bool IsBKeyFrame; + const std::vector *DedupedInstructions; }; } // end anonymous namespace @@ -1801,9 +1880,12 @@ static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); } static unsigned getHashValue(const CIEKey &Key) { + const auto &DedupedInstructions = Key.GetDedupedInstructions(); return static_cast(hash_combine( Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, - Key.IsSignalFrame, Key.IsSimple, Key.RAReg, Key.IsBKeyFrame)); + Key.IsSignalFrame, Key.IsSimple, Key.RAReg, Key.IsBKeyFrame, + hash_combine_range(DedupedInstructions.begin(), + DedupedInstructions.end()))); } static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { @@ -1812,7 +1894,8 @@ LHS.LsdaEncoding == RHS.LsdaEncoding && LHS.IsSignalFrame == RHS.IsSignalFrame && LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg && - LHS.IsBKeyFrame == RHS.IsBKeyFrame; + LHS.IsBKeyFrame == RHS.IsBKeyFrame && + LHS.GetDedupedInstructions() == RHS.GetDedupedInstructions(); } }; @@ -1856,8 +1939,15 @@ MCSymbol *SectionStart = Context.createTempSymbol(); Streamer.EmitLabel(SectionStart); + std::map> DedupedInstructions; DenseMap CIEStarts; + for (const auto &Frame : FrameArray) { + DedupedInstructions[Frame.Begin] = + CIEKey::getDedupedInstructions(Frame.Instructions, Frame.Begin, + Streamer); + } + const MCSymbol *DummyDebugKey = nullptr; bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind(); // Sort the FDEs by their corresponding CIE before we emit them. @@ -1866,8 +1956,9 @@ // an FDE refers to a CIE other than the closest previous CIE. std::vector FrameArrayX(FrameArray.begin(), FrameArray.end()); llvm::stable_sort(FrameArrayX, - [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) { - return CIEKey(X) < CIEKey(Y); + [&](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) { + return CIEKey(X, &DedupedInstructions.at(X.Begin)) < + CIEKey(Y, &DedupedInstructions.at(Y.Begin)); }); for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) { const MCDwarfFrameInfo &Frame = *I; @@ -1878,7 +1969,7 @@ // of by the compact unwind encoding. continue; - CIEKey Key(Frame); + CIEKey Key(Frame, &DedupedInstructions.at(Frame.Begin)); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; if (!CIEStart) CIEStart = &Emitter.EmitCIE(Frame); Index: llvm/lib/MC/MCTargetOptions.cpp =================================================================== --- llvm/lib/MC/MCTargetOptions.cpp +++ llvm/lib/MC/MCTargetOptions.cpp @@ -15,7 +15,8 @@ : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false), MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false), - MCPIECopyRelocations(false), ShowMCEncoding(false), ShowMCInst(false), + MCPIECopyRelocations(false), MCRelocateWithSymbols(false), + ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), PreserveAsmComments(true) {} StringRef MCTargetOptions::getABIName() const { Index: llvm/lib/Target/AArch64/AArch64FrameLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -25,7 +25,7 @@ true /*StackRealignable*/) {} void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI) const; + MachineBasicBlock::iterator MBBI) const override; MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, Index: llvm/lib/Target/TargetLoweringObjectFile.cpp =================================================================== --- llvm/lib/Target/TargetLoweringObjectFile.cpp +++ llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -149,6 +149,10 @@ if (isa(GO)) return SectionKind::getText(); + // Basic blocks are classified as text sections. + if (isa(GO)) + return SectionKind::getText(); + // Global variables require more detailed analysis. const auto *GVar = cast(GO); @@ -301,6 +305,12 @@ return DataSection; } +MCSection *TargetLoweringObjectFile::getSectionForMachineBasicBlock( + const Function &F, const MachineBasicBlock &MBB, const TargetMachine &TM) + const { + return nullptr; +} + /// getTTypeGlobalReference - Return an MCExpr to use for a /// reference to the specified global variable from exception /// handling information. Index: llvm/lib/Target/X86/X86FrameLowering.h =================================================================== --- llvm/lib/Target/X86/X86FrameLowering.h +++ llvm/lib/Target/X86/X86FrameLowering.h @@ -58,6 +58,9 @@ void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override; + void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI) const override; + void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL) const; Index: llvm/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86FrameLowering.cpp +++ llvm/lib/Target/X86/X86FrameLowering.cpp @@ -457,6 +457,27 @@ .addCFIIndex(CFIIndex); } +void X86FrameLowering::emitCalleeSavedFrameMoves( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { + emitCalleeSavedFrameMoves(MBB, MBBI, DebugLoc{}); + + MachineFunction &MF = *MBB.getParent(); + if (hasFP(MF)) { + const MachineModuleInfo &MMI = MF.getMMI(); + const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); + const unsigned FramePtr = TRI->getFrameRegister(MF); + const unsigned MachineFramePtr = + STI.isTarget64BitILP32() + ? unsigned(getX86SubSuperRegister(FramePtr, 64)) + : FramePtr; + unsigned DwarfReg = MRI->getDwarfRegNum(MachineFramePtr, true); + // Offset = space for return address + size of the frame pointer itself. + unsigned Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4); + BuildCFI(MBB, MBBI, DebugLoc{}, + MCCFIInstruction::createOffset(nullptr, DwarfReg, -Offset)); + } +} + void X86FrameLowering::emitCalleeSavedFrameMoves( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL) const { Index: llvm/lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -249,7 +249,8 @@ }); } -std::string llvm::getUniqueModuleId(Module *M) { +std::string llvm::getUniqueModuleId(Module *M, + bool UseModuleId) { MD5 Md5; bool ExportsSymbols = false; auto AddGlobal = [&](GlobalValue &GV) { @@ -270,8 +271,17 @@ for (auto &IF : M->ifuncs()) AddGlobal(IF); - if (!ExportsSymbols) - return ""; + // Using only module id is not guaranteed to keep this unique. So we augment + // the hash with the module id. This also handles the case when we have + // multiple definitions of the same globals in different modules (allowed by + // the "-z muldefs" linker flag). + if (UseModuleId && !M->getModuleIdentifier().empty()) { + Md5.update(M->getModuleIdentifier()); + Md5.update(ArrayRef{0}); + } else { + if (!ExportsSymbols) + return ""; + } MD5::MD5Result R; Md5.final(R); Index: llvm/test/CodeGen/X86/basicblock-sections.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/basicblock-sections.ll @@ -0,0 +1,36 @@ +; RUN: llc < %s -mtriple=x86_64-pc-linux -function-sections -basicblock-sections=all -unique-bb-section-names | FileCheck %s -check-prefix=LINUX-SECTIONS +; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -function-sections -basicblock-sections=all -unique-bb-section-names | FileCheck %s -check-prefix=LINUX-SECTIONS + +define void @_Z3bazb(i1 zeroext) { + %2 = alloca i8, align 1 + %3 = zext i1 %0 to i8 + store i8 %3, i8* %2, align 1 + %4 = load i8, i8* %2, align 1 + %5 = trunc i8 %4 to i1 + br i1 %5, label %6, label %8 + +6: ; preds = %1 + %7 = call i32 @_Z3barv() + br label %10 + +8: ; preds = %1 + %9 = call i32 @_Z3foov() + br label %10 + +10: ; preds = %8, %6 + ret void +} + +declare i32 @_Z3barv() #1 + +declare i32 @_Z3foov() #1 + + +; LINUX-SECTIONS: .section .text._Z3bazb,"ax",@progbits +; LINUX-SECTIONS: _Z3bazb: +; LINUX-SECTIONS: .section .text._Z3bazb.a.BB._Z3bazb,"ax",@progbits,unique,1 +; LINUX-SECTIONS: a.BB._Z3bazb: +; LINUX-SECTIONS: .size a.BB._Z3bazb, .Ltmp0-a.BB._Z3bazb +; LINUX-SECTIONS: .section .text._Z3bazb.aa.BB._Z3bazb,"ax",@progbits,unique,2 +; LINUX-SECTIONS: aa.BB._Z3bazb: +; LINUX-SECTIONS: .size aa.BB._Z3bazb, .Ltmp1-aa.BB._Z3bazb Index: llvm/test/DebugInfo/X86/basicblock-sections-cfi.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/basicblock-sections-cfi.ll @@ -0,0 +1,111 @@ +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-unknown-linux-gnu -filetype=asm -o - | FileCheck --check-prefix=SECTIONS_CFI %s +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o - | llvm-dwarfdump --debug-frame - | FileCheck --check-prefix=DEBUG_FRAME %s + +; From: +; int foo(int a) { +; if (a > 20) +; return 2; +; else +; return 0; +; } + +; SECTIONS_CFI: _Z3fooi +; SECTIONS_CFI: .cfi_startproc +; SECTIONS_CFI: .cfi_def_cfa_offset +; SECTIONS_CFI: .cfi_def_cfa_register +; SECTIONS_CFI: .cfi_endproc + +; SECTIONS_CFI: a.BB._Z3fooi +; SECTIONS_CFI-NEXT: .cfi_startproc +; SECTIONS_CFI-NEXT: .cfi_def_cfa +; SECTIONS_CFI-NEXT: .cfi_offset +; SECTIONS_CFI: .cfi_endproc + +; SECTIONS_CFI: aa.BB._Z3fooi +; SECTIONS_CFI-NEXT: .cfi_startproc +; SECTIONS_CFI-NEXT: .cfi_def_cfa +; SECTIONS_CFI-NEXT: .cfi_offset +; SECTIONS_CFI: .cfi_endproc + + +; There must be 2 CIEs and 4 FDEs + +; DEBUG_FRAME: .debug_frame contents + +; DEBUG_FRAME: CIE +; DEBUG_FRAME: DW_CFA_def_cfa +; DEBUG_FRAME: DW_CFA_offset + +; DEBUG_FRAME: FDE cie= +; DEBUG_FRAME: DW_CFA_def_cfa_offset +; DEBUG_FRAME: DW_CFA_def_cfa_register + +; DEBUG_FRAME: CIE +; DEBUG_FRAME: DW_CFA_def_cfa +; DEBUG_FRAME: DW_CFA_def_cfa + +; DEBUG_FRAME: FDE cie= + +; DEBUG_FRAME: FDE cie= + +; DEBUG_FRAME: FDE cie= +; DEBUG_FRAME: DW_CFA_def_cfa + + +source_filename = "debuginfo.cc" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @_Z3fooi(i32 %0) #0 !dbg !7 { + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + call void @llvm.dbg.declare(metadata i32* %3, metadata !11, metadata !DIExpression()), !dbg !12 + %4 = load i32, i32* %3, align 4, !dbg !13 + %5 = icmp sgt i32 %4, 20, !dbg !15 + br i1 %5, label %6, label %7, !dbg !16 + +6: ; preds = %1 + store i32 2, i32* %2, align 4, !dbg !17 + br label %8, !dbg !17 + +7: ; preds = %1 + store i32 0, i32* %2, align 4, !dbg !18 + br label %8, !dbg !18 + +8: ; preds = %7, %6 + %9 = load i32, i32* %2, align 4, !dbg !19 + ret i32 %9, !dbg !19 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "debuginfo.cc", directory: "/g/tmsriram/Projects_2019/github_repo/Examples") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)"} +!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!12 = !DILocation(line: 1, column: 13, scope: !7) +!13 = !DILocation(line: 2, column: 7, scope: !14) +!14 = distinct !DILexicalBlock(scope: !7, file: !1, line: 2, column: 7) +!15 = !DILocation(line: 2, column: 9, scope: !14) +!16 = !DILocation(line: 2, column: 7, scope: !7) +!17 = !DILocation(line: 3, column: 5, scope: !14) +!18 = !DILocation(line: 5, column: 5, scope: !14) +!19 = !DILocation(line: 6, column: 1, scope: !7) Index: llvm/test/DebugInfo/X86/basicblock-sections-cfiinstr.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/basicblock-sections-cfiinstr.ll @@ -0,0 +1,143 @@ +; RUN: llc -O3 %s -mtriple=x86_64-unknown-linux-gnu -filetype=asm --basicblock-sections=all -stop-after=cfi-instr-inserter -o - | FileCheck --check-prefix=CFI_INSTR %s + +; CFI_INSTR: _Z7computebiiiiiiiiiiii +; CFI_INSTR: bb.0 +; CFI_INSTR: CFI_INSTRUCTION def_cfa_offset +; CFI_INSTR: bb.1 +; CFI_INSTR: CFI_INSTRUCTION def_cfa $rsp +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR: bb.2 +; CFI_INSTR: CFI_INSTRUCTION def_cfa $rsp +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR: bb.3 +; CFI_INSTR: CFI_INSTRUCTION def_cfa $rsp +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset +; CFI_INSTR-NEXT: CFI_INSTRUCTION offset + +; From: +; int compute(bool k, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int pa, int pb, int pc) { +; int result; +; if (k) +; result = p1 * p2 + p3 / p4 - p5 * p6 + p7 / p8 - p9 * pa + pb / pc; +; else +; result = p1 / p2 - p3 * p4 + p5 / p6 - p7 * p8 + p9 / pa - pb * pc; +; return result; +; } + +; ModuleID = 'use_regs.tmp.bc' +source_filename = "use_regs.cc" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: norecurse nounwind readnone uwtable +define dso_local i32 @_Z7computebiiiiiiiiiiii(i1 zeroext %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12) local_unnamed_addr #0 !dbg !7 { + call void @llvm.dbg.value(metadata i1 %0, metadata !13, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %1, metadata !14, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %2, metadata !15, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %3, metadata !16, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %4, metadata !17, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %5, metadata !18, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %6, metadata !19, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %7, metadata !20, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %8, metadata !21, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %9, metadata !22, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %10, metadata !23, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %11, metadata !24, metadata !DIExpression()), !dbg !27 + call void @llvm.dbg.value(metadata i32 %12, metadata !25, metadata !DIExpression()), !dbg !27 + br i1 %0, label %14, label %22, !dbg !28 + +14: ; preds = %13 + %15 = mul nsw i32 %2, %1, !dbg !29 + %16 = sdiv i32 %3, %4, !dbg !31 + %.neg28 = mul i32 %6, %5 + %17 = sdiv i32 %7, %8, !dbg !32 + %.neg29 = mul i32 %10, %9 + %18 = sdiv i32 %11, %12, !dbg !33 + %reass.add30 = add i32 %.neg29, %.neg28 + %19 = sub i32 %15, %reass.add30, !dbg !34 + %20 = add i32 %19, %16, !dbg !35 + %21 = add i32 %20, %17, !dbg !36 + br label %28, !dbg !37 + +22: ; preds = %13 + %23 = sdiv i32 %1, %2, !dbg !38 + %.neg = mul i32 %4, %3 + %24 = sdiv i32 %5, %6, !dbg !39 + %.neg25 = mul i32 %8, %7 + %25 = sdiv i32 %9, %10, !dbg !40 + %.neg26 = mul i32 %12, %11 + %reass.add = add i32 %.neg25, %.neg + %reass.add27 = add i32 %reass.add, %.neg26 + %26 = sub i32 %23, %reass.add27, !dbg !41 + %27 = add i32 %26, %24, !dbg !42 + call void @llvm.dbg.value(metadata i32 %29, metadata !26, metadata !DIExpression()), !dbg !27 + br label %28 + +28: ; preds = %22, %14 + %.sink32 = phi i32 [ %25, %22 ], [ %18, %14 ] + %.sink = phi i32 [ %27, %22 ], [ %21, %14 ] + %29 = add i32 %.sink, %.sink32, !dbg !43 + call void @llvm.dbg.value(metadata i32 %29, metadata !26, metadata !DIExpression()), !dbg !27 + ret i32 %29, !dbg !44 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { norecurse nounwind readnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (git@github.com:google/llvm-propeller.git e414756c805463af90acd9bff57e6b1c805b7925)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "use_regs.cc", directory: "/g/tmsriram/Projects_2019/github_repo/Examples") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (git@github.com:google/llvm-propeller.git e414756c805463af90acd9bff57e6b1c805b7925)"} +!7 = distinct !DISubprogram(name: "compute", linkageName: "_Z7computebiiiiiiiiiiii", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11, !10, !10, !10, !10, !10, !10, !10, !10, !10, !10, !10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) +!12 = !{!13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26} +!13 = !DILocalVariable(name: "k", arg: 1, scope: !7, file: !1, line: 1, type: !11) +!14 = !DILocalVariable(name: "p1", arg: 2, scope: !7, file: !1, line: 1, type: !10) +!15 = !DILocalVariable(name: "p2", arg: 3, scope: !7, file: !1, line: 1, type: !10) +!16 = !DILocalVariable(name: "p3", arg: 4, scope: !7, file: !1, line: 1, type: !10) +!17 = !DILocalVariable(name: "p4", arg: 5, scope: !7, file: !1, line: 1, type: !10) +!18 = !DILocalVariable(name: "p5", arg: 6, scope: !7, file: !1, line: 1, type: !10) +!19 = !DILocalVariable(name: "p6", arg: 7, scope: !7, file: !1, line: 1, type: !10) +!20 = !DILocalVariable(name: "p7", arg: 8, scope: !7, file: !1, line: 1, type: !10) +!21 = !DILocalVariable(name: "p8", arg: 9, scope: !7, file: !1, line: 1, type: !10) +!22 = !DILocalVariable(name: "p9", arg: 10, scope: !7, file: !1, line: 1, type: !10) +!23 = !DILocalVariable(name: "pa", arg: 11, scope: !7, file: !1, line: 1, type: !10) +!24 = !DILocalVariable(name: "pb", arg: 12, scope: !7, file: !1, line: 1, type: !10) +!25 = !DILocalVariable(name: "pc", arg: 13, scope: !7, file: !1, line: 1, type: !10) +!26 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 2, type: !10) +!27 = !DILocation(line: 0, scope: !7) +!28 = !DILocation(line: 3, column: 7, scope: !7) +!29 = !DILocation(line: 4, column: 17, scope: !30) +!30 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 7) +!31 = !DILocation(line: 4, column: 27, scope: !30) +!32 = !DILocation(line: 4, column: 47, scope: !30) +!33 = !DILocation(line: 4, column: 67, scope: !30) +!34 = !DILocation(line: 4, column: 32, scope: !30) +!35 = !DILocation(line: 4, column: 42, scope: !30) +!36 = !DILocation(line: 4, column: 52, scope: !30) +!37 = !DILocation(line: 4, column: 5, scope: !30) +!38 = !DILocation(line: 6, column: 17, scope: !30) +!39 = !DILocation(line: 6, column: 37, scope: !30) +!40 = !DILocation(line: 6, column: 57, scope: !30) +!41 = !DILocation(line: 6, column: 42, scope: !30) +!42 = !DILocation(line: 6, column: 52, scope: !30) +!43 = !DILocation(line: 0, scope: !30) +!44 = !DILocation(line: 7, column: 3, scope: !7) Index: llvm/test/DebugInfo/X86/basicblock-sections_1.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/basicblock-sections_1.ll @@ -0,0 +1,81 @@ +; RUN: llc -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t +; llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=NO-NOSECTIONS %s + +; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t +; llvm-dwarfdump -debug-abbrev %t | FileCheck --check-prefix=BB-SECTIONS %s +; RUN: llvm-readobj --relocations %t | FileCheck --check-prefix=BB-SECTIONS-RELOCS %s +; From: +; int foo(int a) { +; if (a > 20) +; return 2; +; else +; return 0; +; } + +; NO-SECTIONS: DW_AT_low_pc +; NOSECTIONS: DW_AT_high_pc +; BB-SECTIONS: DW_AT_low_pc +; BB-SECTIONS: DW_AT_ranges +; BB-SECTIONS-RELOCS: R_X86_64_64 a.BB._Z3fooi +; BB-SECTIONS-RELOCS-NEXT: R_X86_64_64 +; BB-SECTIONS-RELOCS-NEXT: R_X86_64_64 aa.BB._Z3fooi +; BB-SECTIONS-RELOCS-NEXT: R_X86_64_64 +; BB-SECTIONS-RELOCS: R_X86_64_SIZE32 + +source_filename = "debuginfo.cc" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @_Z3fooi(i32 %0) #0 !dbg !7 { + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + call void @llvm.dbg.declare(metadata i32* %3, metadata !11, metadata !DIExpression()), !dbg !12 + %4 = load i32, i32* %3, align 4, !dbg !13 + %5 = icmp sgt i32 %4, 20, !dbg !15 + br i1 %5, label %6, label %7, !dbg !16 + +6: ; preds = %1 + store i32 2, i32* %2, align 4, !dbg !17 + br label %8, !dbg !17 + +7: ; preds = %1 + store i32 0, i32* %2, align 4, !dbg !18 + br label %8, !dbg !18 + +8: ; preds = %7, %6 + %9 = load i32, i32* %2, align 4, !dbg !19 + ret i32 %9, !dbg !19 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "debuginfo.cc", directory: "/g/tmsriram/Projects_2019/github_repo/Examples") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)"} +!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!12 = !DILocation(line: 1, column: 13, scope: !7) +!13 = !DILocation(line: 2, column: 7, scope: !14) +!14 = distinct !DILexicalBlock(scope: !7, file: !1, line: 2, column: 7) +!15 = !DILocation(line: 2, column: 9, scope: !14) +!16 = !DILocation(line: 2, column: 7, scope: !7) +!17 = !DILocation(line: 3, column: 5, scope: !14) +!18 = !DILocation(line: 5, column: 5, scope: !14) +!19 = !DILocation(line: 6, column: 1, scope: !7)