diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/CodeGen/MachineFunction.cpp | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/CodeGen/MachineFunction.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineFunction.cpp | 283 |
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; } } |