#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericIteratedDominanceFrontier.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/SSAUpdaterImpl.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdint>
#include <functional>
#include <queue>
#include <tuple>
#include <utility>
#include <vector>
#include "InstrRefBasedImpl.h"
#include "LiveDebugValues.h"
using namespace llvm;
using namespace LiveDebugValues;
#undef DEBUG_TYPE
#define DEBUG_TYPE "livedebugvalues"
static cl::opt<bool> EmulateOldLDV("emulate-old-livedebugvalues", cl::Hidden,
cl::desc("Act like old LiveDebugValues did"),
cl::init(false));
static cl::opt<unsigned>
StackWorkingSetLimit("livedebugvalues-max-stack-slots", cl::Hidden,
cl::desc("livedebugvalues-stack-ws-limit"),
cl::init(250));
class TransferTracker {
public:
const TargetInstrInfo *TII;
const TargetLowering *TLI;
MLocTracker *MTracker;
MachineFunction &MF;
bool ShouldEmitDebugEntryValues;
struct Transfer {
MachineBasicBlock::instr_iterator Pos; MachineBasicBlock *MBB; SmallVector<MachineInstr *, 4> Insts; };
struct LocAndProperties {
LocIdx Loc;
DbgValueProperties Properties;
};
SmallVector<Transfer, 32> Transfers;
SmallVector<ValueIDNum, 32> VarLocs;
DenseMap<LocIdx, SmallSet<DebugVariable, 4>> ActiveMLocs;
DenseMap<DebugVariable, LocAndProperties> ActiveVLocs;
SmallVector<MachineInstr *, 4> PendingDbgValues;
struct UseBeforeDef {
ValueIDNum ID;
DebugVariable Var;
DbgValueProperties Properties;
};
DenseMap<unsigned, SmallVector<UseBeforeDef, 1>> UseBeforeDefs;
DenseSet<DebugVariable> UseBeforeDefVariables;
const TargetRegisterInfo &TRI;
const BitVector &CalleeSavedRegs;
TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker,
MachineFunction &MF, const TargetRegisterInfo &TRI,
const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC)
: TII(TII), MTracker(MTracker), MF(MF), TRI(TRI),
CalleeSavedRegs(CalleeSavedRegs) {
TLI = MF.getSubtarget().getTargetLowering();
auto &TM = TPC.getTM<TargetMachine>();
ShouldEmitDebugEntryValues = TM.Options.ShouldEmitDebugEntryValues();
}
void
loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs,
const SmallVectorImpl<std::pair<DebugVariable, DbgValue>> &VLocs,
unsigned NumLocs) {
ActiveMLocs.clear();
ActiveVLocs.clear();
VarLocs.clear();
VarLocs.reserve(NumLocs);
UseBeforeDefs.clear();
UseBeforeDefVariables.clear();
auto isCalleeSaved = [&](LocIdx L) {
unsigned Reg = MTracker->LocIdxToLocID[L];
if (Reg >= MTracker->NumRegs)
return false;
for (MCRegAliasIterator RAI(Reg, &TRI, true); RAI.isValid(); ++RAI)
if (CalleeSavedRegs.test(*RAI))
return true;
return false;
};
DenseMap<ValueIDNum, LocIdx> ValueToLoc;
for (const auto &VLoc : VLocs)
if (VLoc.second.Kind == DbgValue::Def)
ValueToLoc.insert({VLoc.second.ID, LocIdx::MakeIllegalLoc()});
ActiveMLocs.reserve(VLocs.size());
ActiveVLocs.reserve(VLocs.size());
for (auto Location : MTracker->locations()) {
LocIdx Idx = Location.Idx;
ValueIDNum &VNum = MLocs[Idx.asU64()];
VarLocs.push_back(VNum);
auto VIt = ValueToLoc.find(VNum);
if (VIt == ValueToLoc.end())
continue;
LocIdx CurLoc = VIt->second;
if (CurLoc.isIllegal() || MTracker->isSpill(CurLoc) ||
(!isCalleeSaved(CurLoc) && isCalleeSaved(Idx.asU64()))) {
VIt->second = Idx;
}
}
for (const auto &Var : VLocs) {
if (Var.second.Kind == DbgValue::Const) {
PendingDbgValues.push_back(
emitMOLoc(*Var.second.MO, Var.first, Var.second.Properties));
continue;
}
const ValueIDNum &Num = Var.second.ID;
auto ValuesPreferredLoc = ValueToLoc.find(Num);
if (ValuesPreferredLoc->second.isIllegal()) {
if (Num.getBlock() == (unsigned)MBB.getNumber() && !Num.isPHI())
addUseBeforeDef(Var.first, Var.second.Properties, Num);
else
recoverAsEntryValue(Var.first, Var.second.Properties, Num);
continue;
}
LocIdx M = ValuesPreferredLoc->second;
auto NewValue = LocAndProperties{M, Var.second.Properties};
auto Result = ActiveVLocs.insert(std::make_pair(Var.first, NewValue));
if (!Result.second)
Result.first->second = NewValue;
ActiveMLocs[M].insert(Var.first);
PendingDbgValues.push_back(
MTracker->emitLoc(M, Var.first, Var.second.Properties));
}
flushDbgValues(MBB.begin(), &MBB);
}
void addUseBeforeDef(const DebugVariable &Var,
const DbgValueProperties &Properties, ValueIDNum ID) {
UseBeforeDef UBD = {ID, Var, Properties};
UseBeforeDefs[ID.getInst()].push_back(UBD);
UseBeforeDefVariables.insert(Var);
}
void checkInstForNewValues(unsigned Inst, MachineBasicBlock::iterator pos) {
auto MIt = UseBeforeDefs.find(Inst);
if (MIt == UseBeforeDefs.end())
return;
for (auto &Use : MIt->second) {
LocIdx L = Use.ID.getLoc();
if (MTracker->readMLoc(L) != Use.ID)
continue;
if (!UseBeforeDefVariables.count(Use.Var))
continue;
PendingDbgValues.push_back(MTracker->emitLoc(L, Use.Var, Use.Properties));
}
flushDbgValues(pos, nullptr);
}
void flushDbgValues(MachineBasicBlock::iterator Pos, MachineBasicBlock *MBB) {
if (PendingDbgValues.size() == 0)
return;
MachineBasicBlock::instr_iterator BundleStart;
if (MBB && Pos == MBB->begin())
BundleStart = MBB->instr_begin();
else
BundleStart = getBundleStart(Pos->getIterator());
Transfers.push_back({BundleStart, MBB, PendingDbgValues});
PendingDbgValues.clear();
}
bool isEntryValueVariable(const DebugVariable &Var,
const DIExpression *Expr) const {
if (!Var.getVariable()->isParameter())
return false;
if (Var.getInlinedAt())
return false;
if (Expr->getNumElements() > 0)
return false;
return true;
}
bool isEntryValueValue(const ValueIDNum &Val) const {
if (Val.getBlock() || !Val.isPHI())
return false;
if (MTracker->isSpill(Val.getLoc()))
return false;
Register SP = TLI->getStackPointerRegisterToSaveRestore();
Register FP = TRI.getFrameRegister(MF);
Register Reg = MTracker->LocIdxToLocID[Val.getLoc()];
return Reg != SP && Reg != FP;
}
bool recoverAsEntryValue(const DebugVariable &Var,
const DbgValueProperties &Prop,
const ValueIDNum &Num) {
if (!ShouldEmitDebugEntryValues)
return false;
if (!isEntryValueVariable(Var, Prop.DIExpr))
return false;
if (!isEntryValueValue(Num))
return false;
DIExpression *NewExpr =
DIExpression::prepend(Prop.DIExpr, DIExpression::EntryValue);
Register Reg = MTracker->LocIdxToLocID[Num.getLoc()];
MachineOperand MO = MachineOperand::CreateReg(Reg, false);
PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect}));
return true;
}
void redefVar(const MachineInstr &MI) {
DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
MI.getDebugLoc()->getInlinedAt());
DbgValueProperties Properties(MI);
const MachineOperand &MO = MI.getOperand(0);
if (!MO.isReg() || MO.getReg() == 0) {
auto It = ActiveVLocs.find(Var);
if (It != ActiveVLocs.end()) {
ActiveMLocs[It->second.Loc].erase(Var);
ActiveVLocs.erase(It);
}
UseBeforeDefVariables.erase(Var);
return;
}
Register Reg = MO.getReg();
LocIdx NewLoc = MTracker->getRegMLoc(Reg);
redefVar(MI, Properties, NewLoc);
}
void redefVar(const MachineInstr &MI, const DbgValueProperties &Properties,
Optional<LocIdx> OptNewLoc) {
DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(),
MI.getDebugLoc()->getInlinedAt());
UseBeforeDefVariables.erase(Var);
auto It = ActiveVLocs.find(Var);
if (It != ActiveVLocs.end())
ActiveMLocs[It->second.Loc].erase(Var);
if (!OptNewLoc)
return;
LocIdx NewLoc = *OptNewLoc;
if (MTracker->readMLoc(NewLoc) != VarLocs[NewLoc.asU64()]) {
for (const auto &P : ActiveMLocs[NewLoc]) {
ActiveVLocs.erase(P);
}
ActiveMLocs[NewLoc.asU64()].clear();
VarLocs[NewLoc.asU64()] = MTracker->readMLoc(NewLoc);
}
ActiveMLocs[NewLoc].insert(Var);
if (It == ActiveVLocs.end()) {
ActiveVLocs.insert(
std::make_pair(Var, LocAndProperties{NewLoc, Properties}));
} else {
It->second.Loc = NewLoc;
It->second.Properties = Properties;
}
}
void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos,
bool MakeUndef = true) {
auto ActiveMLocIt = ActiveMLocs.find(MLoc);
if (ActiveMLocIt == ActiveMLocs.end())
return;
ValueIDNum OldValue = VarLocs[MLoc.asU64()];
clobberMloc(MLoc, OldValue, Pos, MakeUndef);
}
void clobberMloc(LocIdx MLoc, ValueIDNum OldValue,
MachineBasicBlock::iterator Pos, bool MakeUndef = true) {
auto ActiveMLocIt = ActiveMLocs.find(MLoc);
if (ActiveMLocIt == ActiveMLocs.end())
return;
VarLocs[MLoc.asU64()] = ValueIDNum::EmptyValue;
Optional<LocIdx> NewLoc = None;
for (auto Loc : MTracker->locations())
if (Loc.Value == OldValue)
NewLoc = Loc.Idx;
if (!NewLoc && !MakeUndef) {
for (const auto &Var : ActiveMLocIt->second) {
auto &Prop = ActiveVLocs.find(Var)->second.Properties;
recoverAsEntryValue(Var, Prop, OldValue);
}
flushDbgValues(Pos, nullptr);
return;
}
DenseSet<DebugVariable> NewMLocs;
for (const auto &Var : ActiveMLocIt->second) {
auto ActiveVLocIt = ActiveVLocs.find(Var);
const DbgValueProperties &Properties = ActiveVLocIt->second.Properties;
PendingDbgValues.push_back(MTracker->emitLoc(NewLoc, Var, Properties));
if (!NewLoc) {
ActiveVLocs.erase(ActiveVLocIt);
} else {
ActiveVLocIt->second.Loc = *NewLoc;
NewMLocs.insert(Var);
}
}
if (!NewMLocs.empty())
for (auto &Var : NewMLocs)
ActiveMLocs[*NewLoc].insert(Var);
if (NewLoc)
VarLocs[NewLoc->asU64()] = OldValue;
flushDbgValues(Pos, nullptr);
ActiveMLocIt = ActiveMLocs.find(MLoc);
ActiveMLocIt->second.clear();
}
void transferMlocs(LocIdx Src, LocIdx Dst, MachineBasicBlock::iterator Pos) {
if (VarLocs[Src.asU64()] != MTracker->readMLoc(Src))
return;
auto MovingVars = ActiveMLocs[Src];
ActiveMLocs[Dst] = MovingVars;
VarLocs[Dst.asU64()] = VarLocs[Src.asU64()];
for (const auto &Var : MovingVars) {
auto ActiveVLocIt = ActiveVLocs.find(Var);
assert(ActiveVLocIt != ActiveVLocs.end());
ActiveVLocIt->second.Loc = Dst;
MachineInstr *MI =
MTracker->emitLoc(Dst, Var, ActiveVLocIt->second.Properties);
PendingDbgValues.push_back(MI);
}
ActiveMLocs[Src].clear();
flushDbgValues(Pos, nullptr);
if (EmulateOldLDV)
VarLocs[Src.asU64()] = ValueIDNum::EmptyValue;
}
MachineInstrBuilder emitMOLoc(const MachineOperand &MO,
const DebugVariable &Var,
const DbgValueProperties &Properties) {
DebugLoc DL = DILocation::get(Var.getVariable()->getContext(), 0, 0,
Var.getVariable()->getScope(),
const_cast<DILocation *>(Var.getInlinedAt()));
auto MIB = BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE));
MIB.add(MO);
if (Properties.Indirect)
MIB.addImm(0);
else
MIB.addReg(0);
MIB.addMetadata(Var.getVariable());
MIB.addMetadata(Properties.DIExpr);
return MIB;
}
};
ValueIDNum ValueIDNum::EmptyValue = {UINT_MAX, UINT_MAX, UINT_MAX};
ValueIDNum ValueIDNum::TombstoneValue = {UINT_MAX, UINT_MAX, UINT_MAX - 1};
#ifndef NDEBUG
void DbgValue::dump(const MLocTracker *MTrack) const {
if (Kind == Const) {
MO->dump();
} else if (Kind == NoVal) {
dbgs() << "NoVal(" << BlockNo << ")";
} else if (Kind == VPHI) {
dbgs() << "VPHI(" << BlockNo << "," << MTrack->IDAsString(ID) << ")";
} else {
assert(Kind == Def);
dbgs() << MTrack->IDAsString(ID);
}
if (Properties.Indirect)
dbgs() << " indir";
if (Properties.DIExpr)
dbgs() << " " << *Properties.DIExpr;
}
#endif
MLocTracker::MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const TargetLowering &TLI)
: MF(MF), TII(TII), TRI(TRI), TLI(TLI),
LocIdxToIDNum(ValueIDNum::EmptyValue), LocIdxToLocID(0) {
NumRegs = TRI.getNumRegs();
reset();
LocIDToLocIdx.resize(NumRegs, LocIdx::MakeIllegalLoc());
assert(NumRegs < (1u << NUM_LOC_BITS));
Register SP = TLI.getStackPointerRegisterToSaveRestore();
if (SP) {
unsigned ID = getLocID(SP);
(void)lookupOrTrackRegister(ID);
for (MCRegAliasIterator RAI(SP, &TRI, true); RAI.isValid(); ++RAI)
SPAliases.insert(*RAI);
}
StackSlotIdxes.insert({{8, 0}, 0});
StackSlotIdxes.insert({{16, 0}, 1});
StackSlotIdxes.insert({{32, 0}, 2});
StackSlotIdxes.insert({{64, 0}, 3});
StackSlotIdxes.insert({{128, 0}, 4});
StackSlotIdxes.insert({{256, 0}, 5});
StackSlotIdxes.insert({{512, 0}, 6});
for (unsigned int I = 1; I < TRI.getNumSubRegIndices(); ++I) {
unsigned Size = TRI.getSubRegIdxSize(I);
unsigned Offs = TRI.getSubRegIdxOffset(I);
unsigned Idx = StackSlotIdxes.size();
if (Size > 60000 || Offs > 60000)
continue;
StackSlotIdxes.insert({{Size, Offs}, Idx});
}
for (const TargetRegisterClass *RC : TRI.regclasses()) {
unsigned Size = TRI.getRegSizeInBits(*RC);
if (Size > 512)
continue;
unsigned Idx = StackSlotIdxes.size();
StackSlotIdxes.insert({{Size, 0}, Idx});
}
for (auto &Idx : StackSlotIdxes)
StackIdxesToPos[Idx.second] = Idx.first;
NumSlotIdxes = StackSlotIdxes.size();
}
LocIdx MLocTracker::trackRegister(unsigned ID) {
assert(ID != 0);
LocIdx NewIdx = LocIdx(LocIdxToIDNum.size());
LocIdxToIDNum.grow(NewIdx);
LocIdxToLocID.grow(NewIdx);
ValueIDNum ValNum = {CurBB, 0, NewIdx};
for (const auto &MaskPair : reverse(Masks)) {
if (MaskPair.first->clobbersPhysReg(ID)) {
ValNum = {CurBB, MaskPair.second, NewIdx};
break;
}
}
LocIdxToIDNum[NewIdx] = ValNum;
LocIdxToLocID[NewIdx] = ID;
return NewIdx;
}
void MLocTracker::writeRegMask(const MachineOperand *MO, unsigned CurBB,
unsigned InstID) {
for (auto Location : locations()) {
unsigned ID = LocIdxToLocID[Location.Idx];
if (ID < NumRegs && !SPAliases.count(ID) && MO->clobbersPhysReg(ID))
defReg(ID, CurBB, InstID);
}
Masks.push_back(std::make_pair(MO, InstID));
}
Optional<SpillLocationNo> MLocTracker::getOrTrackSpillLoc(SpillLoc L) {
SpillLocationNo SpillID(SpillLocs.idFor(L));
if (SpillID.id() == 0) {
if (SpillLocs.size() >= StackWorkingSetLimit)
return None;
SpillID = SpillLocationNo(SpillLocs.insert(L));
for (unsigned StackIdx = 0; StackIdx < NumSlotIdxes; ++StackIdx) {
unsigned L = getSpillIDWithIdx(SpillID, StackIdx);
LocIdx Idx = LocIdx(LocIdxToIDNum.size()); LocIdxToIDNum.grow(Idx);
LocIdxToLocID.grow(Idx);
LocIDToLocIdx.push_back(Idx);
LocIdxToLocID[Idx] = L;
LocIdxToIDNum[Idx] = ValueIDNum(CurBB, 0, Idx);
}
}
return SpillID;
}
std::string MLocTracker::LocIdxToName(LocIdx Idx) const {
unsigned ID = LocIdxToLocID[Idx];
if (ID >= NumRegs) {
StackSlotPos Pos = locIDToSpillIdx(ID);
ID -= NumRegs;
unsigned Slot = ID / NumSlotIdxes;
return Twine("slot ")
.concat(Twine(Slot).concat(Twine(" sz ").concat(Twine(Pos.first)
.concat(Twine(" offs ").concat(Twine(Pos.second))))))
.str();
} else {
return TRI.getRegAsmName(ID).str();
}
}
std::string MLocTracker::IDAsString(const ValueIDNum &Num) const {
std::string DefName = LocIdxToName(Num.getLoc());
return Num.asString(DefName);
}
#ifndef NDEBUG
LLVM_DUMP_METHOD void MLocTracker::dump() {
for (auto Location : locations()) {
std::string MLocName = LocIdxToName(Location.Value.getLoc());
std::string DefName = Location.Value.asString(MLocName);
dbgs() << LocIdxToName(Location.Idx) << " --> " << DefName << "\n";
}
}
LLVM_DUMP_METHOD void MLocTracker::dump_mloc_map() {
for (auto Location : locations()) {
std::string foo = LocIdxToName(Location.Idx);
dbgs() << "Idx " << Location.Idx.asU64() << " " << foo << "\n";
}
}
#endif
MachineInstrBuilder MLocTracker::emitLoc(Optional<LocIdx> MLoc,
const DebugVariable &Var,
const DbgValueProperties &Properties) {
DebugLoc DL = DILocation::get(Var.getVariable()->getContext(), 0, 0,
Var.getVariable()->getScope(),
const_cast<DILocation *>(Var.getInlinedAt()));
auto MIB = BuildMI(MF, DL, TII.get(TargetOpcode::DBG_VALUE));
const DIExpression *Expr = Properties.DIExpr;
if (!MLoc) {
MIB.addReg(0);
MIB.addReg(0);
} else if (LocIdxToLocID[*MLoc] >= NumRegs) {
unsigned LocID = LocIdxToLocID[*MLoc];
SpillLocationNo SpillID = locIDToSpill(LocID);
StackSlotPos StackIdx = locIDToSpillIdx(LocID);
unsigned short Offset = StackIdx.second;
if (Offset == 0) {
const SpillLoc &Spill = SpillLocs[SpillID.id()];
unsigned Base = Spill.SpillBase;
MIB.addReg(Base);
bool UseDerefSize = false;
unsigned ValueSizeInBits = getLocSizeInBits(*MLoc);
unsigned DerefSizeInBytes = ValueSizeInBits / 8;
if (auto Fragment = Var.getFragment()) {
unsigned VariableSizeInBits = Fragment->SizeInBits;
if (VariableSizeInBits != ValueSizeInBits || Expr->isComplex())
UseDerefSize = true;
} else if (auto Size = Var.getVariable()->getSizeInBits()) {
if (*Size != ValueSizeInBits) {
UseDerefSize = true;
}
}
if (Properties.Indirect) {
assert(!Expr->isImplicit());
Expr = TRI.prependOffsetExpression(
Expr, DIExpression::ApplyOffset | DIExpression::DerefAfter,
Spill.SpillOffset);
MIB.addImm(0);
} else if (UseDerefSize) {
SmallVector<uint64_t, 2> Ops = {dwarf::DW_OP_deref_size,
DerefSizeInBytes};
Expr = DIExpression::prependOpcodes(Expr, Ops, true);
unsigned Flags = DIExpression::StackValue | DIExpression::ApplyOffset;
Expr = TRI.prependOffsetExpression(Expr, Flags, Spill.SpillOffset);
MIB.addReg(0);
} else if (Expr->isComplex()) {
assert(Expr->isComplex());
Expr = TRI.prependOffsetExpression(
Expr, DIExpression::ApplyOffset | DIExpression::DerefAfter,
Spill.SpillOffset);
MIB.addReg(0);
} else {
Expr = TRI.prependOffsetExpression(Expr, DIExpression::ApplyOffset,
Spill.SpillOffset);
MIB.addImm(0);
}
} else {
MIB.addReg(0);
MIB.addReg(0);
}
} else {
unsigned LocID = LocIdxToLocID[*MLoc];
MIB.addReg(LocID);
if (Properties.Indirect)
MIB.addImm(0);
else
MIB.addReg(0);
}
MIB.addMetadata(Var.getVariable());
MIB.addMetadata(Expr);
return MIB;
}
InstrRefBasedLDV::InstrRefBasedLDV() = default;
bool InstrRefBasedLDV::isCalleeSaved(LocIdx L) const {
unsigned Reg = MTracker->LocIdxToLocID[L];
for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
if (CalleeSavedRegs.test(*RAI))
return true;
return false;
}
#ifndef NDEBUG
#endif
Optional<SpillLocationNo>
InstrRefBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) {
assert(MI.hasOneMemOperand() &&
"Spill instruction does not have exactly one memory operand?");
auto MMOI = MI.memoperands_begin();
const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
assert(PVal->kind() == PseudoSourceValue::FixedStack &&
"Inconsistent memory operand in spill instruction");
int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
const MachineBasicBlock *MBB = MI.getParent();
Register Reg;
StackOffset Offset = TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg);
return MTracker->getOrTrackSpillLoc({Reg, Offset});
}
Optional<LocIdx>
InstrRefBasedLDV::findLocationForMemOperand(const MachineInstr &MI) {
Optional<SpillLocationNo> SpillLoc = extractSpillBaseRegAndOffset(MI);
if (!SpillLoc)
return None;
auto *MemOperand = *MI.memoperands_begin();
unsigned SizeInBits = MemOperand->getSizeInBits();
auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits, 0});
if (IdxIt == MTracker->StackSlotIdxes.end())
return None;
unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillLoc, IdxIt->second);
return MTracker->getSpillMLoc(SpillID);
}
bool InstrRefBasedLDV::transferDebugValue(const MachineInstr &MI) {
if (!MI.isDebugValue())
return false;
const DILocalVariable *Var = MI.getDebugVariable();
const DIExpression *Expr = MI.getDebugExpression();
const DILocation *DebugLoc = MI.getDebugLoc();
const DILocation *InlinedAt = DebugLoc->getInlinedAt();
assert(Var->isValidLocationForIntrinsic(DebugLoc) &&
"Expected inlined-at fields to agree");
DebugVariable V(Var, Expr, InlinedAt);
DbgValueProperties Properties(MI);
auto *Scope = LS.findLexicalScope(MI.getDebugLoc().get());
if (Scope == nullptr)
return true;
if (MI.isDebugValueList()) {
if (VTracker)
VTracker->defVar(MI, Properties, None);
if (TTracker)
TTracker->redefVar(MI, Properties, None);
return true;
}
const MachineOperand &MO = MI.getOperand(0);
if (MO.isReg() && MO.getReg() != 0)
(void)MTracker->readReg(MO.getReg());
if (VTracker) {
if (MO.isReg()) {
if (MO.getReg())
VTracker->defVar(MI, Properties, MTracker->readReg(MO.getReg()));
else
VTracker->defVar(MI, Properties, None);
} else if (MI.getOperand(0).isImm() || MI.getOperand(0).isFPImm() ||
MI.getOperand(0).isCImm()) {
VTracker->defVar(MI, MI.getOperand(0));
}
}
if (TTracker)
TTracker->redefVar(MI);
return true;
}
bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI,
const ValueTable *MLiveOuts,
const ValueTable *MLiveIns) {
if (!MI.isDebugRef())
return false;
if (!VTracker && !TTracker)
return false;
unsigned InstNo = MI.getOperand(0).getImm();
unsigned OpNo = MI.getOperand(1).getImm();
const DILocalVariable *Var = MI.getDebugVariable();
const DIExpression *Expr = MI.getDebugExpression();
const DILocation *DebugLoc = MI.getDebugLoc();
const DILocation *InlinedAt = DebugLoc->getInlinedAt();
assert(Var->isValidLocationForIntrinsic(DebugLoc) &&
"Expected inlined-at fields to agree");
DebugVariable V(Var, Expr, InlinedAt);
auto *Scope = LS.findLexicalScope(MI.getDebugLoc().get());
if (Scope == nullptr)
return true;
const MachineFunction &MF = *MI.getParent()->getParent();
auto SoughtSub =
MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0);
SmallVector<unsigned, 4> SeenSubregs;
auto LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub);
while (LowerBoundIt != MF.DebugValueSubstitutions.end() &&
LowerBoundIt->Src == SoughtSub.Src) {
std::tie(InstNo, OpNo) = LowerBoundIt->Dest;
SoughtSub.Src = LowerBoundIt->Dest;
if (unsigned Subreg = LowerBoundIt->Subreg)
SeenSubregs.push_back(Subreg);
LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub);
}
Optional<ValueIDNum> NewID = None;
auto InstrIt = DebugInstrNumToInstr.find(InstNo);
auto PHIIt = std::lower_bound(DebugPHINumToValue.begin(),
DebugPHINumToValue.end(), InstNo);
if (InstrIt != DebugInstrNumToInstr.end()) {
const MachineInstr &TargetInstr = *InstrIt->second.first;
uint64_t BlockNo = TargetInstr.getParent()->getNumber();
if (OpNo == MachineFunction::DebugOperandMemNumber &&
TargetInstr.hasOneMemOperand()) {
Optional<LocIdx> L = findLocationForMemOperand(TargetInstr);
if (L)
NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L);
} else if (OpNo != MachineFunction::DebugOperandMemNumber) {
if (OpNo < TargetInstr.getNumOperands()) {
const MachineOperand &MO = TargetInstr.getOperand(OpNo);
if (MO.isReg() && MO.isDef() && MO.getReg()) {
unsigned LocID = MTracker->getLocID(MO.getReg());
LocIdx L = MTracker->LocIDToLocIdx[LocID];
NewID = ValueIDNum(BlockNo, InstrIt->second.second, L);
}
}
if (!NewID) {
LLVM_DEBUG(
{ dbgs() << "Seen instruction reference to illegal operand\n"; });
}
}
} else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) {
NewID = resolveDbgPHIs(*MI.getParent()->getParent(), MLiveOuts, MLiveIns,
MI, InstNo);
}
if (NewID && !SeenSubregs.empty()) {
unsigned Offset = 0;
unsigned Size = 0;
for (unsigned Subreg : reverse(SeenSubregs)) {
unsigned ThisSize = TRI->getSubRegIdxSize(Subreg);
unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg);
Offset += ThisOffset;
Size = (Size == 0) ? ThisSize : std::min(Size, ThisSize);
}
LocIdx L = NewID->getLoc();
if (NewID && !MTracker->isSpill(L)) {
Register Reg = MTracker->LocIdxToLocID[L];
const TargetRegisterClass *TRC = nullptr;
for (const auto *TRCI : TRI->regclasses())
if (TRCI->contains(Reg))
TRC = TRCI;
assert(TRC && "Couldn't find target register class?");
unsigned MainRegSize = TRI->getRegSizeInBits(*TRC);
if (Size != MainRegSize || Offset) {
Register NewReg = 0;
for (MCSubRegIterator SRI(Reg, TRI, false); SRI.isValid(); ++SRI) {
unsigned Subreg = TRI->getSubRegIndex(Reg, *SRI);
unsigned SubregSize = TRI->getSubRegIdxSize(Subreg);
unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg);
if (SubregSize == Size && SubregOffset == Offset) {
NewReg = *SRI;
break;
}
}
if (!NewReg) {
NewID = None;
} else {
LocIdx NewLoc = MTracker->lookupOrTrackRegister(NewReg);
NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc);
}
}
} else {
NewID = None;
}
}
DbgValueProperties Properties(Expr, false);
if (VTracker)
VTracker->defVar(MI, Properties, NewID);
if (!TTracker)
return true;
Optional<LocIdx> FoundLoc = None;
for (auto Location : MTracker->locations()) {
LocIdx CurL = Location.Idx;
ValueIDNum ID = MTracker->readMLoc(CurL);
if (NewID && ID == NewID) {
if (!FoundLoc) {
FoundLoc = CurL;
continue;
}
if (MTracker->isSpill(CurL))
FoundLoc = CurL; else if (!MTracker->isSpill(*FoundLoc) &&
!MTracker->isSpill(CurL) &&
!isCalleeSaved(*FoundLoc) &&
isCalleeSaved(CurL))
FoundLoc = CurL; }
}
TTracker->redefVar(MI, Properties, FoundLoc);
if (!FoundLoc && NewID && NewID->getBlock() == CurBB &&
NewID->getInst() > CurInst)
TTracker->addUseBeforeDef(V, {MI.getDebugExpression(), false}, *NewID);
MachineInstr *DbgMI = MTracker->emitLoc(FoundLoc, V, Properties);
TTracker->PendingDbgValues.push_back(DbgMI);
TTracker->flushDbgValues(MI.getIterator(), nullptr);
return true;
}
bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) {
if (!MI.isDebugPHI())
return false;
if (VTracker || TTracker)
return true;
const MachineOperand &MO = MI.getOperand(0);
unsigned InstrNum = MI.getOperand(1).getImm();
auto EmitBadPHI = [this, &MI, InstrNum]() -> bool {
DebugPHINumToValue.push_back({InstrNum, MI.getParent(), None, None});
return true;
};
if (MO.isReg() && MO.getReg()) {
Register Reg = MO.getReg();
ValueIDNum Num = MTracker->readReg(Reg);
auto PHIRec = DebugPHIRecord(
{InstrNum, MI.getParent(), Num, MTracker->lookupOrTrackRegister(Reg)});
DebugPHINumToValue.push_back(PHIRec);
for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
MTracker->lookupOrTrackRegister(*RAI);
} else if (MO.isFI()) {
unsigned FI = MO.getIndex();
if (MFI->isDeadObjectIndex(FI))
return EmitBadPHI();
Register Base;
StackOffset Offs = TFI->getFrameIndexReference(*MI.getMF(), FI, Base);
SpillLoc SL = {Base, Offs};
Optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL);
if (!SpillNo)
return EmitBadPHI();
assert(MI.getNumOperands() == 3 && "Stack DBG_PHI with no size?");
unsigned slotBitSize = MI.getOperand(2).getImm();
unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
ValueIDNum Result = MTracker->readMLoc(SpillLoc);
auto DbgPHI = DebugPHIRecord({InstrNum, MI.getParent(), Result, SpillLoc});
DebugPHINumToValue.push_back(DbgPHI);
} else {
LLVM_DEBUG(
{ dbgs() << "Seen DBG_PHI with unrecognised operand format\n"; });
return EmitBadPHI();
}
return true;
}
void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) {
if (MI.isImplicitDef()) {
ValueIDNum Num = MTracker->readReg(MI.getOperand(0).getReg());
if (Num.getLoc() != 0)
return;
} else if (MI.isMetaInstruction())
return;
bool CallChangesSP = false;
if (AdjustsStackInCalls && MI.isCall() && MI.getOperand(0).isSymbol() &&
!strcmp(MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data()))
CallChangesSP = true;
auto IgnoreSPAlias = [this, &MI, CallChangesSP](Register R) -> bool {
if (CallChangesSP)
return false;
return MI.isCall() && MTracker->SPAliases.count(R);
};
SmallSet<uint32_t, 32> DeadRegs;
SmallVector<const uint32_t *, 4> RegMasks;
SmallVector<const MachineOperand *, 4> RegMaskPtrs;
for (const MachineOperand &MO : MI.operands()) {
if (MO.isReg() && MO.isDef() && MO.getReg() &&
Register::isPhysicalRegister(MO.getReg()) &&
!IgnoreSPAlias(MO.getReg())) {
for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
DeadRegs.insert(*RAI);
} else if (MO.isRegMask()) {
RegMasks.push_back(MO.getRegMask());
RegMaskPtrs.push_back(&MO);
}
}
for (uint32_t DeadReg : DeadRegs)
MTracker->defReg(DeadReg, CurBB, CurInst);
for (const auto *MO : RegMaskPtrs)
MTracker->writeRegMask(MO, CurBB, CurInst);
if (hasFoldedStackStore(MI)) {
if (Optional<SpillLocationNo> SpillNo = extractSpillBaseRegAndOffset(MI)) {
for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) {
unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I);
LocIdx L = MTracker->getSpillMLoc(SpillID);
MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L));
}
}
}
if (!TTracker)
return;
for (uint32_t DeadReg : DeadRegs) {
LocIdx Loc = MTracker->lookupOrTrackRegister(DeadReg);
TTracker->clobberMloc(Loc, MI.getIterator(), false);
}
if (!RegMaskPtrs.empty()) {
for (auto L : MTracker->locations()) {
if (MTracker->isSpill(L.Idx))
continue;
Register Reg = MTracker->LocIdxToLocID[L.Idx];
if (IgnoreSPAlias(Reg))
continue;
for (const auto *MO : RegMaskPtrs)
if (MO->clobbersPhysReg(Reg))
TTracker->clobberMloc(L.Idx, MI.getIterator(), false);
}
}
if (hasFoldedStackStore(MI)) {
if (Optional<SpillLocationNo> SpillNo = extractSpillBaseRegAndOffset(MI)) {
for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) {
unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I);
LocIdx L = MTracker->getSpillMLoc(SpillID);
TTracker->clobberMloc(L, MI.getIterator(), true);
}
}
}
}
void InstrRefBasedLDV::performCopy(Register SrcRegNum, Register DstRegNum) {
for (MCRegAliasIterator RAI(DstRegNum, TRI, true); RAI.isValid(); ++RAI)
MTracker->defReg(*RAI, CurBB, CurInst);
ValueIDNum SrcValue = MTracker->readReg(SrcRegNum);
MTracker->setReg(DstRegNum, SrcValue);
for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) {
unsigned SrcSubReg = SRI.getSubReg();
unsigned SubRegIdx = SRI.getSubRegIndex();
unsigned DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx);
if (!DstSubReg)
continue;
LocIdx SrcL = MTracker->lookupOrTrackRegister(SrcSubReg);
LocIdx DstL = MTracker->lookupOrTrackRegister(DstSubReg);
(void)SrcL;
(void)DstL;
ValueIDNum CpyValue = MTracker->readReg(SrcSubReg);
MTracker->setReg(DstSubReg, CpyValue);
}
}
Optional<SpillLocationNo>
InstrRefBasedLDV::isSpillInstruction(const MachineInstr &MI,
MachineFunction *MF) {
if (!MI.hasOneMemOperand())
return None;
auto MMOI = MI.memoperands_begin();
const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue();
if (PVal->isAliased(MFI))
return None;
if (!MI.getSpillSize(TII) && !MI.getFoldedSpillSize(TII))
return None;
return extractSpillBaseRegAndOffset(MI);
}
bool InstrRefBasedLDV::isLocationSpill(const MachineInstr &MI,
MachineFunction *MF, unsigned &Reg) {
if (!isSpillInstruction(MI, MF))
return false;
int FI;
Reg = TII->isStoreToStackSlotPostFE(MI, FI);
return Reg != 0;
}
Optional<SpillLocationNo>
InstrRefBasedLDV::isRestoreInstruction(const MachineInstr &MI,
MachineFunction *MF, unsigned &Reg) {
if (!MI.hasOneMemOperand())
return None;
if (MI.getRestoreSize(TII)) {
Reg = MI.getOperand(0).getReg();
return extractSpillBaseRegAndOffset(MI);
}
return None;
}
bool InstrRefBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI) {
if (EmulateOldLDV)
return false;
int DummyFI = -1;
if (!TII->isStoreToStackSlotPostFE(MI, DummyFI) &&
!TII->isLoadFromStackSlotPostFE(MI, DummyFI))
return false;
MachineFunction *MF = MI.getMF();
unsigned Reg;
LLVM_DEBUG(dbgs() << "Examining instruction: "; MI.dump(););
int FIDummy;
if (!TII->isStoreToStackSlotPostFE(MI, FIDummy) &&
!TII->isLoadFromStackSlotPostFE(MI, FIDummy))
return false;
if (Optional<SpillLocationNo> Loc = isSpillInstruction(MI, MF)) {
for (unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) {
unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx);
Optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID);
if (!MLoc)
continue;
ValueIDNum Def(CurBB, CurInst, *MLoc);
MTracker->setMLoc(*MLoc, Def);
if (TTracker)
TTracker->clobberMloc(*MLoc, MI.getIterator());
}
}
if (isLocationSpill(MI, MF, Reg)) {
SpillLocationNo Loc = *extractSpillBaseRegAndOffset(MI);
auto DoTransfer = [&](Register SrcReg, unsigned SpillID) {
auto ReadValue = MTracker->readReg(SrcReg);
LocIdx DstLoc = MTracker->getSpillMLoc(SpillID);
MTracker->setMLoc(DstLoc, ReadValue);
if (TTracker) {
LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg);
TTracker->transferMlocs(SrcLoc, DstLoc, MI.getIterator());
}
};
for (MCSubRegIterator SRI(Reg, TRI, false); SRI.isValid(); ++SRI) {
(void)MTracker->lookupOrTrackRegister(*SRI);
unsigned SubregIdx = TRI->getSubRegIndex(Reg, *SRI);
unsigned SpillID = MTracker->getLocID(Loc, SubregIdx);
DoTransfer(*SRI, SpillID);
}
unsigned Size = TRI->getRegSizeInBits(Reg, *MRI);
unsigned SpillID = MTracker->getLocID(Loc, {Size, 0});
DoTransfer(Reg, SpillID);
} else {
Optional<SpillLocationNo> Loc = isRestoreInstruction(MI, MF, Reg);
if (!Loc)
return false;
for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
MTracker->defReg(*RAI, CurBB, CurInst);
auto DoTransfer = [&](Register DestReg, unsigned SpillID) {
LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID);
auto ReadValue = MTracker->readMLoc(SrcIdx);
MTracker->setReg(DestReg, ReadValue);
};
for (MCSubRegIterator SRI(Reg, TRI, false); SRI.isValid(); ++SRI) {
unsigned Subreg = TRI->getSubRegIndex(Reg, *SRI);
unsigned SpillID = MTracker->getLocID(*Loc, Subreg);
DoTransfer(*SRI, SpillID);
}
unsigned Size = TRI->getRegSizeInBits(Reg, *MRI);
unsigned SpillID = MTracker->getLocID(*Loc, {Size, 0});
DoTransfer(Reg, SpillID);
}
return true;
}
bool InstrRefBasedLDV::transferRegisterCopy(MachineInstr &MI) {
auto DestSrc = TII->isCopyInstr(MI);
if (!DestSrc)
return false;
const MachineOperand *DestRegOp = DestSrc->Destination;
const MachineOperand *SrcRegOp = DestSrc->Source;
auto isCalleeSavedReg = [&](unsigned Reg) {
for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI)
if (CalleeSavedRegs.test(*RAI))
return true;
return false;
};
Register SrcReg = SrcRegOp->getReg();
Register DestReg = DestRegOp->getReg();
if (SrcReg == DestReg)
return true;
if (EmulateOldLDV && !isCalleeSavedReg(DestReg))
return false;
if (EmulateOldLDV && !SrcRegOp->isKill())
return false;
DenseMap<LocIdx, ValueIDNum> ClobberedLocs;
if (TTracker) {
for (MCRegAliasIterator RAI(DestReg, TRI, true); RAI.isValid(); ++RAI) {
LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI);
auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc);
if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty())
continue;
ValueIDNum Value = MTracker->readReg(*RAI);
ClobberedLocs[ClobberedLoc] = Value;
}
}
InstrRefBasedLDV::performCopy(SrcReg, DestReg);
if (TTracker) {
for (auto LocVal : ClobberedLocs) {
TTracker->clobberMloc(LocVal.first, LocVal.second, MI.getIterator(), false);
}
}
if (TTracker && isCalleeSavedReg(DestReg) && SrcRegOp->isKill())
TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg),
MTracker->getRegMLoc(DestReg), MI.getIterator());
if (EmulateOldLDV && SrcReg != DestReg)
MTracker->defReg(SrcReg, CurBB, CurInst);
return true;
}
void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) {
assert(MI.isDebugValue() || MI.isDebugRef());
DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),
MI.getDebugLoc()->getInlinedAt());
FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
auto SeenIt = SeenFragments.find(MIVar.getVariable());
if (SeenIt == SeenFragments.end()) {
SmallSet<FragmentInfo, 4> OneFragment;
OneFragment.insert(ThisFragment);
SeenFragments.insert({MIVar.getVariable(), OneFragment});
OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
return;
}
auto IsInOLapMap =
OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
if (!IsInOLapMap.second)
return;
auto &ThisFragmentsOverlaps = IsInOLapMap.first->second;
auto &AllSeenFragments = SeenIt->second;
for (const auto &ASeenFragment : AllSeenFragments) {
if (DIExpression::fragmentsOverlap(ThisFragment, ASeenFragment)) {
ThisFragmentsOverlaps.push_back(ASeenFragment);
auto ASeenFragmentsOverlaps =
OverlapFragments.find({MIVar.getVariable(), ASeenFragment});
assert(ASeenFragmentsOverlaps != OverlapFragments.end() &&
"Previously seen var fragment has no vector of overlaps");
ASeenFragmentsOverlaps->second.push_back(ThisFragment);
}
}
AllSeenFragments.insert(ThisFragment);
}
void InstrRefBasedLDV::process(MachineInstr &MI, const ValueTable *MLiveOuts,
const ValueTable *MLiveIns) {
if (transferDebugValue(MI))
return;
if (transferDebugInstrRef(MI, MLiveOuts, MLiveIns))
return;
if (transferDebugPHI(MI))
return;
if (transferRegisterCopy(MI))
return;
if (transferSpillOrRestoreInst(MI))
return;
transferRegisterDef(MI);
}
void InstrRefBasedLDV::produceMLocTransferFunction(
MachineFunction &MF, SmallVectorImpl<MLocTransferMap> &MLocTransfer,
unsigned MaxNumBlocks) {
SmallVector<BitVector, 32> BlockMasks;
BlockMasks.resize(MaxNumBlocks);
unsigned BVWords = MachineOperand::getRegMaskSize(TRI->getNumRegs());
for (auto &BV : BlockMasks)
BV.resize(TRI->getNumRegs(), true);
for (auto &MBB : MF) {
CurBB = MBB.getNumber();
CurInst = 1;
MTracker->reset();
MTracker->setMPhis(CurBB);
for (auto &MI : MBB) {
process(MI, nullptr, nullptr);
if (MI.isDebugValue() || MI.isDebugRef())
accumulateFragmentMap(MI);
if (uint64_t InstrNo = MI.peekDebugInstrNum()) {
auto InstrAndPos = std::make_pair(&MI, CurInst);
auto InsertResult =
DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos));
assert(InsertResult.second);
(void)InsertResult;
}
++CurInst;
}
for (auto Location : MTracker->locations()) {
LocIdx Idx = Location.Idx;
ValueIDNum &P = Location.Value;
if (P.isPHI() && P.getLoc() == Idx.asU64())
continue;
auto &TransferMap = MLocTransfer[CurBB];
auto Result = TransferMap.insert(std::make_pair(Idx.asU64(), P));
if (!Result.second)
Result.first->second = P;
}
for (auto &P : MTracker->Masks) {
BlockMasks[CurBB].clearBitsNotInMask(P.first->getRegMask(), BVWords);
}
}
BitVector UsedRegs(TRI->getNumRegs());
for (auto Location : MTracker->locations()) {
unsigned ID = MTracker->LocIdxToLocID[Location.Idx];
if (ID >= TRI->getNumRegs() || MTracker->SPAliases.count(ID))
continue;
UsedRegs.set(ID);
}
for (unsigned int I = 0; I < MaxNumBlocks; ++I) {
BitVector &BV = BlockMasks[I];
BV.flip();
BV &= UsedRegs;
for (unsigned Bit : BV.set_bits()) {
unsigned ID = MTracker->getLocID(Bit);
LocIdx Idx = MTracker->LocIDToLocIdx[ID];
auto &TransferMap = MLocTransfer[I];
ValueIDNum NotGeneratedNum = ValueIDNum(I, 1, Idx);
auto Result =
TransferMap.insert(std::make_pair(Idx.asU64(), NotGeneratedNum));
if (!Result.second) {
ValueIDNum &ValueID = Result.first->second;
if (ValueID.getBlock() == I && ValueID.isPHI())
ValueID = NotGeneratedNum;
}
}
}
}
bool InstrRefBasedLDV::mlocJoin(
MachineBasicBlock &MBB, SmallPtrSet<const MachineBasicBlock *, 16> &Visited,
FuncValueTable &OutLocs, ValueTable &InLocs) {
LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n");
bool Changed = false;
SmallVector<const MachineBasicBlock *, 8> BlockOrders;
for (auto *Pred : MBB.predecessors())
BlockOrders.push_back(Pred);
auto Cmp = [&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
return BBToOrder.find(A)->second < BBToOrder.find(B)->second;
};
llvm::sort(BlockOrders, Cmp);
if (BlockOrders.size() == 0)
return false;
for (auto Location : MTracker->locations()) {
LocIdx Idx = Location.Idx;
ValueIDNum FirstVal = OutLocs[BlockOrders[0]->getNumber()][Idx.asU64()];
if (InLocs[Idx.asU64()] != ValueIDNum(MBB.getNumber(), 0, Idx)) {
if (InLocs[Idx.asU64()] != FirstVal) {
InLocs[Idx.asU64()] = FirstVal;
Changed |= true;
}
continue;
}
bool Disagree = false;
for (unsigned int I = 1; I < BlockOrders.size(); ++I) {
const MachineBasicBlock *PredMBB = BlockOrders[I];
const ValueIDNum &PredLiveOut =
OutLocs[PredMBB->getNumber()][Idx.asU64()];
if (FirstVal == PredLiveOut)
continue;
if (PredLiveOut == ValueIDNum(MBB.getNumber(), 0, Idx))
continue;
Disagree = true;
}
if (!Disagree) {
InLocs[Idx.asU64()] = FirstVal;
Changed |= true;
}
}
return Changed;
}
void InstrRefBasedLDV::findStackIndexInterference(
SmallVectorImpl<unsigned> &Slots) {
auto It = MTracker->StackSlotIdxes.find({8, 0});
assert(It != MTracker->StackSlotIdxes.end());
Slots.push_back(It->second);
for (auto &Pair : MTracker->StackSlotIdxes) {
if (!Pair.first.second)
continue;
Slots.push_back(Pair.second);
}
}
void InstrRefBasedLDV::placeMLocPHIs(
MachineFunction &MF, SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks,
FuncValueTable &MInLocs, SmallVectorImpl<MLocTransferMap> &MLocTransfer) {
SmallVector<unsigned, 4> StackUnits;
findStackIndexInterference(StackUnits);
SmallSet<Register, 32> RegUnitsToPHIUp;
SmallSet<LocIdx, 32> NormalLocsToPHI;
SmallSet<SpillLocationNo, 32> StackSlots;
for (auto Location : MTracker->locations()) {
LocIdx L = Location.Idx;
if (MTracker->isSpill(L)) {
StackSlots.insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L]));
continue;
}
Register R = MTracker->LocIdxToLocID[L];
SmallSet<Register, 8> FoundRegUnits;
bool AnyIllegal = false;
for (MCRegUnitIterator RUI(R.asMCReg(), TRI); RUI.isValid(); ++RUI) {
for (MCRegUnitRootIterator URoot(*RUI, TRI); URoot.isValid(); ++URoot){
if (!MTracker->isRegisterTracked(*URoot)) {
AnyIllegal = true;
} else {
FoundRegUnits.insert(*URoot);
}
}
}
if (AnyIllegal) {
NormalLocsToPHI.insert(L);
continue;
}
RegUnitsToPHIUp.insert(FoundRegUnits.begin(), FoundRegUnits.end());
}
SmallVector<MachineBasicBlock *, 32> PHIBlocks;
auto CollectPHIsForLoc = [&](LocIdx L) {
SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
for (unsigned int I = 0; I < OrderToBB.size(); ++I) {
MachineBasicBlock *MBB = OrderToBB[I];
const auto &TransferFunc = MLocTransfer[MBB->getNumber()];
if (TransferFunc.find(L) != TransferFunc.end())
DefBlocks.insert(MBB);
}
if (!DefBlocks.empty())
DefBlocks.insert(&*MF.begin());
PHIBlocks.clear();
BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks);
};
auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx L) {
for (const MachineBasicBlock *MBB : PHIBlocks)
MInLocs[MBB->getNumber()][L.asU64()] = ValueIDNum(MBB->getNumber(), 0, L);
};
for (LocIdx L : NormalLocsToPHI) {
CollectPHIsForLoc(L);
InstallPHIsAtLoc(L);
}
for (SpillLocationNo Slot : StackSlots) {
for (unsigned Idx : StackUnits) {
unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx);
LocIdx L = MTracker->getSpillMLoc(SpillID);
CollectPHIsForLoc(L);
InstallPHIsAtLoc(L);
unsigned Size, Offset;
std::tie(Size, Offset) = MTracker->StackIdxesToPos[Idx];
for (auto &Pair : MTracker->StackSlotIdxes) {
unsigned ThisSize, ThisOffset;
std::tie(ThisSize, ThisOffset) = Pair.first;
if (ThisSize + ThisOffset <= Offset || Size + Offset <= ThisOffset)
continue;
unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second);
LocIdx ThisL = MTracker->getSpillMLoc(ThisID);
InstallPHIsAtLoc(ThisL);
}
}
}
for (Register R : RegUnitsToPHIUp) {
LocIdx L = MTracker->lookupOrTrackRegister(R);
CollectPHIsForLoc(L);
InstallPHIsAtLoc(L);
for (MCRegAliasIterator RAI(R, TRI, true); RAI.isValid(); ++RAI) {
if (!MTracker->isRegisterTracked(*RAI))
continue;
LocIdx AliasLoc = MTracker->lookupOrTrackRegister(*RAI);
InstallPHIsAtLoc(AliasLoc);
}
}
}
void InstrRefBasedLDV::buildMLocValueMap(
MachineFunction &MF, FuncValueTable &MInLocs, FuncValueTable &MOutLocs,
SmallVectorImpl<MLocTransferMap> &MLocTransfer) {
std::priority_queue<unsigned int, std::vector<unsigned int>,
std::greater<unsigned int>>
Worklist, Pending;
SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist;
SmallPtrSet<MachineBasicBlock *, 32> AllBlocks;
for (unsigned int I = 0; I < BBToOrder.size(); ++I) {
Worklist.push(I);
OnWorklist.insert(OrderToBB[I]);
AllBlocks.insert(OrderToBB[I]);
}
for (auto Location : MTracker->locations())
MInLocs[0][Location.Idx.asU64()] = ValueIDNum(0, 0, Location.Idx);
MTracker->reset();
placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
SmallPtrSet<const MachineBasicBlock *, 16> Visited;
while (!Worklist.empty() || !Pending.empty()) {
SmallVector<std::pair<LocIdx, ValueIDNum>, 32> ToRemap;
while (!Worklist.empty()) {
MachineBasicBlock *MBB = OrderToBB[Worklist.top()];
CurBB = MBB->getNumber();
Worklist.pop();
bool InLocsChanged;
InLocsChanged = mlocJoin(*MBB, Visited, MOutLocs, MInLocs[CurBB]);
InLocsChanged |= Visited.insert(MBB).second;
if (!InLocsChanged)
continue;
MTracker->loadFromArray(MInLocs[CurBB], CurBB);
ToRemap.clear();
for (auto &P : MLocTransfer[CurBB]) {
if (P.second.getBlock() == CurBB && P.second.isPHI()) {
ValueIDNum NewID = MTracker->readMLoc(P.second.getLoc());
ToRemap.push_back(std::make_pair(P.first, NewID));
} else {
assert(P.second.getBlock() == CurBB);
ToRemap.push_back(std::make_pair(P.first, P.second));
}
}
for (auto &P : ToRemap)
MTracker->setMLoc(P.first, P.second);
bool OLChanged = false;
for (auto Location : MTracker->locations()) {
OLChanged |= MOutLocs[CurBB][Location.Idx.asU64()] != Location.Value;
MOutLocs[CurBB][Location.Idx.asU64()] = Location.Value;
}
MTracker->reset();
if (!OLChanged)
continue;
for (auto *s : MBB->successors()) {
if (BBToOrder[s] > BBToOrder[MBB]) {
if (OnWorklist.insert(s).second)
Worklist.push(BBToOrder[s]);
} else {
if (OnPending.insert(s).second)
Pending.push(BBToOrder[s]);
}
}
}
Worklist.swap(Pending);
std::swap(OnPending, OnWorklist);
OnPending.clear();
assert(Pending.empty() && "Pending should be empty");
}
}
void InstrRefBasedLDV::BlockPHIPlacement(
const SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks,
const SmallPtrSetImpl<MachineBasicBlock *> &DefBlocks,
SmallVectorImpl<MachineBasicBlock *> &PHIBlocks) {
IDFCalculatorBase<MachineBasicBlock, false> IDF(DomTree->getBase());
IDF.setLiveInBlocks(AllBlocks);
IDF.setDefiningBlocks(DefBlocks);
IDF.calculate(PHIBlocks);
}
Optional<ValueIDNum> InstrRefBasedLDV::pickVPHILoc(
const MachineBasicBlock &MBB, const DebugVariable &Var,
const LiveIdxT &LiveOuts, FuncValueTable &MOutLocs,
const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders) {
SmallVector<SmallVector<LocIdx, 4>, 8> Locs;
SmallVector<const DbgValueProperties *, 4> Properties;
unsigned NumLocs = MTracker->getNumLocs();
if (BlockOrders.empty())
return None;
for (const auto *p : BlockOrders) {
unsigned ThisBBNum = p->getNumber();
auto OutValIt = LiveOuts.find(p);
if (OutValIt == LiveOuts.end())
return None;
const DbgValue &OutVal = *OutValIt->second;
if (OutVal.Kind == DbgValue::Const || OutVal.Kind == DbgValue::NoVal)
return None;
Properties.push_back(&OutVal.Properties);
Locs.resize(Locs.size() + 1);
if (OutVal.Kind == DbgValue::Def ||
(OutVal.Kind == DbgValue::VPHI && OutVal.BlockNo != MBB.getNumber() &&
OutVal.ID != ValueIDNum::EmptyValue)) {
ValueIDNum ValToLookFor = OutVal.ID;
for (unsigned int I = 0; I < NumLocs; ++I) {
if (MOutLocs[ThisBBNum][I] == ValToLookFor)
Locs.back().push_back(LocIdx(I));
}
} else {
assert(OutVal.Kind == DbgValue::VPHI);
if (OutVal.BlockNo != MBB.getNumber())
return None;
for (unsigned int I = 0; I < NumLocs; ++I) {
ValueIDNum MPHI(MBB.getNumber(), 0, LocIdx(I));
if (MOutLocs[ThisBBNum][I] == MPHI)
Locs.back().push_back(LocIdx(I));
}
}
}
assert(Locs.size() == BlockOrders.size());
const DbgValueProperties *Properties0 = Properties[0];
for (const auto *Prop : Properties)
if (*Prop != *Properties0)
return None;
SmallVector<LocIdx, 4> CandidateLocs = Locs[0];
for (unsigned int I = 1; I < Locs.size(); ++I) {
auto &LocVec = Locs[I];
SmallVector<LocIdx, 4> NewCandidates;
std::set_intersection(CandidateLocs.begin(), CandidateLocs.end(),
LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.begin()));
CandidateLocs = NewCandidates;
}
if (CandidateLocs.empty())
return None;
LocIdx L = *CandidateLocs.begin();
ValueIDNum PHIVal = {(unsigned)MBB.getNumber(), 0, L};
return PHIVal;
}
bool InstrRefBasedLDV::vlocJoin(
MachineBasicBlock &MBB, LiveIdxT &VLOCOutLocs,
SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore,
DbgValue &LiveIn) {
LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n");
bool Changed = false;
SmallVector<MachineBasicBlock *, 8> BlockOrders(MBB.predecessors());
auto Cmp = [&](MachineBasicBlock *A, MachineBasicBlock *B) {
return BBToOrder[A] < BBToOrder[B];
};
llvm::sort(BlockOrders, Cmp);
unsigned CurBlockRPONum = BBToOrder[&MBB];
SmallVector<InValueT, 8> Values;
bool Bail = false;
int BackEdgesStart = 0;
for (auto *p : BlockOrders) {
if (!BlocksToExplore.contains(p)) {
Bail = true;
break;
}
DbgValue &OutLoc = *VLOCOutLocs.find(p)->second;
unsigned ThisBBRPONum = BBToOrder[p];
if (ThisBBRPONum < CurBlockRPONum)
++BackEdgesStart;
Values.push_back(std::make_pair(p, &OutLoc));
}
if (Bail || Values.size() == 0)
return false;
const DbgValue &FirstVal = *Values[0].second;
if (LiveIn.Kind != DbgValue::VPHI || LiveIn.BlockNo != MBB.getNumber()) {
Changed = LiveIn != FirstVal;
if (Changed)
LiveIn = FirstVal;
return Changed;
}
for (auto &V : Values) {
if (V.second->Properties != FirstVal.Properties)
return false;
if (V.second->Kind == DbgValue::NoVal)
return false;
if (V.second->Kind == DbgValue::Const && FirstVal.Kind != DbgValue::Const)
return false;
}
bool Disagree = false;
for (auto &V : Values) {
if (*V.second == FirstVal)
continue;
if (V.second->Kind == DbgValue::VPHI &&
V.second->BlockNo == MBB.getNumber() &&
std::distance(Values.begin(), &V) >= BackEdgesStart)
continue;
Disagree = true;
}
if (!Disagree) {
Changed = LiveIn != FirstVal;
if (Changed)
LiveIn = FirstVal;
return Changed;
} else {
DbgValue VPHI(MBB.getNumber(), FirstVal.Properties, DbgValue::VPHI);
Changed = LiveIn != VPHI;
if (Changed)
LiveIn = VPHI;
return Changed;
}
}
void InstrRefBasedLDV::getBlocksForScope(
const DILocation *DILoc,
SmallPtrSetImpl<const MachineBasicBlock *> &BlocksToExplore,
const SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks) {
LS.getMachineBasicBlocks(DILoc, BlocksToExplore);
BlocksToExplore.insert(AssignBlocks.begin(), AssignBlocks.end());
DenseSet<const MachineBasicBlock *> ToAdd;
for (const auto *MBB : BlocksToExplore) {
SmallVector<std::pair<const MachineBasicBlock *,
MachineBasicBlock::const_succ_iterator>,
8>
DFS;
for (auto *succ : MBB->successors()) {
if (BlocksToExplore.count(succ))
continue;
if (!ArtificialBlocks.count(succ))
continue;
ToAdd.insert(succ);
DFS.push_back({succ, succ->succ_begin()});
}
while (!DFS.empty()) {
const MachineBasicBlock *CurBB = DFS.back().first;
MachineBasicBlock::const_succ_iterator &CurSucc = DFS.back().second;
if (CurSucc == CurBB->succ_end()) {
DFS.pop_back();
continue;
}
if (!ToAdd.count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) {
ToAdd.insert(*CurSucc);
DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()});
continue;
}
++CurSucc;
}
};
BlocksToExplore.insert(ToAdd.begin(), ToAdd.end());
}
void InstrRefBasedLDV::buildVLocValueMap(
const DILocation *DILoc, const SmallSet<DebugVariable, 4> &VarsWeCareAbout,
SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks, LiveInsT &Output,
FuncValueTable &MOutLocs, FuncValueTable &MInLocs,
SmallVectorImpl<VLocTracker> &AllTheVLocs) {
std::priority_queue<unsigned int, std::vector<unsigned int>,
std::greater<unsigned int>>
Worklist, Pending;
SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending;
SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
SmallVector<MachineBasicBlock *, 8> BlockOrders;
auto Cmp = [&](MachineBasicBlock *A, MachineBasicBlock *B) {
return BBToOrder[A] < BBToOrder[B];
};
getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks);
if (BlocksToExplore.size() == 1)
return;
SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore;
for (const auto *MBB : BlocksToExplore)
MutBlocksToExplore.insert(const_cast<MachineBasicBlock *>(MBB));
for (const auto *MBB : BlocksToExplore)
BlockOrders.push_back(const_cast<MachineBasicBlock *>(MBB));
llvm::sort(BlockOrders, Cmp);
unsigned NumBlocks = BlockOrders.size();
SmallVector<DbgValue, 32> LiveIns, LiveOuts;
LiveIns.reserve(NumBlocks);
LiveOuts.reserve(NumBlocks);
DbgValueProperties EmptyProperties(EmptyExpr, false);
for (unsigned int I = 0; I < NumBlocks; ++I) {
DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal);
LiveIns.push_back(EmptyDbgValue);
LiveOuts.push_back(EmptyDbgValue);
}
LiveIdxT LiveOutIdx, LiveInIdx;
LiveOutIdx.reserve(NumBlocks);
LiveInIdx.reserve(NumBlocks);
for (unsigned I = 0; I < NumBlocks; ++I) {
LiveOutIdx[BlockOrders[I]] = &LiveOuts[I];
LiveInIdx[BlockOrders[I]] = &LiveIns[I];
}
for (const auto &Var : VarsWeCareAbout) {
for (unsigned int I = 0; I < NumBlocks; ++I) {
DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal);
LiveIns[I] = EmptyDbgValue;
LiveOuts[I] = EmptyDbgValue;
}
SmallPtrSet<MachineBasicBlock *, 32> DefBlocks;
for (const MachineBasicBlock *ExpMBB : BlocksToExplore) {
auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars;
if (TransferFunc.find(Var) != TransferFunc.end())
DefBlocks.insert(const_cast<MachineBasicBlock *>(ExpMBB));
}
SmallVector<MachineBasicBlock *, 32> PHIBlocks;
if (DefBlocks.size() == 1) {
placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.begin(),
AllTheVLocs, Var, Output);
continue;
}
BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks);
for (MachineBasicBlock *PHIMBB : PHIBlocks) {
unsigned BlockNo = PHIMBB->getNumber();
DbgValue *LiveIn = LiveInIdx[PHIMBB];
*LiveIn = DbgValue(BlockNo, EmptyProperties, DbgValue::VPHI);
}
for (auto *MBB : BlockOrders) {
Worklist.push(BBToOrder[MBB]);
OnWorklist.insert(MBB);
}
bool FirstTrip = true;
while (!Worklist.empty() || !Pending.empty()) {
while (!Worklist.empty()) {
auto *MBB = OrderToBB[Worklist.top()];
CurBB = MBB->getNumber();
Worklist.pop();
auto LiveInsIt = LiveInIdx.find(MBB);
assert(LiveInsIt != LiveInIdx.end());
DbgValue *LiveIn = LiveInsIt->second;
bool InLocsChanged =
vlocJoin(*MBB, LiveOutIdx, BlocksToExplore, *LiveIn);
SmallVector<const MachineBasicBlock *, 8> Preds;
for (const auto *Pred : MBB->predecessors())
Preds.push_back(Pred);
if (LiveIn->Kind == DbgValue::VPHI && LiveIn->BlockNo == (int)CurBB) {
Optional<ValueIDNum> ValueNum =
pickVPHILoc(*MBB, Var, LiveOutIdx, MOutLocs, Preds);
if (ValueNum) {
InLocsChanged |= LiveIn->ID != *ValueNum;
LiveIn->ID = *ValueNum;
}
}
if (!InLocsChanged && !FirstTrip)
continue;
DbgValue *LiveOut = LiveOutIdx[MBB];
bool OLChanged = false;
auto &VTracker = AllTheVLocs[MBB->getNumber()];
auto TransferIt = VTracker.Vars.find(Var);
if (TransferIt != VTracker.Vars.end()) {
if (TransferIt->second.Kind == DbgValue::Undef) {
DbgValue NewVal(MBB->getNumber(), EmptyProperties, DbgValue::NoVal);
if (*LiveOut != NewVal) {
*LiveOut = NewVal;
OLChanged = true;
}
} else {
if (*LiveOut != TransferIt->second) {
*LiveOut = TransferIt->second;
OLChanged = true;
}
}
} else {
if (*LiveOut != *LiveIn) {
*LiveOut = *LiveIn;
OLChanged = true;
}
}
if (!OLChanged)
continue;
for (auto *s : MBB->successors()) {
if (LiveInIdx.find(s) == LiveInIdx.end())
continue;
if (BBToOrder[s] > BBToOrder[MBB]) {
if (OnWorklist.insert(s).second)
Worklist.push(BBToOrder[s]);
} else if (OnPending.insert(s).second && (FirstTrip || OLChanged)) {
Pending.push(BBToOrder[s]);
}
}
}
Worklist.swap(Pending);
std::swap(OnWorklist, OnPending);
OnPending.clear();
assert(Pending.empty());
FirstTrip = false;
}
for (auto *MBB : BlockOrders) {
DbgValue *BlockLiveIn = LiveInIdx[MBB];
if (BlockLiveIn->Kind == DbgValue::NoVal)
continue;
if (BlockLiveIn->Kind == DbgValue::VPHI &&
BlockLiveIn->ID == ValueIDNum::EmptyValue)
continue;
if (BlockLiveIn->Kind == DbgValue::VPHI)
BlockLiveIn->Kind = DbgValue::Def;
assert(BlockLiveIn->Properties.DIExpr->getFragmentInfo() ==
Var.getFragment() && "Fragment info missing during value prop");
Output[MBB->getNumber()].push_back(std::make_pair(Var, *BlockLiveIn));
}
}
BlockOrders.clear();
BlocksToExplore.clear();
}
void InstrRefBasedLDV::placePHIsForSingleVarDefinition(
const SmallPtrSetImpl<MachineBasicBlock *> &InScopeBlocks,
MachineBasicBlock *AssignMBB, SmallVectorImpl<VLocTracker> &AllTheVLocs,
const DebugVariable &Var, LiveInsT &Output) {
VLocTracker &VLocs = AllTheVLocs[AssignMBB->getNumber()];
auto ValueIt = VLocs.Vars.find(Var);
const DbgValue &Value = ValueIt->second;
if (Value.Kind == DbgValue::Undef)
return;
for (auto *ScopeBlock : InScopeBlocks) {
if (!DomTree->properlyDominates(AssignMBB, ScopeBlock))
continue;
Output[ScopeBlock->getNumber()].push_back({Var, Value});
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void InstrRefBasedLDV::dump_mloc_transfer(
const MLocTransferMap &mloc_transfer) const {
for (const auto &P : mloc_transfer) {
std::string foo = MTracker->LocIdxToName(P.first);
std::string bar = MTracker->IDAsString(P.second);
dbgs() << "Loc " << foo << " --> " << bar << "\n";
}
}
#endif
void InstrRefBasedLDV::initialSetup(MachineFunction &MF) {
LLVMContext &Context = MF.getFunction().getContext();
EmptyExpr = DIExpression::get(Context, {});
auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool {
if (const DebugLoc &DL = MI.getDebugLoc())
return DL.getLine() != 0;
return false;
};
for (auto &MBB : MF)
if (none_of(MBB.instrs(), hasNonArtificialLocation))
ArtificialBlocks.insert(&MBB);
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
unsigned int RPONumber = 0;
for (MachineBasicBlock *MBB : RPOT) {
OrderToBB[RPONumber] = MBB;
BBToOrder[MBB] = RPONumber;
BBNumToRPO[MBB->getNumber()] = RPONumber;
++RPONumber;
}
llvm::sort(MF.DebugValueSubstitutions);
#ifdef EXPENSIVE_CHECKS
if (MF.DebugValueSubstitutions.size() > 2) {
for (auto It = MF.DebugValueSubstitutions.begin();
It != std::prev(MF.DebugValueSubstitutions.end()); ++It) {
assert(It->Src != std::next(It)->Src && "Duplicate variable location "
"substitution seen");
}
}
#endif
}
void InstrRefBasedLDV::makeDepthFirstEjectionMap(
SmallVectorImpl<unsigned> &EjectionMap,
const ScopeToDILocT &ScopeToDILocation,
ScopeToAssignBlocksT &ScopeToAssignBlocks) {
SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
SmallVector<std::pair<LexicalScope *, ssize_t>, 4> WorkStack;
auto *TopScope = LS.getCurrentFunctionScope();
WorkStack.push_back({TopScope, TopScope->getChildren().size() - 1});
while (!WorkStack.empty()) {
auto &ScopePosition = WorkStack.back();
LexicalScope *WS = ScopePosition.first;
ssize_t ChildNum = ScopePosition.second--;
const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
if (ChildNum >= 0) {
auto &ChildScope = Children[ChildNum];
WorkStack.push_back(
std::make_pair(ChildScope, ChildScope->getChildren().size() - 1));
} else {
WorkStack.pop_back();
auto DILocationIt = ScopeToDILocation.find(WS);
if (DILocationIt != ScopeToDILocation.end()) {
getBlocksForScope(DILocationIt->second, BlocksToExplore,
ScopeToAssignBlocks.find(WS)->second);
for (const auto *MBB : BlocksToExplore) {
unsigned BBNum = MBB->getNumber();
if (EjectionMap[BBNum] == 0)
EjectionMap[BBNum] = WS->getDFSOut();
}
BlocksToExplore.clear();
}
}
}
}
bool InstrRefBasedLDV::depthFirstVLocAndEmit(
unsigned MaxNumBlocks, const ScopeToDILocT &ScopeToDILocation,
const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks,
LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs,
SmallVectorImpl<VLocTracker> &AllTheVLocs, MachineFunction &MF,
DenseMap<DebugVariable, unsigned> &AllVarsNumbering,
const TargetPassConfig &TPC) {
TTracker = new TransferTracker(TII, MTracker, MF, *TRI, CalleeSavedRegs, TPC);
unsigned NumLocs = MTracker->getNumLocs();
VTracker = nullptr;
if (!LS.getCurrentFunctionScope())
return false;
SmallVector<unsigned, 16> EjectionMap;
EjectionMap.resize(MaxNumBlocks, 0);
makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation,
ScopeToAssignBlocks);
auto EjectBlock = [&](MachineBasicBlock &MBB) -> void {
unsigned BBNum = MBB.getNumber();
AllTheVLocs[BBNum].clear();
MTracker->reset();
MTracker->loadFromArray(MInLocs[BBNum], BBNum);
TTracker->loadInlocs(MBB, MInLocs[BBNum], Output[BBNum], NumLocs);
CurBB = BBNum;
CurInst = 1;
for (auto &MI : MBB) {
process(MI, MOutLocs.get(), MInLocs.get());
TTracker->checkInstForNewValues(CurInst, MI.getIterator());
++CurInst;
}
MInLocs[BBNum].reset();
MOutLocs[BBNum].reset();
Output[BBNum].clear();
AllTheVLocs[BBNum].clear();
};
SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore;
SmallVector<std::pair<LexicalScope *, ssize_t>, 4> WorkStack;
WorkStack.push_back({LS.getCurrentFunctionScope(), 0});
unsigned HighestDFSIn = 0;
while (!WorkStack.empty()) {
auto &ScopePosition = WorkStack.back();
LexicalScope *WS = ScopePosition.first;
ssize_t ChildNum = ScopePosition.second++;
auto DILocIt = ScopeToDILocation.find(WS);
if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) {
const DILocation *DILoc = DILocIt->second;
auto &VarsWeCareAbout = ScopeToVars.find(WS)->second;
auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second;
buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs,
MInLocs, AllTheVLocs);
}
HighestDFSIn = std::max(HighestDFSIn, WS->getDFSIn());
const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren();
if (ChildNum < (ssize_t)Children.size()) {
auto &ChildScope = Children[ChildNum];
WorkStack.push_back(std::make_pair(ChildScope, 0));
} else {
WorkStack.pop_back();
auto DILocationIt = ScopeToDILocation.find(WS);
if (DILocationIt == ScopeToDILocation.end())
continue;
getBlocksForScope(DILocationIt->second, BlocksToExplore,
ScopeToAssignBlocks.find(WS)->second);
for (const auto *MBB : BlocksToExplore)
if (WS->getDFSOut() == EjectionMap[MBB->getNumber()])
EjectBlock(const_cast<MachineBasicBlock &>(*MBB));
BlocksToExplore.clear();
}
}
for (auto *MBB : ArtificialBlocks)
if (MOutLocs[MBB->getNumber()])
EjectBlock(*MBB);
return emitTransfers(AllVarsNumbering);
}
bool InstrRefBasedLDV::emitTransfers(
DenseMap<DebugVariable, unsigned> &AllVarsNumbering) {
for (const auto &P : TTracker->Transfers) {
SmallVector<std::pair<unsigned, MachineInstr *>> Insts;
for (MachineInstr *MI : P.Insts) {
DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(),
MI->getDebugLoc()->getInlinedAt());
Insts.emplace_back(AllVarsNumbering.find(Var)->second, MI);
}
llvm::sort(Insts, llvm::less_first());
if (P.MBB) {
MachineBasicBlock &MBB = *P.MBB;
for (const auto &Pair : Insts)
MBB.insert(P.Pos, Pair.second);
} else {
if (P.Pos->isTerminator())
continue;
MachineBasicBlock &MBB = *P.Pos->getParent();
for (const auto &Pair : Insts)
MBB.insertAfterBundle(P.Pos, Pair.second);
}
}
return TTracker->Transfers.size() != 0;
}
bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF,
MachineDominatorTree *DomTree,
TargetPassConfig *TPC,
unsigned InputBBLimit,
unsigned InputDbgValLimit) {
if (!MF.getFunction().getSubprogram())
return false;
LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n");
this->TPC = TPC;
this->DomTree = DomTree;
TRI = MF.getSubtarget().getRegisterInfo();
MRI = &MF.getRegInfo();
TII = MF.getSubtarget().getInstrInfo();
TFI = MF.getSubtarget().getFrameLowering();
TFI->getCalleeSaves(MF, CalleeSavedRegs);
MFI = &MF.getFrameInfo();
LS.initialize(MF);
const auto &STI = MF.getSubtarget();
AdjustsStackInCalls = MFI->adjustsStack() &&
STI.getFrameLowering()->stackProbeFunctionModifiesSP();
if (AdjustsStackInCalls)
StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF);
MTracker =
new MLocTracker(MF, *TII, *TRI, *MF.getSubtarget().getTargetLowering());
VTracker = nullptr;
TTracker = nullptr;
SmallVector<MLocTransferMap, 32> MLocTransfer;
SmallVector<VLocTracker, 8> vlocs;
LiveInsT SavedLiveIns;
int MaxNumBlocks = -1;
for (auto &MBB : MF)
MaxNumBlocks = std::max(MBB.getNumber(), MaxNumBlocks);
assert(MaxNumBlocks >= 0);
++MaxNumBlocks;
initialSetup(MF);
MLocTransfer.resize(MaxNumBlocks);
vlocs.resize(MaxNumBlocks, VLocTracker(OverlapFragments, EmptyExpr));
SavedLiveIns.resize(MaxNumBlocks);
produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks);
FuncValueTable MOutLocs = std::make_unique<ValueTable[]>(MaxNumBlocks);
FuncValueTable MInLocs = std::make_unique<ValueTable[]>(MaxNumBlocks);
unsigned NumLocs = MTracker->getNumLocs();
for (int i = 0; i < MaxNumBlocks; ++i) {
MOutLocs[i] = std::make_unique<ValueIDNum[]>(NumLocs);
MInLocs[i] = std::make_unique<ValueIDNum[]>(NumLocs);
}
buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer);
for (auto &DBG_PHI : DebugPHINumToValue) {
if (!DBG_PHI.ValueRead)
continue;
ValueIDNum &Num = *DBG_PHI.ValueRead;
if (!Num.isPHI())
continue;
unsigned BlockNo = Num.getBlock();
LocIdx LocNo = Num.getLoc();
Num = MInLocs[BlockNo][LocNo.asU64()];
}
llvm::sort(DebugPHINumToValue);
for (auto &OrderPair : OrderToBB) {
MachineBasicBlock &MBB = *OrderPair.second;
CurBB = MBB.getNumber();
VTracker = &vlocs[CurBB];
VTracker->MBB = &MBB;
MTracker->loadFromArray(MInLocs[CurBB], CurBB);
CurInst = 1;
for (auto &MI : MBB) {
process(MI, MOutLocs.get(), MInLocs.get());
++CurInst;
}
MTracker->reset();
}
DenseMap<DebugVariable, unsigned> AllVarsNumbering;
ScopeToVarsT ScopeToVars;
ScopeToAssignBlocksT ScopeToAssignBlocks;
ScopeToDILocT ScopeToDILocation;
unsigned VarAssignCount = 0;
for (unsigned int I = 0; I < OrderToBB.size(); ++I) {
auto *MBB = OrderToBB[I];
auto *VTracker = &vlocs[MBB->getNumber()];
for (auto &idx : VTracker->Vars) {
const auto &Var = idx.first;
const DILocation *ScopeLoc = VTracker->Scopes[Var];
assert(ScopeLoc != nullptr);
auto *Scope = LS.findLexicalScope(ScopeLoc);
assert(Scope != nullptr);
AllVarsNumbering.insert(std::make_pair(Var, AllVarsNumbering.size()));
ScopeToVars[Scope].insert(Var);
ScopeToAssignBlocks[Scope].insert(VTracker->MBB);
ScopeToDILocation[Scope] = ScopeLoc;
++VarAssignCount;
}
}
bool Changed = false;
if ((unsigned)MaxNumBlocks > InputBBLimit &&
VarAssignCount > InputDbgValLimit) {
LLVM_DEBUG(dbgs() << "Disabling InstrRefBasedLDV: " << MF.getName()
<< " has " << MaxNumBlocks << " basic blocks and "
<< VarAssignCount
<< " variable assignments, exceeding limits.\n");
} else {
Changed = depthFirstVLocAndEmit(
MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks,
SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, AllVarsNumbering, *TPC);
}
delete MTracker;
delete TTracker;
MTracker = nullptr;
VTracker = nullptr;
TTracker = nullptr;
ArtificialBlocks.clear();
OrderToBB.clear();
BBToOrder.clear();
BBNumToRPO.clear();
DebugInstrNumToInstr.clear();
DebugPHINumToValue.clear();
OverlapFragments.clear();
SeenFragments.clear();
SeenDbgPHIs.clear();
return Changed;
}
LDVImpl *llvm::makeInstrRefBasedLiveDebugValues() {
return new InstrRefBasedLDV();
}
namespace {
class LDVSSABlock;
class LDVSSAUpdater;
typedef uint64_t BlockValueNum;
class LDVSSAPhi {
public:
SmallVector<std::pair<LDVSSABlock *, BlockValueNum>, 4> IncomingValues;
LDVSSABlock *ParentBlock;
BlockValueNum PHIValNum;
LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock)
: ParentBlock(ParentBlock), PHIValNum(PHIValNum) {}
LDVSSABlock *getParent() { return ParentBlock; }
};
class LDVSSABlockIterator {
public:
MachineBasicBlock::pred_iterator PredIt;
LDVSSAUpdater &Updater;
LDVSSABlockIterator(MachineBasicBlock::pred_iterator PredIt,
LDVSSAUpdater &Updater)
: PredIt(PredIt), Updater(Updater) {}
bool operator!=(const LDVSSABlockIterator &OtherIt) const {
return OtherIt.PredIt != PredIt;
}
LDVSSABlockIterator &operator++() {
++PredIt;
return *this;
}
LDVSSABlock *operator*();
};
class LDVSSABlock {
public:
MachineBasicBlock &BB;
LDVSSAUpdater &Updater;
using PHIListT = SmallVector<LDVSSAPhi, 1>;
PHIListT PHIList;
LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater)
: BB(BB), Updater(Updater) {}
LDVSSABlockIterator succ_begin() {
return LDVSSABlockIterator(BB.succ_begin(), Updater);
}
LDVSSABlockIterator succ_end() {
return LDVSSABlockIterator(BB.succ_end(), Updater);
}
LDVSSAPhi *newPHI(BlockValueNum Value) {
PHIList.emplace_back(Value, this);
return &PHIList.back();
}
PHIListT &phis() { return PHIList; }
};
class LDVSSAUpdater {
public:
DenseMap<BlockValueNum, LDVSSAPhi *> PHIs;
DenseMap<MachineBasicBlock *, BlockValueNum> UndefMap;
DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap;
LocIdx Loc;
const ValueTable *MLiveIns;
LDVSSAUpdater(LocIdx L, const ValueTable *MLiveIns)
: Loc(L), MLiveIns(MLiveIns) {}
void reset() {
for (auto &Block : BlockMap)
delete Block.second;
PHIs.clear();
UndefMap.clear();
BlockMap.clear();
}
~LDVSSAUpdater() { reset(); }
LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) {
auto it = BlockMap.find(BB);
if (it == BlockMap.end()) {
BlockMap[BB] = new LDVSSABlock(*BB, *this);
it = BlockMap.find(BB);
}
return it->second;
}
BlockValueNum getValue(LDVSSABlock *LDVBB) {
return MLiveIns[LDVBB->BB.getNumber()][Loc.asU64()].asU64();
}
};
LDVSSABlock *LDVSSABlockIterator::operator*() {
return Updater.getSSALDVBlock(*PredIt);
}
#ifndef NDEBUG
raw_ostream &operator<<(raw_ostream &out, const LDVSSAPhi &PHI) {
out << "SSALDVPHI " << PHI.PHIValNum;
return out;
}
#endif
}
namespace llvm {
template <> class SSAUpdaterTraits<LDVSSAUpdater> {
public:
using BlkT = LDVSSABlock;
using ValT = BlockValueNum;
using PhiT = LDVSSAPhi;
using BlkSucc_iterator = LDVSSABlockIterator;
static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); }
static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); }
class PHI_iterator {
private:
LDVSSAPhi *PHI;
unsigned Idx;
public:
explicit PHI_iterator(LDVSSAPhi *P) : PHI(P), Idx(0) {}
PHI_iterator(LDVSSAPhi *P, bool) : PHI(P), Idx(PHI->IncomingValues.size()) {}
PHI_iterator &operator++() {
Idx++;
return *this;
}
bool operator==(const PHI_iterator &X) const { return Idx == X.Idx; }
bool operator!=(const PHI_iterator &X) const { return !operator==(X); }
BlockValueNum getIncomingValue() { return PHI->IncomingValues[Idx].second; }
LDVSSABlock *getIncomingBlock() { return PHI->IncomingValues[Idx].first; }
};
static inline PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); }
static inline PHI_iterator PHI_end(PhiT *PHI) {
return PHI_iterator(PHI, true);
}
static void FindPredecessorBlocks(LDVSSABlock *BB,
SmallVectorImpl<LDVSSABlock *> *Preds) {
for (MachineBasicBlock *Pred : BB->BB.predecessors())
Preds->push_back(BB->Updater.getSSALDVBlock(Pred));
}
static BlockValueNum GetUndefVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) {
BlockValueNum Num = ValueIDNum(BB->BB.getNumber(), 0, Updater->Loc).asU64();
Updater->UndefMap[&BB->BB] = Num;
return Num;
}
static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds,
LDVSSAUpdater *Updater) {
BlockValueNum PHIValNum = Updater->getValue(BB);
LDVSSAPhi *PHI = BB->newPHI(PHIValNum);
Updater->PHIs[PHIValNum] = PHI;
return PHIValNum;
}
static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred) {
PHI->IncomingValues.push_back(std::make_pair(Pred, Val));
}
static LDVSSAPhi *ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
auto PHIIt = Updater->PHIs.find(Val);
if (PHIIt == Updater->PHIs.end())
return nullptr;
return PHIIt->second;
}
static LDVSSAPhi *ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater) {
LDVSSAPhi *PHI = ValueIsPHI(Val, Updater);
if (PHI && PHI->IncomingValues.size() == 0)
return PHI;
return nullptr;
}
static BlockValueNum GetPHIValue(LDVSSAPhi *PHI) { return PHI->PHIValNum; }
};
}
Optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs(
MachineFunction &MF, const ValueTable *MLiveOuts,
const ValueTable *MLiveIns, MachineInstr &Here, uint64_t InstrNum) {
assert(MLiveOuts && MLiveIns &&
"Tried to resolve DBG_PHI before location "
"tables allocated?");
auto SeenDbgPHIIt = SeenDbgPHIs.find(&Here);
if (SeenDbgPHIIt != SeenDbgPHIs.end())
return SeenDbgPHIIt->second;
Optional<ValueIDNum> Result =
resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum);
SeenDbgPHIs.insert({&Here, Result});
return Result;
}
Optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl(
MachineFunction &MF, const ValueTable *MLiveOuts,
const ValueTable *MLiveIns, MachineInstr &Here, uint64_t InstrNum) {
auto RangePair = std::equal_range(DebugPHINumToValue.begin(),
DebugPHINumToValue.end(), InstrNum);
auto LowerIt = RangePair.first;
auto UpperIt = RangePair.second;
if (LowerIt == UpperIt)
return None;
auto DBGPHIRange = make_range(LowerIt, UpperIt);
for (const DebugPHIRecord &DBG_PHI : DBGPHIRange)
if (!DBG_PHI.ValueRead)
return None;
if (std::distance(LowerIt, UpperIt) == 1)
return *LowerIt->ValueRead;
LocIdx Loc = *LowerIt->ReadLoc;
LDVSSAUpdater Updater(Loc, MLiveIns);
DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues;
SmallVector<LDVSSAPhi *, 8> CreatedPHIs;
for (const auto &DBG_PHI : DBGPHIRange) {
LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
const ValueIDNum &Num = *DBG_PHI.ValueRead;
AvailableValues.insert(std::make_pair(Block, Num.asU64()));
}
LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.getParent());
const auto &AvailIt = AvailableValues.find(HereBlock);
if (AvailIt != AvailableValues.end()) {
return ValueIDNum::fromU64(AvailIt->second);
}
SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs);
BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.getParent()));
ValueIDNum Result = ValueIDNum::fromU64(ResultInt);
DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues;
for (const auto &DBG_PHI : DBGPHIRange) {
LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB);
const ValueIDNum &Num = *DBG_PHI.ValueRead;
ValidatedValues.insert(std::make_pair(Block, Num));
}
SmallVector<LDVSSAPhi *, 8> SortedPHIs;
for (auto &PHI : CreatedPHIs)
SortedPHIs.push_back(PHI);
llvm::sort(SortedPHIs, [&](LDVSSAPhi *A, LDVSSAPhi *B) {
return BBToOrder[&A->getParent()->BB] < BBToOrder[&B->getParent()->BB];
});
for (auto &PHI : SortedPHIs) {
ValueIDNum ThisBlockValueNum =
MLiveIns[PHI->ParentBlock->BB.getNumber()][Loc.asU64()];
for (auto &PHIIt : PHI->IncomingValues) {
if (Updater.UndefMap.find(&PHIIt.first->BB) != Updater.UndefMap.end())
return None;
ValueIDNum ValueToCheck;
const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB.getNumber()];
auto VVal = ValidatedValues.find(PHIIt.first);
if (VVal == ValidatedValues.end()) {
ValueToCheck = ThisBlockValueNum;
} else {
ValueToCheck = VVal->second;
}
if (BlockLiveOuts[Loc.asU64()] != ValueToCheck)
return None;
}
ValidatedValues.insert({PHI->ParentBlock, ThisBlockValueNum});
}
return Result;
}