aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp72
1 files changed, 43 insertions, 29 deletions
diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
index 3c46a99d0845..adc536f1add8 100644
--- a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
+++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
@@ -15,7 +15,9 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
#include <map>
using namespace llvm;
@@ -40,7 +42,7 @@ void DbgValueHistoryMap::startInstrRange(InlinedVariable Var,
assert(MI.isDebugValue() && "not a DBG_VALUE");
auto &Ranges = VarInstrRanges[Var];
if (!Ranges.empty() && Ranges.back().second == nullptr &&
- Ranges.back().first->isIdenticalTo(&MI)) {
+ Ranges.back().first->isIdenticalTo(MI)) {
DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
<< "\t" << Ranges.back().first << "\t" << MI << "\n");
return;
@@ -122,26 +124,6 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr);
}
-// \brief Collect all registers clobbered by @MI and apply the functor
-// @Func to their RegNo.
-// @Func should be a functor with a void(unsigned) signature. We're
-// not using std::function here for performance reasons. It has a
-// small but measurable impact. By using a functor instead of a
-// std::set& here, we can avoid the overhead of constructing
-// temporaries in calculateDbgValueHistory, which has a significant
-// performance impact.
-template<typename Callable>
-static void applyToClobberedRegisters(const MachineInstr &MI,
- const TargetRegisterInfo *TRI,
- Callable Func) {
- for (const MachineOperand &MO : MI.operands()) {
- if (!MO.isReg() || !MO.isDef() || !MO.getReg())
- continue;
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
- Func(*AI);
- }
-}
-
// \brief Returns the first instruction in @MBB which corresponds to
// the function epilogue, or nullptr if @MBB doesn't contain an epilogue.
static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
@@ -156,12 +138,12 @@ static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
E = MBB.rend();
I != E; ++I) {
if (I->getDebugLoc() != LastLoc)
- return Res;
+ return &*Res;
Res = &*I;
}
// If all instructions have the same debug location, assume whole MBB is
// an epilogue.
- return MBB.begin();
+ return &*MBB.begin();
}
// \brief Collect registers that are modified in the function body (their
@@ -173,10 +155,23 @@ static void collectChangingRegs(const MachineFunction *MF,
auto FirstEpilogueInst = getFirstEpilogueInst(MBB);
for (const auto &MI : MBB) {
+ // Avoid looking at prologue or epilogue instructions.
if (&MI == FirstEpilogueInst)
break;
- if (!MI.getFlag(MachineInstr::FrameSetup))
- applyToClobberedRegisters(MI, TRI, [&](unsigned r) { Regs.set(r); });
+ if (MI.getFlag(MachineInstr::FrameSetup))
+ continue;
+
+ // Look for register defs and register masks. Register masks are
+ // typically on calls and they clobber everything not in the mask.
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg()) {
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
+ ++AI)
+ Regs.set(*AI);
+ } else if (MO.isRegMask()) {
+ Regs.setBitsNotInMask(MO.getRegMask());
+ }
+ }
}
}
}
@@ -187,16 +182,35 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
BitVector ChangingRegs(TRI->getNumRegs());
collectChangingRegs(MF, TRI, ChangingRegs);
+ const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
+ unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
RegDescribedVarsMap RegVars;
for (const auto &MBB : *MF) {
for (const auto &MI : MBB) {
if (!MI.isDebugValue()) {
// Not a DBG_VALUE instruction. It may clobber registers which describe
// some variables.
- applyToClobberedRegisters(MI, TRI, [&](unsigned RegNo) {
- if (ChangingRegs.test(RegNo))
- clobberRegisterUses(RegVars, RegNo, Result, MI);
- });
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg()) {
+ // If this is a register def operand, it may end a debug value
+ // range.
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
+ ++AI)
+ if (ChangingRegs.test(*AI))
+ clobberRegisterUses(RegVars, *AI, Result, MI);
+ } else if (MO.isRegMask()) {
+ // If this is a register mask operand, clobber all debug values in
+ // non-CSRs.
+ for (int I = ChangingRegs.find_first(); I != -1;
+ I = ChangingRegs.find_next(I)) {
+ // Don't consider SP to be clobbered by register masks.
+ if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
+ MO.clobbersPhysReg(I)) {
+ clobberRegisterUses(RegVars, I, Result, MI);
+ }
+ }
+ }
+ }
continue;
}