#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
/// 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;
/// Contains all target-specific information for this \p Candidate.
TargetInstrInfo::MachineOutlinerInfo MInfo;
+ /// If there is a DISubprogram associated with the function that this
+ /// Candidate lives in, return it.
+ DISubprogram *getSubprogramOrNull() const {
+ assert(MF && "Candidate has no MF!");
+ if (DISubprogram *SP = MF->getFunction().getSubprogram())
+ return SP;
+ return nullptr;
+ }
+
/// Return the number of instructions in this Candidate.
unsigned getLength() const { return Len; }
/// 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() {}
/// Contains all target-specific information for this \p OutlinedFunction.
TargetInstrInfo::MachineOutlinerInfo MInfo;
+ /// If there is a DISubprogram for any Candidate for this outlined function,
+ /// then return it. Otherwise, return nullptr.
+ DISubprogram *getSubprogramOrNull() const {
+ for (const auto &C : Candidates)
+ if (DISubprogram *SP = C->getSubprogramOrNull())
+ return SP;
+ return nullptr;
+ }
+
/// Return the number of candidates for this \p OutlinedFunction.
unsigned getOccurrenceCount() { return OccurrenceCount; }
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));
}
}
TII.insertOutlinerEpilogue(MBB, MF, OF.MInfo);
+ // If there's a DISubprogram associated with this outlined function, then
+ // emit debug info for the outlined function.
+ if (DISubprogram *SP = OF.getSubprogramOrNull()) {
+ // We have a DISubprogram. Get its DICompileUnit.
+ DICompileUnit *CU = SP->getUnit();
+ DIBuilder DB(M, true, CU);
+ DIFile *Unit = SP->getFile();
+ Mangler Mg;
+
+ // Walk over each IR function we created in the outliner and create
+ // DISubprograms for each function.
+ for (Function *F : CreatedIRFunctions) {
+ // Get the mangled name of the function for the linkage name.
+ std::string Dummy;
+ llvm::raw_string_ostream MangledNameStream(Dummy);
+ Mg.getNameWithPrefix(MangledNameStream, F, false);
+
+ DISubprogram *SP = DB.createFunction(
+ Unit /* Context */, F->getName(), StringRef(MangledNameStream.str()),
+ Unit /* File */,
+ 0 /* Line 0 is reserved for compiler-generated code. */,
+ DB.createSubroutineType(
+ DB.getOrCreateTypeArray(None)), /* void type */
+ false, true, 0, /* Line 0 is reserved for compiler-generated code. */
+ 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;
}
// 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<DIBuilder> DB = llvm::make_unique<DIBuilder>(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;
}
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" }