Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -90,7 +90,10 @@ /// /// If \c AllowUnresolved, collect unresolved nodes attached to the module /// in order to resolve cycles during \a finalize(). - explicit DIBuilder(Module &M, bool AllowUnresolved = true); + /// + /// If \p CU is given a value other than nullptr, then set \p CUNode to CU. + explicit DIBuilder(Module &M, bool AllowUnresolved = true, + DICompileUnit *CU = nullptr); DIBuilder(const DIBuilder &) = delete; DIBuilder &operator=(const DIBuilder &) = delete; Index: lib/CodeGen/MachineOutliner.cpp =================================================================== --- lib/CodeGen/MachineOutliner.cpp +++ lib/CodeGen/MachineOutliner.cpp @@ -97,6 +97,9 @@ /// The number of instructions in this \p Candidate. unsigned Len; + /// The MachineFunction containing this \p Candidate. + MachineFunction *MF = nullptr; + public: /// Set to false if the candidate overlapped with another candidate. bool InCandidateList = true; @@ -108,6 +111,15 @@ /// Contains all target-specific information for this \p Candidate. TargetInstrInfo::MachineOutlinerInfo MInfo; + /// If there is a DICompileUnit associated with the function that this + /// \p Candidate lives in, return it. + DICompileUnit *getCUIfExists() const { + assert(MF && "Candidate has no MF!"); + if (DISubprogram *SP = MF->getFunction().getSubprogram()) + return SP->getUnit(); + return nullptr; + } + /// Return the number of instructions in this Candidate. unsigned getLength() const { return Len; } @@ -126,8 +138,9 @@ /// for some given candidate. unsigned Benefit = 0; - Candidate(unsigned StartIdx, unsigned Len, unsigned FunctionIdx) - : StartIdx(StartIdx), Len(Len), FunctionIdx(FunctionIdx) {} + Candidate(unsigned StartIdx, unsigned Len, unsigned FunctionIdx, + MachineFunction *MF) + : StartIdx(StartIdx), Len(Len), MF(MF), FunctionIdx(FunctionIdx) {} Candidate() {} @@ -163,6 +176,18 @@ /// Contains all target-specific information for this \p OutlinedFunction. TargetInstrInfo::MachineOutlinerInfo MInfo; + /// \brief If there is a DICompileUnit for any Candidate for this outlined + /// function, then return it. Otherwise, return nullptr. + DICompileUnit *getCUIfExists() const { + DICompileUnit *CU = nullptr; + for (auto &C : Candidates) { + CU = C->getCUIfExists(); + if (CU) + break; + } + return CU; + } + /// Return the number of candidates for this \p OutlinedFunction. unsigned getOccurrenceCount() { return OccurrenceCount; } @@ -979,9 +1004,13 @@ MachineBasicBlock::iterator StartIt = Mapper.InstrList[StartIdx]; MachineBasicBlock::iterator EndIt = Mapper.InstrList[EndIdx]; + // Save the MachineFunction containing the Candidate. + MachineFunction *MF = StartIt->getParent()->getParent(); + assert(MF && "Candidate doesn't have a MF?"); + // Save the candidate and its location. CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, - FunctionList.size()); + FunctionList.size(), MF); RepeatedSequenceLocs.emplace_back(std::make_pair(StartIt, EndIt)); } } @@ -1246,6 +1275,36 @@ TII.insertOutlinerEpilogue(MBB, MF, OF.MInfo); + // If there's a compile unit associated with this outlined function, then + // emit debug info for the outlined function. + if (DICompileUnit *CU = OF.getCUIfExists()) { + + std::unique_ptr DB = llvm::make_unique(M, true, CU); + DIFile *Unit = DB->createFile(CU->getName(), CU->getDirectory()); + + // Walk over each IR function we created in the outliner and create + // DISubprograms for each function. + for (Function *F : CreatedIRFunctions) { + DISubprogram *SP = DB->createFunction( + Unit /* Context */, F->getName(), + StringRef() /* Empty linkage name. */, Unit /* File */, + 0 /* Line numbers don't matter*/, + DB->createSubroutineType(DB->getOrCreateTypeArray(None)), /* void */ + false, true, 0, /* Line in scope doesn't matter*/ + DINode::DIFlags::FlagArtificial /* Compiler-generated code. */, + true /* Outlined code is optimized code by definition. */); + + // Don't add any new variables to the subprogram. + DB->finalizeSubprogram(SP); + + // Attach subprogram to the function. + F->setSubprogram(SP); + } + + // We're done with the DIBuilder. + DB->finalize(); + } + return &MF; } @@ -1388,41 +1447,5 @@ // Outline each of the candidates and return true if something was outlined. bool OutlinedSomething = outline(M, CandidateList, FunctionList, Mapper); - // If we have a compile unit, and we've outlined something, then set debug - // information on the outlined function. - if (M.debug_compile_units_begin() != M.debug_compile_units_end() && - OutlinedSomething) { - std::unique_ptr DB = llvm::make_unique(M); - - // Create a compile unit for the outlined function. - DICompileUnit *MCU = *M.debug_compile_units_begin(); - DIFile *Unit = DB->createFile(M.getName(), "/"); - DB->createCompileUnit(MCU->getSourceLanguage(), Unit, "machine-outliner", - true, "", MCU->getRuntimeVersion(), StringRef(), - DICompileUnit::DebugEmissionKind::NoDebug); - - // Walk over each IR function we created in the outliner and create - // DISubprograms for each function. - for (Function *F : CreatedIRFunctions) { - DISubprogram *SP = DB->createFunction( - Unit /* Context */, F->getName(), - StringRef() /* Empty linkage name. */, Unit /* File */, - 0 /* Line numbers don't matter*/, - DB->createSubroutineType(DB->getOrCreateTypeArray(None)), /* void */ - false, true, 0, /* Line in scope doesn't matter*/ - DINode::DIFlags::FlagArtificial /* Compiler-generated code. */, - true /* Outlined code is optimized code by definition. */); - - // Don't add any new variables to the subprogram. - DB->finalizeSubprogram(SP); - - // Attach subprogram to the function. - F->setSubprogram(SP); - } - - // We're done with the DIBuilder. - DB->finalize(); - } - return OutlinedSomething; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -30,8 +30,8 @@ llvm::cl::desc("Use llvm.dbg.addr for all local variables"), cl::init(false), cl::Hidden); -DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes) - : M(m), VMContext(M.getContext()), CUNode(nullptr), +DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) + : M(m), VMContext(M.getContext()), CUNode(CU), DeclareFn(nullptr), ValueFn(nullptr), AllowUnresolvedNodes(AllowUnresolvedNodes) {} Index: test/CodeGen/X86/machine-outliner-disubprogram.ll =================================================================== --- test/CodeGen/X86/machine-outliner-disubprogram.ll +++ test/CodeGen/X86/machine-outliner-disubprogram.ll @@ -108,31 +108,26 @@ ret i32 0, !dbg !73 } -; CHECK [[UNIT:![0-9]+]] = distinct !DICompileUnit -; CHECK-SAME: file: [[FILE:![0-9]+]], -; CHECK-SAME: producer: "machine-outliner", -; CHECK-SAME: isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug - ; CHECK: distinct !DISubprogram(name: "OUTLINED_FUNCTION_1", -; CHECK-SAME: scope: [[FILE]], -; CHECK-SAME: file: [[FILE]], +; CHECK-SAME: scope: !1, +; CHECK-SAME: file: !1, ; CHECK-SAME: type: [[TYPE:![0-9]+]], ; CHECK-SAME: isLocal: false, ; CHECK-SAME: isDefinition: true, ; CHECK-SAME: flags: DIFlagArtificial, ; CHECK-SAME: isOptimized: true, -; CHECK-SAME: unit: [[UNIT]], +; CHECK-SAME: unit: !0, ; CHECK-SAME: variables: [[VARS:![0-9]+]] -; CHECK: distinct !DISubprogram(name: "OUTLINED_FUNCTION_1", -; CHECK-SAME: scope: [[FILE]], -; CHECK-SAME: file: [[FILE]], +; CHECK: distinct !DISubprogram(name: "OUTLINED_FUNCTION_0", +; CHECK-SAME: scope: !1, +; CHECK-SAME: file: !1, ; CHECK-SAME: type: [[TYPE]], ; CHECK-SAME: isLocal: false, ; CHECK-SAME: isDefinition: true, ; CHECK-SAME: flags: DIFlagArtificial, ; CHECK-SAME: isOptimized: true, -; CHECK-SAME: unit: [[UNIT]], +; CHECK-SAME: unit: !0, ; CHECK-SAME: variables: [[VARS]] attributes #0 = { noinline noredzone nounwind optnone ssp uwtable "no-frame-pointer-elim"="true" }