aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineFunction.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/MachineFunction.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/CodeGen/MachineFunction.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineFunction.cpp283
1 files changed, 258 insertions, 25 deletions
diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp
index 3f44578b1a2c..0a454b68aca3 100644
--- a/llvm/lib/CodeGen/MachineFunction.cpp
+++ b/llvm/lib/CodeGen/MachineFunction.cpp
@@ -438,15 +438,34 @@ MachineMemOperand *MachineFunction::getMachineMemOperand(
}
MachineMemOperand *MachineFunction::getMachineMemOperand(
- const MachineMemOperand *MMO, MachinePointerInfo &PtrInfo, uint64_t Size) {
- return new (Allocator) MachineMemOperand(
- PtrInfo, MMO->getFlags(), Size, MMO->getBaseAlign(), AAMDNodes(), nullptr,
- MMO->getSyncScopeID(), MMO->getOrdering(), MMO->getFailureOrdering());
+ MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy,
+ Align base_alignment, const AAMDNodes &AAInfo, const MDNode *Ranges,
+ SyncScope::ID SSID, AtomicOrdering Ordering,
+ AtomicOrdering FailureOrdering) {
+ return new (Allocator)
+ MachineMemOperand(PtrInfo, f, MemTy, base_alignment, AAInfo, Ranges, SSID,
+ Ordering, FailureOrdering);
+}
+
+MachineMemOperand *MachineFunction::getMachineMemOperand(
+ const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, uint64_t Size) {
+ return new (Allocator)
+ MachineMemOperand(PtrInfo, MMO->getFlags(), Size, MMO->getBaseAlign(),
+ AAMDNodes(), nullptr, MMO->getSyncScopeID(),
+ MMO->getSuccessOrdering(), MMO->getFailureOrdering());
+}
+
+MachineMemOperand *MachineFunction::getMachineMemOperand(
+ const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, LLT Ty) {
+ return new (Allocator)
+ MachineMemOperand(PtrInfo, MMO->getFlags(), Ty, MMO->getBaseAlign(),
+ AAMDNodes(), nullptr, MMO->getSyncScopeID(),
+ MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}
MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
- int64_t Offset, uint64_t Size) {
+ int64_t Offset, LLT Ty) {
const MachinePointerInfo &PtrInfo = MMO->getPointerInfo();
// If there is no pointer value, the offset isn't tracked so we need to adjust
@@ -457,10 +476,10 @@ MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
// Do not preserve ranges, since we don't necessarily know what the high bits
// are anymore.
- return new (Allocator)
- MachineMemOperand(PtrInfo.getWithOffset(Offset), MMO->getFlags(), Size,
- Alignment, MMO->getAAInfo(), nullptr, MMO->getSyncScopeID(),
- MMO->getOrdering(), MMO->getFailureOrdering());
+ return new (Allocator) MachineMemOperand(
+ PtrInfo.getWithOffset(Offset), MMO->getFlags(), Ty, Alignment,
+ MMO->getAAInfo(), nullptr, MMO->getSyncScopeID(),
+ MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}
MachineMemOperand *
@@ -472,7 +491,7 @@ MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
return new (Allocator) MachineMemOperand(
MPI, MMO->getFlags(), MMO->getSize(), MMO->getBaseAlign(), AAInfo,
- MMO->getRanges(), MMO->getSyncScopeID(), MMO->getOrdering(),
+ MMO->getRanges(), MMO->getSyncScopeID(), MMO->getSuccessOrdering(),
MMO->getFailureOrdering());
}
@@ -482,7 +501,7 @@ MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
return new (Allocator) MachineMemOperand(
MMO->getPointerInfo(), Flags, MMO->getSize(), MMO->getBaseAlign(),
MMO->getAAInfo(), MMO->getRanges(), MMO->getSyncScopeID(),
- MMO->getOrdering(), MMO->getFailureOrdering());
+ MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}
MachineInstr::ExtraInfo *MachineFunction::createMIExtraInfo(
@@ -850,9 +869,8 @@ int MachineFunction::getFilterIDFor(std::vector<unsigned> &TyIds) {
// If the new filter coincides with the tail of an existing filter, then
// re-use the existing filter. Folding filters more than this requires
// re-ordering filters and/or their elements - probably not worth it.
- for (std::vector<unsigned>::iterator I = FilterEnds.begin(),
- E = FilterEnds.end(); I != E; ++I) {
- unsigned i = *I, j = TyIds.size();
+ for (unsigned i : FilterEnds) {
+ unsigned j = TyIds.size();
while (i && j)
if (FilterIds[--i] != TyIds[--j])
@@ -951,10 +969,11 @@ void MachineFunction::setDebugInstrNumberingCount(unsigned Num) {
}
void MachineFunction::makeDebugValueSubstitution(DebugInstrOperandPair A,
- DebugInstrOperandPair B) {
- auto Result = DebugValueSubstitutions.insert(std::make_pair(A, B));
- (void)Result;
- assert(Result.second && "Substitution for an already substituted value?");
+ DebugInstrOperandPair B,
+ unsigned Subreg) {
+ // Catch any accidental self-loops.
+ assert(A.first != B.first);
+ DebugValueSubstitutions.push_back({A, B, Subreg});
}
void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,
@@ -971,7 +990,7 @@ void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,
// MIR output.
// Examine all the operands, or the first N specified by the caller.
MaxOperand = std::min(MaxOperand, Old.getNumOperands());
- for (unsigned int I = 0; I < Old.getNumOperands(); ++I) {
+ for (unsigned int I = 0; I < MaxOperand; ++I) {
const auto &OldMO = Old.getOperand(I);
auto &NewMO = New.getOperand(I);
(void)NewMO;
@@ -986,6 +1005,222 @@ void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,
}
}
+auto MachineFunction::salvageCopySSA(MachineInstr &MI)
+ -> DebugInstrOperandPair {
+ MachineRegisterInfo &MRI = getRegInfo();
+ const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
+ const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();
+
+ // Chase the value read by a copy-like instruction back to the instruction
+ // that ultimately _defines_ that value. This may pass:
+ // * Through multiple intermediate copies, including subregister moves /
+ // copies,
+ // * Copies from physical registers that must then be traced back to the
+ // defining instruction,
+ // * Or, physical registers may be live-in to (only) the entry block, which
+ // requires a DBG_PHI to be created.
+ // We can pursue this problem in that order: trace back through copies,
+ // optionally through a physical register, to a defining instruction. We
+ // should never move from physreg to vreg. As we're still in SSA form, no need
+ // to worry about partial definitions of registers.
+
+ // Helper lambda to interpret a copy-like instruction. Takes instruction,
+ // returns the register read and any subregister identifying which part is
+ // read.
+ auto GetRegAndSubreg =
+ [&](const MachineInstr &Cpy) -> std::pair<Register, unsigned> {
+ Register NewReg, OldReg;
+ unsigned SubReg;
+ if (Cpy.isCopy()) {
+ OldReg = Cpy.getOperand(0).getReg();
+ NewReg = Cpy.getOperand(1).getReg();
+ SubReg = Cpy.getOperand(1).getSubReg();
+ } else if (Cpy.isSubregToReg()) {
+ OldReg = Cpy.getOperand(0).getReg();
+ NewReg = Cpy.getOperand(2).getReg();
+ SubReg = Cpy.getOperand(3).getImm();
+ } else {
+ auto CopyDetails = *TII.isCopyInstr(Cpy);
+ const MachineOperand &Src = *CopyDetails.Source;
+ const MachineOperand &Dest = *CopyDetails.Destination;
+ OldReg = Dest.getReg();
+ NewReg = Src.getReg();
+ SubReg = Src.getSubReg();
+ }
+
+ return {NewReg, SubReg};
+ };
+
+ // First seek either the defining instruction, or a copy from a physreg.
+ // During search, the current state is the current copy instruction, and which
+ // register we've read. Accumulate qualifying subregisters into SubregsSeen;
+ // deal with those later.
+ auto State = GetRegAndSubreg(MI);
+ auto CurInst = MI.getIterator();
+ SmallVector<unsigned, 4> SubregsSeen;
+ while (true) {
+ // If we've found a copy from a physreg, first portion of search is over.
+ if (!State.first.isVirtual())
+ break;
+
+ // Record any subregister qualifier.
+ if (State.second)
+ SubregsSeen.push_back(State.second);
+
+ assert(MRI.hasOneDef(State.first));
+ MachineInstr &Inst = *MRI.def_begin(State.first)->getParent();
+ CurInst = Inst.getIterator();
+
+ // Any non-copy instruction is the defining instruction we're seeking.
+ if (!Inst.isCopyLike() && !TII.isCopyInstr(Inst))
+ break;
+ State = GetRegAndSubreg(Inst);
+ };
+
+ // Helper lambda to apply additional subregister substitutions to a known
+ // instruction/operand pair. Adds new (fake) substitutions so that we can
+ // record the subregister. FIXME: this isn't very space efficient if multiple
+ // values are tracked back through the same copies; cache something later.
+ auto ApplySubregisters =
+ [&](DebugInstrOperandPair P) -> DebugInstrOperandPair {
+ for (unsigned Subreg : reverse(SubregsSeen)) {
+ // Fetch a new instruction number, not attached to an actual instruction.
+ unsigned NewInstrNumber = getNewDebugInstrNum();
+ // Add a substitution from the "new" number to the known one, with a
+ // qualifying subreg.
+ makeDebugValueSubstitution({NewInstrNumber, 0}, P, Subreg);
+ // Return the new number; to find the underlying value, consumers need to
+ // deal with the qualifying subreg.
+ P = {NewInstrNumber, 0};
+ }
+ return P;
+ };
+
+ // If we managed to find the defining instruction after COPYs, return an
+ // instruction / operand pair after adding subregister qualifiers.
+ if (State.first.isVirtual()) {
+ // Virtual register def -- we can just look up where this happens.
+ MachineInstr *Inst = MRI.def_begin(State.first)->getParent();
+ for (auto &MO : Inst->operands()) {
+ if (!MO.isReg() || !MO.isDef() || MO.getReg() != State.first)
+ continue;
+ return ApplySubregisters(
+ {Inst->getDebugInstrNum(), Inst->getOperandNo(&MO)});
+ }
+
+ llvm_unreachable("Vreg def with no corresponding operand?");
+ }
+
+ // Our search ended in a copy from a physreg: walk back up the function
+ // looking for whatever defines the physreg.
+ assert(CurInst->isCopyLike() || TII.isCopyInstr(*CurInst));
+ State = GetRegAndSubreg(*CurInst);
+ Register RegToSeek = State.first;
+
+ auto RMII = CurInst->getReverseIterator();
+ auto PrevInstrs = make_range(RMII, CurInst->getParent()->instr_rend());
+ for (auto &ToExamine : PrevInstrs) {
+ for (auto &MO : ToExamine.operands()) {
+ // Test for operand that defines something aliasing RegToSeek.
+ if (!MO.isReg() || !MO.isDef() ||
+ !TRI.regsOverlap(RegToSeek, MO.getReg()))
+ continue;
+
+ return ApplySubregisters(
+ {ToExamine.getDebugInstrNum(), ToExamine.getOperandNo(&MO)});
+ }
+ }
+
+ MachineBasicBlock &InsertBB = *CurInst->getParent();
+
+ // We reached the start of the block before finding a defining instruction.
+ // It could be from a constant register, otherwise it must be an argument.
+ if (TRI.isConstantPhysReg(State.first)) {
+ // We can produce a DBG_PHI that identifies the constant physreg. Doesn't
+ // matter where we put it, as it's constant valued.
+ assert(CurInst->isCopy());
+ } else if (State.first == TRI.getFrameRegister(*this)) {
+ // LLVM IR is allowed to read the framepointer by calling a
+ // llvm.frameaddress.* intrinsic. We can support this by emitting a
+ // DBG_PHI $fp. This isn't ideal, because it extends the behaviours /
+ // position that DBG_PHIs appear at, limiting what can be done later.
+ // TODO: see if there's a better way of expressing these variable
+ // locations.
+ ;
+ } else {
+ // Assert that this is the entry block. If it isn't, then there is some
+ // code construct we don't recognise that deals with physregs across
+ // blocks.
+ assert(!State.first.isVirtual());
+ assert(&*InsertBB.getParent()->begin() == &InsertBB);
+ }
+
+ // Create DBG_PHI for specified physreg.
+ auto Builder = BuildMI(InsertBB, InsertBB.getFirstNonPHI(), DebugLoc(),
+ TII.get(TargetOpcode::DBG_PHI));
+ Builder.addReg(State.first, RegState::Debug);
+ unsigned NewNum = getNewDebugInstrNum();
+ Builder.addImm(NewNum);
+ return ApplySubregisters({NewNum, 0u});
+}
+
+void MachineFunction::finalizeDebugInstrRefs() {
+ auto *TII = getSubtarget().getInstrInfo();
+
+ auto MakeDbgValue = [&](MachineInstr &MI) {
+ const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE);
+ MI.setDesc(RefII);
+ MI.getOperand(1).ChangeToRegister(0, false);
+ MI.getOperand(0).setIsDebug();
+ };
+
+ if (!getTarget().Options.ValueTrackingVariableLocations)
+ return;
+
+ for (auto &MBB : *this) {
+ for (auto &MI : MBB) {
+ if (!MI.isDebugRef() || !MI.getOperand(0).isReg())
+ continue;
+
+ Register Reg = MI.getOperand(0).getReg();
+
+ // Some vregs can be deleted as redundant in the meantime. Mark those
+ // as DBG_VALUE $noreg.
+ if (Reg == 0) {
+ MakeDbgValue(MI);
+ continue;
+ }
+
+ assert(Reg.isVirtual());
+ MachineInstr &DefMI = *RegInfo->def_instr_begin(Reg);
+ assert(RegInfo->hasOneDef(Reg));
+
+ // If we've found a copy-like instruction, follow it back to the
+ // instruction that defines the source value, see salvageCopySSA docs
+ // for why this is important.
+ if (DefMI.isCopyLike() || TII->isCopyInstr(DefMI)) {
+ auto Result = salvageCopySSA(DefMI);
+ MI.getOperand(0).ChangeToImmediate(Result.first);
+ MI.getOperand(1).setImm(Result.second);
+ } else {
+ // Otherwise, identify the operand number that the VReg refers to.
+ unsigned OperandIdx = 0;
+ for (const auto &MO : DefMI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg() == Reg)
+ break;
+ ++OperandIdx;
+ }
+ assert(OperandIdx < DefMI.getNumOperands());
+
+ // Morph this instr ref to point at the given instruction and operand.
+ unsigned ID = DefMI.getDebugInstrNum();
+ MI.getOperand(0).ChangeToImmediate(ID);
+ MI.getOperand(1).setImm(OperandIdx);
+ }
+ }
+ }
+}
+
/// \}
//===----------------------------------------------------------------------===//
@@ -1120,7 +1355,7 @@ unsigned MachineConstantPoolEntry::getSizeInBytes(const DataLayout &DL) const {
bool MachineConstantPoolEntry::needsRelocation() const {
if (isMachineConstantPoolEntry())
return true;
- return Val.ConstVal->needsRelocation();
+ return Val.ConstVal->needsDynamicRelocation();
}
SectionKind
@@ -1150,11 +1385,9 @@ MachineConstantPool::~MachineConstantPool() {
Deleted.insert(Constants[i].Val.MachineCPVal);
delete Constants[i].Val.MachineCPVal;
}
- for (DenseSet<MachineConstantPoolValue*>::iterator I =
- MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end();
- I != E; ++I) {
- if (Deleted.count(*I) == 0)
- delete *I;
+ for (MachineConstantPoolValue *CPV : MachineCPVsSharingEntries) {
+ if (Deleted.count(CPV) == 0)
+ delete CPV;
}
}