diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -162,6 +162,10 @@ /// Indicate that this basic block is the entry block of a cleanup funclet. bool IsCleanupFuncletEntry = false; + /// Propeller ID assigned to this basic block. used with basic block sections + /// and basic block labels. + Optional PropellerID; + /// With basic block sections, this stores the Section ID of the basic block. MBBSectionID SectionID{0}; @@ -570,6 +574,8 @@ void setIsEndSection(bool V = true) { IsEndSection = V; } + Optional getPropellerID() const { return PropellerID; } + /// Returns the section ID of this basic block. MBBSectionID getSectionID() const { return SectionID; } @@ -579,6 +585,8 @@ ((unsigned)SectionID.Type) + SectionID.Number; } + void setPropellerID(unsigned V) { PropellerID = V; } + /// Sets the section ID for this basic block. void setSectionID(MBBSectionID V) { SectionID = V; } diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -352,6 +352,8 @@ bool HasEHScopes = false; bool HasEHFunclets = false; + unsigned NextPropellerID = 0; + /// Section Type for basic blocks, only relevant with basic block sections. BasicBlockSection BBSectionsType = BasicBlockSection::None; diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -802,6 +802,7 @@ uintX_t Addr; // Function address // Struct representing the BBAddrMap information for one basic block. struct BBEntry { + uint32_t ID; // Propeller ID. uint32_t Offset; // Offset of basic block relative to function start. uint32_t Size; // Size of the basic block. @@ -812,8 +813,8 @@ bool IsEHPad; // If this is an exception handling block. bool CanFallThrough; // If this block can fall through to its next. - BBEntry(uint32_t Offset, uint32_t Size, uint32_t Metadata) - : Offset(Offset), Size(Size), HasReturn(Metadata & 1), + BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, uint32_t Metadata) + : ID(ID), Offset(Offset), Size(Size), HasReturn(Metadata & 1), HasTailCall(Metadata & (1 << 1)), IsEHPad(Metadata & (1 << 2)), CanFallThrough(Metadata & (1 << 3)){}; }; diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -157,6 +157,7 @@ struct BBAddrMapEntry { struct BBEntry { + uint32_t PropellerID; llvm::yaml::Hex64 AddressOffset; llvm::yaml::Hex64 Size; llvm::yaml::Hex64 Metadata; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1155,11 +1155,15 @@ for (const MachineBasicBlock &MBB : MF) { const MCSymbol *MBBSymbol = MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol(); + OutStreamer->AddComment("Propeller ID"); + // Emit the Propeller ID for this basic block. + OutStreamer->emitULEB128IntValue(*MBB.getPropellerID()); // Emit the basic block offset. emitLabelDifferenceAsULEB128(MBBSymbol, FunctionSymbol); // Emit the basic block size. When BBs have alignments, their size cannot // always be computed from their offsets. emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol); + // Emit the Metadata. OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB)); } OutStreamer->PopSection(); diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp --- a/llvm/lib/CodeGen/BasicBlockSections.cpp +++ b/llvm/lib/CodeGen/BasicBlockSections.cpp @@ -110,8 +110,8 @@ // This struct represents the cluster information for a machine basic block. struct BBClusterInfo { - // MachineBasicBlock ID. - unsigned MBBNumber; + // MachineBasicBlock Propeller ID. + unsigned PropellerID; // Cluster ID this basic block belongs to. unsigned ClusterID; // Position of basic block within the cluster. @@ -172,14 +172,15 @@ // This function updates and optimizes the branching instructions of every basic // block in a given function to account for changes in the layout. -static void updateBranches( - MachineFunction &MF, - const SmallVector &PreLayoutFallThroughs) { +static void +updateBranches(MachineFunction &MF, + DenseMap + &PreLayoutFallThroughs) { const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); SmallVector Cond; for (auto &MBB : MF) { auto NextMBBI = std::next(MBB.getIterator()); - auto *FTMBB = PreLayoutFallThroughs[MBB.getNumber()]; + auto *FTMBB = PreLayoutFallThroughs[&MBB]; // If this block had a fallthrough before we need an explicit unconditional // branch to that block if either // 1- the block ends a section, which means its next block may be @@ -227,13 +228,13 @@ return true; } - V.resize(MF.getNumBlockIDs()); - for (auto bbClusterInfo : P->second) { - // Bail out if the cluster information contains invalid MBB numbers. - if (bbClusterInfo.MBBNumber >= MF.getNumBlockIDs()) - return false; - V[bbClusterInfo.MBBNumber] = bbClusterInfo; - } + unsigned MaxPropellerID = 0; + for (auto bbClusterInfo : P->second) + if (bbClusterInfo.PropellerID > MaxPropellerID) + MaxPropellerID = bbClusterInfo.PropellerID; + V.resize(MaxPropellerID + 1); + for (auto bbClusterInfo : P->second) + V[bbClusterInfo.PropellerID] = bbClusterInfo; return true; } @@ -246,9 +247,10 @@ // and "Cold" succeeding all other clusters. // FuncBBClusterInfo represent the cluster information for basic blocks. If this // is empty, it means unique sections for all basic blocks in the function. -static void -assignSections(MachineFunction &MF, - const std::vector> &FuncBBClusterInfo) { +static void assignSections( + MachineFunction &MF, + const std::vector> &FuncBBClusterInfo, + const DenseMap &PreLayoutPosition) { assert(MF.hasBBSections() && "BB Sections is not set for function."); // This variable stores the section ID of the cluster containing eh_pads (if // all eh_pads are one cluster). If more than one cluster contain eh_pads, we @@ -265,9 +267,10 @@ // If unique sections are desired for all basic blocks of the function, we // set every basic block's section ID equal to its number (basic block // id). This further ensures that basic blocks are ordered canonically. - MBB.setSectionID({static_cast(MBB.getNumber())}); - } else if (FuncBBClusterInfo[MBB.getNumber()].hasValue()) - MBB.setSectionID(FuncBBClusterInfo[MBB.getNumber()]->ClusterID); + MBB.setSectionID(PreLayoutPosition.lookup(&MBB)); + } else if (*MBB.getPropellerID() < FuncBBClusterInfo.size() && + FuncBBClusterInfo[*MBB.getPropellerID()].hasValue()) + MBB.setSectionID(FuncBBClusterInfo[*MBB.getPropellerID()]->ClusterID); else { // BB goes into the special cold section if it is not specified in the // cluster info map. @@ -295,12 +298,15 @@ void llvm::sortBasicBlocksAndUpdateBranches( MachineFunction &MF, MachineBasicBlockComparator MBBCmp) { - SmallVector PreLayoutFallThroughs( - MF.getNumBlockIDs()); + const MachineBasicBlock *EntryBlock = &MF.front(); + DenseMap + PreLayoutFallThroughs; for (auto &MBB : MF) - PreLayoutFallThroughs[MBB.getNumber()] = MBB.getFallThrough(); + PreLayoutFallThroughs[&MBB] = MBB.getFallThrough(); MF.sort(MBBCmp); + // Check that the entry block is not displaced. + assert(&MF.front() == EntryBlock); // Set IsBeginSection and IsEndSection according to the assigned section IDs. MF.assignBeginEndSections(); @@ -366,11 +372,10 @@ hasInstrProfHashMismatch(MF)) return true; - // Renumber blocks before sorting them for basic block sections. This is - // useful during sorting, basic blocks in the same section will retain the - // default order. This renumbering should also be done for basic block - // labels to match the profiles with the correct blocks. - MF.RenumberBlocks(); + DenseMap PreLayoutPosition; + unsigned Position = 0; + for (const auto &MBB : MF) + PreLayoutPosition[&MBB] = Position++; if (BBSectionsType == BasicBlockSection::Labels) { MF.setBBSectionsType(BBSectionsType); @@ -383,7 +388,7 @@ FuncBBClusterInfo)) return true; MF.setBBSectionsType(BBSectionsType); - assignSections(MF, FuncBBClusterInfo); + assignSections(MF, FuncBBClusterInfo, PreLayoutPosition); // We make sure that the cluster including the entry basic block precedes all // other clusters. @@ -417,9 +422,9 @@ // If the two basic block are in the same section, the order is decided by // their position within the section. if (XSectionID.Type == MBBSectionID::SectionType::Default) - return FuncBBClusterInfo[X.getNumber()]->PositionInCluster < - FuncBBClusterInfo[Y.getNumber()]->PositionInCluster; - return X.getNumber() < Y.getNumber(); + return FuncBBClusterInfo[*X.getPropellerID()]->PositionInCluster < + FuncBBClusterInfo[*Y.getPropellerID()]->PositionInCluster; + return PreLayoutPosition[&X] < PreLayoutPosition[&Y]; }; sortBasicBlocksAndUpdateBranches(MF, Comparator); @@ -476,23 +481,23 @@ if (FI == ProgramBBClusterInfo.end()) return invalidProfileError( "Cluster list does not follow a function name specifier."); - SmallVector BBIndexes; - S.split(BBIndexes, ' '); + SmallVector BBIDs; + S.split(BBIDs, ' '); // Reset current cluster position. CurrentPosition = 0; - for (auto BBIndexStr : BBIndexes) { - unsigned long long BBIndex; - if (getAsUnsignedInteger(BBIndexStr, 10, BBIndex)) + for (auto BBIDStr : BBIDs) { + unsigned long long BBID; + if (getAsUnsignedInteger(BBIDStr, 10, BBID)) return invalidProfileError(Twine("Unsigned integer expected: '") + - BBIndexStr + "'."); - if (!FuncBBIDs.insert(BBIndex).second) + BBIDStr + "'."); + if (!FuncBBIDs.insert(BBID).second) return invalidProfileError(Twine("Duplicate basic block id found '") + - BBIndexStr + "'."); - if (!BBIndex && CurrentPosition) + BBIDStr + "'."); + if (BBID == 0 && CurrentPosition) return invalidProfileError("Entry BB (0) does not begin a cluster."); - FI->second.emplace_back(BBClusterInfo{ - ((unsigned)BBIndex), CurrentCluster, CurrentPosition++}); + FI->second.emplace_back( + BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++}); } CurrentCluster++; } else { // This is a function name specifier. diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -126,6 +126,7 @@ kw_post_instr_symbol, kw_heap_alloc_marker, kw_bbsections, + kw_propeller_id, kw_unknown_size, kw_unknown_address, diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -271,6 +271,7 @@ .Case("post-instr-symbol", MIToken::kw_post_instr_symbol) .Case("heap-alloc-marker", MIToken::kw_heap_alloc_marker) .Case("bbsections", MIToken::kw_bbsections) + .Case("propeller_id", MIToken::kw_propeller_id) .Case("unknown-size", MIToken::kw_unknown_size) .Case("unknown-address", MIToken::kw_unknown_address) .Case("distinct", MIToken::kw_distinct) diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -501,6 +501,7 @@ bool parseAlignment(unsigned &Alignment); bool parseAddrspace(unsigned &Addrspace); bool parseSectionID(Optional &SID); + bool parsePropellerID(Optional &PrID); bool parseOperandsOffset(MachineOperand &Op); bool parseIRValue(const Value *&V); bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags); @@ -663,6 +664,18 @@ return false; } +// Parse Machine Basic Block Propeller ID +bool MIParser::parsePropellerID(Optional &PrID) { + assert(Token.is(MIToken::kw_propeller_id)); + lex(); + unsigned Value = 0; + if (getUnsigned(Value)) + return error("Unknown Propeller ID"); + PrID = Value; + lex(); + return false; +} + bool MIParser::parseBasicBlockDefinition( DenseMap &MBBSlots) { assert(Token.is(MIToken::MachineBasicBlockLabel)); @@ -676,6 +689,7 @@ bool IsLandingPad = false; bool IsEHFuncletEntry = false; Optional SectionID; + Optional PropellerID; unsigned Alignment = 0; BasicBlock *BB = nullptr; if (consumeIfPresent(MIToken::lparen)) { @@ -708,6 +722,10 @@ if (parseSectionID(SectionID)) return true; break; + case MIToken::kw_propeller_id: + if (parsePropellerID(PropellerID)) + return true; + break; default: break; } @@ -742,6 +760,13 @@ MBB->setSectionID(SectionID.getValue()); MF.setBBSectionsType(BasicBlockSection::List); } + if (PropellerID.hasValue()) { + // BBSectionsType is set to `List` if any basic blocks has `SectionID`. + // Here, we set it to `Labels` if it hasn't been set above. + if (!MF.hasBBSections()) + MF.setBBSectionsType(BasicBlockSection::Labels); + MBB->setPropellerID(PropellerID.getValue()); + } return false; } diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -542,6 +542,11 @@ } hasAttributes = true; } + if (getPropellerID().hasValue()) { + os << (hasAttributes ? ", " : " ("); + os << "propeller_id " << *getPropellerID(); + hasAttributes = true; + } } if (hasAttributes) diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -412,8 +412,13 @@ /// `new MachineBasicBlock'. MachineBasicBlock * MachineFunction::CreateMachineBasicBlock(const BasicBlock *bb) { - return new (BasicBlockRecycler.Allocate(Allocator)) - MachineBasicBlock(*this, bb); + MachineBasicBlock *MBB = + new (BasicBlockRecycler.Allocate(Allocator)) + MachineBasicBlock(*this, bb); + if (Target.getBBSectionsType() == BasicBlockSection::Labels || + Target.getBBSectionsType() == BasicBlockSection::List) + MBB->setPropellerID(NextPropellerID++); + return MBB; } /// Delete the given MachineBasicBlock. diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -650,10 +650,11 @@ std::vector BBEntries; for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks); ++BlockID) { + uint32_t ID = ReadULEB128AsUInt32(); uint32_t Offset = ReadULEB128AsUInt32(); uint32_t Size = ReadULEB128AsUInt32(); uint32_t Metadata = ReadULEB128AsUInt32(); - BBEntries.push_back({Offset, Size, Metadata}); + BBEntries.push_back({ID, Offset, Size, Metadata}); } FunctionEntries.push_back({Address, BBEntries}); } diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1408,7 +1408,8 @@ if (!E.BBEntries) continue; for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries) - SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) + + SHeader.sh_size += CBA.writeULEB128(BBE.PropellerID) + + CBA.writeULEB128(BBE.AddressOffset) + CBA.writeULEB128(BBE.Size) + CBA.writeULEB128(BBE.Metadata); } diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1713,6 +1713,7 @@ void MappingTraits::mapping( IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); + IO.mapRequired("ID", E.PropellerID); IO.mapRequired("AddressOffset", E.AddressOffset); IO.mapRequired("Size", E.Size); IO.mapRequired("Metadata", E.Metadata); diff --git a/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir b/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/basic-block-labels-mir-parse.mir @@ -0,0 +1,138 @@ +# Start after bbsections0-prepare and check that the BB address map is generated. +# RUN: llc -mtriple x86_64-unknown-linux-gnu -start-after=bbsections-prepare %s -o - | FileCheck %s -check-prefix=CHECK + +# How to generate the input: +# foo.cc +# int foo(bool k) { +# if (k) return 1; +# return 0; +# } +# +# clang -O0 -S -emit-llvm foo.cc +# llc < foo.ll -stop-after=bbsections-prepare -basic-block-sections=labels + +--- | + ; ModuleID = '' + source_filename = "a.cc" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" + + ; Function Attrs: noinline nounwind optnone uwtable + define dso_local i32 @_Z3foob(i1 zeroext %0) #0 { + %2 = alloca i32, align 4 + %3 = alloca i8, align 1 + %4 = zext i1 %0 to i8 + store i8 %4, i8* %3, align 1 + %5 = load i8, i8* %3, align 1 + %6 = trunc i8 %5 to i1 + br i1 %6, label %7, label %8 + + 7: ; preds = %1 + store i32 1, i32* %2, align 4 + br label %9 + + 8: ; preds = %1 + store i32 0, i32* %2, align 4 + br label %9 + + 9: ; preds = %8, %7 + %10 = load i32, i32* %2, align 4 + ret i32 %10 + } + + 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"="true" "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" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"wchar_size", i32 4} + !1 = !{!"Debian clang version 11.0.1-2"} + +... +--- +name: _Z3foob +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: + - { reg: '$edi', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 8 + offsetAdjustment: -8 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: + - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16, stack-id: default, + callee-saved-register: '', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: '', type: default, offset: -24, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: default, offset: -17, size: 1, alignment: 1, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.1, propeller_id 0): + successors: %bb.2(0x40000000), %bb.1(0x40000000) + liveins: $edi + + frame-setup PUSH64r killed $rbp, implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + $rbp = frame-setup MOV64rr $rsp + CFI_INSTRUCTION def_cfa_register $rbp + renamable $dil = AND8ri renamable $dil, 1, implicit-def dead $eflags, implicit killed $edi, implicit-def $edi + MOV8mr $rbp, 1, $noreg, -1, $noreg, renamable $dil, implicit killed $edi :: (store 1 into %ir.3) + TEST8mi $rbp, 1, $noreg, -1, $noreg, 1, implicit-def $eflags :: (load 1 from %ir.3) + JCC_1 %bb.2, 4, implicit killed $eflags + + bb.1 (%ir-block.7, propeller_id 1): + successors: %bb.3(0x80000000) + + MOV32mi $rbp, 1, $noreg, -8, $noreg, 1 :: (store 4 into %ir.2) + JMP_1 %bb.3 + + bb.2 (%ir-block.8, propeller_id 2): + successors: %bb.3(0x80000000) + + MOV32mi $rbp, 1, $noreg, -8, $noreg, 0 :: (store 4 into %ir.2) + + bb.3 (%ir-block.9, propeller_id 3): + renamable $eax = MOV32rm $rbp, 1, $noreg, -8, $noreg :: (load 4 from %ir.2) + $rbp = frame-destroy POP64r implicit-def $rsp, implicit $rsp + CFI_INSTRUCTION def_cfa $rsp, 8 + RETQ implicit $eax + +... + +# CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text +# CHECK: .byte 0 # Propeller ID +# CHECK: .byte 1 # Propeller ID +# CHECK: .byte 2 # Propeller ID +# CHECK: .byte 3 # Propeller ID diff --git a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll --- a/llvm/test/CodeGen/X86/basic-block-sections-labels.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections-labels.ll @@ -39,8 +39,8 @@ ; CHECK-LABEL: .LBB_END0_1: ; CHECK-LABEL: .LBB0_2: ; CHECK-LABEL: .LBB_END0_2: -; CHECK-LABEL: .LBB0_3: -; CHECK-LABEL: .LBB_END0_3: +; CHECK-LABEL: .LBB0_4: +; CHECK-LABEL: .LBB_END0_4: ; CHECK-LABEL: .Lfunc_end0: ; UNIQ: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3bazb{{$}} @@ -48,15 +48,19 @@ ; NOUNIQ: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text,unique,1 ; CHECK-NEXT: .quad .Lfunc_begin0 ; CHECK-NEXT: .byte 4 +; CHECK-NEXT: .byte 0 ; CHECK-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 ; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0 ; CHECK-NEXT: .byte 8 +; CHECK-NEXT: .byte 1 ; CHECK-NEXT: .uleb128 .LBB0_1-.Lfunc_begin0 ; CHECK-NEXT: .uleb128 .LBB_END0_1-.LBB0_1 ; CHECK-NEXT: .byte 8 +; CHECK-NEXT: .byte 3 ; CHECK-NEXT: .uleb128 .LBB0_2-.Lfunc_begin0 ; CHECK-NEXT: .uleb128 .LBB_END0_2-.LBB0_2 ; CHECK-NEXT: .byte 1 -; CHECK-NEXT: .uleb128 .LBB0_3-.Lfunc_begin0 -; CHECK-NEXT: .uleb128 .LBB_END0_3-.LBB0_3 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .uleb128 .LBB0_4-.Lfunc_begin0 +; CHECK-NEXT: .uleb128 .LBB_END0_4-.LBB0_4 ; CHECK-NEXT: .byte 5 diff --git a/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll b/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll --- a/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll +++ b/llvm/test/CodeGen/X86/basic-block-sections-mir-print.ll @@ -1,8 +1,9 @@ ; Stop after bbsections-prepare and check MIR output for section type. +; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=labels -stop-after=bbsections-prepare | FileCheck %s -check-prefix=BBLABELS ; RUN: echo '!_Z3foob' > %t ; RUN: echo '!!1' >> %t ; RUN: echo '!!2' >> %t -; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -stop-after=bbsections-prepare | FileCheck %s -check-prefix=CHECK +; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t -stop-after=bbsections-prepare | FileCheck %s -check-prefix=BBSECTIONS @_ZTIb = external constant i8* define dso_local i32 @_Z3foob(i1 zeroext %0) { @@ -27,7 +28,12 @@ ret i32 %10 } -; CHECK: bb.0 (%ir-block.1, bbsections Cold): -; CHECK: bb.3 (%ir-block.9, bbsections Cold): -; CHECK: bb.1 (%ir-block.7) -; CHECK: bb.2 (%ir-block.8, bbsections 1): +; BBSECTIONS: bb.0 (%ir-block.1, bbsections Cold, propeller_id 0): +; BBSECTIONS: bb.3 (%ir-block.9, bbsections Cold, propeller_id 3): +; BBSECTIONS: bb.1 (%ir-block.7, propeller_id 1) +; BBSECTIONS: bb.2 (%ir-block.8, bbsections 1, propeller_id 2): + +; BBLABELS: bb.0 (%ir-block.1, propeller_id 0): +; BBLABELS: bb.1 (%ir-block.7, propeller_id 1): +; BBLABELS: bb.2 (%ir-block.8, propeller_id 2): +; BBLABELS: bb.3 (%ir-block.9, propeller_id 3): diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test --- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test +++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test @@ -22,6 +22,7 @@ # LLVM-NEXT: Name: # LLVM-NEXT: BB entries [ # LLVM-NEXT: { +# LLVM-NEXT: ID: 0 # LLVM-NEXT: Offset: 0x0 # LLVM-NEXT: Size: 0x1 # LLVM-NEXT: HasReturn: No @@ -30,6 +31,7 @@ # LLVM-NEXT: CanFallThrough: No # LLVM-NEXT: } # LLVM-NEXT: { +# LLVM-NEXT: ID: 2 # LLVM-NEXT: Offset: 0x3 # LLVM-NEXT: Size: 0x4 # LLVM-NEXT: HasReturn: Yes @@ -44,6 +46,7 @@ # LLVM-NEXT: Name: foo # LLVM-NEXT: BB entries [ # LLVM-NEXT: { +# LLVM-NEXT: ID: 4 # LLVM-NEXT: Offset: 0x6 # LLVM-NEXT: Size: 0x7 # LLVM-NEXT: HasReturn: No @@ -60,6 +63,7 @@ # LLVM-NEXT: Name: bar # LLVM-NEXT: BB entries [ # LLVM-NEXT: { +# LLVM-NEXT: ID: 6 # LLVM-NEXT: Offset: 0x9 # LLVM-NEXT: Size: 0xA # LLVM-NEXT: HasReturn: Yes @@ -83,6 +87,7 @@ # TRUNCATED-NEXT: Name: bar # TRUNCATED-NEXT: BB entries [ # TRUNCATED-NEXT: { +# TRUNCATED-NEXT: ID: 6 # TRUNCATED-NEXT: Offset: 0x9 # TRUNCATED-NEXT: Size: 0xA # TRUNCATED-NEXT: HasReturn: Yes @@ -113,15 +118,18 @@ Entries: - Address: [[ADDR=0x11111]] BBEntries: - - AddressOffset: 0x0 + - ID: 0 + AddressOffset: 0x0 Size: 0x1 Metadata: 0xF0000002 - - AddressOffset: 0x3 + - ID: 2 + AddressOffset: 0x3 Size: 0x4 Metadata: 0x5 - Address: 0x22222 BBEntries: - - AddressOffset: 0x6 + - ID: 4 + AddressOffset: 0x6 Size: 0x7 Metadata: 0x8 - Name: dummy_section @@ -133,7 +141,8 @@ Entries: - Address: 0x33333 BBEntries: - - AddressOffset: 0x9 + - ID: 6 + AddressOffset: 0x9 Size: 0xa Metadata: 0xb Symbols: diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml --- a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml +++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml @@ -16,18 +16,22 @@ # VALID-NEXT: Entries: ## The 'Address' field is omitted when it's zero. # VALID-NEXT: BBEntries: -# VALID-NEXT: - AddressOffset: 0x1 +# VALID-NEXT: - ID: 0 +# VALID-NEXT: AddressOffset: 0x1 # VALID-NEXT: Size: 0x2 # VALID-NEXT: Metadata: 0x3 -# VALID-NEXT: - AddressOffset: 0x4 +# VALID-NEXT: - ID: 1 +# VALID-NEXT: AddressOffset: 0x4 # VALID-NEXT: Size: 0x5 # VALID-NEXT: Metadata: 0x6 -# VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7 +# VALID-NEXT: - ID: 2 +# VALID-NEXT: AddressOffset: 0xFFFFFFFFFFFFFFF7 # VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8 # VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9 # VALID-NEXT: - Address: 0xFFFFFFFFFFFFFF20 # VALID-NEXT: BBEntries: -# VALID-NEXT: - AddressOffset: 0xA +# VALID-NEXT: - ID: 3 +# VALID-NEXT: AddressOffset: 0xA # VALID-NEXT: Size: 0xB # VALID-NEXT: Metadata: 0xC @@ -45,17 +49,21 @@ NumBlocks: [[NUMBLOCKS=]] BBEntries: - AddressOffset: 0x1 + ID: 0 Size: 0x2 Metadata: 0x3 - AddressOffset: 0x4 + ID: 1 Size: 0x5 Metadata: 0x6 - AddressOffset: 0xFFFFFFFFFFFFFFF7 + ID: 2 Size: 0xFFFFFFFFFFFFFFF8 Metadata: 0xFFFFFFFFFFFFFFF9 - Address: 0xFFFFFFFFFFFFFF20 BBEntries: - AddressOffset: 0xA + ID: 3 Size: 0xB Metadata: 0xC @@ -100,7 +108,8 @@ # MULTI-NEXT: Entries: ## The 'Address' field is omitted when it's zero. # MULTI-NEXT: - BBEntries: -# MULTI-NEXT: - AddressOffset: 0x1 +# MULTI-NEXT: - ID: 4 +# MULTI-NEXT: AddressOffset: 0x1 # MULTI-NEXT: Size: 0x2 # MULTI-NEXT: Metadata: 0x3 # MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)' @@ -122,6 +131,7 @@ - Address: 0x0 BBEntries: - AddressOffset: 0x1 + ID: 4 Size: 0x2 Metadata: 0x3 - Name: '.llvm_bb_addr_map (1)' diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml --- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml +++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml @@ -36,7 +36,7 @@ # Case 4: Specify Entries. # CHECK: Name: .llvm_bb_addr_map (1) # CHECK: SectionData ( -# CHECK-NEXT: 0000: 20000000 00000000 01010203 +# CHECK-NEXT: 0000: 20000000 00000000 010B0102 03 # CHECK-NEXT: ) # Case 5: Specify Entries and omit the Address field. @@ -44,13 +44,13 @@ # CHECK: Address: # CHECK-SAME: {{^ 0x0$}} # CHECK: SectionData ( -# CHECK-NEXT: 0000: 00000000 00000000 01010203 +# CHECK-NEXT: 0000: 00000000 00000000 010C0102 03 # CHECK-NEXT: ) # Case 6: Override the NumBlocks field. # CHECK: Name: .llvm_bb_addr_map (1) # CHECK: SectionData ( -# CHECK-NEXT: 0000: 20000000 00000000 02010203 +# CHECK-NEXT: 0000: 20000000 00000000 020D0102 03 # CHECK-NEXT: ) --- !ELF @@ -87,7 +87,8 @@ Entries: - Address: 0x0000000000000020 BBEntries: - - AddressOffset: 0x00000001 + - ID: 11 + AddressOffset: 0x00000001 Size: 0x00000002 Metadata: 0x00000003 @@ -97,7 +98,8 @@ Type: SHT_LLVM_BB_ADDR_MAP Entries: - BBEntries: - - AddressOffset: 0x00000001 + - ID: 12 + AddressOffset: 0x00000001 Size: 0x00000002 Metadata: 0x00000003 @@ -109,7 +111,8 @@ - Address: 0x0000000000000020 NumBlocks: 2 BBEntries: - - AddressOffset: 0x00000001 + - ID: 13 + AddressOffset: 0x00000001 Size: 0x00000002 Metadata: 0x00000003 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -6842,6 +6842,7 @@ ListScope L(W, "BB entries"); for (const typename Elf_BBAddrMap::BBEntry &BBE : AM.BBEntries) { DictScope L(W); + W.printNumber("ID", BBE.ID); W.printHex("Offset", BBE.Offset); W.printHex("Size", BBE.Size); W.printBoolean("HasReturn", BBE.HasReturn); diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -893,10 +893,11 @@ std::vector BBEntries; // Read the specified number of BB entries, or until decoding fails. for (uint64_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) { + uint32_t PropellerID = Data.getULEB128(Cur); uint64_t Offset = Data.getULEB128(Cur); uint64_t Size = Data.getULEB128(Cur); uint64_t Metadata = Data.getULEB128(Cur); - BBEntries.push_back({Offset, Size, Metadata}); + BBEntries.push_back({PropellerID, Offset, Size, Metadata}); } Entries.push_back({Address, /*NumBlocks=*/{}, BBEntries}); } diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -497,7 +497,8 @@ Entries: - Address: 0x11111 BBEntries: - - AddressOffset: 0x0 + - ID: 0 + AddressOffset: 0x0 Size: 0x1 Metadata: 0x2 )"); @@ -530,29 +531,32 @@ SmallVector, 3> OverInt32LimitYamlStrings(3, CommonYamlString); OverInt32LimitYamlStrings[0] += R"( - - AddressOffset: 0x100000000 + - ID: 1 + AddressOffset: 0x100000000 Size: 0xFFFFFFFF Metadata: 0xFFFFFFFF )"; OverInt32LimitYamlStrings[1] += R"( - - AddressOffset: 0xFFFFFFFF + - ID: 2 + AddressOffset: 0xFFFFFFFF Size: 0x100000000 Metadata: 0xFFFFFFFF )"; OverInt32LimitYamlStrings[2] += R"( - - AddressOffset: 0xFFFFFFFF + - ID: 3 + AddressOffset: 0xFFFFFFFF Size: 0xFFFFFFFF Metadata: 0x100000000 )"; DoCheck(OverInt32LimitYamlStrings[0], - "ULEB128 value at offset 0xc exceeds UINT32_MAX (0x100000000)"); + "ULEB128 value at offset 0xe exceeds UINT32_MAX (0x100000000)"); DoCheck(OverInt32LimitYamlStrings[1], - "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); + "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); DoCheck(OverInt32LimitYamlStrings[2], - "ULEB128 value at offset 0x16 exceeds UINT32_MAX (0x100000000)"); + "ULEB128 value at offset 0x18 exceeds UINT32_MAX (0x100000000)"); // Check the proper error handling when the section has fields exceeding // UINT32 and is also truncated. This is for checking that we don't generate @@ -561,24 +565,24 @@ 3, OverInt32LimitYamlStrings[1]); // Truncate before the end of the 5-byte field. OverInt32LimitAndTruncated[0] += R"( - ShSize: 0x15 + ShSize: 0x17 )"; // Truncate at the end of the 5-byte field. OverInt32LimitAndTruncated[1] += R"( - ShSize: 0x16 + ShSize: 0x18 )"; // Truncate after the end of the 5-byte field. OverInt32LimitAndTruncated[2] += R"( - ShSize: 0x17 + ShSize: 0x19 )"; DoCheck(OverInt32LimitAndTruncated[0], - "unable to decode LEB128 at offset 0x00000011: malformed uleb128, " + "unable to decode LEB128 at offset 0x00000013: malformed uleb128, " "extends past end"); DoCheck(OverInt32LimitAndTruncated[1], - "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); + "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); DoCheck(OverInt32LimitAndTruncated[2], - "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); + "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); // Check for proper error handling when the 'NumBlocks' field is overridden // with an out-of-range value.