1e8d8bef9SDimitry Andric //===- InstrRefBasedImpl.cpp - Tracking Debug Value MIs -------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric /// \file InstrRefBasedImpl.cpp 9e8d8bef9SDimitry Andric /// 10e8d8bef9SDimitry Andric /// This is a separate implementation of LiveDebugValues, see 11e8d8bef9SDimitry Andric /// LiveDebugValues.cpp and VarLocBasedImpl.cpp for more information. 12e8d8bef9SDimitry Andric /// 13e8d8bef9SDimitry Andric /// This pass propagates variable locations between basic blocks, resolving 14349cc55cSDimitry Andric /// control flow conflicts between them. The problem is SSA construction, where 15349cc55cSDimitry Andric /// each debug instruction assigns the *value* that a variable has, and every 16349cc55cSDimitry Andric /// instruction where the variable is in scope uses that variable. The resulting 17349cc55cSDimitry Andric /// map of instruction-to-value is then translated into a register (or spill) 18349cc55cSDimitry Andric /// location for each variable over each instruction. 19e8d8bef9SDimitry Andric /// 20349cc55cSDimitry Andric /// The primary difference from normal SSA construction is that we cannot 21349cc55cSDimitry Andric /// _create_ PHI values that contain variable values. CodeGen has already 22349cc55cSDimitry Andric /// completed, and we can't alter it just to make debug-info complete. Thus: 23349cc55cSDimitry Andric /// we can identify function positions where we would like a PHI value for a 24349cc55cSDimitry Andric /// variable, but must search the MachineFunction to see whether such a PHI is 25349cc55cSDimitry Andric /// available. If no such PHI exists, the variable location must be dropped. 26e8d8bef9SDimitry Andric /// 27349cc55cSDimitry Andric /// To achieve this, we perform two kinds of analysis. First, we identify 28e8d8bef9SDimitry Andric /// every value defined by every instruction (ignoring those that only move 29349cc55cSDimitry Andric /// another value), then re-compute an SSA-form representation of the 30349cc55cSDimitry Andric /// MachineFunction, using value propagation to eliminate any un-necessary 31349cc55cSDimitry Andric /// PHI values. This gives us a map of every value computed in the function, 32349cc55cSDimitry Andric /// and its location within the register file / stack. 33e8d8bef9SDimitry Andric /// 34349cc55cSDimitry Andric /// Secondly, for each variable we perform the same analysis, where each debug 35349cc55cSDimitry Andric /// instruction is considered a def, and every instruction where the variable 36349cc55cSDimitry Andric /// is in lexical scope as a use. Value propagation is used again to eliminate 37349cc55cSDimitry Andric /// any un-necessary PHIs. This gives us a map of each variable to the value 38349cc55cSDimitry Andric /// it should have in a block. 39e8d8bef9SDimitry Andric /// 40349cc55cSDimitry Andric /// Once both are complete, we have two maps for each block: 41349cc55cSDimitry Andric /// * Variables to the values they should have, 42349cc55cSDimitry Andric /// * Values to the register / spill slot they are located in. 43349cc55cSDimitry Andric /// After which we can marry-up variable values with a location, and emit 44349cc55cSDimitry Andric /// DBG_VALUE instructions specifying those locations. Variable locations may 45349cc55cSDimitry Andric /// be dropped in this process due to the desired variable value not being 46349cc55cSDimitry Andric /// resident in any machine location, or because there is no PHI value in any 47349cc55cSDimitry Andric /// location that accurately represents the desired value. The building of 48349cc55cSDimitry Andric /// location lists for each block is left to DbgEntityHistoryCalculator. 49e8d8bef9SDimitry Andric /// 50349cc55cSDimitry Andric /// This pass is kept efficient because the size of the first SSA problem 51349cc55cSDimitry Andric /// is proportional to the working-set size of the function, which the compiler 52349cc55cSDimitry Andric /// tries to keep small. (It's also proportional to the number of blocks). 53349cc55cSDimitry Andric /// Additionally, we repeatedly perform the second SSA problem analysis with 54349cc55cSDimitry Andric /// only the variables and blocks in a single lexical scope, exploiting their 55349cc55cSDimitry Andric /// locality. 56e8d8bef9SDimitry Andric /// 57e8d8bef9SDimitry Andric /// ### Terminology 58e8d8bef9SDimitry Andric /// 59e8d8bef9SDimitry Andric /// A machine location is a register or spill slot, a value is something that's 60e8d8bef9SDimitry Andric /// defined by an instruction or PHI node, while a variable value is the value 61e8d8bef9SDimitry Andric /// assigned to a variable. A variable location is a machine location, that must 62e8d8bef9SDimitry Andric /// contain the appropriate variable value. A value that is a PHI node is 63e8d8bef9SDimitry Andric /// occasionally called an mphi. 64e8d8bef9SDimitry Andric /// 65349cc55cSDimitry Andric /// The first SSA problem is the "machine value location" problem, 66e8d8bef9SDimitry Andric /// because we're determining which machine locations contain which values. 67e8d8bef9SDimitry Andric /// The "locations" are constant: what's unknown is what value they contain. 68e8d8bef9SDimitry Andric /// 69349cc55cSDimitry Andric /// The second SSA problem (the one for variables) is the "variable value 70e8d8bef9SDimitry Andric /// problem", because it's determining what values a variable has, rather than 71349cc55cSDimitry Andric /// what location those values are placed in. 72e8d8bef9SDimitry Andric /// 73e8d8bef9SDimitry Andric /// TODO: 74e8d8bef9SDimitry Andric /// Overlapping fragments 75e8d8bef9SDimitry Andric /// Entry values 76e8d8bef9SDimitry Andric /// Add back DEBUG statements for debugging this 77e8d8bef9SDimitry Andric /// Collect statistics 78e8d8bef9SDimitry Andric /// 79e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 80e8d8bef9SDimitry Andric 81e8d8bef9SDimitry Andric #include "llvm/ADT/DenseMap.h" 82e8d8bef9SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 83fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h" 84e8d8bef9SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 85e8d8bef9SDimitry Andric #include "llvm/ADT/SmallSet.h" 86e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 8781ad6265SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 88e8d8bef9SDimitry Andric #include "llvm/CodeGen/LexicalScopes.h" 89e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 90349cc55cSDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 91e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 92e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 93e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 94e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 95fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 96e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 97e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 98e8d8bef9SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h" 99e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h" 100e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 101e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 102e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 103e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 104e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 105e8d8bef9SDimitry Andric #include "llvm/Config/llvm-config.h" 106e8d8bef9SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 107e8d8bef9SDimitry Andric #include "llvm/IR/DebugLoc.h" 108e8d8bef9SDimitry Andric #include "llvm/IR/Function.h" 109e8d8bef9SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 110e8d8bef9SDimitry Andric #include "llvm/Support/Casting.h" 111e8d8bef9SDimitry Andric #include "llvm/Support/Compiler.h" 112e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 11381ad6265SDimitry Andric #include "llvm/Support/GenericIteratedDominanceFrontier.h" 114e8d8bef9SDimitry Andric #include "llvm/Support/TypeSize.h" 115e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 116fe6060f1SDimitry Andric #include "llvm/Target/TargetMachine.h" 117fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdaterImpl.h" 118e8d8bef9SDimitry Andric #include <algorithm> 119e8d8bef9SDimitry Andric #include <cassert> 12081ad6265SDimitry Andric #include <climits> 121e8d8bef9SDimitry Andric #include <cstdint> 122e8d8bef9SDimitry Andric #include <functional> 123e8d8bef9SDimitry Andric #include <queue> 124e8d8bef9SDimitry Andric #include <tuple> 125e8d8bef9SDimitry Andric #include <utility> 126e8d8bef9SDimitry Andric #include <vector> 127e8d8bef9SDimitry Andric 128349cc55cSDimitry Andric #include "InstrRefBasedImpl.h" 129e8d8bef9SDimitry Andric #include "LiveDebugValues.h" 130bdd1243dSDimitry Andric #include <optional> 131e8d8bef9SDimitry Andric 132e8d8bef9SDimitry Andric using namespace llvm; 133349cc55cSDimitry Andric using namespace LiveDebugValues; 134e8d8bef9SDimitry Andric 135fe6060f1SDimitry Andric // SSAUpdaterImple sets DEBUG_TYPE, change it. 136fe6060f1SDimitry Andric #undef DEBUG_TYPE 137e8d8bef9SDimitry Andric #define DEBUG_TYPE "livedebugvalues" 138e8d8bef9SDimitry Andric 139e8d8bef9SDimitry Andric // Act more like the VarLoc implementation, by propagating some locations too 140e8d8bef9SDimitry Andric // far and ignoring some transfers. 141e8d8bef9SDimitry Andric static cl::opt<bool> EmulateOldLDV("emulate-old-livedebugvalues", cl::Hidden, 142e8d8bef9SDimitry Andric cl::desc("Act like old LiveDebugValues did"), 143e8d8bef9SDimitry Andric cl::init(false)); 144e8d8bef9SDimitry Andric 145d56accc7SDimitry Andric // Limit for the maximum number of stack slots we should track, past which we 146d56accc7SDimitry Andric // will ignore any spills. InstrRefBasedLDV gathers detailed information on all 147d56accc7SDimitry Andric // stack slots which leads to high memory consumption, and in some scenarios 148d56accc7SDimitry Andric // (such as asan with very many locals) the working set of the function can be 149d56accc7SDimitry Andric // very large, causing many spills. In these scenarios, it is very unlikely that 150d56accc7SDimitry Andric // the developer has hundreds of variables live at the same time that they're 151d56accc7SDimitry Andric // carefully thinking about -- instead, they probably autogenerated the code. 152d56accc7SDimitry Andric // When this happens, gracefully stop tracking excess spill slots, rather than 153d56accc7SDimitry Andric // consuming all the developer's memory. 154d56accc7SDimitry Andric static cl::opt<unsigned> 155d56accc7SDimitry Andric StackWorkingSetLimit("livedebugvalues-max-stack-slots", cl::Hidden, 156d56accc7SDimitry Andric cl::desc("livedebugvalues-stack-ws-limit"), 157d56accc7SDimitry Andric cl::init(250)); 158d56accc7SDimitry Andric 159bdd1243dSDimitry Andric DbgOpID DbgOpID::UndefID = DbgOpID(0xffffffff); 160bdd1243dSDimitry Andric 161e8d8bef9SDimitry Andric /// Tracker for converting machine value locations and variable values into 162e8d8bef9SDimitry Andric /// variable locations (the output of LiveDebugValues), recorded as DBG_VALUEs 163e8d8bef9SDimitry Andric /// specifying block live-in locations and transfers within blocks. 164e8d8bef9SDimitry Andric /// 165e8d8bef9SDimitry Andric /// Operating on a per-block basis, this class takes a (pre-loaded) MLocTracker 166e8d8bef9SDimitry Andric /// and must be initialized with the set of variable values that are live-in to 167e8d8bef9SDimitry Andric /// the block. The caller then repeatedly calls process(). TransferTracker picks 168e8d8bef9SDimitry Andric /// out variable locations for the live-in variable values (if there _is_ a 169e8d8bef9SDimitry Andric /// location) and creates the corresponding DBG_VALUEs. Then, as the block is 170e8d8bef9SDimitry Andric /// stepped through, transfers of values between machine locations are 171e8d8bef9SDimitry Andric /// identified and if profitable, a DBG_VALUE created. 172e8d8bef9SDimitry Andric /// 173e8d8bef9SDimitry Andric /// This is where debug use-before-defs would be resolved: a variable with an 174e8d8bef9SDimitry Andric /// unavailable value could materialize in the middle of a block, when the 175e8d8bef9SDimitry Andric /// value becomes available. Or, we could detect clobbers and re-specify the 176e8d8bef9SDimitry Andric /// variable in a backup location. (XXX these are unimplemented). 177e8d8bef9SDimitry Andric class TransferTracker { 178e8d8bef9SDimitry Andric public: 179e8d8bef9SDimitry Andric const TargetInstrInfo *TII; 180fe6060f1SDimitry Andric const TargetLowering *TLI; 181e8d8bef9SDimitry Andric /// This machine location tracker is assumed to always contain the up-to-date 182e8d8bef9SDimitry Andric /// value mapping for all machine locations. TransferTracker only reads 183e8d8bef9SDimitry Andric /// information from it. (XXX make it const?) 184e8d8bef9SDimitry Andric MLocTracker *MTracker; 185e8d8bef9SDimitry Andric MachineFunction &MF; 186*0fca6ea1SDimitry Andric const DebugVariableMap &DVMap; 187fe6060f1SDimitry Andric bool ShouldEmitDebugEntryValues; 188e8d8bef9SDimitry Andric 189e8d8bef9SDimitry Andric /// Record of all changes in variable locations at a block position. Awkwardly 190e8d8bef9SDimitry Andric /// we allow inserting either before or after the point: MBB != nullptr 191e8d8bef9SDimitry Andric /// indicates it's before, otherwise after. 192e8d8bef9SDimitry Andric struct Transfer { 193fe6060f1SDimitry Andric MachineBasicBlock::instr_iterator Pos; /// Position to insert DBG_VALUes 194e8d8bef9SDimitry Andric MachineBasicBlock *MBB; /// non-null if we should insert after. 195*0fca6ea1SDimitry Andric /// Vector of DBG_VALUEs to insert. Store with their DebugVariableID so that 196*0fca6ea1SDimitry Andric /// they can be sorted into a stable order for emission at a later time. 197*0fca6ea1SDimitry Andric SmallVector<std::pair<DebugVariableID, MachineInstr *>, 4> Insts; 198e8d8bef9SDimitry Andric }; 199e8d8bef9SDimitry Andric 200bdd1243dSDimitry Andric /// Stores the resolved operands (machine locations and constants) and 201bdd1243dSDimitry Andric /// qualifying meta-information needed to construct a concrete DBG_VALUE-like 202bdd1243dSDimitry Andric /// instruction. 203bdd1243dSDimitry Andric struct ResolvedDbgValue { 204bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> Ops; 205e8d8bef9SDimitry Andric DbgValueProperties Properties; 206bdd1243dSDimitry Andric 207bdd1243dSDimitry Andric ResolvedDbgValue(SmallVectorImpl<ResolvedDbgOp> &Ops, 208bdd1243dSDimitry Andric DbgValueProperties Properties) 209bdd1243dSDimitry Andric : Ops(Ops.begin(), Ops.end()), Properties(Properties) {} 210bdd1243dSDimitry Andric 211bdd1243dSDimitry Andric /// Returns all the LocIdx values used in this struct, in the order in which 212bdd1243dSDimitry Andric /// they appear as operands in the debug value; may contain duplicates. 213bdd1243dSDimitry Andric auto loc_indices() const { 214bdd1243dSDimitry Andric return map_range( 215bdd1243dSDimitry Andric make_filter_range( 216bdd1243dSDimitry Andric Ops, [](const ResolvedDbgOp &Op) { return !Op.IsConst; }), 217bdd1243dSDimitry Andric [](const ResolvedDbgOp &Op) { return Op.Loc; }); 218bdd1243dSDimitry Andric } 219fe6060f1SDimitry Andric }; 220e8d8bef9SDimitry Andric 221e8d8bef9SDimitry Andric /// Collection of transfers (DBG_VALUEs) to be inserted. 222e8d8bef9SDimitry Andric SmallVector<Transfer, 32> Transfers; 223e8d8bef9SDimitry Andric 224e8d8bef9SDimitry Andric /// Local cache of what-value-is-in-what-LocIdx. Used to identify differences 225e8d8bef9SDimitry Andric /// between TransferTrackers view of variable locations and MLocTrackers. For 226e8d8bef9SDimitry Andric /// example, MLocTracker observes all clobbers, but TransferTracker lazily 227e8d8bef9SDimitry Andric /// does not. 228349cc55cSDimitry Andric SmallVector<ValueIDNum, 32> VarLocs; 229e8d8bef9SDimitry Andric 230e8d8bef9SDimitry Andric /// Map from LocIdxes to which DebugVariables are based that location. 231e8d8bef9SDimitry Andric /// Mantained while stepping through the block. Not accurate if 232e8d8bef9SDimitry Andric /// VarLocs[Idx] != MTracker->LocIdxToIDNum[Idx]. 233*0fca6ea1SDimitry Andric DenseMap<LocIdx, SmallSet<DebugVariableID, 4>> ActiveMLocs; 234e8d8bef9SDimitry Andric 235e8d8bef9SDimitry Andric /// Map from DebugVariable to it's current location and qualifying meta 236e8d8bef9SDimitry Andric /// information. To be used in conjunction with ActiveMLocs to construct 237e8d8bef9SDimitry Andric /// enough information for the DBG_VALUEs for a particular LocIdx. 238*0fca6ea1SDimitry Andric DenseMap<DebugVariableID, ResolvedDbgValue> ActiveVLocs; 239e8d8bef9SDimitry Andric 240e8d8bef9SDimitry Andric /// Temporary cache of DBG_VALUEs to be entered into the Transfers collection. 241*0fca6ea1SDimitry Andric SmallVector<std::pair<DebugVariableID, MachineInstr *>, 4> PendingDbgValues; 242e8d8bef9SDimitry Andric 243e8d8bef9SDimitry Andric /// Record of a use-before-def: created when a value that's live-in to the 244e8d8bef9SDimitry Andric /// current block isn't available in any machine location, but it will be 245e8d8bef9SDimitry Andric /// defined in this block. 246e8d8bef9SDimitry Andric struct UseBeforeDef { 247e8d8bef9SDimitry Andric /// Value of this variable, def'd in block. 248bdd1243dSDimitry Andric SmallVector<DbgOp> Values; 249e8d8bef9SDimitry Andric /// Identity of this variable. 250*0fca6ea1SDimitry Andric DebugVariableID VarID; 251e8d8bef9SDimitry Andric /// Additional variable properties. 252e8d8bef9SDimitry Andric DbgValueProperties Properties; 253*0fca6ea1SDimitry Andric UseBeforeDef(ArrayRef<DbgOp> Values, DebugVariableID VarID, 254bdd1243dSDimitry Andric const DbgValueProperties &Properties) 255*0fca6ea1SDimitry Andric : Values(Values.begin(), Values.end()), VarID(VarID), 256bdd1243dSDimitry Andric Properties(Properties) {} 257e8d8bef9SDimitry Andric }; 258e8d8bef9SDimitry Andric 259e8d8bef9SDimitry Andric /// Map from instruction index (within the block) to the set of UseBeforeDefs 260e8d8bef9SDimitry Andric /// that become defined at that instruction. 261e8d8bef9SDimitry Andric DenseMap<unsigned, SmallVector<UseBeforeDef, 1>> UseBeforeDefs; 262e8d8bef9SDimitry Andric 263e8d8bef9SDimitry Andric /// The set of variables that are in UseBeforeDefs and can become a location 264e8d8bef9SDimitry Andric /// once the relevant value is defined. An element being erased from this 265e8d8bef9SDimitry Andric /// collection prevents the use-before-def materializing. 266*0fca6ea1SDimitry Andric DenseSet<DebugVariableID> UseBeforeDefVariables; 267e8d8bef9SDimitry Andric 268e8d8bef9SDimitry Andric const TargetRegisterInfo &TRI; 269e8d8bef9SDimitry Andric const BitVector &CalleeSavedRegs; 270e8d8bef9SDimitry Andric 271e8d8bef9SDimitry Andric TransferTracker(const TargetInstrInfo *TII, MLocTracker *MTracker, 272*0fca6ea1SDimitry Andric MachineFunction &MF, const DebugVariableMap &DVMap, 273*0fca6ea1SDimitry Andric const TargetRegisterInfo &TRI, 274fe6060f1SDimitry Andric const BitVector &CalleeSavedRegs, const TargetPassConfig &TPC) 275*0fca6ea1SDimitry Andric : TII(TII), MTracker(MTracker), MF(MF), DVMap(DVMap), TRI(TRI), 276fe6060f1SDimitry Andric CalleeSavedRegs(CalleeSavedRegs) { 277fe6060f1SDimitry Andric TLI = MF.getSubtarget().getTargetLowering(); 278fe6060f1SDimitry Andric auto &TM = TPC.getTM<TargetMachine>(); 279fe6060f1SDimitry Andric ShouldEmitDebugEntryValues = TM.Options.ShouldEmitDebugEntryValues(); 280fe6060f1SDimitry Andric } 281e8d8bef9SDimitry Andric 282bdd1243dSDimitry Andric bool isCalleeSaved(LocIdx L) const { 283e8d8bef9SDimitry Andric unsigned Reg = MTracker->LocIdxToLocID[L]; 284e8d8bef9SDimitry Andric if (Reg >= MTracker->NumRegs) 285e8d8bef9SDimitry Andric return false; 286e8d8bef9SDimitry Andric for (MCRegAliasIterator RAI(Reg, &TRI, true); RAI.isValid(); ++RAI) 287e8d8bef9SDimitry Andric if (CalleeSavedRegs.test(*RAI)) 288e8d8bef9SDimitry Andric return true; 289e8d8bef9SDimitry Andric return false; 290e8d8bef9SDimitry Andric }; 291e8d8bef9SDimitry Andric 292bdd1243dSDimitry Andric // An estimate of the expected lifespan of values at a machine location, with 293bdd1243dSDimitry Andric // a greater value corresponding to a longer expected lifespan, i.e. spill 294bdd1243dSDimitry Andric // slots generally live longer than callee-saved registers which generally 295bdd1243dSDimitry Andric // live longer than non-callee-saved registers. The minimum value of 0 296bdd1243dSDimitry Andric // corresponds to an illegal location that cannot have a "lifespan" at all. 297bdd1243dSDimitry Andric enum class LocationQuality : unsigned char { 298bdd1243dSDimitry Andric Illegal = 0, 299bdd1243dSDimitry Andric Register, 300bdd1243dSDimitry Andric CalleeSavedRegister, 301bdd1243dSDimitry Andric SpillSlot, 302bdd1243dSDimitry Andric Best = SpillSlot 303bdd1243dSDimitry Andric }; 304bdd1243dSDimitry Andric 305bdd1243dSDimitry Andric class LocationAndQuality { 306bdd1243dSDimitry Andric unsigned Location : 24; 307bdd1243dSDimitry Andric unsigned Quality : 8; 308bdd1243dSDimitry Andric 309bdd1243dSDimitry Andric public: 310bdd1243dSDimitry Andric LocationAndQuality() : Location(0), Quality(0) {} 311bdd1243dSDimitry Andric LocationAndQuality(LocIdx L, LocationQuality Q) 312bdd1243dSDimitry Andric : Location(L.asU64()), Quality(static_cast<unsigned>(Q)) {} 313bdd1243dSDimitry Andric LocIdx getLoc() const { 314bdd1243dSDimitry Andric if (!Quality) 315bdd1243dSDimitry Andric return LocIdx::MakeIllegalLoc(); 316bdd1243dSDimitry Andric return LocIdx(Location); 317bdd1243dSDimitry Andric } 318bdd1243dSDimitry Andric LocationQuality getQuality() const { return LocationQuality(Quality); } 319bdd1243dSDimitry Andric bool isIllegal() const { return !Quality; } 320bdd1243dSDimitry Andric bool isBest() const { return getQuality() == LocationQuality::Best; } 321bdd1243dSDimitry Andric }; 322bdd1243dSDimitry Andric 323*0fca6ea1SDimitry Andric using ValueLocPair = std::pair<ValueIDNum, LocationAndQuality>; 324*0fca6ea1SDimitry Andric 325*0fca6ea1SDimitry Andric static inline bool ValueToLocSort(const ValueLocPair &A, 326*0fca6ea1SDimitry Andric const ValueLocPair &B) { 327*0fca6ea1SDimitry Andric return A.first < B.first; 328*0fca6ea1SDimitry Andric }; 329*0fca6ea1SDimitry Andric 330bdd1243dSDimitry Andric // Returns the LocationQuality for the location L iff the quality of L is 331bdd1243dSDimitry Andric // is strictly greater than the provided minimum quality. 332bdd1243dSDimitry Andric std::optional<LocationQuality> 333bdd1243dSDimitry Andric getLocQualityIfBetter(LocIdx L, LocationQuality Min) const { 334bdd1243dSDimitry Andric if (L.isIllegal()) 335bdd1243dSDimitry Andric return std::nullopt; 336bdd1243dSDimitry Andric if (Min >= LocationQuality::SpillSlot) 337bdd1243dSDimitry Andric return std::nullopt; 338bdd1243dSDimitry Andric if (MTracker->isSpill(L)) 339bdd1243dSDimitry Andric return LocationQuality::SpillSlot; 340bdd1243dSDimitry Andric if (Min >= LocationQuality::CalleeSavedRegister) 341bdd1243dSDimitry Andric return std::nullopt; 342bdd1243dSDimitry Andric if (isCalleeSaved(L)) 343bdd1243dSDimitry Andric return LocationQuality::CalleeSavedRegister; 344bdd1243dSDimitry Andric if (Min >= LocationQuality::Register) 345bdd1243dSDimitry Andric return std::nullopt; 346bdd1243dSDimitry Andric return LocationQuality::Register; 347bdd1243dSDimitry Andric } 348bdd1243dSDimitry Andric 349bdd1243dSDimitry Andric /// For a variable \p Var with the live-in value \p Value, attempts to resolve 350bdd1243dSDimitry Andric /// the DbgValue to a concrete DBG_VALUE, emitting that value and loading the 351bdd1243dSDimitry Andric /// tracking information to track Var throughout the block. 352bdd1243dSDimitry Andric /// \p ValueToLoc is a map containing the best known location for every 353bdd1243dSDimitry Andric /// ValueIDNum that Value may use. 354bdd1243dSDimitry Andric /// \p MBB is the basic block that we are loading the live-in value for. 355bdd1243dSDimitry Andric /// \p DbgOpStore is the map containing the DbgOpID->DbgOp mapping needed to 356bdd1243dSDimitry Andric /// determine the values used by Value. 357bdd1243dSDimitry Andric void loadVarInloc(MachineBasicBlock &MBB, DbgOpIDMap &DbgOpStore, 358*0fca6ea1SDimitry Andric const SmallVectorImpl<ValueLocPair> &ValueToLoc, 359*0fca6ea1SDimitry Andric DebugVariableID VarID, DbgValue Value) { 360bdd1243dSDimitry Andric SmallVector<DbgOp> DbgOps; 361bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> ResolvedDbgOps; 362bdd1243dSDimitry Andric bool IsValueValid = true; 363bdd1243dSDimitry Andric unsigned LastUseBeforeDef = 0; 364bdd1243dSDimitry Andric 365bdd1243dSDimitry Andric // If every value used by the incoming DbgValue is available at block 366bdd1243dSDimitry Andric // entry, ResolvedDbgOps will contain the machine locations/constants for 367bdd1243dSDimitry Andric // those values and will be used to emit a debug location. 368bdd1243dSDimitry Andric // If one or more values are not yet available, but will all be defined in 369bdd1243dSDimitry Andric // this block, then LastUseBeforeDef will track the instruction index in 370bdd1243dSDimitry Andric // this BB at which the last of those values is defined, DbgOps will 371bdd1243dSDimitry Andric // contain the values that we will emit when we reach that instruction. 372bdd1243dSDimitry Andric // If one or more values are undef or not available throughout this block, 373bdd1243dSDimitry Andric // and we can't recover as an entry value, we set IsValueValid=false and 374bdd1243dSDimitry Andric // skip this variable. 375bdd1243dSDimitry Andric for (DbgOpID ID : Value.getDbgOpIDs()) { 376bdd1243dSDimitry Andric DbgOp Op = DbgOpStore.find(ID); 377bdd1243dSDimitry Andric DbgOps.push_back(Op); 378bdd1243dSDimitry Andric if (ID.isUndef()) { 379bdd1243dSDimitry Andric IsValueValid = false; 380bdd1243dSDimitry Andric break; 381bdd1243dSDimitry Andric } 382bdd1243dSDimitry Andric if (ID.isConst()) { 383bdd1243dSDimitry Andric ResolvedDbgOps.push_back(Op.MO); 384bdd1243dSDimitry Andric continue; 385bdd1243dSDimitry Andric } 386bdd1243dSDimitry Andric 387*0fca6ea1SDimitry Andric // Search for the desired ValueIDNum, to examine the best location found 388*0fca6ea1SDimitry Andric // for it. Use an empty ValueLocPair to search for an entry in ValueToLoc. 389bdd1243dSDimitry Andric const ValueIDNum &Num = Op.ID; 390*0fca6ea1SDimitry Andric ValueLocPair Probe(Num, LocationAndQuality()); 391*0fca6ea1SDimitry Andric auto ValuesPreferredLoc = std::lower_bound( 392*0fca6ea1SDimitry Andric ValueToLoc.begin(), ValueToLoc.end(), Probe, ValueToLocSort); 393*0fca6ea1SDimitry Andric 394*0fca6ea1SDimitry Andric // There must be a legitimate entry found for Num. 395*0fca6ea1SDimitry Andric assert(ValuesPreferredLoc != ValueToLoc.end() && 396*0fca6ea1SDimitry Andric ValuesPreferredLoc->first == Num); 397*0fca6ea1SDimitry Andric 398bdd1243dSDimitry Andric if (ValuesPreferredLoc->second.isIllegal()) { 399bdd1243dSDimitry Andric // If it's a def that occurs in this block, register it as a 400bdd1243dSDimitry Andric // use-before-def to be resolved as we step through the block. 401bdd1243dSDimitry Andric // Continue processing values so that we add any other UseBeforeDef 402bdd1243dSDimitry Andric // entries needed for later. 403bdd1243dSDimitry Andric if (Num.getBlock() == (unsigned)MBB.getNumber() && !Num.isPHI()) { 404bdd1243dSDimitry Andric LastUseBeforeDef = std::max(LastUseBeforeDef, 405bdd1243dSDimitry Andric static_cast<unsigned>(Num.getInst())); 406bdd1243dSDimitry Andric continue; 407bdd1243dSDimitry Andric } 408*0fca6ea1SDimitry Andric recoverAsEntryValue(VarID, Value.Properties, Num); 409bdd1243dSDimitry Andric IsValueValid = false; 410bdd1243dSDimitry Andric break; 411bdd1243dSDimitry Andric } 412bdd1243dSDimitry Andric 413bdd1243dSDimitry Andric // Defer modifying ActiveVLocs until after we've confirmed we have a 414bdd1243dSDimitry Andric // live range. 415bdd1243dSDimitry Andric LocIdx M = ValuesPreferredLoc->second.getLoc(); 416bdd1243dSDimitry Andric ResolvedDbgOps.push_back(M); 417bdd1243dSDimitry Andric } 418bdd1243dSDimitry Andric 419bdd1243dSDimitry Andric // If we cannot produce a valid value for the LiveIn value within this 420bdd1243dSDimitry Andric // block, skip this variable. 421bdd1243dSDimitry Andric if (!IsValueValid) 422bdd1243dSDimitry Andric return; 423bdd1243dSDimitry Andric 424bdd1243dSDimitry Andric // Add UseBeforeDef entry for the last value to be defined in this block. 425bdd1243dSDimitry Andric if (LastUseBeforeDef) { 426*0fca6ea1SDimitry Andric addUseBeforeDef(VarID, Value.Properties, DbgOps, LastUseBeforeDef); 427bdd1243dSDimitry Andric return; 428bdd1243dSDimitry Andric } 429bdd1243dSDimitry Andric 430bdd1243dSDimitry Andric // The LiveIn value is available at block entry, begin tracking and record 431bdd1243dSDimitry Andric // the transfer. 432bdd1243dSDimitry Andric for (const ResolvedDbgOp &Op : ResolvedDbgOps) 433bdd1243dSDimitry Andric if (!Op.IsConst) 434*0fca6ea1SDimitry Andric ActiveMLocs[Op.Loc].insert(VarID); 435bdd1243dSDimitry Andric auto NewValue = ResolvedDbgValue{ResolvedDbgOps, Value.Properties}; 436*0fca6ea1SDimitry Andric auto Result = ActiveVLocs.insert(std::make_pair(VarID, NewValue)); 437bdd1243dSDimitry Andric if (!Result.second) 438bdd1243dSDimitry Andric Result.first->second = NewValue; 439*0fca6ea1SDimitry Andric auto &[Var, DILoc] = DVMap.lookupDVID(VarID); 440bdd1243dSDimitry Andric PendingDbgValues.push_back( 441*0fca6ea1SDimitry Andric std::make_pair(VarID, &*MTracker->emitLoc(ResolvedDbgOps, Var, DILoc, 442*0fca6ea1SDimitry Andric Value.Properties))); 443bdd1243dSDimitry Andric } 444bdd1243dSDimitry Andric 445bdd1243dSDimitry Andric /// Load object with live-in variable values. \p mlocs contains the live-in 446bdd1243dSDimitry Andric /// values in each machine location, while \p vlocs the live-in variable 447bdd1243dSDimitry Andric /// values. This method picks variable locations for the live-in variables, 448bdd1243dSDimitry Andric /// creates DBG_VALUEs and puts them in #Transfers, then prepares the other 449bdd1243dSDimitry Andric /// object fields to track variable locations as we step through the block. 450bdd1243dSDimitry Andric /// FIXME: could just examine mloctracker instead of passing in \p mlocs? 451bdd1243dSDimitry Andric void 452bdd1243dSDimitry Andric loadInlocs(MachineBasicBlock &MBB, ValueTable &MLocs, DbgOpIDMap &DbgOpStore, 453*0fca6ea1SDimitry Andric const SmallVectorImpl<std::pair<DebugVariableID, DbgValue>> &VLocs, 454bdd1243dSDimitry Andric unsigned NumLocs) { 455bdd1243dSDimitry Andric ActiveMLocs.clear(); 456bdd1243dSDimitry Andric ActiveVLocs.clear(); 457bdd1243dSDimitry Andric VarLocs.clear(); 458bdd1243dSDimitry Andric VarLocs.reserve(NumLocs); 459bdd1243dSDimitry Andric UseBeforeDefs.clear(); 460bdd1243dSDimitry Andric UseBeforeDefVariables.clear(); 461bdd1243dSDimitry Andric 462*0fca6ea1SDimitry Andric // Mapping of the preferred locations for each value. Collected into this 463*0fca6ea1SDimitry Andric // vector then sorted for easy searching. 464*0fca6ea1SDimitry Andric SmallVector<ValueLocPair, 16> ValueToLoc; 4651fd87a68SDimitry Andric 4661fd87a68SDimitry Andric // Initialized the preferred-location map with illegal locations, to be 4671fd87a68SDimitry Andric // filled in later. 468fcaf7f86SDimitry Andric for (const auto &VLoc : VLocs) 4691fd87a68SDimitry Andric if (VLoc.second.Kind == DbgValue::Def) 470bdd1243dSDimitry Andric for (DbgOpID OpID : VLoc.second.getDbgOpIDs()) 471bdd1243dSDimitry Andric if (!OpID.ID.IsConst) 472*0fca6ea1SDimitry Andric ValueToLoc.push_back( 473*0fca6ea1SDimitry Andric {DbgOpStore.find(OpID).ID, LocationAndQuality()}); 4741fd87a68SDimitry Andric 475*0fca6ea1SDimitry Andric llvm::sort(ValueToLoc, ValueToLocSort); 476349cc55cSDimitry Andric ActiveMLocs.reserve(VLocs.size()); 477349cc55cSDimitry Andric ActiveVLocs.reserve(VLocs.size()); 478e8d8bef9SDimitry Andric 479e8d8bef9SDimitry Andric // Produce a map of value numbers to the current machine locs they live 480e8d8bef9SDimitry Andric // in. When emulating VarLocBasedImpl, there should only be one 481e8d8bef9SDimitry Andric // location; when not, we get to pick. 482e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 483e8d8bef9SDimitry Andric LocIdx Idx = Location.Idx; 484e8d8bef9SDimitry Andric ValueIDNum &VNum = MLocs[Idx.asU64()]; 485bdd1243dSDimitry Andric if (VNum == ValueIDNum::EmptyValue) 486bdd1243dSDimitry Andric continue; 487e8d8bef9SDimitry Andric VarLocs.push_back(VNum); 48804eeddc0SDimitry Andric 4891fd87a68SDimitry Andric // Is there a variable that wants a location for this value? If not, skip. 490*0fca6ea1SDimitry Andric ValueLocPair Probe(VNum, LocationAndQuality()); 491*0fca6ea1SDimitry Andric auto VIt = std::lower_bound(ValueToLoc.begin(), ValueToLoc.end(), Probe, 492*0fca6ea1SDimitry Andric ValueToLocSort); 493*0fca6ea1SDimitry Andric if (VIt == ValueToLoc.end() || VIt->first != VNum) 49404eeddc0SDimitry Andric continue; 49504eeddc0SDimitry Andric 496bdd1243dSDimitry Andric auto &Previous = VIt->second; 497bdd1243dSDimitry Andric // If this is the first location with that value, pick it. Otherwise, 498bdd1243dSDimitry Andric // consider whether it's a "longer term" location. 499bdd1243dSDimitry Andric std::optional<LocationQuality> ReplacementQuality = 500bdd1243dSDimitry Andric getLocQualityIfBetter(Idx, Previous.getQuality()); 501bdd1243dSDimitry Andric if (ReplacementQuality) 502bdd1243dSDimitry Andric Previous = LocationAndQuality(Idx, *ReplacementQuality); 503e8d8bef9SDimitry Andric } 504e8d8bef9SDimitry Andric 505e8d8bef9SDimitry Andric // Now map variables to their picked LocIdxes. 50604eeddc0SDimitry Andric for (const auto &Var : VLocs) { 507bdd1243dSDimitry Andric loadVarInloc(MBB, DbgOpStore, ValueToLoc, Var.first, Var.second); 508e8d8bef9SDimitry Andric } 509e8d8bef9SDimitry Andric flushDbgValues(MBB.begin(), &MBB); 510e8d8bef9SDimitry Andric } 511e8d8bef9SDimitry Andric 512e8d8bef9SDimitry Andric /// Record that \p Var has value \p ID, a value that becomes available 513e8d8bef9SDimitry Andric /// later in the function. 514*0fca6ea1SDimitry Andric void addUseBeforeDef(DebugVariableID VarID, 515bdd1243dSDimitry Andric const DbgValueProperties &Properties, 516bdd1243dSDimitry Andric const SmallVectorImpl<DbgOp> &DbgOps, unsigned Inst) { 517*0fca6ea1SDimitry Andric UseBeforeDefs[Inst].emplace_back(DbgOps, VarID, Properties); 518*0fca6ea1SDimitry Andric UseBeforeDefVariables.insert(VarID); 519e8d8bef9SDimitry Andric } 520e8d8bef9SDimitry Andric 521e8d8bef9SDimitry Andric /// After the instruction at index \p Inst and position \p pos has been 522e8d8bef9SDimitry Andric /// processed, check whether it defines a variable value in a use-before-def. 523e8d8bef9SDimitry Andric /// If so, and the variable value hasn't changed since the start of the 524e8d8bef9SDimitry Andric /// block, create a DBG_VALUE. 525e8d8bef9SDimitry Andric void checkInstForNewValues(unsigned Inst, MachineBasicBlock::iterator pos) { 526e8d8bef9SDimitry Andric auto MIt = UseBeforeDefs.find(Inst); 527e8d8bef9SDimitry Andric if (MIt == UseBeforeDefs.end()) 528e8d8bef9SDimitry Andric return; 529e8d8bef9SDimitry Andric 530bdd1243dSDimitry Andric // Map of values to the locations that store them for every value used by 531bdd1243dSDimitry Andric // the variables that may have become available. 532bdd1243dSDimitry Andric SmallDenseMap<ValueIDNum, LocationAndQuality> ValueToLoc; 533bdd1243dSDimitry Andric 534bdd1243dSDimitry Andric // Populate ValueToLoc with illegal default mappings for every value used by 535bdd1243dSDimitry Andric // any UseBeforeDef variables for this instruction. 536e8d8bef9SDimitry Andric for (auto &Use : MIt->second) { 537*0fca6ea1SDimitry Andric if (!UseBeforeDefVariables.count(Use.VarID)) 538e8d8bef9SDimitry Andric continue; 539e8d8bef9SDimitry Andric 540bdd1243dSDimitry Andric for (DbgOp &Op : Use.Values) { 541bdd1243dSDimitry Andric assert(!Op.isUndef() && "UseBeforeDef erroneously created for a " 542bdd1243dSDimitry Andric "DbgValue with undef values."); 543bdd1243dSDimitry Andric if (Op.IsConst) 544bdd1243dSDimitry Andric continue; 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric ValueToLoc.insert({Op.ID, LocationAndQuality()}); 547bdd1243dSDimitry Andric } 548bdd1243dSDimitry Andric } 549bdd1243dSDimitry Andric 550bdd1243dSDimitry Andric // Exit early if we have no DbgValues to produce. 551bdd1243dSDimitry Andric if (ValueToLoc.empty()) 552bdd1243dSDimitry Andric return; 553bdd1243dSDimitry Andric 554bdd1243dSDimitry Andric // Determine the best location for each desired value. 555bdd1243dSDimitry Andric for (auto Location : MTracker->locations()) { 556bdd1243dSDimitry Andric LocIdx Idx = Location.Idx; 557bdd1243dSDimitry Andric ValueIDNum &LocValueID = Location.Value; 558bdd1243dSDimitry Andric 559bdd1243dSDimitry Andric // Is there a variable that wants a location for this value? If not, skip. 560bdd1243dSDimitry Andric auto VIt = ValueToLoc.find(LocValueID); 561bdd1243dSDimitry Andric if (VIt == ValueToLoc.end()) 562bdd1243dSDimitry Andric continue; 563bdd1243dSDimitry Andric 564bdd1243dSDimitry Andric auto &Previous = VIt->second; 565bdd1243dSDimitry Andric // If this is the first location with that value, pick it. Otherwise, 566bdd1243dSDimitry Andric // consider whether it's a "longer term" location. 567bdd1243dSDimitry Andric std::optional<LocationQuality> ReplacementQuality = 568bdd1243dSDimitry Andric getLocQualityIfBetter(Idx, Previous.getQuality()); 569bdd1243dSDimitry Andric if (ReplacementQuality) 570bdd1243dSDimitry Andric Previous = LocationAndQuality(Idx, *ReplacementQuality); 571bdd1243dSDimitry Andric } 572bdd1243dSDimitry Andric 573bdd1243dSDimitry Andric // Using the map of values to locations, produce a final set of values for 574bdd1243dSDimitry Andric // this variable. 575bdd1243dSDimitry Andric for (auto &Use : MIt->second) { 576*0fca6ea1SDimitry Andric if (!UseBeforeDefVariables.count(Use.VarID)) 577bdd1243dSDimitry Andric continue; 578bdd1243dSDimitry Andric 579bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> DbgOps; 580bdd1243dSDimitry Andric 581bdd1243dSDimitry Andric for (DbgOp &Op : Use.Values) { 582bdd1243dSDimitry Andric if (Op.IsConst) { 583bdd1243dSDimitry Andric DbgOps.push_back(Op.MO); 584bdd1243dSDimitry Andric continue; 585bdd1243dSDimitry Andric } 586bdd1243dSDimitry Andric LocIdx NewLoc = ValueToLoc.find(Op.ID)->second.getLoc(); 587bdd1243dSDimitry Andric if (NewLoc.isIllegal()) 588bdd1243dSDimitry Andric break; 589bdd1243dSDimitry Andric DbgOps.push_back(NewLoc); 590bdd1243dSDimitry Andric } 591bdd1243dSDimitry Andric 592bdd1243dSDimitry Andric // If at least one value used by this debug value is no longer available, 593bdd1243dSDimitry Andric // i.e. one of the values was killed before we finished defining all of 594bdd1243dSDimitry Andric // the values used by this variable, discard. 595bdd1243dSDimitry Andric if (DbgOps.size() != Use.Values.size()) 596bdd1243dSDimitry Andric continue; 597bdd1243dSDimitry Andric 598bdd1243dSDimitry Andric // Otherwise, we're good to go. 599*0fca6ea1SDimitry Andric auto &[Var, DILoc] = DVMap.lookupDVID(Use.VarID); 600*0fca6ea1SDimitry Andric PendingDbgValues.push_back(std::make_pair( 601*0fca6ea1SDimitry Andric Use.VarID, MTracker->emitLoc(DbgOps, Var, DILoc, Use.Properties))); 602e8d8bef9SDimitry Andric } 603e8d8bef9SDimitry Andric flushDbgValues(pos, nullptr); 604e8d8bef9SDimitry Andric } 605e8d8bef9SDimitry Andric 606e8d8bef9SDimitry Andric /// Helper to move created DBG_VALUEs into Transfers collection. 607e8d8bef9SDimitry Andric void flushDbgValues(MachineBasicBlock::iterator Pos, MachineBasicBlock *MBB) { 608fe6060f1SDimitry Andric if (PendingDbgValues.size() == 0) 609fe6060f1SDimitry Andric return; 610fe6060f1SDimitry Andric 611fe6060f1SDimitry Andric // Pick out the instruction start position. 612fe6060f1SDimitry Andric MachineBasicBlock::instr_iterator BundleStart; 613fe6060f1SDimitry Andric if (MBB && Pos == MBB->begin()) 614fe6060f1SDimitry Andric BundleStart = MBB->instr_begin(); 615fe6060f1SDimitry Andric else 616fe6060f1SDimitry Andric BundleStart = getBundleStart(Pos->getIterator()); 617fe6060f1SDimitry Andric 618fe6060f1SDimitry Andric Transfers.push_back({BundleStart, MBB, PendingDbgValues}); 619e8d8bef9SDimitry Andric PendingDbgValues.clear(); 620e8d8bef9SDimitry Andric } 621fe6060f1SDimitry Andric 622fe6060f1SDimitry Andric bool isEntryValueVariable(const DebugVariable &Var, 623fe6060f1SDimitry Andric const DIExpression *Expr) const { 624fe6060f1SDimitry Andric if (!Var.getVariable()->isParameter()) 625fe6060f1SDimitry Andric return false; 626fe6060f1SDimitry Andric 627fe6060f1SDimitry Andric if (Var.getInlinedAt()) 628fe6060f1SDimitry Andric return false; 629fe6060f1SDimitry Andric 63006c3fb27SDimitry Andric if (Expr->getNumElements() > 0 && !Expr->isDeref()) 631fe6060f1SDimitry Andric return false; 632fe6060f1SDimitry Andric 633fe6060f1SDimitry Andric return true; 634fe6060f1SDimitry Andric } 635fe6060f1SDimitry Andric 636fe6060f1SDimitry Andric bool isEntryValueValue(const ValueIDNum &Val) const { 637fe6060f1SDimitry Andric // Must be in entry block (block number zero), and be a PHI / live-in value. 638fe6060f1SDimitry Andric if (Val.getBlock() || !Val.isPHI()) 639fe6060f1SDimitry Andric return false; 640fe6060f1SDimitry Andric 641fe6060f1SDimitry Andric // Entry values must enter in a register. 642fe6060f1SDimitry Andric if (MTracker->isSpill(Val.getLoc())) 643fe6060f1SDimitry Andric return false; 644fe6060f1SDimitry Andric 645fe6060f1SDimitry Andric Register SP = TLI->getStackPointerRegisterToSaveRestore(); 646fe6060f1SDimitry Andric Register FP = TRI.getFrameRegister(MF); 647fe6060f1SDimitry Andric Register Reg = MTracker->LocIdxToLocID[Val.getLoc()]; 648fe6060f1SDimitry Andric return Reg != SP && Reg != FP; 649fe6060f1SDimitry Andric } 650fe6060f1SDimitry Andric 651*0fca6ea1SDimitry Andric bool recoverAsEntryValue(DebugVariableID VarID, 65204eeddc0SDimitry Andric const DbgValueProperties &Prop, 653fe6060f1SDimitry Andric const ValueIDNum &Num) { 654fe6060f1SDimitry Andric // Is this variable location a candidate to be an entry value. First, 655fe6060f1SDimitry Andric // should we be trying this at all? 656fe6060f1SDimitry Andric if (!ShouldEmitDebugEntryValues) 657fe6060f1SDimitry Andric return false; 658fe6060f1SDimitry Andric 659bdd1243dSDimitry Andric const DIExpression *DIExpr = Prop.DIExpr; 660bdd1243dSDimitry Andric 661bdd1243dSDimitry Andric // We don't currently emit entry values for DBG_VALUE_LISTs. 662bdd1243dSDimitry Andric if (Prop.IsVariadic) { 663bdd1243dSDimitry Andric // If this debug value can be converted to be non-variadic, then do so; 664bdd1243dSDimitry Andric // otherwise give up. 665bdd1243dSDimitry Andric auto NonVariadicExpression = 666bdd1243dSDimitry Andric DIExpression::convertToNonVariadicExpression(DIExpr); 667bdd1243dSDimitry Andric if (!NonVariadicExpression) 668bdd1243dSDimitry Andric return false; 669bdd1243dSDimitry Andric DIExpr = *NonVariadicExpression; 670bdd1243dSDimitry Andric } 671bdd1243dSDimitry Andric 672*0fca6ea1SDimitry Andric auto &[Var, DILoc] = DVMap.lookupDVID(VarID); 673*0fca6ea1SDimitry Andric 674fe6060f1SDimitry Andric // Is the variable appropriate for entry values (i.e., is a parameter). 675bdd1243dSDimitry Andric if (!isEntryValueVariable(Var, DIExpr)) 676fe6060f1SDimitry Andric return false; 677fe6060f1SDimitry Andric 678fe6060f1SDimitry Andric // Is the value assigned to this variable still the entry value? 679fe6060f1SDimitry Andric if (!isEntryValueValue(Num)) 680fe6060f1SDimitry Andric return false; 681fe6060f1SDimitry Andric 682fe6060f1SDimitry Andric // Emit a variable location using an entry value expression. 683fe6060f1SDimitry Andric DIExpression *NewExpr = 684bdd1243dSDimitry Andric DIExpression::prepend(DIExpr, DIExpression::EntryValue); 685fe6060f1SDimitry Andric Register Reg = MTracker->LocIdxToLocID[Num.getLoc()]; 686fe6060f1SDimitry Andric MachineOperand MO = MachineOperand::CreateReg(Reg, false); 687*0fca6ea1SDimitry Andric PendingDbgValues.push_back(std::make_pair( 688*0fca6ea1SDimitry Andric VarID, &*emitMOLoc(MO, Var, {NewExpr, Prop.Indirect, false}))); 689fe6060f1SDimitry Andric return true; 690e8d8bef9SDimitry Andric } 691e8d8bef9SDimitry Andric 692e8d8bef9SDimitry Andric /// Change a variable value after encountering a DBG_VALUE inside a block. 693e8d8bef9SDimitry Andric void redefVar(const MachineInstr &MI) { 694e8d8bef9SDimitry Andric DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), 695e8d8bef9SDimitry Andric MI.getDebugLoc()->getInlinedAt()); 696e8d8bef9SDimitry Andric DbgValueProperties Properties(MI); 697*0fca6ea1SDimitry Andric DebugVariableID VarID = DVMap.getDVID(Var); 698e8d8bef9SDimitry Andric 699e8d8bef9SDimitry Andric // Ignore non-register locations, we don't transfer those. 700bdd1243dSDimitry Andric if (MI.isUndefDebugValue() || 701bdd1243dSDimitry Andric all_of(MI.debug_operands(), 702bdd1243dSDimitry Andric [](const MachineOperand &MO) { return !MO.isReg(); })) { 703*0fca6ea1SDimitry Andric auto It = ActiveVLocs.find(VarID); 704e8d8bef9SDimitry Andric if (It != ActiveVLocs.end()) { 705bdd1243dSDimitry Andric for (LocIdx Loc : It->second.loc_indices()) 706*0fca6ea1SDimitry Andric ActiveMLocs[Loc].erase(VarID); 707e8d8bef9SDimitry Andric ActiveVLocs.erase(It); 708e8d8bef9SDimitry Andric } 709e8d8bef9SDimitry Andric // Any use-before-defs no longer apply. 710*0fca6ea1SDimitry Andric UseBeforeDefVariables.erase(VarID); 711e8d8bef9SDimitry Andric return; 712e8d8bef9SDimitry Andric } 713e8d8bef9SDimitry Andric 714bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> NewLocs; 715bdd1243dSDimitry Andric for (const MachineOperand &MO : MI.debug_operands()) { 716bdd1243dSDimitry Andric if (MO.isReg()) { 717bdd1243dSDimitry Andric // Any undef regs have already been filtered out above. 718e8d8bef9SDimitry Andric Register Reg = MO.getReg(); 719e8d8bef9SDimitry Andric LocIdx NewLoc = MTracker->getRegMLoc(Reg); 720bdd1243dSDimitry Andric NewLocs.push_back(NewLoc); 721bdd1243dSDimitry Andric } else { 722bdd1243dSDimitry Andric NewLocs.push_back(MO); 723bdd1243dSDimitry Andric } 724bdd1243dSDimitry Andric } 725bdd1243dSDimitry Andric 726bdd1243dSDimitry Andric redefVar(MI, Properties, NewLocs); 727e8d8bef9SDimitry Andric } 728e8d8bef9SDimitry Andric 729e8d8bef9SDimitry Andric /// Handle a change in variable location within a block. Terminate the 730e8d8bef9SDimitry Andric /// variables current location, and record the value it now refers to, so 731e8d8bef9SDimitry Andric /// that we can detect location transfers later on. 732e8d8bef9SDimitry Andric void redefVar(const MachineInstr &MI, const DbgValueProperties &Properties, 733bdd1243dSDimitry Andric SmallVectorImpl<ResolvedDbgOp> &NewLocs) { 734e8d8bef9SDimitry Andric DebugVariable Var(MI.getDebugVariable(), MI.getDebugExpression(), 735e8d8bef9SDimitry Andric MI.getDebugLoc()->getInlinedAt()); 736*0fca6ea1SDimitry Andric DebugVariableID VarID = DVMap.getDVID(Var); 737e8d8bef9SDimitry Andric // Any use-before-defs no longer apply. 738*0fca6ea1SDimitry Andric UseBeforeDefVariables.erase(VarID); 739e8d8bef9SDimitry Andric 740bdd1243dSDimitry Andric // Erase any previous location. 741*0fca6ea1SDimitry Andric auto It = ActiveVLocs.find(VarID); 742bdd1243dSDimitry Andric if (It != ActiveVLocs.end()) { 743bdd1243dSDimitry Andric for (LocIdx Loc : It->second.loc_indices()) 744*0fca6ea1SDimitry Andric ActiveMLocs[Loc].erase(VarID); 745bdd1243dSDimitry Andric } 746e8d8bef9SDimitry Andric 747e8d8bef9SDimitry Andric // If there _is_ no new location, all we had to do was erase. 748bdd1243dSDimitry Andric if (NewLocs.empty()) { 749bdd1243dSDimitry Andric if (It != ActiveVLocs.end()) 750bdd1243dSDimitry Andric ActiveVLocs.erase(It); 751e8d8bef9SDimitry Andric return; 752bdd1243dSDimitry Andric } 753e8d8bef9SDimitry Andric 754*0fca6ea1SDimitry Andric SmallVector<std::pair<LocIdx, DebugVariableID>> LostMLocs; 755bdd1243dSDimitry Andric for (ResolvedDbgOp &Op : NewLocs) { 756bdd1243dSDimitry Andric if (Op.IsConst) 757bdd1243dSDimitry Andric continue; 758bdd1243dSDimitry Andric 759bdd1243dSDimitry Andric LocIdx NewLoc = Op.Loc; 760bdd1243dSDimitry Andric 761bdd1243dSDimitry Andric // Check whether our local copy of values-by-location in #VarLocs is out 762bdd1243dSDimitry Andric // of date. Wipe old tracking data for the location if it's been clobbered 763bdd1243dSDimitry Andric // in the meantime. 764349cc55cSDimitry Andric if (MTracker->readMLoc(NewLoc) != VarLocs[NewLoc.asU64()]) { 765fcaf7f86SDimitry Andric for (const auto &P : ActiveMLocs[NewLoc]) { 766bdd1243dSDimitry Andric auto LostVLocIt = ActiveVLocs.find(P); 767bdd1243dSDimitry Andric if (LostVLocIt != ActiveVLocs.end()) { 768bdd1243dSDimitry Andric for (LocIdx Loc : LostVLocIt->second.loc_indices()) { 769bdd1243dSDimitry Andric // Every active variable mapping for NewLoc will be cleared, no 770bdd1243dSDimitry Andric // need to track individual variables. 771bdd1243dSDimitry Andric if (Loc == NewLoc) 772bdd1243dSDimitry Andric continue; 773bdd1243dSDimitry Andric LostMLocs.emplace_back(Loc, P); 774bdd1243dSDimitry Andric } 775bdd1243dSDimitry Andric } 776e8d8bef9SDimitry Andric ActiveVLocs.erase(P); 777e8d8bef9SDimitry Andric } 778bdd1243dSDimitry Andric for (const auto &LostMLoc : LostMLocs) 779bdd1243dSDimitry Andric ActiveMLocs[LostMLoc.first].erase(LostMLoc.second); 780bdd1243dSDimitry Andric LostMLocs.clear(); 781*0fca6ea1SDimitry Andric It = ActiveVLocs.find(VarID); 782e8d8bef9SDimitry Andric ActiveMLocs[NewLoc.asU64()].clear(); 783349cc55cSDimitry Andric VarLocs[NewLoc.asU64()] = MTracker->readMLoc(NewLoc); 784e8d8bef9SDimitry Andric } 785e8d8bef9SDimitry Andric 786*0fca6ea1SDimitry Andric ActiveMLocs[NewLoc].insert(VarID); 787bdd1243dSDimitry Andric } 788bdd1243dSDimitry Andric 789e8d8bef9SDimitry Andric if (It == ActiveVLocs.end()) { 790e8d8bef9SDimitry Andric ActiveVLocs.insert( 791*0fca6ea1SDimitry Andric std::make_pair(VarID, ResolvedDbgValue(NewLocs, Properties))); 792e8d8bef9SDimitry Andric } else { 793bdd1243dSDimitry Andric It->second.Ops.assign(NewLocs); 794e8d8bef9SDimitry Andric It->second.Properties = Properties; 795e8d8bef9SDimitry Andric } 796e8d8bef9SDimitry Andric } 797e8d8bef9SDimitry Andric 798fe6060f1SDimitry Andric /// Account for a location \p mloc being clobbered. Examine the variable 799fe6060f1SDimitry Andric /// locations that will be terminated: and try to recover them by using 800fe6060f1SDimitry Andric /// another location. Optionally, given \p MakeUndef, emit a DBG_VALUE to 801fe6060f1SDimitry Andric /// explicitly terminate a location if it can't be recovered. 802fe6060f1SDimitry Andric void clobberMloc(LocIdx MLoc, MachineBasicBlock::iterator Pos, 803fe6060f1SDimitry Andric bool MakeUndef = true) { 804e8d8bef9SDimitry Andric auto ActiveMLocIt = ActiveMLocs.find(MLoc); 805e8d8bef9SDimitry Andric if (ActiveMLocIt == ActiveMLocs.end()) 806e8d8bef9SDimitry Andric return; 807e8d8bef9SDimitry Andric 808fe6060f1SDimitry Andric // What was the old variable value? 809fe6060f1SDimitry Andric ValueIDNum OldValue = VarLocs[MLoc.asU64()]; 810753f127fSDimitry Andric clobberMloc(MLoc, OldValue, Pos, MakeUndef); 811753f127fSDimitry Andric } 812753f127fSDimitry Andric /// Overload that takes an explicit value \p OldValue for when the value in 813753f127fSDimitry Andric /// \p MLoc has changed and the TransferTracker's locations have not been 814753f127fSDimitry Andric /// updated yet. 815753f127fSDimitry Andric void clobberMloc(LocIdx MLoc, ValueIDNum OldValue, 816753f127fSDimitry Andric MachineBasicBlock::iterator Pos, bool MakeUndef = true) { 817753f127fSDimitry Andric auto ActiveMLocIt = ActiveMLocs.find(MLoc); 818753f127fSDimitry Andric if (ActiveMLocIt == ActiveMLocs.end()) 819753f127fSDimitry Andric return; 820753f127fSDimitry Andric 821e8d8bef9SDimitry Andric VarLocs[MLoc.asU64()] = ValueIDNum::EmptyValue; 822e8d8bef9SDimitry Andric 823fe6060f1SDimitry Andric // Examine the remaining variable locations: if we can find the same value 824fe6060f1SDimitry Andric // again, we can recover the location. 825bdd1243dSDimitry Andric std::optional<LocIdx> NewLoc; 826fe6060f1SDimitry Andric for (auto Loc : MTracker->locations()) 827fe6060f1SDimitry Andric if (Loc.Value == OldValue) 828fe6060f1SDimitry Andric NewLoc = Loc.Idx; 829fe6060f1SDimitry Andric 830fe6060f1SDimitry Andric // If there is no location, and we weren't asked to make the variable 831fe6060f1SDimitry Andric // explicitly undef, then stop here. 832fe6060f1SDimitry Andric if (!NewLoc && !MakeUndef) { 833fe6060f1SDimitry Andric // Try and recover a few more locations with entry values. 834*0fca6ea1SDimitry Andric for (DebugVariableID VarID : ActiveMLocIt->second) { 835*0fca6ea1SDimitry Andric auto &Prop = ActiveVLocs.find(VarID)->second.Properties; 836*0fca6ea1SDimitry Andric recoverAsEntryValue(VarID, Prop, OldValue); 837fe6060f1SDimitry Andric } 838fe6060f1SDimitry Andric flushDbgValues(Pos, nullptr); 839fe6060f1SDimitry Andric return; 840fe6060f1SDimitry Andric } 841fe6060f1SDimitry Andric 842fe6060f1SDimitry Andric // Examine all the variables based on this location. 843*0fca6ea1SDimitry Andric DenseSet<DebugVariableID> NewMLocs; 844bdd1243dSDimitry Andric // If no new location has been found, every variable that depends on this 845bdd1243dSDimitry Andric // MLoc is dead, so end their existing MLoc->Var mappings as well. 846*0fca6ea1SDimitry Andric SmallVector<std::pair<LocIdx, DebugVariableID>> LostMLocs; 847*0fca6ea1SDimitry Andric for (DebugVariableID VarID : ActiveMLocIt->second) { 848*0fca6ea1SDimitry Andric auto ActiveVLocIt = ActiveVLocs.find(VarID); 849fe6060f1SDimitry Andric // Re-state the variable location: if there's no replacement then NewLoc 850bdd1243dSDimitry Andric // is std::nullopt and a $noreg DBG_VALUE will be created. Otherwise, a 851bdd1243dSDimitry Andric // DBG_VALUE identifying the alternative location will be emitted. 8524824e7fdSDimitry Andric const DbgValueProperties &Properties = ActiveVLocIt->second.Properties; 853bdd1243dSDimitry Andric 854bdd1243dSDimitry Andric // Produce the new list of debug ops - an empty list if no new location 855bdd1243dSDimitry Andric // was found, or the existing list with the substitution MLoc -> NewLoc 856bdd1243dSDimitry Andric // otherwise. 857bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> DbgOps; 858bdd1243dSDimitry Andric if (NewLoc) { 859bdd1243dSDimitry Andric ResolvedDbgOp OldOp(MLoc); 860bdd1243dSDimitry Andric ResolvedDbgOp NewOp(*NewLoc); 861bdd1243dSDimitry Andric // Insert illegal ops to overwrite afterwards. 862bdd1243dSDimitry Andric DbgOps.insert(DbgOps.begin(), ActiveVLocIt->second.Ops.size(), 863bdd1243dSDimitry Andric ResolvedDbgOp(LocIdx::MakeIllegalLoc())); 864bdd1243dSDimitry Andric replace_copy(ActiveVLocIt->second.Ops, DbgOps.begin(), OldOp, NewOp); 865bdd1243dSDimitry Andric } 866bdd1243dSDimitry Andric 867*0fca6ea1SDimitry Andric auto &[Var, DILoc] = DVMap.lookupDVID(VarID); 868*0fca6ea1SDimitry Andric PendingDbgValues.push_back(std::make_pair( 869*0fca6ea1SDimitry Andric VarID, &*MTracker->emitLoc(DbgOps, Var, DILoc, Properties))); 870fe6060f1SDimitry Andric 871fe6060f1SDimitry Andric // Update machine locations <=> variable locations maps. Defer updating 872bdd1243dSDimitry Andric // ActiveMLocs to avoid invalidating the ActiveMLocIt iterator. 873fe6060f1SDimitry Andric if (!NewLoc) { 874bdd1243dSDimitry Andric for (LocIdx Loc : ActiveVLocIt->second.loc_indices()) { 875bdd1243dSDimitry Andric if (Loc != MLoc) 876*0fca6ea1SDimitry Andric LostMLocs.emplace_back(Loc, VarID); 877bdd1243dSDimitry Andric } 878e8d8bef9SDimitry Andric ActiveVLocs.erase(ActiveVLocIt); 879fe6060f1SDimitry Andric } else { 880bdd1243dSDimitry Andric ActiveVLocIt->second.Ops = DbgOps; 881*0fca6ea1SDimitry Andric NewMLocs.insert(VarID); 882e8d8bef9SDimitry Andric } 883fe6060f1SDimitry Andric } 884fe6060f1SDimitry Andric 885bdd1243dSDimitry Andric // Remove variables from ActiveMLocs if they no longer use any other MLocs 886bdd1243dSDimitry Andric // due to being killed by this clobber. 887bdd1243dSDimitry Andric for (auto &LocVarIt : LostMLocs) { 888bdd1243dSDimitry Andric auto LostMLocIt = ActiveMLocs.find(LocVarIt.first); 889bdd1243dSDimitry Andric assert(LostMLocIt != ActiveMLocs.end() && 890bdd1243dSDimitry Andric "Variable was using this MLoc, but ActiveMLocs[MLoc] has no " 891bdd1243dSDimitry Andric "entries?"); 892bdd1243dSDimitry Andric LostMLocIt->second.erase(LocVarIt.second); 893bdd1243dSDimitry Andric } 894fe6060f1SDimitry Andric 895fe6060f1SDimitry Andric // We lazily track what locations have which values; if we've found a new 896fe6060f1SDimitry Andric // location for the clobbered value, remember it. 897fe6060f1SDimitry Andric if (NewLoc) 898fe6060f1SDimitry Andric VarLocs[NewLoc->asU64()] = OldValue; 899fe6060f1SDimitry Andric 900e8d8bef9SDimitry Andric flushDbgValues(Pos, nullptr); 901e8d8bef9SDimitry Andric 902bdd1243dSDimitry Andric // Commit ActiveMLoc changes. 903e8d8bef9SDimitry Andric ActiveMLocIt->second.clear(); 904bdd1243dSDimitry Andric if (!NewMLocs.empty()) 905*0fca6ea1SDimitry Andric for (DebugVariableID VarID : NewMLocs) 906*0fca6ea1SDimitry Andric ActiveMLocs[*NewLoc].insert(VarID); 907e8d8bef9SDimitry Andric } 908e8d8bef9SDimitry Andric 909e8d8bef9SDimitry Andric /// Transfer variables based on \p Src to be based on \p Dst. This handles 910e8d8bef9SDimitry Andric /// both register copies as well as spills and restores. Creates DBG_VALUEs 911e8d8bef9SDimitry Andric /// describing the movement. 912e8d8bef9SDimitry Andric void transferMlocs(LocIdx Src, LocIdx Dst, MachineBasicBlock::iterator Pos) { 913e8d8bef9SDimitry Andric // Does Src still contain the value num we expect? If not, it's been 914e8d8bef9SDimitry Andric // clobbered in the meantime, and our variable locations are stale. 915349cc55cSDimitry Andric if (VarLocs[Src.asU64()] != MTracker->readMLoc(Src)) 916e8d8bef9SDimitry Andric return; 917e8d8bef9SDimitry Andric 918e8d8bef9SDimitry Andric // assert(ActiveMLocs[Dst].size() == 0); 919e8d8bef9SDimitry Andric //^^^ Legitimate scenario on account of un-clobbered slot being assigned to? 920349cc55cSDimitry Andric 921349cc55cSDimitry Andric // Move set of active variables from one location to another. 922349cc55cSDimitry Andric auto MovingVars = ActiveMLocs[Src]; 923bdd1243dSDimitry Andric ActiveMLocs[Dst].insert(MovingVars.begin(), MovingVars.end()); 924e8d8bef9SDimitry Andric VarLocs[Dst.asU64()] = VarLocs[Src.asU64()]; 925e8d8bef9SDimitry Andric 926e8d8bef9SDimitry Andric // For each variable based on Src; create a location at Dst. 927bdd1243dSDimitry Andric ResolvedDbgOp SrcOp(Src); 928bdd1243dSDimitry Andric ResolvedDbgOp DstOp(Dst); 929*0fca6ea1SDimitry Andric for (DebugVariableID VarID : MovingVars) { 930*0fca6ea1SDimitry Andric auto ActiveVLocIt = ActiveVLocs.find(VarID); 931e8d8bef9SDimitry Andric assert(ActiveVLocIt != ActiveVLocs.end()); 932e8d8bef9SDimitry Andric 933bdd1243dSDimitry Andric // Update all instances of Src in the variable's tracked values to Dst. 934bdd1243dSDimitry Andric std::replace(ActiveVLocIt->second.Ops.begin(), 935bdd1243dSDimitry Andric ActiveVLocIt->second.Ops.end(), SrcOp, DstOp); 936bdd1243dSDimitry Andric 937*0fca6ea1SDimitry Andric auto &[Var, DILoc] = DVMap.lookupDVID(VarID); 938*0fca6ea1SDimitry Andric MachineInstr *MI = MTracker->emitLoc(ActiveVLocIt->second.Ops, Var, DILoc, 939bdd1243dSDimitry Andric ActiveVLocIt->second.Properties); 940*0fca6ea1SDimitry Andric PendingDbgValues.push_back(std::make_pair(VarID, MI)); 941e8d8bef9SDimitry Andric } 942e8d8bef9SDimitry Andric ActiveMLocs[Src].clear(); 943e8d8bef9SDimitry Andric flushDbgValues(Pos, nullptr); 944e8d8bef9SDimitry Andric 945e8d8bef9SDimitry Andric // XXX XXX XXX "pretend to be old LDV" means dropping all tracking data 946e8d8bef9SDimitry Andric // about the old location. 947e8d8bef9SDimitry Andric if (EmulateOldLDV) 948e8d8bef9SDimitry Andric VarLocs[Src.asU64()] = ValueIDNum::EmptyValue; 949e8d8bef9SDimitry Andric } 950e8d8bef9SDimitry Andric 951e8d8bef9SDimitry Andric MachineInstrBuilder emitMOLoc(const MachineOperand &MO, 952e8d8bef9SDimitry Andric const DebugVariable &Var, 953e8d8bef9SDimitry Andric const DbgValueProperties &Properties) { 954e8d8bef9SDimitry Andric DebugLoc DL = DILocation::get(Var.getVariable()->getContext(), 0, 0, 955e8d8bef9SDimitry Andric Var.getVariable()->getScope(), 956e8d8bef9SDimitry Andric const_cast<DILocation *>(Var.getInlinedAt())); 957e8d8bef9SDimitry Andric auto MIB = BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE)); 958e8d8bef9SDimitry Andric MIB.add(MO); 959e8d8bef9SDimitry Andric if (Properties.Indirect) 960e8d8bef9SDimitry Andric MIB.addImm(0); 961e8d8bef9SDimitry Andric else 962e8d8bef9SDimitry Andric MIB.addReg(0); 963e8d8bef9SDimitry Andric MIB.addMetadata(Var.getVariable()); 964e8d8bef9SDimitry Andric MIB.addMetadata(Properties.DIExpr); 965e8d8bef9SDimitry Andric return MIB; 966e8d8bef9SDimitry Andric } 967e8d8bef9SDimitry Andric }; 968e8d8bef9SDimitry Andric 969349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 970349cc55cSDimitry Andric // Implementation 971349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 972e8d8bef9SDimitry Andric 973349cc55cSDimitry Andric ValueIDNum ValueIDNum::EmptyValue = {UINT_MAX, UINT_MAX, UINT_MAX}; 974349cc55cSDimitry Andric ValueIDNum ValueIDNum::TombstoneValue = {UINT_MAX, UINT_MAX, UINT_MAX - 1}; 975e8d8bef9SDimitry Andric 976349cc55cSDimitry Andric #ifndef NDEBUG 977bdd1243dSDimitry Andric void ResolvedDbgOp::dump(const MLocTracker *MTrack) const { 978bdd1243dSDimitry Andric if (IsConst) { 979bdd1243dSDimitry Andric dbgs() << MO; 980349cc55cSDimitry Andric } else { 981bdd1243dSDimitry Andric dbgs() << MTrack->LocIdxToName(Loc); 982bdd1243dSDimitry Andric } 983bdd1243dSDimitry Andric } 984bdd1243dSDimitry Andric void DbgOp::dump(const MLocTracker *MTrack) const { 985bdd1243dSDimitry Andric if (IsConst) { 986bdd1243dSDimitry Andric dbgs() << MO; 987bdd1243dSDimitry Andric } else if (!isUndef()) { 988349cc55cSDimitry Andric dbgs() << MTrack->IDAsString(ID); 989349cc55cSDimitry Andric } 990bdd1243dSDimitry Andric } 991bdd1243dSDimitry Andric void DbgOpID::dump(const MLocTracker *MTrack, const DbgOpIDMap *OpStore) const { 992bdd1243dSDimitry Andric if (!OpStore) { 993bdd1243dSDimitry Andric dbgs() << "ID(" << asU32() << ")"; 994bdd1243dSDimitry Andric } else { 995bdd1243dSDimitry Andric OpStore->find(*this).dump(MTrack); 996bdd1243dSDimitry Andric } 997bdd1243dSDimitry Andric } 998bdd1243dSDimitry Andric void DbgValue::dump(const MLocTracker *MTrack, 999bdd1243dSDimitry Andric const DbgOpIDMap *OpStore) const { 1000bdd1243dSDimitry Andric if (Kind == NoVal) { 1001bdd1243dSDimitry Andric dbgs() << "NoVal(" << BlockNo << ")"; 1002bdd1243dSDimitry Andric } else if (Kind == VPHI || Kind == Def) { 1003bdd1243dSDimitry Andric if (Kind == VPHI) 1004bdd1243dSDimitry Andric dbgs() << "VPHI(" << BlockNo << ","; 1005bdd1243dSDimitry Andric else 1006bdd1243dSDimitry Andric dbgs() << "Def("; 1007bdd1243dSDimitry Andric for (unsigned Idx = 0; Idx < getDbgOpIDs().size(); ++Idx) { 1008bdd1243dSDimitry Andric getDbgOpID(Idx).dump(MTrack, OpStore); 1009bdd1243dSDimitry Andric if (Idx != 0) 1010bdd1243dSDimitry Andric dbgs() << ","; 1011bdd1243dSDimitry Andric } 1012bdd1243dSDimitry Andric dbgs() << ")"; 1013bdd1243dSDimitry Andric } 1014349cc55cSDimitry Andric if (Properties.Indirect) 1015349cc55cSDimitry Andric dbgs() << " indir"; 1016349cc55cSDimitry Andric if (Properties.DIExpr) 1017349cc55cSDimitry Andric dbgs() << " " << *Properties.DIExpr; 1018349cc55cSDimitry Andric } 1019349cc55cSDimitry Andric #endif 1020e8d8bef9SDimitry Andric 1021349cc55cSDimitry Andric MLocTracker::MLocTracker(MachineFunction &MF, const TargetInstrInfo &TII, 1022349cc55cSDimitry Andric const TargetRegisterInfo &TRI, 1023349cc55cSDimitry Andric const TargetLowering &TLI) 1024349cc55cSDimitry Andric : MF(MF), TII(TII), TRI(TRI), TLI(TLI), 1025349cc55cSDimitry Andric LocIdxToIDNum(ValueIDNum::EmptyValue), LocIdxToLocID(0) { 1026349cc55cSDimitry Andric NumRegs = TRI.getNumRegs(); 1027349cc55cSDimitry Andric reset(); 1028349cc55cSDimitry Andric LocIDToLocIdx.resize(NumRegs, LocIdx::MakeIllegalLoc()); 1029349cc55cSDimitry Andric assert(NumRegs < (1u << NUM_LOC_BITS)); // Detect bit packing failure 1030e8d8bef9SDimitry Andric 1031349cc55cSDimitry Andric // Always track SP. This avoids the implicit clobbering caused by regmasks 1032349cc55cSDimitry Andric // from affectings its values. (LiveDebugValues disbelieves calls and 1033349cc55cSDimitry Andric // regmasks that claim to clobber SP). 1034349cc55cSDimitry Andric Register SP = TLI.getStackPointerRegisterToSaveRestore(); 1035349cc55cSDimitry Andric if (SP) { 1036349cc55cSDimitry Andric unsigned ID = getLocID(SP); 1037349cc55cSDimitry Andric (void)lookupOrTrackRegister(ID); 1038e8d8bef9SDimitry Andric 1039349cc55cSDimitry Andric for (MCRegAliasIterator RAI(SP, &TRI, true); RAI.isValid(); ++RAI) 1040349cc55cSDimitry Andric SPAliases.insert(*RAI); 1041349cc55cSDimitry Andric } 1042e8d8bef9SDimitry Andric 1043349cc55cSDimitry Andric // Build some common stack positions -- full registers being spilt to the 1044349cc55cSDimitry Andric // stack. 1045349cc55cSDimitry Andric StackSlotIdxes.insert({{8, 0}, 0}); 1046349cc55cSDimitry Andric StackSlotIdxes.insert({{16, 0}, 1}); 1047349cc55cSDimitry Andric StackSlotIdxes.insert({{32, 0}, 2}); 1048349cc55cSDimitry Andric StackSlotIdxes.insert({{64, 0}, 3}); 1049349cc55cSDimitry Andric StackSlotIdxes.insert({{128, 0}, 4}); 1050349cc55cSDimitry Andric StackSlotIdxes.insert({{256, 0}, 5}); 1051349cc55cSDimitry Andric StackSlotIdxes.insert({{512, 0}, 6}); 1052e8d8bef9SDimitry Andric 1053349cc55cSDimitry Andric // Traverse all the subregister idxes, and ensure there's an index for them. 1054349cc55cSDimitry Andric // Duplicates are no problem: we're interested in their position in the 1055349cc55cSDimitry Andric // stack slot, we don't want to type the slot. 1056349cc55cSDimitry Andric for (unsigned int I = 1; I < TRI.getNumSubRegIndices(); ++I) { 1057349cc55cSDimitry Andric unsigned Size = TRI.getSubRegIdxSize(I); 1058349cc55cSDimitry Andric unsigned Offs = TRI.getSubRegIdxOffset(I); 1059349cc55cSDimitry Andric unsigned Idx = StackSlotIdxes.size(); 1060e8d8bef9SDimitry Andric 1061349cc55cSDimitry Andric // Some subregs have -1, -2 and so forth fed into their fields, to mean 1062349cc55cSDimitry Andric // special backend things. Ignore those. 1063349cc55cSDimitry Andric if (Size > 60000 || Offs > 60000) 1064349cc55cSDimitry Andric continue; 1065e8d8bef9SDimitry Andric 1066349cc55cSDimitry Andric StackSlotIdxes.insert({{Size, Offs}, Idx}); 1067349cc55cSDimitry Andric } 1068e8d8bef9SDimitry Andric 106981ad6265SDimitry Andric // There may also be strange register class sizes (think x86 fp80s). 107081ad6265SDimitry Andric for (const TargetRegisterClass *RC : TRI.regclasses()) { 107181ad6265SDimitry Andric unsigned Size = TRI.getRegSizeInBits(*RC); 107281ad6265SDimitry Andric 107381ad6265SDimitry Andric // We might see special reserved values as sizes, and classes for other 107481ad6265SDimitry Andric // stuff the machine tries to model. If it's more than 512 bits, then it 107581ad6265SDimitry Andric // is very unlikely to be a register than can be spilt. 107681ad6265SDimitry Andric if (Size > 512) 107781ad6265SDimitry Andric continue; 107881ad6265SDimitry Andric 107981ad6265SDimitry Andric unsigned Idx = StackSlotIdxes.size(); 108081ad6265SDimitry Andric StackSlotIdxes.insert({{Size, 0}, Idx}); 108181ad6265SDimitry Andric } 108281ad6265SDimitry Andric 1083349cc55cSDimitry Andric for (auto &Idx : StackSlotIdxes) 1084349cc55cSDimitry Andric StackIdxesToPos[Idx.second] = Idx.first; 1085e8d8bef9SDimitry Andric 1086349cc55cSDimitry Andric NumSlotIdxes = StackSlotIdxes.size(); 1087349cc55cSDimitry Andric } 1088e8d8bef9SDimitry Andric 1089349cc55cSDimitry Andric LocIdx MLocTracker::trackRegister(unsigned ID) { 1090349cc55cSDimitry Andric assert(ID != 0); 1091349cc55cSDimitry Andric LocIdx NewIdx = LocIdx(LocIdxToIDNum.size()); 1092349cc55cSDimitry Andric LocIdxToIDNum.grow(NewIdx); 1093349cc55cSDimitry Andric LocIdxToLocID.grow(NewIdx); 1094e8d8bef9SDimitry Andric 1095349cc55cSDimitry Andric // Default: it's an mphi. 1096349cc55cSDimitry Andric ValueIDNum ValNum = {CurBB, 0, NewIdx}; 1097349cc55cSDimitry Andric // Was this reg ever touched by a regmask? 1098349cc55cSDimitry Andric for (const auto &MaskPair : reverse(Masks)) { 1099349cc55cSDimitry Andric if (MaskPair.first->clobbersPhysReg(ID)) { 1100349cc55cSDimitry Andric // There was an earlier def we skipped. 1101349cc55cSDimitry Andric ValNum = {CurBB, MaskPair.second, NewIdx}; 1102349cc55cSDimitry Andric break; 1103349cc55cSDimitry Andric } 1104349cc55cSDimitry Andric } 1105e8d8bef9SDimitry Andric 1106349cc55cSDimitry Andric LocIdxToIDNum[NewIdx] = ValNum; 1107349cc55cSDimitry Andric LocIdxToLocID[NewIdx] = ID; 1108349cc55cSDimitry Andric return NewIdx; 1109349cc55cSDimitry Andric } 1110e8d8bef9SDimitry Andric 1111349cc55cSDimitry Andric void MLocTracker::writeRegMask(const MachineOperand *MO, unsigned CurBB, 1112349cc55cSDimitry Andric unsigned InstID) { 1113349cc55cSDimitry Andric // Def any register we track have that isn't preserved. The regmask 1114349cc55cSDimitry Andric // terminates the liveness of a register, meaning its value can't be 1115349cc55cSDimitry Andric // relied upon -- we represent this by giving it a new value. 1116349cc55cSDimitry Andric for (auto Location : locations()) { 1117349cc55cSDimitry Andric unsigned ID = LocIdxToLocID[Location.Idx]; 1118349cc55cSDimitry Andric // Don't clobber SP, even if the mask says it's clobbered. 1119349cc55cSDimitry Andric if (ID < NumRegs && !SPAliases.count(ID) && MO->clobbersPhysReg(ID)) 1120349cc55cSDimitry Andric defReg(ID, CurBB, InstID); 1121349cc55cSDimitry Andric } 1122349cc55cSDimitry Andric Masks.push_back(std::make_pair(MO, InstID)); 1123349cc55cSDimitry Andric } 1124e8d8bef9SDimitry Andric 1125bdd1243dSDimitry Andric std::optional<SpillLocationNo> MLocTracker::getOrTrackSpillLoc(SpillLoc L) { 1126349cc55cSDimitry Andric SpillLocationNo SpillID(SpillLocs.idFor(L)); 1127d56accc7SDimitry Andric 1128349cc55cSDimitry Andric if (SpillID.id() == 0) { 1129d56accc7SDimitry Andric // If there is no location, and we have reached the limit of how many stack 1130d56accc7SDimitry Andric // slots to track, then don't track this one. 1131d56accc7SDimitry Andric if (SpillLocs.size() >= StackWorkingSetLimit) 1132bdd1243dSDimitry Andric return std::nullopt; 1133d56accc7SDimitry Andric 1134349cc55cSDimitry Andric // Spill location is untracked: create record for this one, and all 1135349cc55cSDimitry Andric // subregister slots too. 1136349cc55cSDimitry Andric SpillID = SpillLocationNo(SpillLocs.insert(L)); 1137349cc55cSDimitry Andric for (unsigned StackIdx = 0; StackIdx < NumSlotIdxes; ++StackIdx) { 1138349cc55cSDimitry Andric unsigned L = getSpillIDWithIdx(SpillID, StackIdx); 1139349cc55cSDimitry Andric LocIdx Idx = LocIdx(LocIdxToIDNum.size()); // New idx 1140349cc55cSDimitry Andric LocIdxToIDNum.grow(Idx); 1141349cc55cSDimitry Andric LocIdxToLocID.grow(Idx); 1142349cc55cSDimitry Andric LocIDToLocIdx.push_back(Idx); 1143349cc55cSDimitry Andric LocIdxToLocID[Idx] = L; 1144349cc55cSDimitry Andric // Initialize to PHI value; corresponds to the location's live-in value 1145349cc55cSDimitry Andric // during transfer function construction. 1146349cc55cSDimitry Andric LocIdxToIDNum[Idx] = ValueIDNum(CurBB, 0, Idx); 1147349cc55cSDimitry Andric } 1148349cc55cSDimitry Andric } 1149349cc55cSDimitry Andric return SpillID; 1150349cc55cSDimitry Andric } 1151fe6060f1SDimitry Andric 1152349cc55cSDimitry Andric std::string MLocTracker::LocIdxToName(LocIdx Idx) const { 1153349cc55cSDimitry Andric unsigned ID = LocIdxToLocID[Idx]; 1154349cc55cSDimitry Andric if (ID >= NumRegs) { 1155349cc55cSDimitry Andric StackSlotPos Pos = locIDToSpillIdx(ID); 1156349cc55cSDimitry Andric ID -= NumRegs; 1157349cc55cSDimitry Andric unsigned Slot = ID / NumSlotIdxes; 1158349cc55cSDimitry Andric return Twine("slot ") 1159349cc55cSDimitry Andric .concat(Twine(Slot).concat(Twine(" sz ").concat(Twine(Pos.first) 1160349cc55cSDimitry Andric .concat(Twine(" offs ").concat(Twine(Pos.second)))))) 1161349cc55cSDimitry Andric .str(); 1162349cc55cSDimitry Andric } else { 1163349cc55cSDimitry Andric return TRI.getRegAsmName(ID).str(); 1164349cc55cSDimitry Andric } 1165349cc55cSDimitry Andric } 1166fe6060f1SDimitry Andric 1167349cc55cSDimitry Andric std::string MLocTracker::IDAsString(const ValueIDNum &Num) const { 1168349cc55cSDimitry Andric std::string DefName = LocIdxToName(Num.getLoc()); 1169349cc55cSDimitry Andric return Num.asString(DefName); 1170349cc55cSDimitry Andric } 1171fe6060f1SDimitry Andric 1172349cc55cSDimitry Andric #ifndef NDEBUG 1173349cc55cSDimitry Andric LLVM_DUMP_METHOD void MLocTracker::dump() { 1174349cc55cSDimitry Andric for (auto Location : locations()) { 1175349cc55cSDimitry Andric std::string MLocName = LocIdxToName(Location.Value.getLoc()); 1176349cc55cSDimitry Andric std::string DefName = Location.Value.asString(MLocName); 1177349cc55cSDimitry Andric dbgs() << LocIdxToName(Location.Idx) << " --> " << DefName << "\n"; 1178349cc55cSDimitry Andric } 1179349cc55cSDimitry Andric } 1180e8d8bef9SDimitry Andric 1181349cc55cSDimitry Andric LLVM_DUMP_METHOD void MLocTracker::dump_mloc_map() { 1182349cc55cSDimitry Andric for (auto Location : locations()) { 1183349cc55cSDimitry Andric std::string foo = LocIdxToName(Location.Idx); 1184349cc55cSDimitry Andric dbgs() << "Idx " << Location.Idx.asU64() << " " << foo << "\n"; 1185349cc55cSDimitry Andric } 1186349cc55cSDimitry Andric } 1187349cc55cSDimitry Andric #endif 1188e8d8bef9SDimitry Andric 1189bdd1243dSDimitry Andric MachineInstrBuilder 1190bdd1243dSDimitry Andric MLocTracker::emitLoc(const SmallVectorImpl<ResolvedDbgOp> &DbgOps, 1191*0fca6ea1SDimitry Andric const DebugVariable &Var, const DILocation *DILoc, 1192349cc55cSDimitry Andric const DbgValueProperties &Properties) { 1193*0fca6ea1SDimitry Andric DebugLoc DL = DebugLoc(DILoc); 1194bdd1243dSDimitry Andric 1195bdd1243dSDimitry Andric const MCInstrDesc &Desc = Properties.IsVariadic 1196bdd1243dSDimitry Andric ? TII.get(TargetOpcode::DBG_VALUE_LIST) 1197bdd1243dSDimitry Andric : TII.get(TargetOpcode::DBG_VALUE); 1198bdd1243dSDimitry Andric 1199bdd1243dSDimitry Andric #ifdef EXPENSIVE_CHECKS 1200bdd1243dSDimitry Andric assert(all_of(DbgOps, 1201bdd1243dSDimitry Andric [](const ResolvedDbgOp &Op) { 1202bdd1243dSDimitry Andric return Op.IsConst || !Op.Loc.isIllegal(); 1203bdd1243dSDimitry Andric }) && 1204bdd1243dSDimitry Andric "Did not expect illegal ops in DbgOps."); 1205bdd1243dSDimitry Andric assert((DbgOps.size() == 0 || 1206bdd1243dSDimitry Andric DbgOps.size() == Properties.getLocationOpCount()) && 1207bdd1243dSDimitry Andric "Expected to have either one DbgOp per MI LocationOp, or none."); 1208bdd1243dSDimitry Andric #endif 1209bdd1243dSDimitry Andric 1210bdd1243dSDimitry Andric auto GetRegOp = [](unsigned Reg) -> MachineOperand { 1211bdd1243dSDimitry Andric return MachineOperand::CreateReg( 1212bdd1243dSDimitry Andric /* Reg */ Reg, /* isDef */ false, /* isImp */ false, 1213bdd1243dSDimitry Andric /* isKill */ false, /* isDead */ false, 1214bdd1243dSDimitry Andric /* isUndef */ false, /* isEarlyClobber */ false, 1215bdd1243dSDimitry Andric /* SubReg */ 0, /* isDebug */ true); 1216bdd1243dSDimitry Andric }; 1217bdd1243dSDimitry Andric 1218bdd1243dSDimitry Andric SmallVector<MachineOperand> MOs; 1219bdd1243dSDimitry Andric 1220bdd1243dSDimitry Andric auto EmitUndef = [&]() { 1221bdd1243dSDimitry Andric MOs.clear(); 1222bdd1243dSDimitry Andric MOs.assign(Properties.getLocationOpCount(), GetRegOp(0)); 1223bdd1243dSDimitry Andric return BuildMI(MF, DL, Desc, false, MOs, Var.getVariable(), 1224bdd1243dSDimitry Andric Properties.DIExpr); 1225bdd1243dSDimitry Andric }; 1226bdd1243dSDimitry Andric 1227bdd1243dSDimitry Andric // Don't bother passing any real operands to BuildMI if any of them would be 1228bdd1243dSDimitry Andric // $noreg. 1229bdd1243dSDimitry Andric if (DbgOps.empty()) 1230bdd1243dSDimitry Andric return EmitUndef(); 1231bdd1243dSDimitry Andric 1232bdd1243dSDimitry Andric bool Indirect = Properties.Indirect; 1233e8d8bef9SDimitry Andric 1234349cc55cSDimitry Andric const DIExpression *Expr = Properties.DIExpr; 1235bdd1243dSDimitry Andric 1236bdd1243dSDimitry Andric assert(DbgOps.size() == Properties.getLocationOpCount()); 1237bdd1243dSDimitry Andric 1238bdd1243dSDimitry Andric // If all locations are valid, accumulate them into our list of 1239bdd1243dSDimitry Andric // MachineOperands. For any spilled locations, either update the indirectness 1240bdd1243dSDimitry Andric // register or apply the appropriate transformations in the DIExpression. 1241bdd1243dSDimitry Andric for (size_t Idx = 0; Idx < Properties.getLocationOpCount(); ++Idx) { 1242bdd1243dSDimitry Andric const ResolvedDbgOp &Op = DbgOps[Idx]; 1243bdd1243dSDimitry Andric 1244bdd1243dSDimitry Andric if (Op.IsConst) { 1245bdd1243dSDimitry Andric MOs.push_back(Op.MO); 1246bdd1243dSDimitry Andric continue; 1247bdd1243dSDimitry Andric } 1248bdd1243dSDimitry Andric 1249bdd1243dSDimitry Andric LocIdx MLoc = Op.Loc; 1250bdd1243dSDimitry Andric unsigned LocID = LocIdxToLocID[MLoc]; 1251bdd1243dSDimitry Andric if (LocID >= NumRegs) { 1252349cc55cSDimitry Andric SpillLocationNo SpillID = locIDToSpill(LocID); 1253349cc55cSDimitry Andric StackSlotPos StackIdx = locIDToSpillIdx(LocID); 1254349cc55cSDimitry Andric unsigned short Offset = StackIdx.second; 1255e8d8bef9SDimitry Andric 1256349cc55cSDimitry Andric // TODO: support variables that are located in spill slots, with non-zero 1257349cc55cSDimitry Andric // offsets from the start of the spill slot. It would require some more 1258349cc55cSDimitry Andric // complex DIExpression calculations. This doesn't seem to be produced by 1259349cc55cSDimitry Andric // LLVM right now, so don't try and support it. 1260349cc55cSDimitry Andric // Accept no-subregister slots and subregisters where the offset is zero. 1261349cc55cSDimitry Andric // The consumer should already have type information to work out how large 1262349cc55cSDimitry Andric // the variable is. 1263349cc55cSDimitry Andric if (Offset == 0) { 1264349cc55cSDimitry Andric const SpillLoc &Spill = SpillLocs[SpillID.id()]; 1265349cc55cSDimitry Andric unsigned Base = Spill.SpillBase; 12664824e7fdSDimitry Andric 126781ad6265SDimitry Andric // There are several ways we can dereference things, and several inputs 126881ad6265SDimitry Andric // to consider: 126981ad6265SDimitry Andric // * NRVO variables will appear with IsIndirect set, but should have 127081ad6265SDimitry Andric // nothing else in their DIExpressions, 127181ad6265SDimitry Andric // * Variables with DW_OP_stack_value in their expr already need an 127281ad6265SDimitry Andric // explicit dereference of the stack location, 127381ad6265SDimitry Andric // * Values that don't match the variable size need DW_OP_deref_size, 127481ad6265SDimitry Andric // * Everything else can just become a simple location expression. 127581ad6265SDimitry Andric 127681ad6265SDimitry Andric // We need to use deref_size whenever there's a mismatch between the 127781ad6265SDimitry Andric // size of value and the size of variable portion being read. 127881ad6265SDimitry Andric // Additionally, we should use it whenever dealing with stack_value 127981ad6265SDimitry Andric // fragments, to avoid the consumer having to determine the deref size 128081ad6265SDimitry Andric // from DW_OP_piece. 128181ad6265SDimitry Andric bool UseDerefSize = false; 1282bdd1243dSDimitry Andric unsigned ValueSizeInBits = getLocSizeInBits(MLoc); 128381ad6265SDimitry Andric unsigned DerefSizeInBytes = ValueSizeInBits / 8; 128481ad6265SDimitry Andric if (auto Fragment = Var.getFragment()) { 128581ad6265SDimitry Andric unsigned VariableSizeInBits = Fragment->SizeInBits; 128681ad6265SDimitry Andric if (VariableSizeInBits != ValueSizeInBits || Expr->isComplex()) 128781ad6265SDimitry Andric UseDerefSize = true; 128881ad6265SDimitry Andric } else if (auto Size = Var.getVariable()->getSizeInBits()) { 128981ad6265SDimitry Andric if (*Size != ValueSizeInBits) { 129081ad6265SDimitry Andric UseDerefSize = true; 129181ad6265SDimitry Andric } 129281ad6265SDimitry Andric } 129381ad6265SDimitry Andric 1294bdd1243dSDimitry Andric SmallVector<uint64_t, 5> OffsetOps; 1295bdd1243dSDimitry Andric TRI.getOffsetOpcodes(Spill.SpillOffset, OffsetOps); 1296bdd1243dSDimitry Andric bool StackValue = false; 1297bdd1243dSDimitry Andric 12984824e7fdSDimitry Andric if (Properties.Indirect) { 129981ad6265SDimitry Andric // This is something like an NRVO variable, where the pointer has been 1300bdd1243dSDimitry Andric // spilt to the stack. It should end up being a memory location, with 1301bdd1243dSDimitry Andric // the pointer to the variable loaded off the stack with a deref: 130281ad6265SDimitry Andric assert(!Expr->isImplicit()); 1303bdd1243dSDimitry Andric OffsetOps.push_back(dwarf::DW_OP_deref); 1304bdd1243dSDimitry Andric } else if (UseDerefSize && Expr->isSingleLocationExpression()) { 1305bdd1243dSDimitry Andric // TODO: Figure out how to handle deref size issues for variadic 1306bdd1243dSDimitry Andric // values. 130781ad6265SDimitry Andric // We're loading a value off the stack that's not the same size as the 1308bdd1243dSDimitry Andric // variable. Add / subtract stack offset, explicitly deref with a 1309bdd1243dSDimitry Andric // size, and add DW_OP_stack_value if not already present. 1310bdd1243dSDimitry Andric OffsetOps.push_back(dwarf::DW_OP_deref_size); 1311bdd1243dSDimitry Andric OffsetOps.push_back(DerefSizeInBytes); 1312bdd1243dSDimitry Andric StackValue = true; 1313bdd1243dSDimitry Andric } else if (Expr->isComplex() || Properties.IsVariadic) { 131481ad6265SDimitry Andric // A variable with no size ambiguity, but with extra elements in it's 131581ad6265SDimitry Andric // expression. Manually dereference the stack location. 1316bdd1243dSDimitry Andric OffsetOps.push_back(dwarf::DW_OP_deref); 131781ad6265SDimitry Andric } else { 131881ad6265SDimitry Andric // A plain value that has been spilt to the stack, with no further 131981ad6265SDimitry Andric // context. Request a location expression, marking the DBG_VALUE as 132081ad6265SDimitry Andric // IsIndirect. 1321bdd1243dSDimitry Andric Indirect = true; 13224824e7fdSDimitry Andric } 1323bdd1243dSDimitry Andric 1324bdd1243dSDimitry Andric Expr = DIExpression::appendOpsToArg(Expr, OffsetOps, Idx, StackValue); 1325bdd1243dSDimitry Andric MOs.push_back(GetRegOp(Base)); 1326349cc55cSDimitry Andric } else { 1327bdd1243dSDimitry Andric // This is a stack location with a weird subregister offset: emit an 1328bdd1243dSDimitry Andric // undef DBG_VALUE instead. 1329bdd1243dSDimitry Andric return EmitUndef(); 1330349cc55cSDimitry Andric } 1331349cc55cSDimitry Andric } else { 1332349cc55cSDimitry Andric // Non-empty, non-stack slot, must be a plain register. 1333bdd1243dSDimitry Andric MOs.push_back(GetRegOp(LocID)); 1334bdd1243dSDimitry Andric } 1335349cc55cSDimitry Andric } 1336e8d8bef9SDimitry Andric 1337bdd1243dSDimitry Andric return BuildMI(MF, DL, Desc, Indirect, MOs, Var.getVariable(), Expr); 1338349cc55cSDimitry Andric } 1339e8d8bef9SDimitry Andric 1340e8d8bef9SDimitry Andric /// Default construct and initialize the pass. 134181ad6265SDimitry Andric InstrRefBasedLDV::InstrRefBasedLDV() = default; 1342e8d8bef9SDimitry Andric 1343349cc55cSDimitry Andric bool InstrRefBasedLDV::isCalleeSaved(LocIdx L) const { 1344e8d8bef9SDimitry Andric unsigned Reg = MTracker->LocIdxToLocID[L]; 1345bdd1243dSDimitry Andric return isCalleeSavedReg(Reg); 1346bdd1243dSDimitry Andric } 1347bdd1243dSDimitry Andric bool InstrRefBasedLDV::isCalleeSavedReg(Register R) const { 1348bdd1243dSDimitry Andric for (MCRegAliasIterator RAI(R, TRI, true); RAI.isValid(); ++RAI) 1349e8d8bef9SDimitry Andric if (CalleeSavedRegs.test(*RAI)) 1350e8d8bef9SDimitry Andric return true; 1351e8d8bef9SDimitry Andric return false; 1352e8d8bef9SDimitry Andric } 1353e8d8bef9SDimitry Andric 1354e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1355e8d8bef9SDimitry Andric // Debug Range Extension Implementation 1356e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1357e8d8bef9SDimitry Andric 1358e8d8bef9SDimitry Andric #ifndef NDEBUG 1359e8d8bef9SDimitry Andric // Something to restore in the future. 1360e8d8bef9SDimitry Andric // void InstrRefBasedLDV::printVarLocInMBB(..) 1361e8d8bef9SDimitry Andric #endif 1362e8d8bef9SDimitry Andric 1363bdd1243dSDimitry Andric std::optional<SpillLocationNo> 1364e8d8bef9SDimitry Andric InstrRefBasedLDV::extractSpillBaseRegAndOffset(const MachineInstr &MI) { 1365e8d8bef9SDimitry Andric assert(MI.hasOneMemOperand() && 1366e8d8bef9SDimitry Andric "Spill instruction does not have exactly one memory operand?"); 1367e8d8bef9SDimitry Andric auto MMOI = MI.memoperands_begin(); 1368e8d8bef9SDimitry Andric const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue(); 1369e8d8bef9SDimitry Andric assert(PVal->kind() == PseudoSourceValue::FixedStack && 1370e8d8bef9SDimitry Andric "Inconsistent memory operand in spill instruction"); 1371e8d8bef9SDimitry Andric int FI = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex(); 1372e8d8bef9SDimitry Andric const MachineBasicBlock *MBB = MI.getParent(); 1373e8d8bef9SDimitry Andric Register Reg; 1374e8d8bef9SDimitry Andric StackOffset Offset = TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg); 1375349cc55cSDimitry Andric return MTracker->getOrTrackSpillLoc({Reg, Offset}); 1376349cc55cSDimitry Andric } 1377349cc55cSDimitry Andric 1378bdd1243dSDimitry Andric std::optional<LocIdx> 1379d56accc7SDimitry Andric InstrRefBasedLDV::findLocationForMemOperand(const MachineInstr &MI) { 1380bdd1243dSDimitry Andric std::optional<SpillLocationNo> SpillLoc = extractSpillBaseRegAndOffset(MI); 1381d56accc7SDimitry Andric if (!SpillLoc) 1382bdd1243dSDimitry Andric return std::nullopt; 1383349cc55cSDimitry Andric 1384349cc55cSDimitry Andric // Where in the stack slot is this value defined -- i.e., what size of value 1385349cc55cSDimitry Andric // is this? An important question, because it could be loaded into a register 1386349cc55cSDimitry Andric // from the stack at some point. Happily the memory operand will tell us 1387349cc55cSDimitry Andric // the size written to the stack. 1388349cc55cSDimitry Andric auto *MemOperand = *MI.memoperands_begin(); 1389*0fca6ea1SDimitry Andric LocationSize SizeInBits = MemOperand->getSizeInBits(); 1390*0fca6ea1SDimitry Andric assert(SizeInBits.hasValue() && "Expected to find a valid size!"); 1391349cc55cSDimitry Andric 1392349cc55cSDimitry Andric // Find that position in the stack indexes we're tracking. 1393*0fca6ea1SDimitry Andric auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.getValue(), 0}); 1394349cc55cSDimitry Andric if (IdxIt == MTracker->StackSlotIdxes.end()) 1395349cc55cSDimitry Andric // That index is not tracked. This is suprising, and unlikely to ever 1396349cc55cSDimitry Andric // occur, but the safe action is to indicate the variable is optimised out. 1397bdd1243dSDimitry Andric return std::nullopt; 1398349cc55cSDimitry Andric 1399d56accc7SDimitry Andric unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillLoc, IdxIt->second); 1400349cc55cSDimitry Andric return MTracker->getSpillMLoc(SpillID); 1401e8d8bef9SDimitry Andric } 1402e8d8bef9SDimitry Andric 1403e8d8bef9SDimitry Andric /// End all previous ranges related to @MI and start a new range from @MI 1404e8d8bef9SDimitry Andric /// if it is a DBG_VALUE instr. 1405e8d8bef9SDimitry Andric bool InstrRefBasedLDV::transferDebugValue(const MachineInstr &MI) { 1406e8d8bef9SDimitry Andric if (!MI.isDebugValue()) 1407e8d8bef9SDimitry Andric return false; 1408e8d8bef9SDimitry Andric 1409cb14a3feSDimitry Andric assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) && 1410e8d8bef9SDimitry Andric "Expected inlined-at fields to agree"); 1411e8d8bef9SDimitry Andric 1412e8d8bef9SDimitry Andric // If there are no instructions in this lexical scope, do no location tracking 1413e8d8bef9SDimitry Andric // at all, this variable shouldn't get a legitimate location range. 1414e8d8bef9SDimitry Andric auto *Scope = LS.findLexicalScope(MI.getDebugLoc().get()); 1415e8d8bef9SDimitry Andric if (Scope == nullptr) 1416e8d8bef9SDimitry Andric return true; // handled it; by doing nothing 1417e8d8bef9SDimitry Andric 1418e8d8bef9SDimitry Andric // MLocTracker needs to know that this register is read, even if it's only 1419e8d8bef9SDimitry Andric // read by a debug inst. 1420bdd1243dSDimitry Andric for (const MachineOperand &MO : MI.debug_operands()) 1421e8d8bef9SDimitry Andric if (MO.isReg() && MO.getReg() != 0) 1422e8d8bef9SDimitry Andric (void)MTracker->readReg(MO.getReg()); 1423e8d8bef9SDimitry Andric 1424e8d8bef9SDimitry Andric // If we're preparing for the second analysis (variables), the machine value 1425e8d8bef9SDimitry Andric // locations are already solved, and we report this DBG_VALUE and the value 1426e8d8bef9SDimitry Andric // it refers to to VLocTracker. 1427e8d8bef9SDimitry Andric if (VTracker) { 1428bdd1243dSDimitry Andric SmallVector<DbgOpID> DebugOps; 1429bdd1243dSDimitry Andric // Feed defVar the new variable location, or if this is a DBG_VALUE $noreg, 1430bdd1243dSDimitry Andric // feed defVar None. 1431bdd1243dSDimitry Andric if (!MI.isUndefDebugValue()) { 1432bdd1243dSDimitry Andric for (const MachineOperand &MO : MI.debug_operands()) { 1433bdd1243dSDimitry Andric // There should be no undef registers here, as we've screened for undef 1434bdd1243dSDimitry Andric // debug values. 1435e8d8bef9SDimitry Andric if (MO.isReg()) { 1436bdd1243dSDimitry Andric DebugOps.push_back(DbgOpStore.insert(MTracker->readReg(MO.getReg()))); 1437bdd1243dSDimitry Andric } else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) { 1438bdd1243dSDimitry Andric DebugOps.push_back(DbgOpStore.insert(MO)); 1439bdd1243dSDimitry Andric } else { 1440bdd1243dSDimitry Andric llvm_unreachable("Unexpected debug operand type."); 1441e8d8bef9SDimitry Andric } 1442e8d8bef9SDimitry Andric } 1443bdd1243dSDimitry Andric } 1444cb14a3feSDimitry Andric VTracker->defVar(MI, DbgValueProperties(MI), DebugOps); 1445bdd1243dSDimitry Andric } 1446e8d8bef9SDimitry Andric 1447e8d8bef9SDimitry Andric // If performing final tracking of transfers, report this variable definition 1448e8d8bef9SDimitry Andric // to the TransferTracker too. 1449e8d8bef9SDimitry Andric if (TTracker) 1450e8d8bef9SDimitry Andric TTracker->redefVar(MI); 1451e8d8bef9SDimitry Andric return true; 1452e8d8bef9SDimitry Andric } 1453e8d8bef9SDimitry Andric 1454bdd1243dSDimitry Andric std::optional<ValueIDNum> InstrRefBasedLDV::getValueForInstrRef( 1455bdd1243dSDimitry Andric unsigned InstNo, unsigned OpNo, MachineInstr &MI, 14565f757f3fSDimitry Andric const FuncValueTable *MLiveOuts, const FuncValueTable *MLiveIns) { 1457e8d8bef9SDimitry Andric // Various optimizations may have happened to the value during codegen, 1458e8d8bef9SDimitry Andric // recorded in the value substitution table. Apply any substitutions to 1459fe6060f1SDimitry Andric // the instruction / operand number in this DBG_INSTR_REF, and collect 1460fe6060f1SDimitry Andric // any subregister extractions performed during optimization. 1461bdd1243dSDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 1462fe6060f1SDimitry Andric 1463fe6060f1SDimitry Andric // Create dummy substitution with Src set, for lookup. 1464fe6060f1SDimitry Andric auto SoughtSub = 1465fe6060f1SDimitry Andric MachineFunction::DebugSubstitution({InstNo, OpNo}, {0, 0}, 0); 1466fe6060f1SDimitry Andric 1467fe6060f1SDimitry Andric SmallVector<unsigned, 4> SeenSubregs; 1468fe6060f1SDimitry Andric auto LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub); 1469fe6060f1SDimitry Andric while (LowerBoundIt != MF.DebugValueSubstitutions.end() && 1470fe6060f1SDimitry Andric LowerBoundIt->Src == SoughtSub.Src) { 1471fe6060f1SDimitry Andric std::tie(InstNo, OpNo) = LowerBoundIt->Dest; 1472fe6060f1SDimitry Andric SoughtSub.Src = LowerBoundIt->Dest; 1473fe6060f1SDimitry Andric if (unsigned Subreg = LowerBoundIt->Subreg) 1474fe6060f1SDimitry Andric SeenSubregs.push_back(Subreg); 1475fe6060f1SDimitry Andric LowerBoundIt = llvm::lower_bound(MF.DebugValueSubstitutions, SoughtSub); 1476e8d8bef9SDimitry Andric } 1477e8d8bef9SDimitry Andric 1478e8d8bef9SDimitry Andric // Default machine value number is <None> -- if no instruction defines 1479e8d8bef9SDimitry Andric // the corresponding value, it must have been optimized out. 1480bdd1243dSDimitry Andric std::optional<ValueIDNum> NewID; 1481e8d8bef9SDimitry Andric 1482e8d8bef9SDimitry Andric // Try to lookup the instruction number, and find the machine value number 1483fe6060f1SDimitry Andric // that it defines. It could be an instruction, or a PHI. 1484e8d8bef9SDimitry Andric auto InstrIt = DebugInstrNumToInstr.find(InstNo); 1485bdd1243dSDimitry Andric auto PHIIt = llvm::lower_bound(DebugPHINumToValue, InstNo); 1486e8d8bef9SDimitry Andric if (InstrIt != DebugInstrNumToInstr.end()) { 1487e8d8bef9SDimitry Andric const MachineInstr &TargetInstr = *InstrIt->second.first; 1488e8d8bef9SDimitry Andric uint64_t BlockNo = TargetInstr.getParent()->getNumber(); 1489e8d8bef9SDimitry Andric 1490349cc55cSDimitry Andric // Pick out the designated operand. It might be a memory reference, if 1491349cc55cSDimitry Andric // a register def was folded into a stack store. 1492349cc55cSDimitry Andric if (OpNo == MachineFunction::DebugOperandMemNumber && 1493349cc55cSDimitry Andric TargetInstr.hasOneMemOperand()) { 1494bdd1243dSDimitry Andric std::optional<LocIdx> L = findLocationForMemOperand(TargetInstr); 1495349cc55cSDimitry Andric if (L) 1496349cc55cSDimitry Andric NewID = ValueIDNum(BlockNo, InstrIt->second.second, *L); 1497349cc55cSDimitry Andric } else if (OpNo != MachineFunction::DebugOperandMemNumber) { 149881ad6265SDimitry Andric // Permit the debug-info to be completely wrong: identifying a nonexistant 149981ad6265SDimitry Andric // operand, or one that is not a register definition, means something 150081ad6265SDimitry Andric // unexpected happened during optimisation. Broken debug-info, however, 150181ad6265SDimitry Andric // shouldn't crash the compiler -- instead leave the variable value as 150281ad6265SDimitry Andric // None, which will make it appear "optimised out". 150381ad6265SDimitry Andric if (OpNo < TargetInstr.getNumOperands()) { 1504e8d8bef9SDimitry Andric const MachineOperand &MO = TargetInstr.getOperand(OpNo); 1505e8d8bef9SDimitry Andric 150681ad6265SDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg()) { 1507349cc55cSDimitry Andric unsigned LocID = MTracker->getLocID(MO.getReg()); 1508e8d8bef9SDimitry Andric LocIdx L = MTracker->LocIDToLocIdx[LocID]; 1509e8d8bef9SDimitry Andric NewID = ValueIDNum(BlockNo, InstrIt->second.second, L); 1510349cc55cSDimitry Andric } 151181ad6265SDimitry Andric } 151281ad6265SDimitry Andric 151381ad6265SDimitry Andric if (!NewID) { 151481ad6265SDimitry Andric LLVM_DEBUG( 151581ad6265SDimitry Andric { dbgs() << "Seen instruction reference to illegal operand\n"; }); 151681ad6265SDimitry Andric } 151781ad6265SDimitry Andric } 1518349cc55cSDimitry Andric // else: NewID is left as None. 1519fe6060f1SDimitry Andric } else if (PHIIt != DebugPHINumToValue.end() && PHIIt->InstrNum == InstNo) { 1520fe6060f1SDimitry Andric // It's actually a PHI value. Which value it is might not be obvious, use 1521fe6060f1SDimitry Andric // the resolver helper to find out. 15225f757f3fSDimitry Andric assert(MLiveOuts && MLiveIns); 15235f757f3fSDimitry Andric NewID = resolveDbgPHIs(*MI.getParent()->getParent(), *MLiveOuts, *MLiveIns, 1524fe6060f1SDimitry Andric MI, InstNo); 1525fe6060f1SDimitry Andric } 1526fe6060f1SDimitry Andric 1527fe6060f1SDimitry Andric // Apply any subregister extractions, in reverse. We might have seen code 1528fe6060f1SDimitry Andric // like this: 1529fe6060f1SDimitry Andric // CALL64 @foo, implicit-def $rax 1530fe6060f1SDimitry Andric // %0:gr64 = COPY $rax 1531fe6060f1SDimitry Andric // %1:gr32 = COPY %0.sub_32bit 1532fe6060f1SDimitry Andric // %2:gr16 = COPY %1.sub_16bit 1533fe6060f1SDimitry Andric // %3:gr8 = COPY %2.sub_8bit 1534fe6060f1SDimitry Andric // In which case each copy would have been recorded as a substitution with 1535fe6060f1SDimitry Andric // a subregister qualifier. Apply those qualifiers now. 1536fe6060f1SDimitry Andric if (NewID && !SeenSubregs.empty()) { 1537fe6060f1SDimitry Andric unsigned Offset = 0; 1538fe6060f1SDimitry Andric unsigned Size = 0; 1539fe6060f1SDimitry Andric 1540fe6060f1SDimitry Andric // Look at each subregister that we passed through, and progressively 1541fe6060f1SDimitry Andric // narrow in, accumulating any offsets that occur. Substitutions should 1542fe6060f1SDimitry Andric // only ever be the same or narrower width than what they read from; 1543fe6060f1SDimitry Andric // iterate in reverse order so that we go from wide to small. 1544fe6060f1SDimitry Andric for (unsigned Subreg : reverse(SeenSubregs)) { 1545fe6060f1SDimitry Andric unsigned ThisSize = TRI->getSubRegIdxSize(Subreg); 1546fe6060f1SDimitry Andric unsigned ThisOffset = TRI->getSubRegIdxOffset(Subreg); 1547fe6060f1SDimitry Andric Offset += ThisOffset; 1548fe6060f1SDimitry Andric Size = (Size == 0) ? ThisSize : std::min(Size, ThisSize); 1549fe6060f1SDimitry Andric } 1550fe6060f1SDimitry Andric 1551fe6060f1SDimitry Andric // If that worked, look for an appropriate subregister with the register 1552fe6060f1SDimitry Andric // where the define happens. Don't look at values that were defined during 1553fe6060f1SDimitry Andric // a stack write: we can't currently express register locations within 1554fe6060f1SDimitry Andric // spills. 1555fe6060f1SDimitry Andric LocIdx L = NewID->getLoc(); 1556fe6060f1SDimitry Andric if (NewID && !MTracker->isSpill(L)) { 1557fe6060f1SDimitry Andric // Find the register class for the register where this def happened. 1558fe6060f1SDimitry Andric // FIXME: no index for this? 1559fe6060f1SDimitry Andric Register Reg = MTracker->LocIdxToLocID[L]; 1560fe6060f1SDimitry Andric const TargetRegisterClass *TRC = nullptr; 1561fcaf7f86SDimitry Andric for (const auto *TRCI : TRI->regclasses()) 1562fe6060f1SDimitry Andric if (TRCI->contains(Reg)) 1563fe6060f1SDimitry Andric TRC = TRCI; 1564fe6060f1SDimitry Andric assert(TRC && "Couldn't find target register class?"); 1565fe6060f1SDimitry Andric 1566fe6060f1SDimitry Andric // If the register we have isn't the right size or in the right place, 1567fe6060f1SDimitry Andric // Try to find a subregister inside it. 1568fe6060f1SDimitry Andric unsigned MainRegSize = TRI->getRegSizeInBits(*TRC); 1569fe6060f1SDimitry Andric if (Size != MainRegSize || Offset) { 1570fe6060f1SDimitry Andric // Enumerate all subregisters, searching. 1571fe6060f1SDimitry Andric Register NewReg = 0; 157206c3fb27SDimitry Andric for (MCPhysReg SR : TRI->subregs(Reg)) { 157306c3fb27SDimitry Andric unsigned Subreg = TRI->getSubRegIndex(Reg, SR); 1574fe6060f1SDimitry Andric unsigned SubregSize = TRI->getSubRegIdxSize(Subreg); 1575fe6060f1SDimitry Andric unsigned SubregOffset = TRI->getSubRegIdxOffset(Subreg); 1576fe6060f1SDimitry Andric if (SubregSize == Size && SubregOffset == Offset) { 157706c3fb27SDimitry Andric NewReg = SR; 1578fe6060f1SDimitry Andric break; 1579fe6060f1SDimitry Andric } 1580fe6060f1SDimitry Andric } 1581fe6060f1SDimitry Andric 1582fe6060f1SDimitry Andric // If we didn't find anything: there's no way to express our value. 1583fe6060f1SDimitry Andric if (!NewReg) { 1584bdd1243dSDimitry Andric NewID = std::nullopt; 1585fe6060f1SDimitry Andric } else { 1586fe6060f1SDimitry Andric // Re-state the value as being defined within the subregister 1587fe6060f1SDimitry Andric // that we found. 1588fe6060f1SDimitry Andric LocIdx NewLoc = MTracker->lookupOrTrackRegister(NewReg); 1589fe6060f1SDimitry Andric NewID = ValueIDNum(NewID->getBlock(), NewID->getInst(), NewLoc); 1590fe6060f1SDimitry Andric } 1591fe6060f1SDimitry Andric } 1592fe6060f1SDimitry Andric } else { 1593fe6060f1SDimitry Andric // If we can't handle subregisters, unset the new value. 1594bdd1243dSDimitry Andric NewID = std::nullopt; 1595fe6060f1SDimitry Andric } 1596e8d8bef9SDimitry Andric } 1597e8d8bef9SDimitry Andric 1598bdd1243dSDimitry Andric return NewID; 1599bdd1243dSDimitry Andric } 1600bdd1243dSDimitry Andric 1601bdd1243dSDimitry Andric bool InstrRefBasedLDV::transferDebugInstrRef(MachineInstr &MI, 16025f757f3fSDimitry Andric const FuncValueTable *MLiveOuts, 16035f757f3fSDimitry Andric const FuncValueTable *MLiveIns) { 1604bdd1243dSDimitry Andric if (!MI.isDebugRef()) 1605bdd1243dSDimitry Andric return false; 1606bdd1243dSDimitry Andric 1607bdd1243dSDimitry Andric // Only handle this instruction when we are building the variable value 1608bdd1243dSDimitry Andric // transfer function. 1609bdd1243dSDimitry Andric if (!VTracker && !TTracker) 1610bdd1243dSDimitry Andric return false; 1611bdd1243dSDimitry Andric 1612bdd1243dSDimitry Andric const DILocalVariable *Var = MI.getDebugVariable(); 1613bdd1243dSDimitry Andric const DIExpression *Expr = MI.getDebugExpression(); 1614bdd1243dSDimitry Andric const DILocation *DebugLoc = MI.getDebugLoc(); 1615bdd1243dSDimitry Andric const DILocation *InlinedAt = DebugLoc->getInlinedAt(); 1616bdd1243dSDimitry Andric assert(Var->isValidLocationForIntrinsic(DebugLoc) && 1617bdd1243dSDimitry Andric "Expected inlined-at fields to agree"); 1618bdd1243dSDimitry Andric 1619bdd1243dSDimitry Andric DebugVariable V(Var, Expr, InlinedAt); 1620bdd1243dSDimitry Andric 1621bdd1243dSDimitry Andric auto *Scope = LS.findLexicalScope(MI.getDebugLoc().get()); 1622bdd1243dSDimitry Andric if (Scope == nullptr) 1623bdd1243dSDimitry Andric return true; // Handled by doing nothing. This variable is never in scope. 1624bdd1243dSDimitry Andric 1625bdd1243dSDimitry Andric SmallVector<DbgOpID> DbgOpIDs; 1626bdd1243dSDimitry Andric for (const MachineOperand &MO : MI.debug_operands()) { 1627bdd1243dSDimitry Andric if (!MO.isDbgInstrRef()) { 1628bdd1243dSDimitry Andric assert(!MO.isReg() && "DBG_INSTR_REF should not contain registers"); 1629bdd1243dSDimitry Andric DbgOpID ConstOpID = DbgOpStore.insert(DbgOp(MO)); 1630bdd1243dSDimitry Andric DbgOpIDs.push_back(ConstOpID); 1631bdd1243dSDimitry Andric continue; 1632bdd1243dSDimitry Andric } 1633bdd1243dSDimitry Andric 1634bdd1243dSDimitry Andric unsigned InstNo = MO.getInstrRefInstrIndex(); 1635bdd1243dSDimitry Andric unsigned OpNo = MO.getInstrRefOpIndex(); 1636bdd1243dSDimitry Andric 1637bdd1243dSDimitry Andric // Default machine value number is <None> -- if no instruction defines 1638bdd1243dSDimitry Andric // the corresponding value, it must have been optimized out. 1639bdd1243dSDimitry Andric std::optional<ValueIDNum> NewID = 1640bdd1243dSDimitry Andric getValueForInstrRef(InstNo, OpNo, MI, MLiveOuts, MLiveIns); 1641bdd1243dSDimitry Andric // We have a value number or std::nullopt. If the latter, then kill the 1642bdd1243dSDimitry Andric // entire debug value. 1643bdd1243dSDimitry Andric if (NewID) { 1644bdd1243dSDimitry Andric DbgOpIDs.push_back(DbgOpStore.insert(*NewID)); 1645bdd1243dSDimitry Andric } else { 1646bdd1243dSDimitry Andric DbgOpIDs.clear(); 1647bdd1243dSDimitry Andric break; 1648bdd1243dSDimitry Andric } 1649bdd1243dSDimitry Andric } 1650bdd1243dSDimitry Andric 1651bdd1243dSDimitry Andric // We have a DbgOpID for every value or for none. Tell the variable value 1652bdd1243dSDimitry Andric // tracker about it. The rest of this LiveDebugValues implementation acts 1653bdd1243dSDimitry Andric // exactly the same for DBG_INSTR_REFs as DBG_VALUEs (just, the former can 1654bdd1243dSDimitry Andric // refer to values that aren't immediately available). 1655bdd1243dSDimitry Andric DbgValueProperties Properties(Expr, false, true); 1656d56accc7SDimitry Andric if (VTracker) 1657bdd1243dSDimitry Andric VTracker->defVar(MI, Properties, DbgOpIDs); 1658e8d8bef9SDimitry Andric 1659e8d8bef9SDimitry Andric // If we're on the final pass through the function, decompose this INSTR_REF 1660e8d8bef9SDimitry Andric // into a plain DBG_VALUE. 1661e8d8bef9SDimitry Andric if (!TTracker) 1662e8d8bef9SDimitry Andric return true; 1663e8d8bef9SDimitry Andric 1664bdd1243dSDimitry Andric // Fetch the concrete DbgOps now, as we will need them later. 1665bdd1243dSDimitry Andric SmallVector<DbgOp> DbgOps; 1666bdd1243dSDimitry Andric for (DbgOpID OpID : DbgOpIDs) { 1667bdd1243dSDimitry Andric DbgOps.push_back(DbgOpStore.find(OpID)); 1668bdd1243dSDimitry Andric } 1669bdd1243dSDimitry Andric 1670e8d8bef9SDimitry Andric // Pick a location for the machine value number, if such a location exists. 1671e8d8bef9SDimitry Andric // (This information could be stored in TransferTracker to make it faster). 1672bdd1243dSDimitry Andric SmallDenseMap<ValueIDNum, TransferTracker::LocationAndQuality> FoundLocs; 1673bdd1243dSDimitry Andric SmallVector<ValueIDNum> ValuesToFind; 1674bdd1243dSDimitry Andric // Initialized the preferred-location map with illegal locations, to be 1675bdd1243dSDimitry Andric // filled in later. 1676bdd1243dSDimitry Andric for (const DbgOp &Op : DbgOps) { 1677bdd1243dSDimitry Andric if (!Op.IsConst) 1678bdd1243dSDimitry Andric if (FoundLocs.insert({Op.ID, TransferTracker::LocationAndQuality()}) 1679bdd1243dSDimitry Andric .second) 1680bdd1243dSDimitry Andric ValuesToFind.push_back(Op.ID); 1681bdd1243dSDimitry Andric } 1682bdd1243dSDimitry Andric 1683e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 1684e8d8bef9SDimitry Andric LocIdx CurL = Location.Idx; 1685349cc55cSDimitry Andric ValueIDNum ID = MTracker->readMLoc(CurL); 1686bdd1243dSDimitry Andric auto ValueToFindIt = find(ValuesToFind, ID); 1687bdd1243dSDimitry Andric if (ValueToFindIt == ValuesToFind.end()) 1688bdd1243dSDimitry Andric continue; 1689bdd1243dSDimitry Andric auto &Previous = FoundLocs.find(ID)->second; 1690e8d8bef9SDimitry Andric // If this is the first location with that value, pick it. Otherwise, 1691e8d8bef9SDimitry Andric // consider whether it's a "longer term" location. 1692bdd1243dSDimitry Andric std::optional<TransferTracker::LocationQuality> ReplacementQuality = 1693bdd1243dSDimitry Andric TTracker->getLocQualityIfBetter(CurL, Previous.getQuality()); 1694bdd1243dSDimitry Andric if (ReplacementQuality) { 1695bdd1243dSDimitry Andric Previous = TransferTracker::LocationAndQuality(CurL, *ReplacementQuality); 1696bdd1243dSDimitry Andric if (Previous.isBest()) { 1697bdd1243dSDimitry Andric ValuesToFind.erase(ValueToFindIt); 1698bdd1243dSDimitry Andric if (ValuesToFind.empty()) 1699bdd1243dSDimitry Andric break; 1700bdd1243dSDimitry Andric } 1701bdd1243dSDimitry Andric } 1702bdd1243dSDimitry Andric } 1703bdd1243dSDimitry Andric 1704bdd1243dSDimitry Andric SmallVector<ResolvedDbgOp> NewLocs; 1705bdd1243dSDimitry Andric for (const DbgOp &DbgOp : DbgOps) { 1706bdd1243dSDimitry Andric if (DbgOp.IsConst) { 1707bdd1243dSDimitry Andric NewLocs.push_back(DbgOp.MO); 1708e8d8bef9SDimitry Andric continue; 1709e8d8bef9SDimitry Andric } 1710bdd1243dSDimitry Andric LocIdx FoundLoc = FoundLocs.find(DbgOp.ID)->second.getLoc(); 1711bdd1243dSDimitry Andric if (FoundLoc.isIllegal()) { 1712bdd1243dSDimitry Andric NewLocs.clear(); 1713bdd1243dSDimitry Andric break; 1714e8d8bef9SDimitry Andric } 1715bdd1243dSDimitry Andric NewLocs.push_back(FoundLoc); 1716e8d8bef9SDimitry Andric } 1717e8d8bef9SDimitry Andric // Tell transfer tracker that the variable value has changed. 1718bdd1243dSDimitry Andric TTracker->redefVar(MI, Properties, NewLocs); 1719e8d8bef9SDimitry Andric 1720bdd1243dSDimitry Andric // If there were values with no location, but all such values are defined in 1721bdd1243dSDimitry Andric // later instructions in this block, this is a block-local use-before-def. 1722bdd1243dSDimitry Andric if (!DbgOps.empty() && NewLocs.empty()) { 1723bdd1243dSDimitry Andric bool IsValidUseBeforeDef = true; 1724bdd1243dSDimitry Andric uint64_t LastUseBeforeDef = 0; 1725bdd1243dSDimitry Andric for (auto ValueLoc : FoundLocs) { 1726bdd1243dSDimitry Andric ValueIDNum NewID = ValueLoc.first; 1727bdd1243dSDimitry Andric LocIdx FoundLoc = ValueLoc.second.getLoc(); 1728bdd1243dSDimitry Andric if (!FoundLoc.isIllegal()) 1729bdd1243dSDimitry Andric continue; 1730bdd1243dSDimitry Andric // If we have an value with no location that is not defined in this block, 1731bdd1243dSDimitry Andric // then it has no location in this block, leaving this value undefined. 1732bdd1243dSDimitry Andric if (NewID.getBlock() != CurBB || NewID.getInst() <= CurInst) { 1733bdd1243dSDimitry Andric IsValidUseBeforeDef = false; 1734bdd1243dSDimitry Andric break; 1735bdd1243dSDimitry Andric } 1736bdd1243dSDimitry Andric LastUseBeforeDef = std::max(LastUseBeforeDef, NewID.getInst()); 1737bdd1243dSDimitry Andric } 1738bdd1243dSDimitry Andric if (IsValidUseBeforeDef) { 1739*0fca6ea1SDimitry Andric DebugVariableID VID = DVMap.insertDVID(V, MI.getDebugLoc().get()); 1740*0fca6ea1SDimitry Andric TTracker->addUseBeforeDef(VID, {MI.getDebugExpression(), false, true}, 1741bdd1243dSDimitry Andric DbgOps, LastUseBeforeDef); 1742bdd1243dSDimitry Andric } 1743bdd1243dSDimitry Andric } 1744e8d8bef9SDimitry Andric 1745e8d8bef9SDimitry Andric // Produce a DBG_VALUE representing what this DBG_INSTR_REF meant. 1746e8d8bef9SDimitry Andric // This DBG_VALUE is potentially a $noreg / undefined location, if 1747bdd1243dSDimitry Andric // FoundLoc is illegal. 1748e8d8bef9SDimitry Andric // (XXX -- could morph the DBG_INSTR_REF in the future). 1749*0fca6ea1SDimitry Andric MachineInstr *DbgMI = 1750*0fca6ea1SDimitry Andric MTracker->emitLoc(NewLocs, V, MI.getDebugLoc().get(), Properties); 1751*0fca6ea1SDimitry Andric DebugVariableID ID = DVMap.getDVID(V); 1752bdd1243dSDimitry Andric 1753*0fca6ea1SDimitry Andric TTracker->PendingDbgValues.push_back(std::make_pair(ID, DbgMI)); 1754e8d8bef9SDimitry Andric TTracker->flushDbgValues(MI.getIterator(), nullptr); 1755fe6060f1SDimitry Andric return true; 1756fe6060f1SDimitry Andric } 1757fe6060f1SDimitry Andric 1758fe6060f1SDimitry Andric bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) { 1759fe6060f1SDimitry Andric if (!MI.isDebugPHI()) 1760fe6060f1SDimitry Andric return false; 1761fe6060f1SDimitry Andric 1762fe6060f1SDimitry Andric // Analyse these only when solving the machine value location problem. 1763fe6060f1SDimitry Andric if (VTracker || TTracker) 1764fe6060f1SDimitry Andric return true; 1765fe6060f1SDimitry Andric 1766fe6060f1SDimitry Andric // First operand is the value location, either a stack slot or register. 1767fe6060f1SDimitry Andric // Second is the debug instruction number of the original PHI. 1768fe6060f1SDimitry Andric const MachineOperand &MO = MI.getOperand(0); 1769fe6060f1SDimitry Andric unsigned InstrNum = MI.getOperand(1).getImm(); 1770fe6060f1SDimitry Andric 1771972a253aSDimitry Andric auto EmitBadPHI = [this, &MI, InstrNum]() -> bool { 177281ad6265SDimitry Andric // Helper lambda to do any accounting when we fail to find a location for 177381ad6265SDimitry Andric // a DBG_PHI. This can happen if DBG_PHIs are malformed, or refer to a 177481ad6265SDimitry Andric // dead stack slot, for example. 177581ad6265SDimitry Andric // Record a DebugPHIRecord with an empty value + location. 1776bdd1243dSDimitry Andric DebugPHINumToValue.push_back( 1777bdd1243dSDimitry Andric {InstrNum, MI.getParent(), std::nullopt, std::nullopt}); 177881ad6265SDimitry Andric return true; 177981ad6265SDimitry Andric }; 178081ad6265SDimitry Andric 178181ad6265SDimitry Andric if (MO.isReg() && MO.getReg()) { 1782fe6060f1SDimitry Andric // The value is whatever's currently in the register. Read and record it, 1783fe6060f1SDimitry Andric // to be analysed later. 1784fe6060f1SDimitry Andric Register Reg = MO.getReg(); 1785fe6060f1SDimitry Andric ValueIDNum Num = MTracker->readReg(Reg); 1786fe6060f1SDimitry Andric auto PHIRec = DebugPHIRecord( 1787fe6060f1SDimitry Andric {InstrNum, MI.getParent(), Num, MTracker->lookupOrTrackRegister(Reg)}); 1788fe6060f1SDimitry Andric DebugPHINumToValue.push_back(PHIRec); 1789349cc55cSDimitry Andric 1790349cc55cSDimitry Andric // Ensure this register is tracked. 1791349cc55cSDimitry Andric for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) 1792349cc55cSDimitry Andric MTracker->lookupOrTrackRegister(*RAI); 179381ad6265SDimitry Andric } else if (MO.isFI()) { 1794fe6060f1SDimitry Andric // The value is whatever's in this stack slot. 1795fe6060f1SDimitry Andric unsigned FI = MO.getIndex(); 1796fe6060f1SDimitry Andric 1797fe6060f1SDimitry Andric // If the stack slot is dead, then this was optimized away. 1798fe6060f1SDimitry Andric // FIXME: stack slot colouring should account for slots that get merged. 1799fe6060f1SDimitry Andric if (MFI->isDeadObjectIndex(FI)) 180081ad6265SDimitry Andric return EmitBadPHI(); 1801fe6060f1SDimitry Andric 1802349cc55cSDimitry Andric // Identify this spill slot, ensure it's tracked. 1803fe6060f1SDimitry Andric Register Base; 1804fe6060f1SDimitry Andric StackOffset Offs = TFI->getFrameIndexReference(*MI.getMF(), FI, Base); 1805fe6060f1SDimitry Andric SpillLoc SL = {Base, Offs}; 1806bdd1243dSDimitry Andric std::optional<SpillLocationNo> SpillNo = MTracker->getOrTrackSpillLoc(SL); 1807d56accc7SDimitry Andric 1808d56accc7SDimitry Andric // We might be able to find a value, but have chosen not to, to avoid 1809d56accc7SDimitry Andric // tracking too much stack information. 1810d56accc7SDimitry Andric if (!SpillNo) 181181ad6265SDimitry Andric return EmitBadPHI(); 1812fe6060f1SDimitry Andric 181381ad6265SDimitry Andric // Any stack location DBG_PHI should have an associate bit-size. 181481ad6265SDimitry Andric assert(MI.getNumOperands() == 3 && "Stack DBG_PHI with no size?"); 181581ad6265SDimitry Andric unsigned slotBitSize = MI.getOperand(2).getImm(); 1816349cc55cSDimitry Andric 181781ad6265SDimitry Andric unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0}); 181881ad6265SDimitry Andric LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID); 181981ad6265SDimitry Andric ValueIDNum Result = MTracker->readMLoc(SpillLoc); 1820fe6060f1SDimitry Andric 1821fe6060f1SDimitry Andric // Record this DBG_PHI for later analysis. 182281ad6265SDimitry Andric auto DbgPHI = DebugPHIRecord({InstrNum, MI.getParent(), Result, SpillLoc}); 1823fe6060f1SDimitry Andric DebugPHINumToValue.push_back(DbgPHI); 182481ad6265SDimitry Andric } else { 182581ad6265SDimitry Andric // Else: if the operand is neither a legal register or a stack slot, then 182681ad6265SDimitry Andric // we're being fed illegal debug-info. Record an empty PHI, so that any 182781ad6265SDimitry Andric // debug users trying to read this number will be put off trying to 182881ad6265SDimitry Andric // interpret the value. 182981ad6265SDimitry Andric LLVM_DEBUG( 183081ad6265SDimitry Andric { dbgs() << "Seen DBG_PHI with unrecognised operand format\n"; }); 183181ad6265SDimitry Andric return EmitBadPHI(); 1832fe6060f1SDimitry Andric } 1833e8d8bef9SDimitry Andric 1834e8d8bef9SDimitry Andric return true; 1835e8d8bef9SDimitry Andric } 1836e8d8bef9SDimitry Andric 1837e8d8bef9SDimitry Andric void InstrRefBasedLDV::transferRegisterDef(MachineInstr &MI) { 1838e8d8bef9SDimitry Andric // Meta Instructions do not affect the debug liveness of any register they 1839e8d8bef9SDimitry Andric // define. 1840e8d8bef9SDimitry Andric if (MI.isImplicitDef()) { 1841e8d8bef9SDimitry Andric // Except when there's an implicit def, and the location it's defining has 1842e8d8bef9SDimitry Andric // no value number. The whole point of an implicit def is to announce that 1843e8d8bef9SDimitry Andric // the register is live, without be specific about it's value. So define 1844e8d8bef9SDimitry Andric // a value if there isn't one already. 1845e8d8bef9SDimitry Andric ValueIDNum Num = MTracker->readReg(MI.getOperand(0).getReg()); 1846e8d8bef9SDimitry Andric // Has a legitimate value -> ignore the implicit def. 1847e8d8bef9SDimitry Andric if (Num.getLoc() != 0) 1848e8d8bef9SDimitry Andric return; 1849e8d8bef9SDimitry Andric // Otherwise, def it here. 1850e8d8bef9SDimitry Andric } else if (MI.isMetaInstruction()) 1851e8d8bef9SDimitry Andric return; 1852e8d8bef9SDimitry Andric 18534824e7fdSDimitry Andric // We always ignore SP defines on call instructions, they don't actually 18544824e7fdSDimitry Andric // change the value of the stack pointer... except for win32's _chkstk. This 18554824e7fdSDimitry Andric // is rare: filter quickly for the common case (no stack adjustments, not a 18564824e7fdSDimitry Andric // call, etc). If it is a call that modifies SP, recognise the SP register 18574824e7fdSDimitry Andric // defs. 18584824e7fdSDimitry Andric bool CallChangesSP = false; 18594824e7fdSDimitry Andric if (AdjustsStackInCalls && MI.isCall() && MI.getOperand(0).isSymbol() && 18604824e7fdSDimitry Andric !strcmp(MI.getOperand(0).getSymbolName(), StackProbeSymbolName.data())) 18614824e7fdSDimitry Andric CallChangesSP = true; 18624824e7fdSDimitry Andric 18634824e7fdSDimitry Andric // Test whether we should ignore a def of this register due to it being part 18644824e7fdSDimitry Andric // of the stack pointer. 18654824e7fdSDimitry Andric auto IgnoreSPAlias = [this, &MI, CallChangesSP](Register R) -> bool { 18664824e7fdSDimitry Andric if (CallChangesSP) 18674824e7fdSDimitry Andric return false; 18684824e7fdSDimitry Andric return MI.isCall() && MTracker->SPAliases.count(R); 18694824e7fdSDimitry Andric }; 18704824e7fdSDimitry Andric 1871e8d8bef9SDimitry Andric // Find the regs killed by MI, and find regmasks of preserved regs. 1872e8d8bef9SDimitry Andric // Max out the number of statically allocated elements in `DeadRegs`, as this 1873e8d8bef9SDimitry Andric // prevents fallback to std::set::count() operations. 1874e8d8bef9SDimitry Andric SmallSet<uint32_t, 32> DeadRegs; 1875e8d8bef9SDimitry Andric SmallVector<const uint32_t *, 4> RegMasks; 1876e8d8bef9SDimitry Andric SmallVector<const MachineOperand *, 4> RegMaskPtrs; 1877e8d8bef9SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 1878e8d8bef9SDimitry Andric // Determine whether the operand is a register def. 1879bdd1243dSDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg() && MO.getReg().isPhysical() && 18804824e7fdSDimitry Andric !IgnoreSPAlias(MO.getReg())) { 1881e8d8bef9SDimitry Andric // Remove ranges of all aliased registers. 1882e8d8bef9SDimitry Andric for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) 1883e8d8bef9SDimitry Andric // FIXME: Can we break out of this loop early if no insertion occurs? 1884e8d8bef9SDimitry Andric DeadRegs.insert(*RAI); 1885e8d8bef9SDimitry Andric } else if (MO.isRegMask()) { 1886e8d8bef9SDimitry Andric RegMasks.push_back(MO.getRegMask()); 1887e8d8bef9SDimitry Andric RegMaskPtrs.push_back(&MO); 1888e8d8bef9SDimitry Andric } 1889e8d8bef9SDimitry Andric } 1890e8d8bef9SDimitry Andric 1891e8d8bef9SDimitry Andric // Tell MLocTracker about all definitions, of regmasks and otherwise. 1892e8d8bef9SDimitry Andric for (uint32_t DeadReg : DeadRegs) 1893e8d8bef9SDimitry Andric MTracker->defReg(DeadReg, CurBB, CurInst); 1894e8d8bef9SDimitry Andric 1895fcaf7f86SDimitry Andric for (const auto *MO : RegMaskPtrs) 1896e8d8bef9SDimitry Andric MTracker->writeRegMask(MO, CurBB, CurInst); 1897fe6060f1SDimitry Andric 1898349cc55cSDimitry Andric // If this instruction writes to a spill slot, def that slot. 1899349cc55cSDimitry Andric if (hasFoldedStackStore(MI)) { 1900bdd1243dSDimitry Andric if (std::optional<SpillLocationNo> SpillNo = 1901bdd1243dSDimitry Andric extractSpillBaseRegAndOffset(MI)) { 1902349cc55cSDimitry Andric for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) { 1903d56accc7SDimitry Andric unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I); 1904349cc55cSDimitry Andric LocIdx L = MTracker->getSpillMLoc(SpillID); 1905349cc55cSDimitry Andric MTracker->setMLoc(L, ValueIDNum(CurBB, CurInst, L)); 1906349cc55cSDimitry Andric } 1907349cc55cSDimitry Andric } 1908d56accc7SDimitry Andric } 1909349cc55cSDimitry Andric 1910fe6060f1SDimitry Andric if (!TTracker) 1911fe6060f1SDimitry Andric return; 1912fe6060f1SDimitry Andric 1913fe6060f1SDimitry Andric // When committing variable values to locations: tell transfer tracker that 1914fe6060f1SDimitry Andric // we've clobbered things. It may be able to recover the variable from a 1915fe6060f1SDimitry Andric // different location. 1916fe6060f1SDimitry Andric 1917fe6060f1SDimitry Andric // Inform TTracker about any direct clobbers. 1918fe6060f1SDimitry Andric for (uint32_t DeadReg : DeadRegs) { 1919fe6060f1SDimitry Andric LocIdx Loc = MTracker->lookupOrTrackRegister(DeadReg); 1920fe6060f1SDimitry Andric TTracker->clobberMloc(Loc, MI.getIterator(), false); 1921fe6060f1SDimitry Andric } 1922fe6060f1SDimitry Andric 1923fe6060f1SDimitry Andric // Look for any clobbers performed by a register mask. Only test locations 1924fe6060f1SDimitry Andric // that are actually being tracked. 19251fd87a68SDimitry Andric if (!RegMaskPtrs.empty()) { 1926fe6060f1SDimitry Andric for (auto L : MTracker->locations()) { 1927fe6060f1SDimitry Andric // Stack locations can't be clobbered by regmasks. 1928fe6060f1SDimitry Andric if (MTracker->isSpill(L.Idx)) 1929fe6060f1SDimitry Andric continue; 1930fe6060f1SDimitry Andric 1931fe6060f1SDimitry Andric Register Reg = MTracker->LocIdxToLocID[L.Idx]; 19324824e7fdSDimitry Andric if (IgnoreSPAlias(Reg)) 19334824e7fdSDimitry Andric continue; 19344824e7fdSDimitry Andric 1935fcaf7f86SDimitry Andric for (const auto *MO : RegMaskPtrs) 1936fe6060f1SDimitry Andric if (MO->clobbersPhysReg(Reg)) 1937fe6060f1SDimitry Andric TTracker->clobberMloc(L.Idx, MI.getIterator(), false); 1938fe6060f1SDimitry Andric } 19391fd87a68SDimitry Andric } 1940349cc55cSDimitry Andric 1941349cc55cSDimitry Andric // Tell TTracker about any folded stack store. 1942349cc55cSDimitry Andric if (hasFoldedStackStore(MI)) { 1943bdd1243dSDimitry Andric if (std::optional<SpillLocationNo> SpillNo = 1944bdd1243dSDimitry Andric extractSpillBaseRegAndOffset(MI)) { 1945349cc55cSDimitry Andric for (unsigned int I = 0; I < MTracker->NumSlotIdxes; ++I) { 1946d56accc7SDimitry Andric unsigned SpillID = MTracker->getSpillIDWithIdx(*SpillNo, I); 1947349cc55cSDimitry Andric LocIdx L = MTracker->getSpillMLoc(SpillID); 1948349cc55cSDimitry Andric TTracker->clobberMloc(L, MI.getIterator(), true); 1949349cc55cSDimitry Andric } 1950349cc55cSDimitry Andric } 1951e8d8bef9SDimitry Andric } 1952d56accc7SDimitry Andric } 1953e8d8bef9SDimitry Andric 1954e8d8bef9SDimitry Andric void InstrRefBasedLDV::performCopy(Register SrcRegNum, Register DstRegNum) { 1955349cc55cSDimitry Andric // In all circumstances, re-def all aliases. It's definitely a new value now. 1956349cc55cSDimitry Andric for (MCRegAliasIterator RAI(DstRegNum, TRI, true); RAI.isValid(); ++RAI) 1957349cc55cSDimitry Andric MTracker->defReg(*RAI, CurBB, CurInst); 1958e8d8bef9SDimitry Andric 1959349cc55cSDimitry Andric ValueIDNum SrcValue = MTracker->readReg(SrcRegNum); 1960e8d8bef9SDimitry Andric MTracker->setReg(DstRegNum, SrcValue); 1961e8d8bef9SDimitry Andric 1962349cc55cSDimitry Andric // Copy subregisters from one location to another. 1963e8d8bef9SDimitry Andric for (MCSubRegIndexIterator SRI(SrcRegNum, TRI); SRI.isValid(); ++SRI) { 1964e8d8bef9SDimitry Andric unsigned SrcSubReg = SRI.getSubReg(); 1965e8d8bef9SDimitry Andric unsigned SubRegIdx = SRI.getSubRegIndex(); 1966e8d8bef9SDimitry Andric unsigned DstSubReg = TRI->getSubReg(DstRegNum, SubRegIdx); 1967e8d8bef9SDimitry Andric if (!DstSubReg) 1968e8d8bef9SDimitry Andric continue; 1969e8d8bef9SDimitry Andric 1970e8d8bef9SDimitry Andric // Do copy. There are two matching subregisters, the source value should 1971e8d8bef9SDimitry Andric // have been def'd when the super-reg was, the latter might not be tracked 1972e8d8bef9SDimitry Andric // yet. 1973349cc55cSDimitry Andric // This will force SrcSubReg to be tracked, if it isn't yet. Will read 1974349cc55cSDimitry Andric // mphi values if it wasn't tracked. 1975349cc55cSDimitry Andric LocIdx SrcL = MTracker->lookupOrTrackRegister(SrcSubReg); 1976349cc55cSDimitry Andric LocIdx DstL = MTracker->lookupOrTrackRegister(DstSubReg); 1977349cc55cSDimitry Andric (void)SrcL; 1978e8d8bef9SDimitry Andric (void)DstL; 1979349cc55cSDimitry Andric ValueIDNum CpyValue = MTracker->readReg(SrcSubReg); 1980e8d8bef9SDimitry Andric 1981e8d8bef9SDimitry Andric MTracker->setReg(DstSubReg, CpyValue); 1982e8d8bef9SDimitry Andric } 1983e8d8bef9SDimitry Andric } 1984e8d8bef9SDimitry Andric 1985bdd1243dSDimitry Andric std::optional<SpillLocationNo> 1986d56accc7SDimitry Andric InstrRefBasedLDV::isSpillInstruction(const MachineInstr &MI, 1987e8d8bef9SDimitry Andric MachineFunction *MF) { 1988e8d8bef9SDimitry Andric // TODO: Handle multiple stores folded into one. 1989e8d8bef9SDimitry Andric if (!MI.hasOneMemOperand()) 1990bdd1243dSDimitry Andric return std::nullopt; 1991e8d8bef9SDimitry Andric 1992349cc55cSDimitry Andric // Reject any memory operand that's aliased -- we can't guarantee its value. 1993349cc55cSDimitry Andric auto MMOI = MI.memoperands_begin(); 1994349cc55cSDimitry Andric const PseudoSourceValue *PVal = (*MMOI)->getPseudoValue(); 1995349cc55cSDimitry Andric if (PVal->isAliased(MFI)) 1996bdd1243dSDimitry Andric return std::nullopt; 1997349cc55cSDimitry Andric 1998e8d8bef9SDimitry Andric if (!MI.getSpillSize(TII) && !MI.getFoldedSpillSize(TII)) 1999bdd1243dSDimitry Andric return std::nullopt; // This is not a spill instruction, since no valid size 2000bdd1243dSDimitry Andric // was returned from either function. 2001e8d8bef9SDimitry Andric 2002d56accc7SDimitry Andric return extractSpillBaseRegAndOffset(MI); 2003e8d8bef9SDimitry Andric } 2004e8d8bef9SDimitry Andric 2005e8d8bef9SDimitry Andric bool InstrRefBasedLDV::isLocationSpill(const MachineInstr &MI, 2006e8d8bef9SDimitry Andric MachineFunction *MF, unsigned &Reg) { 2007e8d8bef9SDimitry Andric if (!isSpillInstruction(MI, MF)) 2008e8d8bef9SDimitry Andric return false; 2009e8d8bef9SDimitry Andric 2010e8d8bef9SDimitry Andric int FI; 2011e8d8bef9SDimitry Andric Reg = TII->isStoreToStackSlotPostFE(MI, FI); 2012e8d8bef9SDimitry Andric return Reg != 0; 2013e8d8bef9SDimitry Andric } 2014e8d8bef9SDimitry Andric 2015bdd1243dSDimitry Andric std::optional<SpillLocationNo> 2016e8d8bef9SDimitry Andric InstrRefBasedLDV::isRestoreInstruction(const MachineInstr &MI, 2017e8d8bef9SDimitry Andric MachineFunction *MF, unsigned &Reg) { 2018e8d8bef9SDimitry Andric if (!MI.hasOneMemOperand()) 2019bdd1243dSDimitry Andric return std::nullopt; 2020e8d8bef9SDimitry Andric 2021e8d8bef9SDimitry Andric // FIXME: Handle folded restore instructions with more than one memory 2022e8d8bef9SDimitry Andric // operand. 2023e8d8bef9SDimitry Andric if (MI.getRestoreSize(TII)) { 2024e8d8bef9SDimitry Andric Reg = MI.getOperand(0).getReg(); 2025e8d8bef9SDimitry Andric return extractSpillBaseRegAndOffset(MI); 2026e8d8bef9SDimitry Andric } 2027bdd1243dSDimitry Andric return std::nullopt; 2028e8d8bef9SDimitry Andric } 2029e8d8bef9SDimitry Andric 2030e8d8bef9SDimitry Andric bool InstrRefBasedLDV::transferSpillOrRestoreInst(MachineInstr &MI) { 2031e8d8bef9SDimitry Andric // XXX -- it's too difficult to implement VarLocBasedImpl's stack location 2032e8d8bef9SDimitry Andric // limitations under the new model. Therefore, when comparing them, compare 2033e8d8bef9SDimitry Andric // versions that don't attempt spills or restores at all. 2034e8d8bef9SDimitry Andric if (EmulateOldLDV) 2035e8d8bef9SDimitry Andric return false; 2036e8d8bef9SDimitry Andric 2037349cc55cSDimitry Andric // Strictly limit ourselves to plain loads and stores, not all instructions 2038349cc55cSDimitry Andric // that can access the stack. 2039349cc55cSDimitry Andric int DummyFI = -1; 2040349cc55cSDimitry Andric if (!TII->isStoreToStackSlotPostFE(MI, DummyFI) && 2041349cc55cSDimitry Andric !TII->isLoadFromStackSlotPostFE(MI, DummyFI)) 2042349cc55cSDimitry Andric return false; 2043349cc55cSDimitry Andric 2044e8d8bef9SDimitry Andric MachineFunction *MF = MI.getMF(); 2045e8d8bef9SDimitry Andric unsigned Reg; 2046e8d8bef9SDimitry Andric 2047e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "Examining instruction: "; MI.dump();); 2048e8d8bef9SDimitry Andric 2049349cc55cSDimitry Andric // Strictly limit ourselves to plain loads and stores, not all instructions 2050349cc55cSDimitry Andric // that can access the stack. 2051349cc55cSDimitry Andric int FIDummy; 2052349cc55cSDimitry Andric if (!TII->isStoreToStackSlotPostFE(MI, FIDummy) && 2053349cc55cSDimitry Andric !TII->isLoadFromStackSlotPostFE(MI, FIDummy)) 2054349cc55cSDimitry Andric return false; 2055349cc55cSDimitry Andric 2056e8d8bef9SDimitry Andric // First, if there are any DBG_VALUEs pointing at a spill slot that is 2057e8d8bef9SDimitry Andric // written to, terminate that variable location. The value in memory 2058e8d8bef9SDimitry Andric // will have changed. DbgEntityHistoryCalculator doesn't try to detect this. 2059bdd1243dSDimitry Andric if (std::optional<SpillLocationNo> Loc = isSpillInstruction(MI, MF)) { 2060349cc55cSDimitry Andric // Un-set this location and clobber, so that earlier locations don't 2061349cc55cSDimitry Andric // continue past this store. 2062349cc55cSDimitry Andric for (unsigned SlotIdx = 0; SlotIdx < MTracker->NumSlotIdxes; ++SlotIdx) { 2063d56accc7SDimitry Andric unsigned SpillID = MTracker->getSpillIDWithIdx(*Loc, SlotIdx); 2064bdd1243dSDimitry Andric std::optional<LocIdx> MLoc = MTracker->getSpillMLoc(SpillID); 2065349cc55cSDimitry Andric if (!MLoc) 2066349cc55cSDimitry Andric continue; 2067349cc55cSDimitry Andric 2068349cc55cSDimitry Andric // We need to over-write the stack slot with something (here, a def at 2069349cc55cSDimitry Andric // this instruction) to ensure no values are preserved in this stack slot 2070349cc55cSDimitry Andric // after the spill. It also prevents TTracker from trying to recover the 2071349cc55cSDimitry Andric // location and re-installing it in the same place. 2072349cc55cSDimitry Andric ValueIDNum Def(CurBB, CurInst, *MLoc); 2073349cc55cSDimitry Andric MTracker->setMLoc(*MLoc, Def); 2074349cc55cSDimitry Andric if (TTracker) 2075e8d8bef9SDimitry Andric TTracker->clobberMloc(*MLoc, MI.getIterator()); 2076e8d8bef9SDimitry Andric } 2077e8d8bef9SDimitry Andric } 2078e8d8bef9SDimitry Andric 2079e8d8bef9SDimitry Andric // Try to recognise spill and restore instructions that may transfer a value. 2080e8d8bef9SDimitry Andric if (isLocationSpill(MI, MF, Reg)) { 2081d56accc7SDimitry Andric // isLocationSpill returning true should guarantee we can extract a 2082d56accc7SDimitry Andric // location. 2083d56accc7SDimitry Andric SpillLocationNo Loc = *extractSpillBaseRegAndOffset(MI); 2084e8d8bef9SDimitry Andric 2085349cc55cSDimitry Andric auto DoTransfer = [&](Register SrcReg, unsigned SpillID) { 2086349cc55cSDimitry Andric auto ReadValue = MTracker->readReg(SrcReg); 2087349cc55cSDimitry Andric LocIdx DstLoc = MTracker->getSpillMLoc(SpillID); 2088349cc55cSDimitry Andric MTracker->setMLoc(DstLoc, ReadValue); 2089e8d8bef9SDimitry Andric 2090349cc55cSDimitry Andric if (TTracker) { 2091349cc55cSDimitry Andric LocIdx SrcLoc = MTracker->getRegMLoc(SrcReg); 2092349cc55cSDimitry Andric TTracker->transferMlocs(SrcLoc, DstLoc, MI.getIterator()); 2093e8d8bef9SDimitry Andric } 2094349cc55cSDimitry Andric }; 2095349cc55cSDimitry Andric 2096349cc55cSDimitry Andric // Then, transfer subreg bits. 209706c3fb27SDimitry Andric for (MCPhysReg SR : TRI->subregs(Reg)) { 2098349cc55cSDimitry Andric // Ensure this reg is tracked, 209906c3fb27SDimitry Andric (void)MTracker->lookupOrTrackRegister(SR); 210006c3fb27SDimitry Andric unsigned SubregIdx = TRI->getSubRegIndex(Reg, SR); 2101349cc55cSDimitry Andric unsigned SpillID = MTracker->getLocID(Loc, SubregIdx); 210206c3fb27SDimitry Andric DoTransfer(SR, SpillID); 2103349cc55cSDimitry Andric } 2104349cc55cSDimitry Andric 2105349cc55cSDimitry Andric // Directly lookup size of main source reg, and transfer. 2106349cc55cSDimitry Andric unsigned Size = TRI->getRegSizeInBits(Reg, *MRI); 2107349cc55cSDimitry Andric unsigned SpillID = MTracker->getLocID(Loc, {Size, 0}); 2108349cc55cSDimitry Andric DoTransfer(Reg, SpillID); 2109349cc55cSDimitry Andric } else { 2110bdd1243dSDimitry Andric std::optional<SpillLocationNo> Loc = isRestoreInstruction(MI, MF, Reg); 2111d56accc7SDimitry Andric if (!Loc) 2112349cc55cSDimitry Andric return false; 2113349cc55cSDimitry Andric 2114349cc55cSDimitry Andric // Assumption: we're reading from the base of the stack slot, not some 2115349cc55cSDimitry Andric // offset into it. It seems very unlikely LLVM would ever generate 2116349cc55cSDimitry Andric // restores where this wasn't true. This then becomes a question of what 2117349cc55cSDimitry Andric // subregisters in the destination register line up with positions in the 2118349cc55cSDimitry Andric // stack slot. 2119349cc55cSDimitry Andric 2120349cc55cSDimitry Andric // Def all registers that alias the destination. 2121349cc55cSDimitry Andric for (MCRegAliasIterator RAI(Reg, TRI, true); RAI.isValid(); ++RAI) 2122349cc55cSDimitry Andric MTracker->defReg(*RAI, CurBB, CurInst); 2123349cc55cSDimitry Andric 2124349cc55cSDimitry Andric // Now find subregisters within the destination register, and load values 2125349cc55cSDimitry Andric // from stack slot positions. 2126349cc55cSDimitry Andric auto DoTransfer = [&](Register DestReg, unsigned SpillID) { 2127349cc55cSDimitry Andric LocIdx SrcIdx = MTracker->getSpillMLoc(SpillID); 2128349cc55cSDimitry Andric auto ReadValue = MTracker->readMLoc(SrcIdx); 2129349cc55cSDimitry Andric MTracker->setReg(DestReg, ReadValue); 2130349cc55cSDimitry Andric }; 2131349cc55cSDimitry Andric 213206c3fb27SDimitry Andric for (MCPhysReg SR : TRI->subregs(Reg)) { 213306c3fb27SDimitry Andric unsigned Subreg = TRI->getSubRegIndex(Reg, SR); 2134d56accc7SDimitry Andric unsigned SpillID = MTracker->getLocID(*Loc, Subreg); 213506c3fb27SDimitry Andric DoTransfer(SR, SpillID); 2136349cc55cSDimitry Andric } 2137349cc55cSDimitry Andric 2138349cc55cSDimitry Andric // Directly look up this registers slot idx by size, and transfer. 2139349cc55cSDimitry Andric unsigned Size = TRI->getRegSizeInBits(Reg, *MRI); 2140d56accc7SDimitry Andric unsigned SpillID = MTracker->getLocID(*Loc, {Size, 0}); 2141349cc55cSDimitry Andric DoTransfer(Reg, SpillID); 2142e8d8bef9SDimitry Andric } 2143e8d8bef9SDimitry Andric return true; 2144e8d8bef9SDimitry Andric } 2145e8d8bef9SDimitry Andric 2146e8d8bef9SDimitry Andric bool InstrRefBasedLDV::transferRegisterCopy(MachineInstr &MI) { 21475f757f3fSDimitry Andric auto DestSrc = TII->isCopyLikeInstr(MI); 2148e8d8bef9SDimitry Andric if (!DestSrc) 2149e8d8bef9SDimitry Andric return false; 2150e8d8bef9SDimitry Andric 2151e8d8bef9SDimitry Andric const MachineOperand *DestRegOp = DestSrc->Destination; 2152e8d8bef9SDimitry Andric const MachineOperand *SrcRegOp = DestSrc->Source; 2153e8d8bef9SDimitry Andric 2154e8d8bef9SDimitry Andric Register SrcReg = SrcRegOp->getReg(); 2155e8d8bef9SDimitry Andric Register DestReg = DestRegOp->getReg(); 2156e8d8bef9SDimitry Andric 2157e8d8bef9SDimitry Andric // Ignore identity copies. Yep, these make it as far as LiveDebugValues. 2158e8d8bef9SDimitry Andric if (SrcReg == DestReg) 2159e8d8bef9SDimitry Andric return true; 2160e8d8bef9SDimitry Andric 2161e8d8bef9SDimitry Andric // For emulating VarLocBasedImpl: 2162e8d8bef9SDimitry Andric // We want to recognize instructions where destination register is callee 2163e8d8bef9SDimitry Andric // saved register. If register that could be clobbered by the call is 2164e8d8bef9SDimitry Andric // included, there would be a great chance that it is going to be clobbered 2165e8d8bef9SDimitry Andric // soon. It is more likely that previous register, which is callee saved, is 2166e8d8bef9SDimitry Andric // going to stay unclobbered longer, even if it is killed. 2167e8d8bef9SDimitry Andric // 2168e8d8bef9SDimitry Andric // For InstrRefBasedImpl, we can track multiple locations per value, so 2169e8d8bef9SDimitry Andric // ignore this condition. 2170e8d8bef9SDimitry Andric if (EmulateOldLDV && !isCalleeSavedReg(DestReg)) 2171e8d8bef9SDimitry Andric return false; 2172e8d8bef9SDimitry Andric 2173e8d8bef9SDimitry Andric // InstrRefBasedImpl only followed killing copies. 2174e8d8bef9SDimitry Andric if (EmulateOldLDV && !SrcRegOp->isKill()) 2175e8d8bef9SDimitry Andric return false; 2176e8d8bef9SDimitry Andric 2177753f127fSDimitry Andric // Before we update MTracker, remember which values were present in each of 2178753f127fSDimitry Andric // the locations about to be overwritten, so that we can recover any 2179753f127fSDimitry Andric // potentially clobbered variables. 2180753f127fSDimitry Andric DenseMap<LocIdx, ValueIDNum> ClobberedLocs; 2181753f127fSDimitry Andric if (TTracker) { 2182753f127fSDimitry Andric for (MCRegAliasIterator RAI(DestReg, TRI, true); RAI.isValid(); ++RAI) { 2183753f127fSDimitry Andric LocIdx ClobberedLoc = MTracker->getRegMLoc(*RAI); 2184753f127fSDimitry Andric auto MLocIt = TTracker->ActiveMLocs.find(ClobberedLoc); 2185753f127fSDimitry Andric // If ActiveMLocs isn't tracking this location or there are no variables 2186753f127fSDimitry Andric // using it, don't bother remembering. 2187753f127fSDimitry Andric if (MLocIt == TTracker->ActiveMLocs.end() || MLocIt->second.empty()) 2188753f127fSDimitry Andric continue; 2189753f127fSDimitry Andric ValueIDNum Value = MTracker->readReg(*RAI); 2190753f127fSDimitry Andric ClobberedLocs[ClobberedLoc] = Value; 2191753f127fSDimitry Andric } 2192753f127fSDimitry Andric } 2193753f127fSDimitry Andric 2194e8d8bef9SDimitry Andric // Copy MTracker info, including subregs if available. 2195e8d8bef9SDimitry Andric InstrRefBasedLDV::performCopy(SrcReg, DestReg); 2196e8d8bef9SDimitry Andric 2197753f127fSDimitry Andric // The copy might have clobbered variables based on the destination register. 2198753f127fSDimitry Andric // Tell TTracker about it, passing the old ValueIDNum to search for 2199753f127fSDimitry Andric // alternative locations (or else terminating those variables). 2200753f127fSDimitry Andric if (TTracker) { 2201753f127fSDimitry Andric for (auto LocVal : ClobberedLocs) { 2202753f127fSDimitry Andric TTracker->clobberMloc(LocVal.first, LocVal.second, MI.getIterator(), false); 2203753f127fSDimitry Andric } 2204753f127fSDimitry Andric } 2205753f127fSDimitry Andric 2206e8d8bef9SDimitry Andric // Only produce a transfer of DBG_VALUE within a block where old LDV 2207e8d8bef9SDimitry Andric // would have. We might make use of the additional value tracking in some 2208e8d8bef9SDimitry Andric // other way, later. 2209e8d8bef9SDimitry Andric if (TTracker && isCalleeSavedReg(DestReg) && SrcRegOp->isKill()) 2210e8d8bef9SDimitry Andric TTracker->transferMlocs(MTracker->getRegMLoc(SrcReg), 2211e8d8bef9SDimitry Andric MTracker->getRegMLoc(DestReg), MI.getIterator()); 2212e8d8bef9SDimitry Andric 2213e8d8bef9SDimitry Andric // VarLocBasedImpl would quit tracking the old location after copying. 2214e8d8bef9SDimitry Andric if (EmulateOldLDV && SrcReg != DestReg) 2215e8d8bef9SDimitry Andric MTracker->defReg(SrcReg, CurBB, CurInst); 2216e8d8bef9SDimitry Andric 2217e8d8bef9SDimitry Andric return true; 2218e8d8bef9SDimitry Andric } 2219e8d8bef9SDimitry Andric 2220e8d8bef9SDimitry Andric /// Accumulate a mapping between each DILocalVariable fragment and other 2221e8d8bef9SDimitry Andric /// fragments of that DILocalVariable which overlap. This reduces work during 2222e8d8bef9SDimitry Andric /// the data-flow stage from "Find any overlapping fragments" to "Check if the 2223e8d8bef9SDimitry Andric /// known-to-overlap fragments are present". 22244824e7fdSDimitry Andric /// \param MI A previously unprocessed debug instruction to analyze for 2225e8d8bef9SDimitry Andric /// fragment usage. 2226e8d8bef9SDimitry Andric void InstrRefBasedLDV::accumulateFragmentMap(MachineInstr &MI) { 2227bdd1243dSDimitry Andric assert(MI.isDebugValueLike()); 2228e8d8bef9SDimitry Andric DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(), 2229e8d8bef9SDimitry Andric MI.getDebugLoc()->getInlinedAt()); 2230e8d8bef9SDimitry Andric FragmentInfo ThisFragment = MIVar.getFragmentOrDefault(); 2231e8d8bef9SDimitry Andric 2232e8d8bef9SDimitry Andric // If this is the first sighting of this variable, then we are guaranteed 2233e8d8bef9SDimitry Andric // there are currently no overlapping fragments either. Initialize the set 2234e8d8bef9SDimitry Andric // of seen fragments, record no overlaps for the current one, and return. 2235e8d8bef9SDimitry Andric auto SeenIt = SeenFragments.find(MIVar.getVariable()); 2236e8d8bef9SDimitry Andric if (SeenIt == SeenFragments.end()) { 2237e8d8bef9SDimitry Andric SmallSet<FragmentInfo, 4> OneFragment; 2238e8d8bef9SDimitry Andric OneFragment.insert(ThisFragment); 2239e8d8bef9SDimitry Andric SeenFragments.insert({MIVar.getVariable(), OneFragment}); 2240e8d8bef9SDimitry Andric 2241e8d8bef9SDimitry Andric OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}}); 2242e8d8bef9SDimitry Andric return; 2243e8d8bef9SDimitry Andric } 2244e8d8bef9SDimitry Andric 2245e8d8bef9SDimitry Andric // If this particular Variable/Fragment pair already exists in the overlap 2246e8d8bef9SDimitry Andric // map, it has already been accounted for. 2247e8d8bef9SDimitry Andric auto IsInOLapMap = 2248e8d8bef9SDimitry Andric OverlapFragments.insert({{MIVar.getVariable(), ThisFragment}, {}}); 2249e8d8bef9SDimitry Andric if (!IsInOLapMap.second) 2250e8d8bef9SDimitry Andric return; 2251e8d8bef9SDimitry Andric 2252e8d8bef9SDimitry Andric auto &ThisFragmentsOverlaps = IsInOLapMap.first->second; 2253e8d8bef9SDimitry Andric auto &AllSeenFragments = SeenIt->second; 2254e8d8bef9SDimitry Andric 2255e8d8bef9SDimitry Andric // Otherwise, examine all other seen fragments for this variable, with "this" 2256e8d8bef9SDimitry Andric // fragment being a previously unseen fragment. Record any pair of 2257e8d8bef9SDimitry Andric // overlapping fragments. 2258fcaf7f86SDimitry Andric for (const auto &ASeenFragment : AllSeenFragments) { 2259e8d8bef9SDimitry Andric // Does this previously seen fragment overlap? 2260e8d8bef9SDimitry Andric if (DIExpression::fragmentsOverlap(ThisFragment, ASeenFragment)) { 2261e8d8bef9SDimitry Andric // Yes: Mark the current fragment as being overlapped. 2262e8d8bef9SDimitry Andric ThisFragmentsOverlaps.push_back(ASeenFragment); 2263e8d8bef9SDimitry Andric // Mark the previously seen fragment as being overlapped by the current 2264e8d8bef9SDimitry Andric // one. 2265e8d8bef9SDimitry Andric auto ASeenFragmentsOverlaps = 2266e8d8bef9SDimitry Andric OverlapFragments.find({MIVar.getVariable(), ASeenFragment}); 2267e8d8bef9SDimitry Andric assert(ASeenFragmentsOverlaps != OverlapFragments.end() && 2268e8d8bef9SDimitry Andric "Previously seen var fragment has no vector of overlaps"); 2269e8d8bef9SDimitry Andric ASeenFragmentsOverlaps->second.push_back(ThisFragment); 2270e8d8bef9SDimitry Andric } 2271e8d8bef9SDimitry Andric } 2272e8d8bef9SDimitry Andric 2273e8d8bef9SDimitry Andric AllSeenFragments.insert(ThisFragment); 2274e8d8bef9SDimitry Andric } 2275e8d8bef9SDimitry Andric 22765f757f3fSDimitry Andric void InstrRefBasedLDV::process(MachineInstr &MI, 22775f757f3fSDimitry Andric const FuncValueTable *MLiveOuts, 22785f757f3fSDimitry Andric const FuncValueTable *MLiveIns) { 2279e8d8bef9SDimitry Andric // Try to interpret an MI as a debug or transfer instruction. Only if it's 2280e8d8bef9SDimitry Andric // none of these should we interpret it's register defs as new value 2281e8d8bef9SDimitry Andric // definitions. 2282e8d8bef9SDimitry Andric if (transferDebugValue(MI)) 2283e8d8bef9SDimitry Andric return; 2284fe6060f1SDimitry Andric if (transferDebugInstrRef(MI, MLiveOuts, MLiveIns)) 2285fe6060f1SDimitry Andric return; 2286fe6060f1SDimitry Andric if (transferDebugPHI(MI)) 2287e8d8bef9SDimitry Andric return; 2288e8d8bef9SDimitry Andric if (transferRegisterCopy(MI)) 2289e8d8bef9SDimitry Andric return; 2290e8d8bef9SDimitry Andric if (transferSpillOrRestoreInst(MI)) 2291e8d8bef9SDimitry Andric return; 2292e8d8bef9SDimitry Andric transferRegisterDef(MI); 2293e8d8bef9SDimitry Andric } 2294e8d8bef9SDimitry Andric 2295e8d8bef9SDimitry Andric void InstrRefBasedLDV::produceMLocTransferFunction( 2296e8d8bef9SDimitry Andric MachineFunction &MF, SmallVectorImpl<MLocTransferMap> &MLocTransfer, 2297e8d8bef9SDimitry Andric unsigned MaxNumBlocks) { 2298e8d8bef9SDimitry Andric // Because we try to optimize around register mask operands by ignoring regs 2299e8d8bef9SDimitry Andric // that aren't currently tracked, we set up something ugly for later: RegMask 2300e8d8bef9SDimitry Andric // operands that are seen earlier than the first use of a register, still need 2301e8d8bef9SDimitry Andric // to clobber that register in the transfer function. But this information 2302e8d8bef9SDimitry Andric // isn't actively recorded. Instead, we track each RegMask used in each block, 2303e8d8bef9SDimitry Andric // and accumulated the clobbered but untracked registers in each block into 2304e8d8bef9SDimitry Andric // the following bitvector. Later, if new values are tracked, we can add 2305e8d8bef9SDimitry Andric // appropriate clobbers. 2306e8d8bef9SDimitry Andric SmallVector<BitVector, 32> BlockMasks; 2307e8d8bef9SDimitry Andric BlockMasks.resize(MaxNumBlocks); 2308e8d8bef9SDimitry Andric 2309e8d8bef9SDimitry Andric // Reserve one bit per register for the masks described above. 2310e8d8bef9SDimitry Andric unsigned BVWords = MachineOperand::getRegMaskSize(TRI->getNumRegs()); 2311e8d8bef9SDimitry Andric for (auto &BV : BlockMasks) 2312e8d8bef9SDimitry Andric BV.resize(TRI->getNumRegs(), true); 2313e8d8bef9SDimitry Andric 2314e8d8bef9SDimitry Andric // Step through all instructions and inhale the transfer function. 2315e8d8bef9SDimitry Andric for (auto &MBB : MF) { 2316e8d8bef9SDimitry Andric // Object fields that are read by trackers to know where we are in the 2317e8d8bef9SDimitry Andric // function. 2318e8d8bef9SDimitry Andric CurBB = MBB.getNumber(); 2319e8d8bef9SDimitry Andric CurInst = 1; 2320e8d8bef9SDimitry Andric 2321e8d8bef9SDimitry Andric // Set all machine locations to a PHI value. For transfer function 2322e8d8bef9SDimitry Andric // production only, this signifies the live-in value to the block. 2323e8d8bef9SDimitry Andric MTracker->reset(); 2324e8d8bef9SDimitry Andric MTracker->setMPhis(CurBB); 2325e8d8bef9SDimitry Andric 2326e8d8bef9SDimitry Andric // Step through each instruction in this block. 2327e8d8bef9SDimitry Andric for (auto &MI : MBB) { 232881ad6265SDimitry Andric // Pass in an empty unique_ptr for the value tables when accumulating the 232981ad6265SDimitry Andric // machine transfer function. 233081ad6265SDimitry Andric process(MI, nullptr, nullptr); 233181ad6265SDimitry Andric 2332e8d8bef9SDimitry Andric // Also accumulate fragment map. 2333bdd1243dSDimitry Andric if (MI.isDebugValueLike()) 2334e8d8bef9SDimitry Andric accumulateFragmentMap(MI); 2335e8d8bef9SDimitry Andric 2336e8d8bef9SDimitry Andric // Create a map from the instruction number (if present) to the 2337e8d8bef9SDimitry Andric // MachineInstr and its position. 2338e8d8bef9SDimitry Andric if (uint64_t InstrNo = MI.peekDebugInstrNum()) { 2339e8d8bef9SDimitry Andric auto InstrAndPos = std::make_pair(&MI, CurInst); 2340e8d8bef9SDimitry Andric auto InsertResult = 2341e8d8bef9SDimitry Andric DebugInstrNumToInstr.insert(std::make_pair(InstrNo, InstrAndPos)); 2342e8d8bef9SDimitry Andric 2343e8d8bef9SDimitry Andric // There should never be duplicate instruction numbers. 2344e8d8bef9SDimitry Andric assert(InsertResult.second); 2345e8d8bef9SDimitry Andric (void)InsertResult; 2346e8d8bef9SDimitry Andric } 2347e8d8bef9SDimitry Andric 2348e8d8bef9SDimitry Andric ++CurInst; 2349e8d8bef9SDimitry Andric } 2350e8d8bef9SDimitry Andric 2351e8d8bef9SDimitry Andric // Produce the transfer function, a map of machine location to new value. If 2352e8d8bef9SDimitry Andric // any machine location has the live-in phi value from the start of the 2353e8d8bef9SDimitry Andric // block, it's live-through and doesn't need recording in the transfer 2354e8d8bef9SDimitry Andric // function. 2355e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 2356e8d8bef9SDimitry Andric LocIdx Idx = Location.Idx; 2357e8d8bef9SDimitry Andric ValueIDNum &P = Location.Value; 2358e8d8bef9SDimitry Andric if (P.isPHI() && P.getLoc() == Idx.asU64()) 2359e8d8bef9SDimitry Andric continue; 2360e8d8bef9SDimitry Andric 2361e8d8bef9SDimitry Andric // Insert-or-update. 2362e8d8bef9SDimitry Andric auto &TransferMap = MLocTransfer[CurBB]; 2363e8d8bef9SDimitry Andric auto Result = TransferMap.insert(std::make_pair(Idx.asU64(), P)); 2364e8d8bef9SDimitry Andric if (!Result.second) 2365e8d8bef9SDimitry Andric Result.first->second = P; 2366e8d8bef9SDimitry Andric } 2367e8d8bef9SDimitry Andric 2368bdd1243dSDimitry Andric // Accumulate any bitmask operands into the clobbered reg mask for this 2369e8d8bef9SDimitry Andric // block. 2370e8d8bef9SDimitry Andric for (auto &P : MTracker->Masks) { 2371e8d8bef9SDimitry Andric BlockMasks[CurBB].clearBitsNotInMask(P.first->getRegMask(), BVWords); 2372e8d8bef9SDimitry Andric } 2373e8d8bef9SDimitry Andric } 2374e8d8bef9SDimitry Andric 2375e8d8bef9SDimitry Andric // Compute a bitvector of all the registers that are tracked in this block. 2376e8d8bef9SDimitry Andric BitVector UsedRegs(TRI->getNumRegs()); 2377e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 2378e8d8bef9SDimitry Andric unsigned ID = MTracker->LocIdxToLocID[Location.Idx]; 2379349cc55cSDimitry Andric // Ignore stack slots, and aliases of the stack pointer. 2380349cc55cSDimitry Andric if (ID >= TRI->getNumRegs() || MTracker->SPAliases.count(ID)) 2381e8d8bef9SDimitry Andric continue; 2382e8d8bef9SDimitry Andric UsedRegs.set(ID); 2383e8d8bef9SDimitry Andric } 2384e8d8bef9SDimitry Andric 2385e8d8bef9SDimitry Andric // Check that any regmask-clobber of a register that gets tracked, is not 2386e8d8bef9SDimitry Andric // live-through in the transfer function. It needs to be clobbered at the 2387e8d8bef9SDimitry Andric // very least. 2388e8d8bef9SDimitry Andric for (unsigned int I = 0; I < MaxNumBlocks; ++I) { 2389e8d8bef9SDimitry Andric BitVector &BV = BlockMasks[I]; 2390e8d8bef9SDimitry Andric BV.flip(); 2391e8d8bef9SDimitry Andric BV &= UsedRegs; 2392e8d8bef9SDimitry Andric // This produces all the bits that we clobber, but also use. Check that 2393e8d8bef9SDimitry Andric // they're all clobbered or at least set in the designated transfer 2394e8d8bef9SDimitry Andric // elem. 2395e8d8bef9SDimitry Andric for (unsigned Bit : BV.set_bits()) { 2396349cc55cSDimitry Andric unsigned ID = MTracker->getLocID(Bit); 2397e8d8bef9SDimitry Andric LocIdx Idx = MTracker->LocIDToLocIdx[ID]; 2398e8d8bef9SDimitry Andric auto &TransferMap = MLocTransfer[I]; 2399e8d8bef9SDimitry Andric 2400e8d8bef9SDimitry Andric // Install a value representing the fact that this location is effectively 2401e8d8bef9SDimitry Andric // written to in this block. As there's no reserved value, instead use 2402e8d8bef9SDimitry Andric // a value number that is never generated. Pick the value number for the 2403e8d8bef9SDimitry Andric // first instruction in the block, def'ing this location, which we know 2404e8d8bef9SDimitry Andric // this block never used anyway. 2405e8d8bef9SDimitry Andric ValueIDNum NotGeneratedNum = ValueIDNum(I, 1, Idx); 2406e8d8bef9SDimitry Andric auto Result = 2407e8d8bef9SDimitry Andric TransferMap.insert(std::make_pair(Idx.asU64(), NotGeneratedNum)); 2408e8d8bef9SDimitry Andric if (!Result.second) { 2409e8d8bef9SDimitry Andric ValueIDNum &ValueID = Result.first->second; 2410e8d8bef9SDimitry Andric if (ValueID.getBlock() == I && ValueID.isPHI()) 2411e8d8bef9SDimitry Andric // It was left as live-through. Set it to clobbered. 2412e8d8bef9SDimitry Andric ValueID = NotGeneratedNum; 2413e8d8bef9SDimitry Andric } 2414e8d8bef9SDimitry Andric } 2415e8d8bef9SDimitry Andric } 2416e8d8bef9SDimitry Andric } 2417e8d8bef9SDimitry Andric 2418349cc55cSDimitry Andric bool InstrRefBasedLDV::mlocJoin( 2419349cc55cSDimitry Andric MachineBasicBlock &MBB, SmallPtrSet<const MachineBasicBlock *, 16> &Visited, 242081ad6265SDimitry Andric FuncValueTable &OutLocs, ValueTable &InLocs) { 2421e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n"); 2422e8d8bef9SDimitry Andric bool Changed = false; 2423e8d8bef9SDimitry Andric 2424349cc55cSDimitry Andric // Handle value-propagation when control flow merges on entry to a block. For 2425349cc55cSDimitry Andric // any location without a PHI already placed, the location has the same value 2426349cc55cSDimitry Andric // as its predecessors. If a PHI is placed, test to see whether it's now a 2427349cc55cSDimitry Andric // redundant PHI that we can eliminate. 2428349cc55cSDimitry Andric 2429e8d8bef9SDimitry Andric SmallVector<const MachineBasicBlock *, 8> BlockOrders; 2430fcaf7f86SDimitry Andric for (auto *Pred : MBB.predecessors()) 2431e8d8bef9SDimitry Andric BlockOrders.push_back(Pred); 2432e8d8bef9SDimitry Andric 2433e8d8bef9SDimitry Andric // Visit predecessors in RPOT order. 2434e8d8bef9SDimitry Andric auto Cmp = [&](const MachineBasicBlock *A, const MachineBasicBlock *B) { 2435e8d8bef9SDimitry Andric return BBToOrder.find(A)->second < BBToOrder.find(B)->second; 2436e8d8bef9SDimitry Andric }; 2437e8d8bef9SDimitry Andric llvm::sort(BlockOrders, Cmp); 2438e8d8bef9SDimitry Andric 2439e8d8bef9SDimitry Andric // Skip entry block. 2440297eecfbSDimitry Andric if (BlockOrders.size() == 0) { 2441297eecfbSDimitry Andric // FIXME: We don't use assert here to prevent instr-ref-unreachable.mir 2442297eecfbSDimitry Andric // failing. 2443297eecfbSDimitry Andric LLVM_DEBUG(if (!MBB.isEntryBlock()) dbgs() 2444297eecfbSDimitry Andric << "Found not reachable block " << MBB.getFullName() 2445297eecfbSDimitry Andric << " from entry which may lead out of " 2446297eecfbSDimitry Andric "bound access to VarLocs\n"); 2447349cc55cSDimitry Andric return false; 2448297eecfbSDimitry Andric } 2449e8d8bef9SDimitry Andric 2450349cc55cSDimitry Andric // Step through all machine locations, look at each predecessor and test 2451349cc55cSDimitry Andric // whether we can eliminate redundant PHIs. 2452e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 2453e8d8bef9SDimitry Andric LocIdx Idx = Location.Idx; 2454349cc55cSDimitry Andric 2455e8d8bef9SDimitry Andric // Pick out the first predecessors live-out value for this location. It's 2456349cc55cSDimitry Andric // guaranteed to not be a backedge, as we order by RPO. 2457cb14a3feSDimitry Andric ValueIDNum FirstVal = OutLocs[*BlockOrders[0]][Idx.asU64()]; 2458e8d8bef9SDimitry Andric 2459349cc55cSDimitry Andric // If we've already eliminated a PHI here, do no further checking, just 2460349cc55cSDimitry Andric // propagate the first live-in value into this block. 2461349cc55cSDimitry Andric if (InLocs[Idx.asU64()] != ValueIDNum(MBB.getNumber(), 0, Idx)) { 2462349cc55cSDimitry Andric if (InLocs[Idx.asU64()] != FirstVal) { 2463349cc55cSDimitry Andric InLocs[Idx.asU64()] = FirstVal; 2464349cc55cSDimitry Andric Changed |= true; 2465349cc55cSDimitry Andric } 2466349cc55cSDimitry Andric continue; 2467349cc55cSDimitry Andric } 2468349cc55cSDimitry Andric 2469349cc55cSDimitry Andric // We're now examining a PHI to see whether it's un-necessary. Loop around 2470349cc55cSDimitry Andric // the other live-in values and test whether they're all the same. 2471e8d8bef9SDimitry Andric bool Disagree = false; 2472e8d8bef9SDimitry Andric for (unsigned int I = 1; I < BlockOrders.size(); ++I) { 2473349cc55cSDimitry Andric const MachineBasicBlock *PredMBB = BlockOrders[I]; 2474cb14a3feSDimitry Andric const ValueIDNum &PredLiveOut = OutLocs[*PredMBB][Idx.asU64()]; 2475349cc55cSDimitry Andric 2476349cc55cSDimitry Andric // Incoming values agree, continue trying to eliminate this PHI. 2477349cc55cSDimitry Andric if (FirstVal == PredLiveOut) 2478349cc55cSDimitry Andric continue; 2479349cc55cSDimitry Andric 2480349cc55cSDimitry Andric // We can also accept a PHI value that feeds back into itself. 2481349cc55cSDimitry Andric if (PredLiveOut == ValueIDNum(MBB.getNumber(), 0, Idx)) 2482349cc55cSDimitry Andric continue; 2483349cc55cSDimitry Andric 2484e8d8bef9SDimitry Andric // Live-out of a predecessor disagrees with the first predecessor. 2485e8d8bef9SDimitry Andric Disagree = true; 2486e8d8bef9SDimitry Andric } 2487e8d8bef9SDimitry Andric 2488349cc55cSDimitry Andric // No disagreement? No PHI. Otherwise, leave the PHI in live-ins. 2489349cc55cSDimitry Andric if (!Disagree) { 2490349cc55cSDimitry Andric InLocs[Idx.asU64()] = FirstVal; 2491e8d8bef9SDimitry Andric Changed |= true; 2492e8d8bef9SDimitry Andric } 2493e8d8bef9SDimitry Andric } 2494e8d8bef9SDimitry Andric 2495e8d8bef9SDimitry Andric // TODO: Reimplement NumInserted and NumRemoved. 2496349cc55cSDimitry Andric return Changed; 2497e8d8bef9SDimitry Andric } 2498e8d8bef9SDimitry Andric 2499349cc55cSDimitry Andric void InstrRefBasedLDV::findStackIndexInterference( 2500349cc55cSDimitry Andric SmallVectorImpl<unsigned> &Slots) { 2501349cc55cSDimitry Andric // We could spend a bit of time finding the exact, minimal, set of stack 2502349cc55cSDimitry Andric // indexes that interfere with each other, much like reg units. Or, we can 2503349cc55cSDimitry Andric // rely on the fact that: 2504349cc55cSDimitry Andric // * The smallest / lowest index will interfere with everything at zero 2505349cc55cSDimitry Andric // offset, which will be the largest set of registers, 2506349cc55cSDimitry Andric // * Most indexes with non-zero offset will end up being interference units 2507349cc55cSDimitry Andric // anyway. 2508349cc55cSDimitry Andric // So just pick those out and return them. 2509349cc55cSDimitry Andric 2510349cc55cSDimitry Andric // We can rely on a single-byte stack index existing already, because we 2511349cc55cSDimitry Andric // initialize them in MLocTracker. 2512349cc55cSDimitry Andric auto It = MTracker->StackSlotIdxes.find({8, 0}); 2513349cc55cSDimitry Andric assert(It != MTracker->StackSlotIdxes.end()); 2514349cc55cSDimitry Andric Slots.push_back(It->second); 2515349cc55cSDimitry Andric 2516349cc55cSDimitry Andric // Find anything that has a non-zero offset and add that too. 2517349cc55cSDimitry Andric for (auto &Pair : MTracker->StackSlotIdxes) { 2518349cc55cSDimitry Andric // Is offset zero? If so, ignore. 2519349cc55cSDimitry Andric if (!Pair.first.second) 2520349cc55cSDimitry Andric continue; 2521349cc55cSDimitry Andric Slots.push_back(Pair.second); 2522349cc55cSDimitry Andric } 2523349cc55cSDimitry Andric } 2524349cc55cSDimitry Andric 2525349cc55cSDimitry Andric void InstrRefBasedLDV::placeMLocPHIs( 2526349cc55cSDimitry Andric MachineFunction &MF, SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks, 252781ad6265SDimitry Andric FuncValueTable &MInLocs, SmallVectorImpl<MLocTransferMap> &MLocTransfer) { 2528349cc55cSDimitry Andric SmallVector<unsigned, 4> StackUnits; 2529349cc55cSDimitry Andric findStackIndexInterference(StackUnits); 2530349cc55cSDimitry Andric 2531349cc55cSDimitry Andric // To avoid repeatedly running the PHI placement algorithm, leverage the 2532349cc55cSDimitry Andric // fact that a def of register MUST also def its register units. Find the 2533349cc55cSDimitry Andric // units for registers, place PHIs for them, and then replicate them for 2534349cc55cSDimitry Andric // aliasing registers. Some inputs that are never def'd (DBG_PHIs of 2535349cc55cSDimitry Andric // arguments) don't lead to register units being tracked, just place PHIs for 2536349cc55cSDimitry Andric // those registers directly. Stack slots have their own form of "unit", 2537349cc55cSDimitry Andric // store them to one side. 2538349cc55cSDimitry Andric SmallSet<Register, 32> RegUnitsToPHIUp; 2539349cc55cSDimitry Andric SmallSet<LocIdx, 32> NormalLocsToPHI; 2540349cc55cSDimitry Andric SmallSet<SpillLocationNo, 32> StackSlots; 2541349cc55cSDimitry Andric for (auto Location : MTracker->locations()) { 2542349cc55cSDimitry Andric LocIdx L = Location.Idx; 2543349cc55cSDimitry Andric if (MTracker->isSpill(L)) { 2544349cc55cSDimitry Andric StackSlots.insert(MTracker->locIDToSpill(MTracker->LocIdxToLocID[L])); 2545349cc55cSDimitry Andric continue; 2546349cc55cSDimitry Andric } 2547349cc55cSDimitry Andric 2548349cc55cSDimitry Andric Register R = MTracker->LocIdxToLocID[L]; 2549349cc55cSDimitry Andric SmallSet<Register, 8> FoundRegUnits; 2550349cc55cSDimitry Andric bool AnyIllegal = false; 255106c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(R.asMCReg())) { 255206c3fb27SDimitry Andric for (MCRegUnitRootIterator URoot(Unit, TRI); URoot.isValid(); ++URoot) { 2553349cc55cSDimitry Andric if (!MTracker->isRegisterTracked(*URoot)) { 2554349cc55cSDimitry Andric // Not all roots were loaded into the tracking map: this register 2555349cc55cSDimitry Andric // isn't actually def'd anywhere, we only read from it. Generate PHIs 2556349cc55cSDimitry Andric // for this reg, but don't iterate units. 2557349cc55cSDimitry Andric AnyIllegal = true; 2558349cc55cSDimitry Andric } else { 2559349cc55cSDimitry Andric FoundRegUnits.insert(*URoot); 2560349cc55cSDimitry Andric } 2561349cc55cSDimitry Andric } 2562349cc55cSDimitry Andric } 2563349cc55cSDimitry Andric 2564349cc55cSDimitry Andric if (AnyIllegal) { 2565349cc55cSDimitry Andric NormalLocsToPHI.insert(L); 2566349cc55cSDimitry Andric continue; 2567349cc55cSDimitry Andric } 2568349cc55cSDimitry Andric 2569349cc55cSDimitry Andric RegUnitsToPHIUp.insert(FoundRegUnits.begin(), FoundRegUnits.end()); 2570349cc55cSDimitry Andric } 2571349cc55cSDimitry Andric 2572349cc55cSDimitry Andric // Lambda to fetch PHIs for a given location, and write into the PHIBlocks 2573349cc55cSDimitry Andric // collection. 2574349cc55cSDimitry Andric SmallVector<MachineBasicBlock *, 32> PHIBlocks; 2575349cc55cSDimitry Andric auto CollectPHIsForLoc = [&](LocIdx L) { 2576349cc55cSDimitry Andric // Collect the set of defs. 2577349cc55cSDimitry Andric SmallPtrSet<MachineBasicBlock *, 32> DefBlocks; 2578349cc55cSDimitry Andric for (unsigned int I = 0; I < OrderToBB.size(); ++I) { 2579349cc55cSDimitry Andric MachineBasicBlock *MBB = OrderToBB[I]; 2580349cc55cSDimitry Andric const auto &TransferFunc = MLocTransfer[MBB->getNumber()]; 25815f757f3fSDimitry Andric if (TransferFunc.contains(L)) 2582349cc55cSDimitry Andric DefBlocks.insert(MBB); 2583349cc55cSDimitry Andric } 2584349cc55cSDimitry Andric 2585349cc55cSDimitry Andric // The entry block defs the location too: it's the live-in / argument value. 2586349cc55cSDimitry Andric // Only insert if there are other defs though; everything is trivially live 2587349cc55cSDimitry Andric // through otherwise. 2588349cc55cSDimitry Andric if (!DefBlocks.empty()) 2589349cc55cSDimitry Andric DefBlocks.insert(&*MF.begin()); 2590349cc55cSDimitry Andric 2591349cc55cSDimitry Andric // Ask the SSA construction algorithm where we should put PHIs. Clear 2592349cc55cSDimitry Andric // anything that might have been hanging around from earlier. 2593349cc55cSDimitry Andric PHIBlocks.clear(); 2594349cc55cSDimitry Andric BlockPHIPlacement(AllBlocks, DefBlocks, PHIBlocks); 2595349cc55cSDimitry Andric }; 2596349cc55cSDimitry Andric 2597349cc55cSDimitry Andric auto InstallPHIsAtLoc = [&PHIBlocks, &MInLocs](LocIdx L) { 2598349cc55cSDimitry Andric for (const MachineBasicBlock *MBB : PHIBlocks) 2599cb14a3feSDimitry Andric MInLocs[*MBB][L.asU64()] = ValueIDNum(MBB->getNumber(), 0, L); 2600349cc55cSDimitry Andric }; 2601349cc55cSDimitry Andric 2602349cc55cSDimitry Andric // For locations with no reg units, just place PHIs. 2603349cc55cSDimitry Andric for (LocIdx L : NormalLocsToPHI) { 2604349cc55cSDimitry Andric CollectPHIsForLoc(L); 2605349cc55cSDimitry Andric // Install those PHI values into the live-in value array. 2606349cc55cSDimitry Andric InstallPHIsAtLoc(L); 2607349cc55cSDimitry Andric } 2608349cc55cSDimitry Andric 2609349cc55cSDimitry Andric // For stack slots, calculate PHIs for the equivalent of the units, then 2610349cc55cSDimitry Andric // install for each index. 2611349cc55cSDimitry Andric for (SpillLocationNo Slot : StackSlots) { 2612349cc55cSDimitry Andric for (unsigned Idx : StackUnits) { 2613349cc55cSDimitry Andric unsigned SpillID = MTracker->getSpillIDWithIdx(Slot, Idx); 2614349cc55cSDimitry Andric LocIdx L = MTracker->getSpillMLoc(SpillID); 2615349cc55cSDimitry Andric CollectPHIsForLoc(L); 2616349cc55cSDimitry Andric InstallPHIsAtLoc(L); 2617349cc55cSDimitry Andric 2618349cc55cSDimitry Andric // Find anything that aliases this stack index, install PHIs for it too. 2619349cc55cSDimitry Andric unsigned Size, Offset; 2620349cc55cSDimitry Andric std::tie(Size, Offset) = MTracker->StackIdxesToPos[Idx]; 2621349cc55cSDimitry Andric for (auto &Pair : MTracker->StackSlotIdxes) { 2622349cc55cSDimitry Andric unsigned ThisSize, ThisOffset; 2623349cc55cSDimitry Andric std::tie(ThisSize, ThisOffset) = Pair.first; 2624349cc55cSDimitry Andric if (ThisSize + ThisOffset <= Offset || Size + Offset <= ThisOffset) 2625349cc55cSDimitry Andric continue; 2626349cc55cSDimitry Andric 2627349cc55cSDimitry Andric unsigned ThisID = MTracker->getSpillIDWithIdx(Slot, Pair.second); 2628349cc55cSDimitry Andric LocIdx ThisL = MTracker->getSpillMLoc(ThisID); 2629349cc55cSDimitry Andric InstallPHIsAtLoc(ThisL); 2630349cc55cSDimitry Andric } 2631349cc55cSDimitry Andric } 2632349cc55cSDimitry Andric } 2633349cc55cSDimitry Andric 2634349cc55cSDimitry Andric // For reg units, place PHIs, and then place them for any aliasing registers. 2635349cc55cSDimitry Andric for (Register R : RegUnitsToPHIUp) { 2636349cc55cSDimitry Andric LocIdx L = MTracker->lookupOrTrackRegister(R); 2637349cc55cSDimitry Andric CollectPHIsForLoc(L); 2638349cc55cSDimitry Andric 2639349cc55cSDimitry Andric // Install those PHI values into the live-in value array. 2640349cc55cSDimitry Andric InstallPHIsAtLoc(L); 2641349cc55cSDimitry Andric 2642349cc55cSDimitry Andric // Now find aliases and install PHIs for those. 2643349cc55cSDimitry Andric for (MCRegAliasIterator RAI(R, TRI, true); RAI.isValid(); ++RAI) { 2644349cc55cSDimitry Andric // Super-registers that are "above" the largest register read/written by 2645349cc55cSDimitry Andric // the function will alias, but will not be tracked. 2646349cc55cSDimitry Andric if (!MTracker->isRegisterTracked(*RAI)) 2647349cc55cSDimitry Andric continue; 2648349cc55cSDimitry Andric 2649349cc55cSDimitry Andric LocIdx AliasLoc = MTracker->lookupOrTrackRegister(*RAI); 2650349cc55cSDimitry Andric InstallPHIsAtLoc(AliasLoc); 2651349cc55cSDimitry Andric } 2652349cc55cSDimitry Andric } 2653349cc55cSDimitry Andric } 2654349cc55cSDimitry Andric 2655349cc55cSDimitry Andric void InstrRefBasedLDV::buildMLocValueMap( 265681ad6265SDimitry Andric MachineFunction &MF, FuncValueTable &MInLocs, FuncValueTable &MOutLocs, 2657e8d8bef9SDimitry Andric SmallVectorImpl<MLocTransferMap> &MLocTransfer) { 2658e8d8bef9SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>, 2659e8d8bef9SDimitry Andric std::greater<unsigned int>> 2660e8d8bef9SDimitry Andric Worklist, Pending; 2661e8d8bef9SDimitry Andric 2662e8d8bef9SDimitry Andric // We track what is on the current and pending worklist to avoid inserting 2663e8d8bef9SDimitry Andric // the same thing twice. We could avoid this with a custom priority queue, 2664e8d8bef9SDimitry Andric // but this is probably not worth it. 2665e8d8bef9SDimitry Andric SmallPtrSet<MachineBasicBlock *, 16> OnPending, OnWorklist; 2666e8d8bef9SDimitry Andric 2667349cc55cSDimitry Andric // Initialize worklist with every block to be visited. Also produce list of 2668349cc55cSDimitry Andric // all blocks. 2669349cc55cSDimitry Andric SmallPtrSet<MachineBasicBlock *, 32> AllBlocks; 2670e8d8bef9SDimitry Andric for (unsigned int I = 0; I < BBToOrder.size(); ++I) { 2671e8d8bef9SDimitry Andric Worklist.push(I); 2672e8d8bef9SDimitry Andric OnWorklist.insert(OrderToBB[I]); 2673349cc55cSDimitry Andric AllBlocks.insert(OrderToBB[I]); 2674e8d8bef9SDimitry Andric } 2675e8d8bef9SDimitry Andric 2676349cc55cSDimitry Andric // Initialize entry block to PHIs. These represent arguments. 2677349cc55cSDimitry Andric for (auto Location : MTracker->locations()) 2678cb14a3feSDimitry Andric MInLocs.tableForEntryMBB()[Location.Idx.asU64()] = 2679cb14a3feSDimitry Andric ValueIDNum(0, 0, Location.Idx); 2680349cc55cSDimitry Andric 2681e8d8bef9SDimitry Andric MTracker->reset(); 2682e8d8bef9SDimitry Andric 2683349cc55cSDimitry Andric // Start by placing PHIs, using the usual SSA constructor algorithm. Consider 2684349cc55cSDimitry Andric // any machine-location that isn't live-through a block to be def'd in that 2685349cc55cSDimitry Andric // block. 2686349cc55cSDimitry Andric placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer); 2687e8d8bef9SDimitry Andric 2688349cc55cSDimitry Andric // Propagate values to eliminate redundant PHIs. At the same time, this 2689349cc55cSDimitry Andric // produces the table of Block x Location => Value for the entry to each 2690349cc55cSDimitry Andric // block. 2691349cc55cSDimitry Andric // The kind of PHIs we can eliminate are, for example, where one path in a 2692349cc55cSDimitry Andric // conditional spills and restores a register, and the register still has 2693349cc55cSDimitry Andric // the same value once control flow joins, unbeknowns to the PHI placement 2694349cc55cSDimitry Andric // code. Propagating values allows us to identify such un-necessary PHIs and 2695349cc55cSDimitry Andric // remove them. 2696e8d8bef9SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> Visited; 2697e8d8bef9SDimitry Andric while (!Worklist.empty() || !Pending.empty()) { 2698e8d8bef9SDimitry Andric // Vector for storing the evaluated block transfer function. 2699e8d8bef9SDimitry Andric SmallVector<std::pair<LocIdx, ValueIDNum>, 32> ToRemap; 2700e8d8bef9SDimitry Andric 2701e8d8bef9SDimitry Andric while (!Worklist.empty()) { 2702e8d8bef9SDimitry Andric MachineBasicBlock *MBB = OrderToBB[Worklist.top()]; 2703e8d8bef9SDimitry Andric CurBB = MBB->getNumber(); 2704e8d8bef9SDimitry Andric Worklist.pop(); 2705e8d8bef9SDimitry Andric 2706e8d8bef9SDimitry Andric // Join the values in all predecessor blocks. 2707349cc55cSDimitry Andric bool InLocsChanged; 2708cb14a3feSDimitry Andric InLocsChanged = mlocJoin(*MBB, Visited, MOutLocs, MInLocs[*MBB]); 2709e8d8bef9SDimitry Andric InLocsChanged |= Visited.insert(MBB).second; 2710e8d8bef9SDimitry Andric 2711e8d8bef9SDimitry Andric // Don't examine transfer function if we've visited this loc at least 2712e8d8bef9SDimitry Andric // once, and inlocs haven't changed. 2713e8d8bef9SDimitry Andric if (!InLocsChanged) 2714e8d8bef9SDimitry Andric continue; 2715e8d8bef9SDimitry Andric 2716e8d8bef9SDimitry Andric // Load the current set of live-ins into MLocTracker. 2717cb14a3feSDimitry Andric MTracker->loadFromArray(MInLocs[*MBB], CurBB); 2718e8d8bef9SDimitry Andric 2719e8d8bef9SDimitry Andric // Each element of the transfer function can be a new def, or a read of 2720e8d8bef9SDimitry Andric // a live-in value. Evaluate each element, and store to "ToRemap". 2721e8d8bef9SDimitry Andric ToRemap.clear(); 2722e8d8bef9SDimitry Andric for (auto &P : MLocTransfer[CurBB]) { 2723e8d8bef9SDimitry Andric if (P.second.getBlock() == CurBB && P.second.isPHI()) { 2724e8d8bef9SDimitry Andric // This is a movement of whatever was live in. Read it. 2725349cc55cSDimitry Andric ValueIDNum NewID = MTracker->readMLoc(P.second.getLoc()); 2726e8d8bef9SDimitry Andric ToRemap.push_back(std::make_pair(P.first, NewID)); 2727e8d8bef9SDimitry Andric } else { 2728e8d8bef9SDimitry Andric // It's a def. Just set it. 2729e8d8bef9SDimitry Andric assert(P.second.getBlock() == CurBB); 2730e8d8bef9SDimitry Andric ToRemap.push_back(std::make_pair(P.first, P.second)); 2731e8d8bef9SDimitry Andric } 2732e8d8bef9SDimitry Andric } 2733e8d8bef9SDimitry Andric 2734e8d8bef9SDimitry Andric // Commit the transfer function changes into mloc tracker, which 2735e8d8bef9SDimitry Andric // transforms the contents of the MLocTracker into the live-outs. 2736e8d8bef9SDimitry Andric for (auto &P : ToRemap) 2737e8d8bef9SDimitry Andric MTracker->setMLoc(P.first, P.second); 2738e8d8bef9SDimitry Andric 2739e8d8bef9SDimitry Andric // Now copy out-locs from mloc tracker into out-loc vector, checking 2740e8d8bef9SDimitry Andric // whether changes have occurred. These changes can have come from both 2741e8d8bef9SDimitry Andric // the transfer function, and mlocJoin. 2742e8d8bef9SDimitry Andric bool OLChanged = false; 2743e8d8bef9SDimitry Andric for (auto Location : MTracker->locations()) { 2744cb14a3feSDimitry Andric OLChanged |= MOutLocs[*MBB][Location.Idx.asU64()] != Location.Value; 2745cb14a3feSDimitry Andric MOutLocs[*MBB][Location.Idx.asU64()] = Location.Value; 2746e8d8bef9SDimitry Andric } 2747e8d8bef9SDimitry Andric 2748e8d8bef9SDimitry Andric MTracker->reset(); 2749e8d8bef9SDimitry Andric 2750e8d8bef9SDimitry Andric // No need to examine successors again if out-locs didn't change. 2751e8d8bef9SDimitry Andric if (!OLChanged) 2752e8d8bef9SDimitry Andric continue; 2753e8d8bef9SDimitry Andric 2754e8d8bef9SDimitry Andric // All successors should be visited: put any back-edges on the pending 2755349cc55cSDimitry Andric // list for the next pass-through, and any other successors to be 2756349cc55cSDimitry Andric // visited this pass, if they're not going to be already. 2757fcaf7f86SDimitry Andric for (auto *s : MBB->successors()) { 2758e8d8bef9SDimitry Andric // Does branching to this successor represent a back-edge? 2759e8d8bef9SDimitry Andric if (BBToOrder[s] > BBToOrder[MBB]) { 2760e8d8bef9SDimitry Andric // No: visit it during this dataflow iteration. 2761e8d8bef9SDimitry Andric if (OnWorklist.insert(s).second) 2762e8d8bef9SDimitry Andric Worklist.push(BBToOrder[s]); 2763e8d8bef9SDimitry Andric } else { 2764e8d8bef9SDimitry Andric // Yes: visit it on the next iteration. 2765e8d8bef9SDimitry Andric if (OnPending.insert(s).second) 2766e8d8bef9SDimitry Andric Pending.push(BBToOrder[s]); 2767e8d8bef9SDimitry Andric } 2768e8d8bef9SDimitry Andric } 2769e8d8bef9SDimitry Andric } 2770e8d8bef9SDimitry Andric 2771e8d8bef9SDimitry Andric Worklist.swap(Pending); 2772e8d8bef9SDimitry Andric std::swap(OnPending, OnWorklist); 2773e8d8bef9SDimitry Andric OnPending.clear(); 2774e8d8bef9SDimitry Andric // At this point, pending must be empty, since it was just the empty 2775e8d8bef9SDimitry Andric // worklist 2776e8d8bef9SDimitry Andric assert(Pending.empty() && "Pending should be empty"); 2777e8d8bef9SDimitry Andric } 2778e8d8bef9SDimitry Andric 2779349cc55cSDimitry Andric // Once all the live-ins don't change on mlocJoin(), we've eliminated all 2780349cc55cSDimitry Andric // redundant PHIs. 2781e8d8bef9SDimitry Andric } 2782e8d8bef9SDimitry Andric 2783349cc55cSDimitry Andric void InstrRefBasedLDV::BlockPHIPlacement( 2784349cc55cSDimitry Andric const SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks, 2785349cc55cSDimitry Andric const SmallPtrSetImpl<MachineBasicBlock *> &DefBlocks, 2786349cc55cSDimitry Andric SmallVectorImpl<MachineBasicBlock *> &PHIBlocks) { 2787349cc55cSDimitry Andric // Apply IDF calculator to the designated set of location defs, storing 2788349cc55cSDimitry Andric // required PHIs into PHIBlocks. Uses the dominator tree stored in the 2789349cc55cSDimitry Andric // InstrRefBasedLDV object. 27901fd87a68SDimitry Andric IDFCalculatorBase<MachineBasicBlock, false> IDF(DomTree->getBase()); 2791349cc55cSDimitry Andric 2792349cc55cSDimitry Andric IDF.setLiveInBlocks(AllBlocks); 2793349cc55cSDimitry Andric IDF.setDefiningBlocks(DefBlocks); 2794349cc55cSDimitry Andric IDF.calculate(PHIBlocks); 2795e8d8bef9SDimitry Andric } 2796e8d8bef9SDimitry Andric 2797bdd1243dSDimitry Andric bool InstrRefBasedLDV::pickVPHILoc( 2798bdd1243dSDimitry Andric SmallVectorImpl<DbgOpID> &OutValues, const MachineBasicBlock &MBB, 279981ad6265SDimitry Andric const LiveIdxT &LiveOuts, FuncValueTable &MOutLocs, 2800349cc55cSDimitry Andric const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders) { 2801349cc55cSDimitry Andric 2802349cc55cSDimitry Andric // No predecessors means no PHIs. 2803349cc55cSDimitry Andric if (BlockOrders.empty()) 2804bdd1243dSDimitry Andric return false; 2805e8d8bef9SDimitry Andric 2806bdd1243dSDimitry Andric // All the location operands that do not already agree need to be joined, 2807bdd1243dSDimitry Andric // track the indices of each such location operand here. 2808bdd1243dSDimitry Andric SmallDenseSet<unsigned> LocOpsToJoin; 2809bdd1243dSDimitry Andric 2810bdd1243dSDimitry Andric auto FirstValueIt = LiveOuts.find(BlockOrders[0]); 2811bdd1243dSDimitry Andric if (FirstValueIt == LiveOuts.end()) 2812bdd1243dSDimitry Andric return false; 2813bdd1243dSDimitry Andric const DbgValue &FirstValue = *FirstValueIt->second; 2814bdd1243dSDimitry Andric 2815bdd1243dSDimitry Andric for (const auto p : BlockOrders) { 2816349cc55cSDimitry Andric auto OutValIt = LiveOuts.find(p); 2817349cc55cSDimitry Andric if (OutValIt == LiveOuts.end()) 2818349cc55cSDimitry Andric // If we have a predecessor not in scope, we'll never find a PHI position. 2819bdd1243dSDimitry Andric return false; 2820349cc55cSDimitry Andric const DbgValue &OutVal = *OutValIt->second; 2821e8d8bef9SDimitry Andric 2822bdd1243dSDimitry Andric // No-values cannot have locations we can join on. 2823bdd1243dSDimitry Andric if (OutVal.Kind == DbgValue::NoVal) 2824bdd1243dSDimitry Andric return false; 2825e8d8bef9SDimitry Andric 2826bdd1243dSDimitry Andric // For unjoined VPHIs where we don't know the location, we definitely 2827bdd1243dSDimitry Andric // can't find a join loc unless the VPHI is a backedge. 2828bdd1243dSDimitry Andric if (OutVal.isUnjoinedPHI() && OutVal.BlockNo != MBB.getNumber()) 2829bdd1243dSDimitry Andric return false; 2830bdd1243dSDimitry Andric 2831bdd1243dSDimitry Andric if (!FirstValue.Properties.isJoinable(OutVal.Properties)) 2832bdd1243dSDimitry Andric return false; 2833bdd1243dSDimitry Andric 2834bdd1243dSDimitry Andric for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) { 2835bdd1243dSDimitry Andric // An unjoined PHI has no defined locations, and so a shared location must 2836bdd1243dSDimitry Andric // be found for every operand. 2837bdd1243dSDimitry Andric if (OutVal.isUnjoinedPHI()) { 2838bdd1243dSDimitry Andric LocOpsToJoin.insert(Idx); 2839bdd1243dSDimitry Andric continue; 2840bdd1243dSDimitry Andric } 2841bdd1243dSDimitry Andric DbgOpID FirstValOp = FirstValue.getDbgOpID(Idx); 2842bdd1243dSDimitry Andric DbgOpID OutValOp = OutVal.getDbgOpID(Idx); 2843bdd1243dSDimitry Andric if (FirstValOp != OutValOp) { 2844bdd1243dSDimitry Andric // We can never join constant ops - the ops must either both be equal 2845bdd1243dSDimitry Andric // constant ops or non-const ops. 2846bdd1243dSDimitry Andric if (FirstValOp.isConst() || OutValOp.isConst()) 2847bdd1243dSDimitry Andric return false; 2848bdd1243dSDimitry Andric else 2849bdd1243dSDimitry Andric LocOpsToJoin.insert(Idx); 2850bdd1243dSDimitry Andric } 2851bdd1243dSDimitry Andric } 2852bdd1243dSDimitry Andric } 2853bdd1243dSDimitry Andric 2854bdd1243dSDimitry Andric SmallVector<DbgOpID> NewDbgOps; 2855bdd1243dSDimitry Andric 2856bdd1243dSDimitry Andric for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) { 2857bdd1243dSDimitry Andric // If this op doesn't need to be joined because the values agree, use that 2858bdd1243dSDimitry Andric // already-agreed value. 2859bdd1243dSDimitry Andric if (!LocOpsToJoin.contains(Idx)) { 2860bdd1243dSDimitry Andric NewDbgOps.push_back(FirstValue.getDbgOpID(Idx)); 2861bdd1243dSDimitry Andric continue; 2862bdd1243dSDimitry Andric } 2863bdd1243dSDimitry Andric 2864bdd1243dSDimitry Andric std::optional<ValueIDNum> JoinedOpLoc = 2865bdd1243dSDimitry Andric pickOperandPHILoc(Idx, MBB, LiveOuts, MOutLocs, BlockOrders); 2866bdd1243dSDimitry Andric 2867bdd1243dSDimitry Andric if (!JoinedOpLoc) 2868bdd1243dSDimitry Andric return false; 2869bdd1243dSDimitry Andric 2870bdd1243dSDimitry Andric NewDbgOps.push_back(DbgOpStore.insert(*JoinedOpLoc)); 2871bdd1243dSDimitry Andric } 2872bdd1243dSDimitry Andric 2873bdd1243dSDimitry Andric OutValues.append(NewDbgOps); 2874bdd1243dSDimitry Andric return true; 2875bdd1243dSDimitry Andric } 2876bdd1243dSDimitry Andric 2877bdd1243dSDimitry Andric std::optional<ValueIDNum> InstrRefBasedLDV::pickOperandPHILoc( 2878bdd1243dSDimitry Andric unsigned DbgOpIdx, const MachineBasicBlock &MBB, const LiveIdxT &LiveOuts, 2879bdd1243dSDimitry Andric FuncValueTable &MOutLocs, 2880bdd1243dSDimitry Andric const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders) { 2881bdd1243dSDimitry Andric 2882bdd1243dSDimitry Andric // Collect a set of locations from predecessor where its live-out value can 2883bdd1243dSDimitry Andric // be found. 2884bdd1243dSDimitry Andric SmallVector<SmallVector<LocIdx, 4>, 8> Locs; 2885bdd1243dSDimitry Andric unsigned NumLocs = MTracker->getNumLocs(); 2886bdd1243dSDimitry Andric 2887bdd1243dSDimitry Andric for (const auto p : BlockOrders) { 2888bdd1243dSDimitry Andric auto OutValIt = LiveOuts.find(p); 2889bdd1243dSDimitry Andric assert(OutValIt != LiveOuts.end()); 2890bdd1243dSDimitry Andric const DbgValue &OutVal = *OutValIt->second; 2891bdd1243dSDimitry Andric DbgOpID OutValOpID = OutVal.getDbgOpID(DbgOpIdx); 2892bdd1243dSDimitry Andric DbgOp OutValOp = DbgOpStore.find(OutValOpID); 2893bdd1243dSDimitry Andric assert(!OutValOp.IsConst); 2894349cc55cSDimitry Andric 2895349cc55cSDimitry Andric // Create new empty vector of locations. 2896349cc55cSDimitry Andric Locs.resize(Locs.size() + 1); 2897349cc55cSDimitry Andric 2898349cc55cSDimitry Andric // If the live-in value is a def, find the locations where that value is 2899349cc55cSDimitry Andric // present. Do the same for VPHIs where we know the VPHI value. 2900349cc55cSDimitry Andric if (OutVal.Kind == DbgValue::Def || 2901349cc55cSDimitry Andric (OutVal.Kind == DbgValue::VPHI && OutVal.BlockNo != MBB.getNumber() && 2902bdd1243dSDimitry Andric !OutValOp.isUndef())) { 2903bdd1243dSDimitry Andric ValueIDNum ValToLookFor = OutValOp.ID; 2904e8d8bef9SDimitry Andric // Search the live-outs of the predecessor for the specified value. 2905e8d8bef9SDimitry Andric for (unsigned int I = 0; I < NumLocs; ++I) { 2906cb14a3feSDimitry Andric if (MOutLocs[*p][I] == ValToLookFor) 2907e8d8bef9SDimitry Andric Locs.back().push_back(LocIdx(I)); 2908e8d8bef9SDimitry Andric } 2909349cc55cSDimitry Andric } else { 2910349cc55cSDimitry Andric assert(OutVal.Kind == DbgValue::VPHI); 2911349cc55cSDimitry Andric // Otherwise: this is a VPHI on a backedge feeding back into itself, i.e. 2912349cc55cSDimitry Andric // a value that's live-through the whole loop. (It has to be a backedge, 2913349cc55cSDimitry Andric // because a block can't dominate itself). We can accept as a PHI location 2914349cc55cSDimitry Andric // any location where the other predecessors agree, _and_ the machine 2915349cc55cSDimitry Andric // locations feed back into themselves. Therefore, add all self-looping 2916349cc55cSDimitry Andric // machine-value PHI locations. 2917349cc55cSDimitry Andric for (unsigned int I = 0; I < NumLocs; ++I) { 2918349cc55cSDimitry Andric ValueIDNum MPHI(MBB.getNumber(), 0, LocIdx(I)); 2919cb14a3feSDimitry Andric if (MOutLocs[*p][I] == MPHI) 2920349cc55cSDimitry Andric Locs.back().push_back(LocIdx(I)); 2921349cc55cSDimitry Andric } 2922349cc55cSDimitry Andric } 2923e8d8bef9SDimitry Andric } 2924349cc55cSDimitry Andric // We should have found locations for all predecessors, or returned. 2925349cc55cSDimitry Andric assert(Locs.size() == BlockOrders.size()); 2926e8d8bef9SDimitry Andric 2927e8d8bef9SDimitry Andric // Starting with the first set of locations, take the intersection with 2928e8d8bef9SDimitry Andric // subsequent sets. 2929349cc55cSDimitry Andric SmallVector<LocIdx, 4> CandidateLocs = Locs[0]; 2930349cc55cSDimitry Andric for (unsigned int I = 1; I < Locs.size(); ++I) { 2931349cc55cSDimitry Andric auto &LocVec = Locs[I]; 2932349cc55cSDimitry Andric SmallVector<LocIdx, 4> NewCandidates; 2933349cc55cSDimitry Andric std::set_intersection(CandidateLocs.begin(), CandidateLocs.end(), 2934349cc55cSDimitry Andric LocVec.begin(), LocVec.end(), std::inserter(NewCandidates, NewCandidates.begin())); 2935349cc55cSDimitry Andric CandidateLocs = NewCandidates; 2936e8d8bef9SDimitry Andric } 2937349cc55cSDimitry Andric if (CandidateLocs.empty()) 2938bdd1243dSDimitry Andric return std::nullopt; 2939e8d8bef9SDimitry Andric 2940e8d8bef9SDimitry Andric // We now have a set of LocIdxes that contain the right output value in 2941e8d8bef9SDimitry Andric // each of the predecessors. Pick the lowest; if there's a register loc, 2942e8d8bef9SDimitry Andric // that'll be it. 2943349cc55cSDimitry Andric LocIdx L = *CandidateLocs.begin(); 2944e8d8bef9SDimitry Andric 2945e8d8bef9SDimitry Andric // Return a PHI-value-number for the found location. 2946e8d8bef9SDimitry Andric ValueIDNum PHIVal = {(unsigned)MBB.getNumber(), 0, L}; 2947349cc55cSDimitry Andric return PHIVal; 2948e8d8bef9SDimitry Andric } 2949e8d8bef9SDimitry Andric 2950349cc55cSDimitry Andric bool InstrRefBasedLDV::vlocJoin( 2951349cc55cSDimitry Andric MachineBasicBlock &MBB, LiveIdxT &VLOCOutLocs, 2952e8d8bef9SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore, 2953349cc55cSDimitry Andric DbgValue &LiveIn) { 2954e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "join MBB: " << MBB.getNumber() << "\n"); 2955e8d8bef9SDimitry Andric bool Changed = false; 2956e8d8bef9SDimitry Andric 2957e8d8bef9SDimitry Andric // Order predecessors by RPOT order, for exploring them in that order. 2958fe6060f1SDimitry Andric SmallVector<MachineBasicBlock *, 8> BlockOrders(MBB.predecessors()); 2959e8d8bef9SDimitry Andric 2960e8d8bef9SDimitry Andric auto Cmp = [&](MachineBasicBlock *A, MachineBasicBlock *B) { 2961e8d8bef9SDimitry Andric return BBToOrder[A] < BBToOrder[B]; 2962e8d8bef9SDimitry Andric }; 2963e8d8bef9SDimitry Andric 2964e8d8bef9SDimitry Andric llvm::sort(BlockOrders, Cmp); 2965e8d8bef9SDimitry Andric 2966e8d8bef9SDimitry Andric unsigned CurBlockRPONum = BBToOrder[&MBB]; 2967e8d8bef9SDimitry Andric 2968349cc55cSDimitry Andric // Collect all the incoming DbgValues for this variable, from predecessor 2969349cc55cSDimitry Andric // live-out values. 2970e8d8bef9SDimitry Andric SmallVector<InValueT, 8> Values; 2971e8d8bef9SDimitry Andric bool Bail = false; 2972349cc55cSDimitry Andric int BackEdgesStart = 0; 2973fcaf7f86SDimitry Andric for (auto *p : BlockOrders) { 2974e8d8bef9SDimitry Andric // If the predecessor isn't in scope / to be explored, we'll never be 2975e8d8bef9SDimitry Andric // able to join any locations. 2976e8d8bef9SDimitry Andric if (!BlocksToExplore.contains(p)) { 2977e8d8bef9SDimitry Andric Bail = true; 2978e8d8bef9SDimitry Andric break; 2979e8d8bef9SDimitry Andric } 2980e8d8bef9SDimitry Andric 2981349cc55cSDimitry Andric // All Live-outs will have been initialized. 2982349cc55cSDimitry Andric DbgValue &OutLoc = *VLOCOutLocs.find(p)->second; 2983e8d8bef9SDimitry Andric 2984e8d8bef9SDimitry Andric // Keep track of where back-edges begin in the Values vector. Relies on 2985e8d8bef9SDimitry Andric // BlockOrders being sorted by RPO. 2986e8d8bef9SDimitry Andric unsigned ThisBBRPONum = BBToOrder[p]; 2987e8d8bef9SDimitry Andric if (ThisBBRPONum < CurBlockRPONum) 2988e8d8bef9SDimitry Andric ++BackEdgesStart; 2989e8d8bef9SDimitry Andric 2990349cc55cSDimitry Andric Values.push_back(std::make_pair(p, &OutLoc)); 2991e8d8bef9SDimitry Andric } 2992e8d8bef9SDimitry Andric 2993e8d8bef9SDimitry Andric // If there were no values, or one of the predecessors couldn't have a 2994e8d8bef9SDimitry Andric // value, then give up immediately. It's not safe to produce a live-in 2995349cc55cSDimitry Andric // value. Leave as whatever it was before. 2996e8d8bef9SDimitry Andric if (Bail || Values.size() == 0) 2997349cc55cSDimitry Andric return false; 2998e8d8bef9SDimitry Andric 2999e8d8bef9SDimitry Andric // All (non-entry) blocks have at least one non-backedge predecessor. 3000e8d8bef9SDimitry Andric // Pick the variable value from the first of these, to compare against 3001e8d8bef9SDimitry Andric // all others. 3002e8d8bef9SDimitry Andric const DbgValue &FirstVal = *Values[0].second; 3003e8d8bef9SDimitry Andric 3004349cc55cSDimitry Andric // If the old live-in value is not a PHI then either a) no PHI is needed 3005349cc55cSDimitry Andric // here, or b) we eliminated the PHI that was here. If so, we can just 3006349cc55cSDimitry Andric // propagate in the first parent's incoming value. 3007349cc55cSDimitry Andric if (LiveIn.Kind != DbgValue::VPHI || LiveIn.BlockNo != MBB.getNumber()) { 3008349cc55cSDimitry Andric Changed = LiveIn != FirstVal; 3009349cc55cSDimitry Andric if (Changed) 3010349cc55cSDimitry Andric LiveIn = FirstVal; 3011349cc55cSDimitry Andric return Changed; 3012349cc55cSDimitry Andric } 3013349cc55cSDimitry Andric 3014349cc55cSDimitry Andric // Scan for variable values that can never be resolved: if they have 3015349cc55cSDimitry Andric // different DIExpressions, different indirectness, or are mixed constants / 3016e8d8bef9SDimitry Andric // non-constants. 3017bdd1243dSDimitry Andric for (const auto &V : Values) { 3018bdd1243dSDimitry Andric if (!V.second->Properties.isJoinable(FirstVal.Properties)) 3019349cc55cSDimitry Andric return false; 3020349cc55cSDimitry Andric if (V.second->Kind == DbgValue::NoVal) 3021349cc55cSDimitry Andric return false; 3022bdd1243dSDimitry Andric if (!V.second->hasJoinableLocOps(FirstVal)) 3023349cc55cSDimitry Andric return false; 3024e8d8bef9SDimitry Andric } 3025e8d8bef9SDimitry Andric 3026349cc55cSDimitry Andric // Try to eliminate this PHI. Do the incoming values all agree? 3027e8d8bef9SDimitry Andric bool Disagree = false; 3028e8d8bef9SDimitry Andric for (auto &V : Values) { 3029e8d8bef9SDimitry Andric if (*V.second == FirstVal) 3030e8d8bef9SDimitry Andric continue; // No disagreement. 3031e8d8bef9SDimitry Andric 3032bdd1243dSDimitry Andric // If both values are not equal but have equal non-empty IDs then they refer 3033bdd1243dSDimitry Andric // to the same value from different sources (e.g. one is VPHI and the other 3034bdd1243dSDimitry Andric // is Def), which does not cause disagreement. 3035bdd1243dSDimitry Andric if (V.second->hasIdenticalValidLocOps(FirstVal)) 3036bdd1243dSDimitry Andric continue; 3037bdd1243dSDimitry Andric 3038349cc55cSDimitry Andric // Eliminate if a backedge feeds a VPHI back into itself. 3039349cc55cSDimitry Andric if (V.second->Kind == DbgValue::VPHI && 3040349cc55cSDimitry Andric V.second->BlockNo == MBB.getNumber() && 3041349cc55cSDimitry Andric // Is this a backedge? 3042349cc55cSDimitry Andric std::distance(Values.begin(), &V) >= BackEdgesStart) 3043349cc55cSDimitry Andric continue; 3044349cc55cSDimitry Andric 3045e8d8bef9SDimitry Andric Disagree = true; 3046e8d8bef9SDimitry Andric } 3047e8d8bef9SDimitry Andric 3048349cc55cSDimitry Andric // No disagreement -> live-through value. 3049349cc55cSDimitry Andric if (!Disagree) { 3050349cc55cSDimitry Andric Changed = LiveIn != FirstVal; 3051e8d8bef9SDimitry Andric if (Changed) 3052349cc55cSDimitry Andric LiveIn = FirstVal; 3053349cc55cSDimitry Andric return Changed; 3054349cc55cSDimitry Andric } else { 3055349cc55cSDimitry Andric // Otherwise use a VPHI. 3056349cc55cSDimitry Andric DbgValue VPHI(MBB.getNumber(), FirstVal.Properties, DbgValue::VPHI); 3057349cc55cSDimitry Andric Changed = LiveIn != VPHI; 3058349cc55cSDimitry Andric if (Changed) 3059349cc55cSDimitry Andric LiveIn = VPHI; 3060349cc55cSDimitry Andric return Changed; 3061349cc55cSDimitry Andric } 3062e8d8bef9SDimitry Andric } 3063e8d8bef9SDimitry Andric 30641fd87a68SDimitry Andric void InstrRefBasedLDV::getBlocksForScope( 30651fd87a68SDimitry Andric const DILocation *DILoc, 30661fd87a68SDimitry Andric SmallPtrSetImpl<const MachineBasicBlock *> &BlocksToExplore, 30671fd87a68SDimitry Andric const SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks) { 30681fd87a68SDimitry Andric // Get the set of "normal" in-lexical-scope blocks. 30691fd87a68SDimitry Andric LS.getMachineBasicBlocks(DILoc, BlocksToExplore); 30701fd87a68SDimitry Andric 30711fd87a68SDimitry Andric // VarLoc LiveDebugValues tracks variable locations that are defined in 30721fd87a68SDimitry Andric // blocks not in scope. This is something we could legitimately ignore, but 30731fd87a68SDimitry Andric // lets allow it for now for the sake of coverage. 30741fd87a68SDimitry Andric BlocksToExplore.insert(AssignBlocks.begin(), AssignBlocks.end()); 30751fd87a68SDimitry Andric 30761fd87a68SDimitry Andric // Storage for artificial blocks we intend to add to BlocksToExplore. 30771fd87a68SDimitry Andric DenseSet<const MachineBasicBlock *> ToAdd; 30781fd87a68SDimitry Andric 30791fd87a68SDimitry Andric // To avoid needlessly dropping large volumes of variable locations, propagate 30801fd87a68SDimitry Andric // variables through aritifical blocks, i.e. those that don't have any 30811fd87a68SDimitry Andric // instructions in scope at all. To accurately replicate VarLoc 30821fd87a68SDimitry Andric // LiveDebugValues, this means exploring all artificial successors too. 30831fd87a68SDimitry Andric // Perform a depth-first-search to enumerate those blocks. 3084fcaf7f86SDimitry Andric for (const auto *MBB : BlocksToExplore) { 30851fd87a68SDimitry Andric // Depth-first-search state: each node is a block and which successor 30861fd87a68SDimitry Andric // we're currently exploring. 30871fd87a68SDimitry Andric SmallVector<std::pair<const MachineBasicBlock *, 30881fd87a68SDimitry Andric MachineBasicBlock::const_succ_iterator>, 30891fd87a68SDimitry Andric 8> 30901fd87a68SDimitry Andric DFS; 30911fd87a68SDimitry Andric 30921fd87a68SDimitry Andric // Find any artificial successors not already tracked. 30931fd87a68SDimitry Andric for (auto *succ : MBB->successors()) { 30941fd87a68SDimitry Andric if (BlocksToExplore.count(succ)) 30951fd87a68SDimitry Andric continue; 30961fd87a68SDimitry Andric if (!ArtificialBlocks.count(succ)) 30971fd87a68SDimitry Andric continue; 30981fd87a68SDimitry Andric ToAdd.insert(succ); 30991fd87a68SDimitry Andric DFS.push_back({succ, succ->succ_begin()}); 31001fd87a68SDimitry Andric } 31011fd87a68SDimitry Andric 31021fd87a68SDimitry Andric // Search all those blocks, depth first. 31031fd87a68SDimitry Andric while (!DFS.empty()) { 31041fd87a68SDimitry Andric const MachineBasicBlock *CurBB = DFS.back().first; 31051fd87a68SDimitry Andric MachineBasicBlock::const_succ_iterator &CurSucc = DFS.back().second; 31061fd87a68SDimitry Andric // Walk back if we've explored this blocks successors to the end. 31071fd87a68SDimitry Andric if (CurSucc == CurBB->succ_end()) { 31081fd87a68SDimitry Andric DFS.pop_back(); 31091fd87a68SDimitry Andric continue; 31101fd87a68SDimitry Andric } 31111fd87a68SDimitry Andric 31121fd87a68SDimitry Andric // If the current successor is artificial and unexplored, descend into 31131fd87a68SDimitry Andric // it. 31141fd87a68SDimitry Andric if (!ToAdd.count(*CurSucc) && ArtificialBlocks.count(*CurSucc)) { 31151fd87a68SDimitry Andric ToAdd.insert(*CurSucc); 31161fd87a68SDimitry Andric DFS.push_back({*CurSucc, (*CurSucc)->succ_begin()}); 31171fd87a68SDimitry Andric continue; 31181fd87a68SDimitry Andric } 31191fd87a68SDimitry Andric 31201fd87a68SDimitry Andric ++CurSucc; 31211fd87a68SDimitry Andric } 31221fd87a68SDimitry Andric }; 31231fd87a68SDimitry Andric 31241fd87a68SDimitry Andric BlocksToExplore.insert(ToAdd.begin(), ToAdd.end()); 31251fd87a68SDimitry Andric } 31261fd87a68SDimitry Andric 31271fd87a68SDimitry Andric void InstrRefBasedLDV::buildVLocValueMap( 3128*0fca6ea1SDimitry Andric const DILocation *DILoc, 3129*0fca6ea1SDimitry Andric const SmallSet<DebugVariableID, 4> &VarsWeCareAbout, 3130e8d8bef9SDimitry Andric SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks, LiveInsT &Output, 313181ad6265SDimitry Andric FuncValueTable &MOutLocs, FuncValueTable &MInLocs, 3132e8d8bef9SDimitry Andric SmallVectorImpl<VLocTracker> &AllTheVLocs) { 3133349cc55cSDimitry Andric // This method is much like buildMLocValueMap: but focuses on a single 3134e8d8bef9SDimitry Andric // LexicalScope at a time. Pick out a set of blocks and variables that are 3135e8d8bef9SDimitry Andric // to have their value assignments solved, then run our dataflow algorithm 3136e8d8bef9SDimitry Andric // until a fixedpoint is reached. 3137e8d8bef9SDimitry Andric std::priority_queue<unsigned int, std::vector<unsigned int>, 3138e8d8bef9SDimitry Andric std::greater<unsigned int>> 3139e8d8bef9SDimitry Andric Worklist, Pending; 3140e8d8bef9SDimitry Andric SmallPtrSet<MachineBasicBlock *, 16> OnWorklist, OnPending; 3141e8d8bef9SDimitry Andric 3142e8d8bef9SDimitry Andric // The set of blocks we'll be examining. 3143e8d8bef9SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore; 3144e8d8bef9SDimitry Andric 3145e8d8bef9SDimitry Andric // The order in which to examine them (RPO). 3146*0fca6ea1SDimitry Andric SmallVector<MachineBasicBlock *, 16> BlockOrders; 3147*0fca6ea1SDimitry Andric SmallVector<unsigned, 32> BlockOrderNums; 3148e8d8bef9SDimitry Andric 31491fd87a68SDimitry Andric getBlocksForScope(DILoc, BlocksToExplore, AssignBlocks); 3150e8d8bef9SDimitry Andric 3151e8d8bef9SDimitry Andric // Single block scope: not interesting! No propagation at all. Note that 3152e8d8bef9SDimitry Andric // this could probably go above ArtificialBlocks without damage, but 3153e8d8bef9SDimitry Andric // that then produces output differences from original-live-debug-values, 3154e8d8bef9SDimitry Andric // which propagates from a single block into many artificial ones. 3155e8d8bef9SDimitry Andric if (BlocksToExplore.size() == 1) 3156e8d8bef9SDimitry Andric return; 3157e8d8bef9SDimitry Andric 3158349cc55cSDimitry Andric // Convert a const set to a non-const set. LexicalScopes 3159349cc55cSDimitry Andric // getMachineBasicBlocks returns const MBB pointers, IDF wants mutable ones. 3160349cc55cSDimitry Andric // (Neither of them mutate anything). 3161349cc55cSDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> MutBlocksToExplore; 3162349cc55cSDimitry Andric for (const auto *MBB : BlocksToExplore) 3163349cc55cSDimitry Andric MutBlocksToExplore.insert(const_cast<MachineBasicBlock *>(MBB)); 3164349cc55cSDimitry Andric 3165*0fca6ea1SDimitry Andric // Picks out relevants blocks RPO order and sort them. Sort their 3166*0fca6ea1SDimitry Andric // order-numbers and map back to MBB pointers later, to avoid repeated 3167*0fca6ea1SDimitry Andric // DenseMap queries during comparisons. 3168fcaf7f86SDimitry Andric for (const auto *MBB : BlocksToExplore) 3169*0fca6ea1SDimitry Andric BlockOrderNums.push_back(BBToOrder[MBB]); 3170e8d8bef9SDimitry Andric 3171*0fca6ea1SDimitry Andric llvm::sort(BlockOrderNums); 3172*0fca6ea1SDimitry Andric for (unsigned int I : BlockOrderNums) 3173*0fca6ea1SDimitry Andric BlockOrders.push_back(OrderToBB[I]); 3174*0fca6ea1SDimitry Andric BlockOrderNums.clear(); 3175e8d8bef9SDimitry Andric unsigned NumBlocks = BlockOrders.size(); 3176e8d8bef9SDimitry Andric 3177e8d8bef9SDimitry Andric // Allocate some vectors for storing the live ins and live outs. Large. 3178349cc55cSDimitry Andric SmallVector<DbgValue, 32> LiveIns, LiveOuts; 3179349cc55cSDimitry Andric LiveIns.reserve(NumBlocks); 3180349cc55cSDimitry Andric LiveOuts.reserve(NumBlocks); 3181349cc55cSDimitry Andric 3182349cc55cSDimitry Andric // Initialize all values to start as NoVals. This signifies "it's live 3183349cc55cSDimitry Andric // through, but we don't know what it is". 3184bdd1243dSDimitry Andric DbgValueProperties EmptyProperties(EmptyExpr, false, false); 3185349cc55cSDimitry Andric for (unsigned int I = 0; I < NumBlocks; ++I) { 3186349cc55cSDimitry Andric DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal); 3187349cc55cSDimitry Andric LiveIns.push_back(EmptyDbgValue); 3188349cc55cSDimitry Andric LiveOuts.push_back(EmptyDbgValue); 3189349cc55cSDimitry Andric } 3190e8d8bef9SDimitry Andric 3191e8d8bef9SDimitry Andric // Produce by-MBB indexes of live-in/live-outs, to ease lookup within 3192e8d8bef9SDimitry Andric // vlocJoin. 3193e8d8bef9SDimitry Andric LiveIdxT LiveOutIdx, LiveInIdx; 3194e8d8bef9SDimitry Andric LiveOutIdx.reserve(NumBlocks); 3195e8d8bef9SDimitry Andric LiveInIdx.reserve(NumBlocks); 3196e8d8bef9SDimitry Andric for (unsigned I = 0; I < NumBlocks; ++I) { 3197e8d8bef9SDimitry Andric LiveOutIdx[BlockOrders[I]] = &LiveOuts[I]; 3198e8d8bef9SDimitry Andric LiveInIdx[BlockOrders[I]] = &LiveIns[I]; 3199e8d8bef9SDimitry Andric } 3200e8d8bef9SDimitry Andric 3201349cc55cSDimitry Andric // Loop over each variable and place PHIs for it, then propagate values 3202349cc55cSDimitry Andric // between blocks. This keeps the locality of working on one lexical scope at 3203349cc55cSDimitry Andric // at time, but avoids re-processing variable values because some other 3204349cc55cSDimitry Andric // variable has been assigned. 3205*0fca6ea1SDimitry Andric for (DebugVariableID VarID : VarsWeCareAbout) { 3206349cc55cSDimitry Andric // Re-initialize live-ins and live-outs, to clear the remains of previous 3207349cc55cSDimitry Andric // variables live-ins / live-outs. 3208349cc55cSDimitry Andric for (unsigned int I = 0; I < NumBlocks; ++I) { 3209349cc55cSDimitry Andric DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal); 3210349cc55cSDimitry Andric LiveIns[I] = EmptyDbgValue; 3211349cc55cSDimitry Andric LiveOuts[I] = EmptyDbgValue; 3212349cc55cSDimitry Andric } 3213349cc55cSDimitry Andric 3214349cc55cSDimitry Andric // Place PHIs for variable values, using the LLVM IDF calculator. 3215349cc55cSDimitry Andric // Collect the set of blocks where variables are def'd. 3216349cc55cSDimitry Andric SmallPtrSet<MachineBasicBlock *, 32> DefBlocks; 3217349cc55cSDimitry Andric for (const MachineBasicBlock *ExpMBB : BlocksToExplore) { 3218349cc55cSDimitry Andric auto &TransferFunc = AllTheVLocs[ExpMBB->getNumber()].Vars; 3219*0fca6ea1SDimitry Andric if (TransferFunc.contains(VarID)) 3220349cc55cSDimitry Andric DefBlocks.insert(const_cast<MachineBasicBlock *>(ExpMBB)); 3221349cc55cSDimitry Andric } 3222349cc55cSDimitry Andric 3223349cc55cSDimitry Andric SmallVector<MachineBasicBlock *, 32> PHIBlocks; 3224349cc55cSDimitry Andric 32251fd87a68SDimitry Andric // Request the set of PHIs we should insert for this variable. If there's 32261fd87a68SDimitry Andric // only one value definition, things are very simple. 32271fd87a68SDimitry Andric if (DefBlocks.size() == 1) { 32281fd87a68SDimitry Andric placePHIsForSingleVarDefinition(MutBlocksToExplore, *DefBlocks.begin(), 3229*0fca6ea1SDimitry Andric AllTheVLocs, VarID, Output); 32301fd87a68SDimitry Andric continue; 32311fd87a68SDimitry Andric } 32321fd87a68SDimitry Andric 32331fd87a68SDimitry Andric // Otherwise: we need to place PHIs through SSA and propagate values. 3234349cc55cSDimitry Andric BlockPHIPlacement(MutBlocksToExplore, DefBlocks, PHIBlocks); 3235349cc55cSDimitry Andric 3236349cc55cSDimitry Andric // Insert PHIs into the per-block live-in tables for this variable. 3237349cc55cSDimitry Andric for (MachineBasicBlock *PHIMBB : PHIBlocks) { 3238349cc55cSDimitry Andric unsigned BlockNo = PHIMBB->getNumber(); 3239349cc55cSDimitry Andric DbgValue *LiveIn = LiveInIdx[PHIMBB]; 3240349cc55cSDimitry Andric *LiveIn = DbgValue(BlockNo, EmptyProperties, DbgValue::VPHI); 3241349cc55cSDimitry Andric } 3242349cc55cSDimitry Andric 3243e8d8bef9SDimitry Andric for (auto *MBB : BlockOrders) { 3244e8d8bef9SDimitry Andric Worklist.push(BBToOrder[MBB]); 3245e8d8bef9SDimitry Andric OnWorklist.insert(MBB); 3246e8d8bef9SDimitry Andric } 3247e8d8bef9SDimitry Andric 3248349cc55cSDimitry Andric // Iterate over all the blocks we selected, propagating the variables value. 3249349cc55cSDimitry Andric // This loop does two things: 3250349cc55cSDimitry Andric // * Eliminates un-necessary VPHIs in vlocJoin, 3251349cc55cSDimitry Andric // * Evaluates the blocks transfer function (i.e. variable assignments) and 3252349cc55cSDimitry Andric // stores the result to the blocks live-outs. 3253349cc55cSDimitry Andric // Always evaluate the transfer function on the first iteration, and when 3254349cc55cSDimitry Andric // the live-ins change thereafter. 3255e8d8bef9SDimitry Andric bool FirstTrip = true; 3256e8d8bef9SDimitry Andric while (!Worklist.empty() || !Pending.empty()) { 3257e8d8bef9SDimitry Andric while (!Worklist.empty()) { 3258e8d8bef9SDimitry Andric auto *MBB = OrderToBB[Worklist.top()]; 3259e8d8bef9SDimitry Andric CurBB = MBB->getNumber(); 3260e8d8bef9SDimitry Andric Worklist.pop(); 3261e8d8bef9SDimitry Andric 3262349cc55cSDimitry Andric auto LiveInsIt = LiveInIdx.find(MBB); 3263349cc55cSDimitry Andric assert(LiveInsIt != LiveInIdx.end()); 3264349cc55cSDimitry Andric DbgValue *LiveIn = LiveInsIt->second; 3265e8d8bef9SDimitry Andric 3266e8d8bef9SDimitry Andric // Join values from predecessors. Updates LiveInIdx, and writes output 3267e8d8bef9SDimitry Andric // into JoinedInLocs. 3268349cc55cSDimitry Andric bool InLocsChanged = 32694824e7fdSDimitry Andric vlocJoin(*MBB, LiveOutIdx, BlocksToExplore, *LiveIn); 3270e8d8bef9SDimitry Andric 3271349cc55cSDimitry Andric SmallVector<const MachineBasicBlock *, 8> Preds; 3272349cc55cSDimitry Andric for (const auto *Pred : MBB->predecessors()) 3273349cc55cSDimitry Andric Preds.push_back(Pred); 3274e8d8bef9SDimitry Andric 3275349cc55cSDimitry Andric // If this block's live-in value is a VPHI, try to pick a machine-value 3276349cc55cSDimitry Andric // for it. This makes the machine-value available and propagated 3277349cc55cSDimitry Andric // through all blocks by the time value propagation finishes. We can't 3278349cc55cSDimitry Andric // do this any earlier as it needs to read the block live-outs. 3279349cc55cSDimitry Andric if (LiveIn->Kind == DbgValue::VPHI && LiveIn->BlockNo == (int)CurBB) { 3280349cc55cSDimitry Andric // There's a small possibility that on a preceeding path, a VPHI is 3281349cc55cSDimitry Andric // eliminated and transitions from VPHI-with-location to 3282349cc55cSDimitry Andric // live-through-value. As a result, the selected location of any VPHI 3283349cc55cSDimitry Andric // might change, so we need to re-compute it on each iteration. 3284bdd1243dSDimitry Andric SmallVector<DbgOpID> JoinedOps; 3285e8d8bef9SDimitry Andric 3286bdd1243dSDimitry Andric if (pickVPHILoc(JoinedOps, *MBB, LiveOutIdx, MOutLocs, Preds)) { 3287bdd1243dSDimitry Andric bool NewLocPicked = !equal(LiveIn->getDbgOpIDs(), JoinedOps); 3288bdd1243dSDimitry Andric InLocsChanged |= NewLocPicked; 3289bdd1243dSDimitry Andric if (NewLocPicked) 3290bdd1243dSDimitry Andric LiveIn->setDbgOpIDs(JoinedOps); 3291349cc55cSDimitry Andric } 3292349cc55cSDimitry Andric } 3293e8d8bef9SDimitry Andric 3294349cc55cSDimitry Andric if (!InLocsChanged && !FirstTrip) 3295e8d8bef9SDimitry Andric continue; 3296e8d8bef9SDimitry Andric 3297349cc55cSDimitry Andric DbgValue *LiveOut = LiveOutIdx[MBB]; 3298349cc55cSDimitry Andric bool OLChanged = false; 3299349cc55cSDimitry Andric 3300e8d8bef9SDimitry Andric // Do transfer function. 3301e8d8bef9SDimitry Andric auto &VTracker = AllTheVLocs[MBB->getNumber()]; 3302*0fca6ea1SDimitry Andric auto TransferIt = VTracker.Vars.find(VarID); 3303349cc55cSDimitry Andric if (TransferIt != VTracker.Vars.end()) { 3304e8d8bef9SDimitry Andric // Erase on empty transfer (DBG_VALUE $noreg). 3305349cc55cSDimitry Andric if (TransferIt->second.Kind == DbgValue::Undef) { 3306349cc55cSDimitry Andric DbgValue NewVal(MBB->getNumber(), EmptyProperties, DbgValue::NoVal); 3307349cc55cSDimitry Andric if (*LiveOut != NewVal) { 3308349cc55cSDimitry Andric *LiveOut = NewVal; 3309349cc55cSDimitry Andric OLChanged = true; 3310349cc55cSDimitry Andric } 3311e8d8bef9SDimitry Andric } else { 3312e8d8bef9SDimitry Andric // Insert new variable value; or overwrite. 3313349cc55cSDimitry Andric if (*LiveOut != TransferIt->second) { 3314349cc55cSDimitry Andric *LiveOut = TransferIt->second; 3315349cc55cSDimitry Andric OLChanged = true; 3316e8d8bef9SDimitry Andric } 3317e8d8bef9SDimitry Andric } 3318349cc55cSDimitry Andric } else { 3319349cc55cSDimitry Andric // Just copy live-ins to live-outs, for anything not transferred. 3320349cc55cSDimitry Andric if (*LiveOut != *LiveIn) { 3321349cc55cSDimitry Andric *LiveOut = *LiveIn; 3322349cc55cSDimitry Andric OLChanged = true; 3323349cc55cSDimitry Andric } 3324e8d8bef9SDimitry Andric } 3325e8d8bef9SDimitry Andric 3326349cc55cSDimitry Andric // If no live-out value changed, there's no need to explore further. 3327e8d8bef9SDimitry Andric if (!OLChanged) 3328e8d8bef9SDimitry Andric continue; 3329e8d8bef9SDimitry Andric 3330e8d8bef9SDimitry Andric // We should visit all successors. Ensure we'll visit any non-backedge 3331e8d8bef9SDimitry Andric // successors during this dataflow iteration; book backedge successors 3332e8d8bef9SDimitry Andric // to be visited next time around. 3333fcaf7f86SDimitry Andric for (auto *s : MBB->successors()) { 3334e8d8bef9SDimitry Andric // Ignore out of scope / not-to-be-explored successors. 333506c3fb27SDimitry Andric if (!LiveInIdx.contains(s)) 3336e8d8bef9SDimitry Andric continue; 3337e8d8bef9SDimitry Andric 3338e8d8bef9SDimitry Andric if (BBToOrder[s] > BBToOrder[MBB]) { 3339e8d8bef9SDimitry Andric if (OnWorklist.insert(s).second) 3340e8d8bef9SDimitry Andric Worklist.push(BBToOrder[s]); 3341e8d8bef9SDimitry Andric } else if (OnPending.insert(s).second && (FirstTrip || OLChanged)) { 3342e8d8bef9SDimitry Andric Pending.push(BBToOrder[s]); 3343e8d8bef9SDimitry Andric } 3344e8d8bef9SDimitry Andric } 3345e8d8bef9SDimitry Andric } 3346e8d8bef9SDimitry Andric Worklist.swap(Pending); 3347e8d8bef9SDimitry Andric std::swap(OnWorklist, OnPending); 3348e8d8bef9SDimitry Andric OnPending.clear(); 3349e8d8bef9SDimitry Andric assert(Pending.empty()); 3350e8d8bef9SDimitry Andric FirstTrip = false; 3351e8d8bef9SDimitry Andric } 3352e8d8bef9SDimitry Andric 3353349cc55cSDimitry Andric // Save live-ins to output vector. Ignore any that are still marked as being 3354349cc55cSDimitry Andric // VPHIs with no location -- those are variables that we know the value of, 3355349cc55cSDimitry Andric // but are not actually available in the register file. 3356e8d8bef9SDimitry Andric for (auto *MBB : BlockOrders) { 3357349cc55cSDimitry Andric DbgValue *BlockLiveIn = LiveInIdx[MBB]; 3358349cc55cSDimitry Andric if (BlockLiveIn->Kind == DbgValue::NoVal) 3359e8d8bef9SDimitry Andric continue; 3360bdd1243dSDimitry Andric if (BlockLiveIn->isUnjoinedPHI()) 3361349cc55cSDimitry Andric continue; 3362349cc55cSDimitry Andric if (BlockLiveIn->Kind == DbgValue::VPHI) 3363349cc55cSDimitry Andric BlockLiveIn->Kind = DbgValue::Def; 3364*0fca6ea1SDimitry Andric [[maybe_unused]] auto &[Var, DILoc] = DVMap.lookupDVID(VarID); 33654824e7fdSDimitry Andric assert(BlockLiveIn->Properties.DIExpr->getFragmentInfo() == 3366*0fca6ea1SDimitry Andric Var.getFragment() && 3367*0fca6ea1SDimitry Andric "Fragment info missing during value prop"); 3368*0fca6ea1SDimitry Andric Output[MBB->getNumber()].push_back(std::make_pair(VarID, *BlockLiveIn)); 3369e8d8bef9SDimitry Andric } 3370349cc55cSDimitry Andric } // Per-variable loop. 3371e8d8bef9SDimitry Andric 3372e8d8bef9SDimitry Andric BlockOrders.clear(); 3373e8d8bef9SDimitry Andric BlocksToExplore.clear(); 3374e8d8bef9SDimitry Andric } 3375e8d8bef9SDimitry Andric 33761fd87a68SDimitry Andric void InstrRefBasedLDV::placePHIsForSingleVarDefinition( 33771fd87a68SDimitry Andric const SmallPtrSetImpl<MachineBasicBlock *> &InScopeBlocks, 33781fd87a68SDimitry Andric MachineBasicBlock *AssignMBB, SmallVectorImpl<VLocTracker> &AllTheVLocs, 3379*0fca6ea1SDimitry Andric DebugVariableID VarID, LiveInsT &Output) { 33801fd87a68SDimitry Andric // If there is a single definition of the variable, then working out it's 33811fd87a68SDimitry Andric // value everywhere is very simple: it's every block dominated by the 33821fd87a68SDimitry Andric // definition. At the dominance frontier, the usual algorithm would: 33831fd87a68SDimitry Andric // * Place PHIs, 33841fd87a68SDimitry Andric // * Propagate values into them, 33851fd87a68SDimitry Andric // * Find there's no incoming variable value from the other incoming branches 33861fd87a68SDimitry Andric // of the dominance frontier, 33871fd87a68SDimitry Andric // * Specify there's no variable value in blocks past the frontier. 33881fd87a68SDimitry Andric // This is a common case, hence it's worth special-casing it. 33891fd87a68SDimitry Andric 33901fd87a68SDimitry Andric // Pick out the variables value from the block transfer function. 33911fd87a68SDimitry Andric VLocTracker &VLocs = AllTheVLocs[AssignMBB->getNumber()]; 3392*0fca6ea1SDimitry Andric auto ValueIt = VLocs.Vars.find(VarID); 33931fd87a68SDimitry Andric const DbgValue &Value = ValueIt->second; 33941fd87a68SDimitry Andric 3395d56accc7SDimitry Andric // If it's an explicit assignment of "undef", that means there is no location 3396d56accc7SDimitry Andric // anyway, anywhere. 3397d56accc7SDimitry Andric if (Value.Kind == DbgValue::Undef) 3398d56accc7SDimitry Andric return; 3399d56accc7SDimitry Andric 34001fd87a68SDimitry Andric // Assign the variable value to entry to each dominated block that's in scope. 34011fd87a68SDimitry Andric // Skip the definition block -- it's assigned the variable value in the middle 34021fd87a68SDimitry Andric // of the block somewhere. 34031fd87a68SDimitry Andric for (auto *ScopeBlock : InScopeBlocks) { 34041fd87a68SDimitry Andric if (!DomTree->properlyDominates(AssignMBB, ScopeBlock)) 34051fd87a68SDimitry Andric continue; 34061fd87a68SDimitry Andric 3407*0fca6ea1SDimitry Andric Output[ScopeBlock->getNumber()].push_back({VarID, Value}); 34081fd87a68SDimitry Andric } 34091fd87a68SDimitry Andric 34101fd87a68SDimitry Andric // All blocks that aren't dominated have no live-in value, thus no variable 34111fd87a68SDimitry Andric // value will be given to them. 34121fd87a68SDimitry Andric } 34131fd87a68SDimitry Andric 3414e8d8bef9SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 3415e8d8bef9SDimitry Andric void InstrRefBasedLDV::dump_mloc_transfer( 3416e8d8bef9SDimitry Andric const MLocTransferMap &mloc_transfer) const { 3417fcaf7f86SDimitry Andric for (const auto &P : mloc_transfer) { 3418e8d8bef9SDimitry Andric std::string foo = MTracker->LocIdxToName(P.first); 3419e8d8bef9SDimitry Andric std::string bar = MTracker->IDAsString(P.second); 3420e8d8bef9SDimitry Andric dbgs() << "Loc " << foo << " --> " << bar << "\n"; 3421e8d8bef9SDimitry Andric } 3422e8d8bef9SDimitry Andric } 3423e8d8bef9SDimitry Andric #endif 3424e8d8bef9SDimitry Andric 3425e8d8bef9SDimitry Andric void InstrRefBasedLDV::initialSetup(MachineFunction &MF) { 3426e8d8bef9SDimitry Andric // Build some useful data structures. 3427349cc55cSDimitry Andric 3428349cc55cSDimitry Andric LLVMContext &Context = MF.getFunction().getContext(); 3429349cc55cSDimitry Andric EmptyExpr = DIExpression::get(Context, {}); 3430349cc55cSDimitry Andric 3431e8d8bef9SDimitry Andric auto hasNonArtificialLocation = [](const MachineInstr &MI) -> bool { 3432e8d8bef9SDimitry Andric if (const DebugLoc &DL = MI.getDebugLoc()) 3433e8d8bef9SDimitry Andric return DL.getLine() != 0; 3434e8d8bef9SDimitry Andric return false; 3435e8d8bef9SDimitry Andric }; 3436*0fca6ea1SDimitry Andric 3437*0fca6ea1SDimitry Andric // Collect a set of all the artificial blocks. Collect the size too, ilist 3438*0fca6ea1SDimitry Andric // size calls are O(n). 3439*0fca6ea1SDimitry Andric unsigned int Size = 0; 3440*0fca6ea1SDimitry Andric for (auto &MBB : MF) { 3441*0fca6ea1SDimitry Andric ++Size; 3442e8d8bef9SDimitry Andric if (none_of(MBB.instrs(), hasNonArtificialLocation)) 3443e8d8bef9SDimitry Andric ArtificialBlocks.insert(&MBB); 3444*0fca6ea1SDimitry Andric } 3445e8d8bef9SDimitry Andric 3446e8d8bef9SDimitry Andric // Compute mappings of block <=> RPO order. 3447e8d8bef9SDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(&MF); 3448e8d8bef9SDimitry Andric unsigned int RPONumber = 0; 3449*0fca6ea1SDimitry Andric OrderToBB.reserve(Size); 3450*0fca6ea1SDimitry Andric BBToOrder.reserve(Size); 3451*0fca6ea1SDimitry Andric BBNumToRPO.reserve(Size); 3452bdd1243dSDimitry Andric auto processMBB = [&](MachineBasicBlock *MBB) { 3453*0fca6ea1SDimitry Andric OrderToBB.push_back(MBB); 3454fe6060f1SDimitry Andric BBToOrder[MBB] = RPONumber; 3455fe6060f1SDimitry Andric BBNumToRPO[MBB->getNumber()] = RPONumber; 3456e8d8bef9SDimitry Andric ++RPONumber; 3457bdd1243dSDimitry Andric }; 3458bdd1243dSDimitry Andric for (MachineBasicBlock *MBB : RPOT) 3459bdd1243dSDimitry Andric processMBB(MBB); 3460bdd1243dSDimitry Andric for (MachineBasicBlock &MBB : MF) 346106c3fb27SDimitry Andric if (!BBToOrder.contains(&MBB)) 3462bdd1243dSDimitry Andric processMBB(&MBB); 3463fe6060f1SDimitry Andric 3464fe6060f1SDimitry Andric // Order value substitutions by their "source" operand pair, for quick lookup. 3465fe6060f1SDimitry Andric llvm::sort(MF.DebugValueSubstitutions); 3466fe6060f1SDimitry Andric 3467fe6060f1SDimitry Andric #ifdef EXPENSIVE_CHECKS 3468fe6060f1SDimitry Andric // As an expensive check, test whether there are any duplicate substitution 3469fe6060f1SDimitry Andric // sources in the collection. 3470fe6060f1SDimitry Andric if (MF.DebugValueSubstitutions.size() > 2) { 3471fe6060f1SDimitry Andric for (auto It = MF.DebugValueSubstitutions.begin(); 3472fe6060f1SDimitry Andric It != std::prev(MF.DebugValueSubstitutions.end()); ++It) { 3473fe6060f1SDimitry Andric assert(It->Src != std::next(It)->Src && "Duplicate variable location " 3474fe6060f1SDimitry Andric "substitution seen"); 3475fe6060f1SDimitry Andric } 3476fe6060f1SDimitry Andric } 3477fe6060f1SDimitry Andric #endif 3478e8d8bef9SDimitry Andric } 3479e8d8bef9SDimitry Andric 3480d56accc7SDimitry Andric // Produce an "ejection map" for blocks, i.e., what's the highest-numbered 3481d56accc7SDimitry Andric // lexical scope it's used in. When exploring in DFS order and we pass that 3482d56accc7SDimitry Andric // scope, the block can be processed and any tracking information freed. 3483d56accc7SDimitry Andric void InstrRefBasedLDV::makeDepthFirstEjectionMap( 3484d56accc7SDimitry Andric SmallVectorImpl<unsigned> &EjectionMap, 3485d56accc7SDimitry Andric const ScopeToDILocT &ScopeToDILocation, 3486d56accc7SDimitry Andric ScopeToAssignBlocksT &ScopeToAssignBlocks) { 3487d56accc7SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore; 3488d56accc7SDimitry Andric SmallVector<std::pair<LexicalScope *, ssize_t>, 4> WorkStack; 3489d56accc7SDimitry Andric auto *TopScope = LS.getCurrentFunctionScope(); 3490d56accc7SDimitry Andric 3491d56accc7SDimitry Andric // Unlike lexical scope explorers, we explore in reverse order, to find the 3492d56accc7SDimitry Andric // "last" lexical scope used for each block early. 3493d56accc7SDimitry Andric WorkStack.push_back({TopScope, TopScope->getChildren().size() - 1}); 3494d56accc7SDimitry Andric 3495d56accc7SDimitry Andric while (!WorkStack.empty()) { 3496d56accc7SDimitry Andric auto &ScopePosition = WorkStack.back(); 3497d56accc7SDimitry Andric LexicalScope *WS = ScopePosition.first; 3498d56accc7SDimitry Andric ssize_t ChildNum = ScopePosition.second--; 3499d56accc7SDimitry Andric 3500d56accc7SDimitry Andric const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); 3501d56accc7SDimitry Andric if (ChildNum >= 0) { 3502d56accc7SDimitry Andric // If ChildNum is positive, there are remaining children to explore. 3503d56accc7SDimitry Andric // Push the child and its children-count onto the stack. 3504d56accc7SDimitry Andric auto &ChildScope = Children[ChildNum]; 3505d56accc7SDimitry Andric WorkStack.push_back( 3506d56accc7SDimitry Andric std::make_pair(ChildScope, ChildScope->getChildren().size() - 1)); 3507d56accc7SDimitry Andric } else { 3508d56accc7SDimitry Andric WorkStack.pop_back(); 3509d56accc7SDimitry Andric 3510d56accc7SDimitry Andric // We've explored all children and any later blocks: examine all blocks 3511d56accc7SDimitry Andric // in our scope. If they haven't yet had an ejection number set, then 3512d56accc7SDimitry Andric // this scope will be the last to use that block. 3513d56accc7SDimitry Andric auto DILocationIt = ScopeToDILocation.find(WS); 3514d56accc7SDimitry Andric if (DILocationIt != ScopeToDILocation.end()) { 3515d56accc7SDimitry Andric getBlocksForScope(DILocationIt->second, BlocksToExplore, 3516d56accc7SDimitry Andric ScopeToAssignBlocks.find(WS)->second); 3517fcaf7f86SDimitry Andric for (const auto *MBB : BlocksToExplore) { 3518d56accc7SDimitry Andric unsigned BBNum = MBB->getNumber(); 3519d56accc7SDimitry Andric if (EjectionMap[BBNum] == 0) 3520d56accc7SDimitry Andric EjectionMap[BBNum] = WS->getDFSOut(); 3521d56accc7SDimitry Andric } 3522d56accc7SDimitry Andric 3523d56accc7SDimitry Andric BlocksToExplore.clear(); 3524d56accc7SDimitry Andric } 3525d56accc7SDimitry Andric } 3526d56accc7SDimitry Andric } 3527d56accc7SDimitry Andric } 3528d56accc7SDimitry Andric 3529d56accc7SDimitry Andric bool InstrRefBasedLDV::depthFirstVLocAndEmit( 3530d56accc7SDimitry Andric unsigned MaxNumBlocks, const ScopeToDILocT &ScopeToDILocation, 3531d56accc7SDimitry Andric const ScopeToVarsT &ScopeToVars, ScopeToAssignBlocksT &ScopeToAssignBlocks, 353281ad6265SDimitry Andric LiveInsT &Output, FuncValueTable &MOutLocs, FuncValueTable &MInLocs, 3533d56accc7SDimitry Andric SmallVectorImpl<VLocTracker> &AllTheVLocs, MachineFunction &MF, 3534d56accc7SDimitry Andric const TargetPassConfig &TPC) { 3535*0fca6ea1SDimitry Andric TTracker = 3536*0fca6ea1SDimitry Andric new TransferTracker(TII, MTracker, MF, DVMap, *TRI, CalleeSavedRegs, TPC); 3537d56accc7SDimitry Andric unsigned NumLocs = MTracker->getNumLocs(); 3538d56accc7SDimitry Andric VTracker = nullptr; 3539d56accc7SDimitry Andric 3540d56accc7SDimitry Andric // No scopes? No variable locations. 354181ad6265SDimitry Andric if (!LS.getCurrentFunctionScope()) 3542d56accc7SDimitry Andric return false; 3543d56accc7SDimitry Andric 3544d56accc7SDimitry Andric // Build map from block number to the last scope that uses the block. 3545d56accc7SDimitry Andric SmallVector<unsigned, 16> EjectionMap; 3546d56accc7SDimitry Andric EjectionMap.resize(MaxNumBlocks, 0); 3547d56accc7SDimitry Andric makeDepthFirstEjectionMap(EjectionMap, ScopeToDILocation, 3548d56accc7SDimitry Andric ScopeToAssignBlocks); 3549d56accc7SDimitry Andric 3550d56accc7SDimitry Andric // Helper lambda for ejecting a block -- if nothing is going to use the block, 3551d56accc7SDimitry Andric // we can translate the variable location information into DBG_VALUEs and then 3552d56accc7SDimitry Andric // free all of InstrRefBasedLDV's data structures. 3553d56accc7SDimitry Andric auto EjectBlock = [&](MachineBasicBlock &MBB) -> void { 3554d56accc7SDimitry Andric unsigned BBNum = MBB.getNumber(); 3555d56accc7SDimitry Andric AllTheVLocs[BBNum].clear(); 3556d56accc7SDimitry Andric 3557d56accc7SDimitry Andric // Prime the transfer-tracker, and then step through all the block 3558d56accc7SDimitry Andric // instructions, installing transfers. 3559d56accc7SDimitry Andric MTracker->reset(); 3560cb14a3feSDimitry Andric MTracker->loadFromArray(MInLocs[MBB], BBNum); 3561cb14a3feSDimitry Andric TTracker->loadInlocs(MBB, MInLocs[MBB], DbgOpStore, Output[BBNum], NumLocs); 3562d56accc7SDimitry Andric 3563d56accc7SDimitry Andric CurBB = BBNum; 3564d56accc7SDimitry Andric CurInst = 1; 3565d56accc7SDimitry Andric for (auto &MI : MBB) { 35665f757f3fSDimitry Andric process(MI, &MOutLocs, &MInLocs); 3567d56accc7SDimitry Andric TTracker->checkInstForNewValues(CurInst, MI.getIterator()); 3568d56accc7SDimitry Andric ++CurInst; 3569d56accc7SDimitry Andric } 3570d56accc7SDimitry Andric 3571d56accc7SDimitry Andric // Free machine-location tables for this block. 3572cb14a3feSDimitry Andric MInLocs.ejectTableForBlock(MBB); 3573cb14a3feSDimitry Andric MOutLocs.ejectTableForBlock(MBB); 3574d56accc7SDimitry Andric // We don't need live-in variable values for this block either. 3575d56accc7SDimitry Andric Output[BBNum].clear(); 3576d56accc7SDimitry Andric AllTheVLocs[BBNum].clear(); 3577d56accc7SDimitry Andric }; 3578d56accc7SDimitry Andric 3579d56accc7SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 8> BlocksToExplore; 3580d56accc7SDimitry Andric SmallVector<std::pair<LexicalScope *, ssize_t>, 4> WorkStack; 3581d56accc7SDimitry Andric WorkStack.push_back({LS.getCurrentFunctionScope(), 0}); 3582d56accc7SDimitry Andric unsigned HighestDFSIn = 0; 3583d56accc7SDimitry Andric 3584d56accc7SDimitry Andric // Proceed to explore in depth first order. 3585d56accc7SDimitry Andric while (!WorkStack.empty()) { 3586d56accc7SDimitry Andric auto &ScopePosition = WorkStack.back(); 3587d56accc7SDimitry Andric LexicalScope *WS = ScopePosition.first; 3588d56accc7SDimitry Andric ssize_t ChildNum = ScopePosition.second++; 3589d56accc7SDimitry Andric 3590d56accc7SDimitry Andric // We obesrve scopes with children twice here, once descending in, once 3591d56accc7SDimitry Andric // ascending out of the scope nest. Use HighestDFSIn as a ratchet to ensure 3592d56accc7SDimitry Andric // we don't process a scope twice. Additionally, ignore scopes that don't 3593d56accc7SDimitry Andric // have a DILocation -- by proxy, this means we never tracked any variable 3594d56accc7SDimitry Andric // assignments in that scope. 3595d56accc7SDimitry Andric auto DILocIt = ScopeToDILocation.find(WS); 3596d56accc7SDimitry Andric if (HighestDFSIn <= WS->getDFSIn() && DILocIt != ScopeToDILocation.end()) { 3597d56accc7SDimitry Andric const DILocation *DILoc = DILocIt->second; 3598d56accc7SDimitry Andric auto &VarsWeCareAbout = ScopeToVars.find(WS)->second; 3599d56accc7SDimitry Andric auto &BlocksInScope = ScopeToAssignBlocks.find(WS)->second; 3600d56accc7SDimitry Andric 3601d56accc7SDimitry Andric buildVLocValueMap(DILoc, VarsWeCareAbout, BlocksInScope, Output, MOutLocs, 3602d56accc7SDimitry Andric MInLocs, AllTheVLocs); 3603d56accc7SDimitry Andric } 3604d56accc7SDimitry Andric 3605d56accc7SDimitry Andric HighestDFSIn = std::max(HighestDFSIn, WS->getDFSIn()); 3606d56accc7SDimitry Andric 3607d56accc7SDimitry Andric // Descend into any scope nests. 3608d56accc7SDimitry Andric const SmallVectorImpl<LexicalScope *> &Children = WS->getChildren(); 3609d56accc7SDimitry Andric if (ChildNum < (ssize_t)Children.size()) { 3610d56accc7SDimitry Andric // There are children to explore -- push onto stack and continue. 3611d56accc7SDimitry Andric auto &ChildScope = Children[ChildNum]; 3612d56accc7SDimitry Andric WorkStack.push_back(std::make_pair(ChildScope, 0)); 3613d56accc7SDimitry Andric } else { 3614d56accc7SDimitry Andric WorkStack.pop_back(); 3615d56accc7SDimitry Andric 3616d56accc7SDimitry Andric // We've explored a leaf, or have explored all the children of a scope. 3617d56accc7SDimitry Andric // Try to eject any blocks where this is the last scope it's relevant to. 3618d56accc7SDimitry Andric auto DILocationIt = ScopeToDILocation.find(WS); 3619d56accc7SDimitry Andric if (DILocationIt == ScopeToDILocation.end()) 3620d56accc7SDimitry Andric continue; 3621d56accc7SDimitry Andric 3622d56accc7SDimitry Andric getBlocksForScope(DILocationIt->second, BlocksToExplore, 3623d56accc7SDimitry Andric ScopeToAssignBlocks.find(WS)->second); 3624fcaf7f86SDimitry Andric for (const auto *MBB : BlocksToExplore) 3625d56accc7SDimitry Andric if (WS->getDFSOut() == EjectionMap[MBB->getNumber()]) 3626d56accc7SDimitry Andric EjectBlock(const_cast<MachineBasicBlock &>(*MBB)); 3627d56accc7SDimitry Andric 3628d56accc7SDimitry Andric BlocksToExplore.clear(); 3629d56accc7SDimitry Andric } 3630d56accc7SDimitry Andric } 3631d56accc7SDimitry Andric 3632d56accc7SDimitry Andric // Some artificial blocks may not have been ejected, meaning they're not 3633d56accc7SDimitry Andric // connected to an actual legitimate scope. This can technically happen 3634d56accc7SDimitry Andric // with things like the entry block. In theory, we shouldn't need to do 3635d56accc7SDimitry Andric // anything for such out-of-scope blocks, but for the sake of being similar 3636d56accc7SDimitry Andric // to VarLocBasedLDV, eject these too. 3637d56accc7SDimitry Andric for (auto *MBB : ArtificialBlocks) 3638cb14a3feSDimitry Andric if (MInLocs.hasTableFor(*MBB)) 3639d56accc7SDimitry Andric EjectBlock(*MBB); 3640d56accc7SDimitry Andric 3641*0fca6ea1SDimitry Andric return emitTransfers(); 3642d56accc7SDimitry Andric } 3643d56accc7SDimitry Andric 3644*0fca6ea1SDimitry Andric bool InstrRefBasedLDV::emitTransfers() { 36451fd87a68SDimitry Andric // Go through all the transfers recorded in the TransferTracker -- this is 36461fd87a68SDimitry Andric // both the live-ins to a block, and any movements of values that happen 36471fd87a68SDimitry Andric // in the middle. 3648*0fca6ea1SDimitry Andric for (auto &P : TTracker->Transfers) { 36491fd87a68SDimitry Andric // We have to insert DBG_VALUEs in a consistent order, otherwise they 36501fd87a68SDimitry Andric // appear in DWARF in different orders. Use the order that they appear 36511fd87a68SDimitry Andric // when walking through each block / each instruction, stored in 3652*0fca6ea1SDimitry Andric // DVMap. 3653*0fca6ea1SDimitry Andric llvm::sort(P.Insts, llvm::less_first()); 36541fd87a68SDimitry Andric 36551fd87a68SDimitry Andric // Insert either before or after the designated point... 36561fd87a68SDimitry Andric if (P.MBB) { 36571fd87a68SDimitry Andric MachineBasicBlock &MBB = *P.MBB; 3658*0fca6ea1SDimitry Andric for (const auto &Pair : P.Insts) 36591fd87a68SDimitry Andric MBB.insert(P.Pos, Pair.second); 36601fd87a68SDimitry Andric } else { 36611fd87a68SDimitry Andric // Terminators, like tail calls, can clobber things. Don't try and place 36621fd87a68SDimitry Andric // transfers after them. 36631fd87a68SDimitry Andric if (P.Pos->isTerminator()) 36641fd87a68SDimitry Andric continue; 36651fd87a68SDimitry Andric 36661fd87a68SDimitry Andric MachineBasicBlock &MBB = *P.Pos->getParent(); 3667*0fca6ea1SDimitry Andric for (const auto &Pair : P.Insts) 36681fd87a68SDimitry Andric MBB.insertAfterBundle(P.Pos, Pair.second); 36691fd87a68SDimitry Andric } 36701fd87a68SDimitry Andric } 36711fd87a68SDimitry Andric 36721fd87a68SDimitry Andric return TTracker->Transfers.size() != 0; 36731fd87a68SDimitry Andric } 36741fd87a68SDimitry Andric 3675e8d8bef9SDimitry Andric /// Calculate the liveness information for the given machine function and 3676e8d8bef9SDimitry Andric /// extend ranges across basic blocks. 3677e8d8bef9SDimitry Andric bool InstrRefBasedLDV::ExtendRanges(MachineFunction &MF, 3678349cc55cSDimitry Andric MachineDominatorTree *DomTree, 3679349cc55cSDimitry Andric TargetPassConfig *TPC, 3680349cc55cSDimitry Andric unsigned InputBBLimit, 3681349cc55cSDimitry Andric unsigned InputDbgValLimit) { 3682e8d8bef9SDimitry Andric // No subprogram means this function contains no debuginfo. 3683e8d8bef9SDimitry Andric if (!MF.getFunction().getSubprogram()) 3684e8d8bef9SDimitry Andric return false; 3685e8d8bef9SDimitry Andric 3686e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "\nDebug Range Extension\n"); 3687e8d8bef9SDimitry Andric this->TPC = TPC; 3688e8d8bef9SDimitry Andric 3689349cc55cSDimitry Andric this->DomTree = DomTree; 3690e8d8bef9SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 3691349cc55cSDimitry Andric MRI = &MF.getRegInfo(); 3692e8d8bef9SDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 3693e8d8bef9SDimitry Andric TFI = MF.getSubtarget().getFrameLowering(); 3694e8d8bef9SDimitry Andric TFI->getCalleeSaves(MF, CalleeSavedRegs); 3695fe6060f1SDimitry Andric MFI = &MF.getFrameInfo(); 3696e8d8bef9SDimitry Andric LS.initialize(MF); 3697e8d8bef9SDimitry Andric 36984824e7fdSDimitry Andric const auto &STI = MF.getSubtarget(); 36994824e7fdSDimitry Andric AdjustsStackInCalls = MFI->adjustsStack() && 37004824e7fdSDimitry Andric STI.getFrameLowering()->stackProbeFunctionModifiesSP(); 37014824e7fdSDimitry Andric if (AdjustsStackInCalls) 37024824e7fdSDimitry Andric StackProbeSymbolName = STI.getTargetLowering()->getStackProbeSymbolName(MF); 37034824e7fdSDimitry Andric 3704e8d8bef9SDimitry Andric MTracker = 3705e8d8bef9SDimitry Andric new MLocTracker(MF, *TII, *TRI, *MF.getSubtarget().getTargetLowering()); 3706e8d8bef9SDimitry Andric VTracker = nullptr; 3707e8d8bef9SDimitry Andric TTracker = nullptr; 3708e8d8bef9SDimitry Andric 3709e8d8bef9SDimitry Andric SmallVector<MLocTransferMap, 32> MLocTransfer; 3710e8d8bef9SDimitry Andric SmallVector<VLocTracker, 8> vlocs; 3711e8d8bef9SDimitry Andric LiveInsT SavedLiveIns; 3712e8d8bef9SDimitry Andric 3713e8d8bef9SDimitry Andric int MaxNumBlocks = -1; 3714e8d8bef9SDimitry Andric for (auto &MBB : MF) 3715e8d8bef9SDimitry Andric MaxNumBlocks = std::max(MBB.getNumber(), MaxNumBlocks); 3716e8d8bef9SDimitry Andric assert(MaxNumBlocks >= 0); 3717e8d8bef9SDimitry Andric ++MaxNumBlocks; 3718e8d8bef9SDimitry Andric 371981ad6265SDimitry Andric initialSetup(MF); 372081ad6265SDimitry Andric 3721e8d8bef9SDimitry Andric MLocTransfer.resize(MaxNumBlocks); 3722*0fca6ea1SDimitry Andric vlocs.resize(MaxNumBlocks, VLocTracker(DVMap, OverlapFragments, EmptyExpr)); 3723e8d8bef9SDimitry Andric SavedLiveIns.resize(MaxNumBlocks); 3724e8d8bef9SDimitry Andric 3725e8d8bef9SDimitry Andric produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks); 3726e8d8bef9SDimitry Andric 3727e8d8bef9SDimitry Andric // Allocate and initialize two array-of-arrays for the live-in and live-out 3728e8d8bef9SDimitry Andric // machine values. The outer dimension is the block number; while the inner 3729e8d8bef9SDimitry Andric // dimension is a LocIdx from MLocTracker. 3730e8d8bef9SDimitry Andric unsigned NumLocs = MTracker->getNumLocs(); 3731cb14a3feSDimitry Andric FuncValueTable MOutLocs(MaxNumBlocks, NumLocs); 3732cb14a3feSDimitry Andric FuncValueTable MInLocs(MaxNumBlocks, NumLocs); 3733e8d8bef9SDimitry Andric 3734e8d8bef9SDimitry Andric // Solve the machine value dataflow problem using the MLocTransfer function, 3735e8d8bef9SDimitry Andric // storing the computed live-ins / live-outs into the array-of-arrays. We use 3736e8d8bef9SDimitry Andric // both live-ins and live-outs for decision making in the variable value 3737e8d8bef9SDimitry Andric // dataflow problem. 3738349cc55cSDimitry Andric buildMLocValueMap(MF, MInLocs, MOutLocs, MLocTransfer); 3739e8d8bef9SDimitry Andric 3740fe6060f1SDimitry Andric // Patch up debug phi numbers, turning unknown block-live-in values into 3741fe6060f1SDimitry Andric // either live-through machine values, or PHIs. 3742fe6060f1SDimitry Andric for (auto &DBG_PHI : DebugPHINumToValue) { 3743fe6060f1SDimitry Andric // Identify unresolved block-live-ins. 374481ad6265SDimitry Andric if (!DBG_PHI.ValueRead) 374581ad6265SDimitry Andric continue; 374681ad6265SDimitry Andric 374781ad6265SDimitry Andric ValueIDNum &Num = *DBG_PHI.ValueRead; 3748fe6060f1SDimitry Andric if (!Num.isPHI()) 3749fe6060f1SDimitry Andric continue; 3750fe6060f1SDimitry Andric 3751fe6060f1SDimitry Andric unsigned BlockNo = Num.getBlock(); 3752fe6060f1SDimitry Andric LocIdx LocNo = Num.getLoc(); 375306c3fb27SDimitry Andric ValueIDNum ResolvedValue = MInLocs[BlockNo][LocNo.asU64()]; 375406c3fb27SDimitry Andric // If there is no resolved value for this live-in then it is not directly 375506c3fb27SDimitry Andric // reachable from the entry block -- model it as a PHI on entry to this 375606c3fb27SDimitry Andric // block, which means we leave the ValueIDNum unchanged. 375706c3fb27SDimitry Andric if (ResolvedValue != ValueIDNum::EmptyValue) 375806c3fb27SDimitry Andric Num = ResolvedValue; 3759fe6060f1SDimitry Andric } 3760fe6060f1SDimitry Andric // Later, we'll be looking up ranges of instruction numbers. 3761fe6060f1SDimitry Andric llvm::sort(DebugPHINumToValue); 3762fe6060f1SDimitry Andric 3763e8d8bef9SDimitry Andric // Walk back through each block / instruction, collecting DBG_VALUE 3764e8d8bef9SDimitry Andric // instructions and recording what machine value their operands refer to. 3765*0fca6ea1SDimitry Andric for (MachineBasicBlock *MBB : OrderToBB) { 3766*0fca6ea1SDimitry Andric CurBB = MBB->getNumber(); 3767e8d8bef9SDimitry Andric VTracker = &vlocs[CurBB]; 3768*0fca6ea1SDimitry Andric VTracker->MBB = MBB; 3769*0fca6ea1SDimitry Andric MTracker->loadFromArray(MInLocs[*MBB], CurBB); 3770e8d8bef9SDimitry Andric CurInst = 1; 3771*0fca6ea1SDimitry Andric for (auto &MI : *MBB) { 37725f757f3fSDimitry Andric process(MI, &MOutLocs, &MInLocs); 3773e8d8bef9SDimitry Andric ++CurInst; 3774e8d8bef9SDimitry Andric } 3775e8d8bef9SDimitry Andric MTracker->reset(); 3776e8d8bef9SDimitry Andric } 3777e8d8bef9SDimitry Andric 3778e8d8bef9SDimitry Andric // Map from one LexicalScope to all the variables in that scope. 37791fd87a68SDimitry Andric ScopeToVarsT ScopeToVars; 3780e8d8bef9SDimitry Andric 37811fd87a68SDimitry Andric // Map from One lexical scope to all blocks where assignments happen for 37821fd87a68SDimitry Andric // that scope. 37831fd87a68SDimitry Andric ScopeToAssignBlocksT ScopeToAssignBlocks; 3784e8d8bef9SDimitry Andric 37851fd87a68SDimitry Andric // Store map of DILocations that describes scopes. 37861fd87a68SDimitry Andric ScopeToDILocT ScopeToDILocation; 3787e8d8bef9SDimitry Andric 3788e8d8bef9SDimitry Andric // To mirror old LiveDebugValues, enumerate variables in RPOT order. Otherwise 3789e8d8bef9SDimitry Andric // the order is unimportant, it just has to be stable. 3790349cc55cSDimitry Andric unsigned VarAssignCount = 0; 3791e8d8bef9SDimitry Andric for (unsigned int I = 0; I < OrderToBB.size(); ++I) { 3792e8d8bef9SDimitry Andric auto *MBB = OrderToBB[I]; 3793e8d8bef9SDimitry Andric auto *VTracker = &vlocs[MBB->getNumber()]; 3794e8d8bef9SDimitry Andric // Collect each variable with a DBG_VALUE in this block. 3795e8d8bef9SDimitry Andric for (auto &idx : VTracker->Vars) { 3796*0fca6ea1SDimitry Andric DebugVariableID VarID = idx.first; 3797*0fca6ea1SDimitry Andric const DILocation *ScopeLoc = VTracker->Scopes[VarID]; 3798e8d8bef9SDimitry Andric assert(ScopeLoc != nullptr); 3799e8d8bef9SDimitry Andric auto *Scope = LS.findLexicalScope(ScopeLoc); 3800e8d8bef9SDimitry Andric 3801e8d8bef9SDimitry Andric // No insts in scope -> shouldn't have been recorded. 3802e8d8bef9SDimitry Andric assert(Scope != nullptr); 3803e8d8bef9SDimitry Andric 3804*0fca6ea1SDimitry Andric ScopeToVars[Scope].insert(VarID); 38051fd87a68SDimitry Andric ScopeToAssignBlocks[Scope].insert(VTracker->MBB); 3806e8d8bef9SDimitry Andric ScopeToDILocation[Scope] = ScopeLoc; 3807349cc55cSDimitry Andric ++VarAssignCount; 3808e8d8bef9SDimitry Andric } 3809e8d8bef9SDimitry Andric } 3810e8d8bef9SDimitry Andric 3811349cc55cSDimitry Andric bool Changed = false; 3812349cc55cSDimitry Andric 3813349cc55cSDimitry Andric // If we have an extremely large number of variable assignments and blocks, 3814349cc55cSDimitry Andric // bail out at this point. We've burnt some time doing analysis already, 3815349cc55cSDimitry Andric // however we should cut our losses. 3816349cc55cSDimitry Andric if ((unsigned)MaxNumBlocks > InputBBLimit && 3817349cc55cSDimitry Andric VarAssignCount > InputDbgValLimit) { 3818349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Disabling InstrRefBasedLDV: " << MF.getName() 3819349cc55cSDimitry Andric << " has " << MaxNumBlocks << " basic blocks and " 3820349cc55cSDimitry Andric << VarAssignCount 3821349cc55cSDimitry Andric << " variable assignments, exceeding limits.\n"); 3822d56accc7SDimitry Andric } else { 3823d56accc7SDimitry Andric // Optionally, solve the variable value problem and emit to blocks by using 3824d56accc7SDimitry Andric // a lexical-scope-depth search. It should be functionally identical to 3825d56accc7SDimitry Andric // the "else" block of this condition. 3826d56accc7SDimitry Andric Changed = depthFirstVLocAndEmit( 3827d56accc7SDimitry Andric MaxNumBlocks, ScopeToDILocation, ScopeToVars, ScopeToAssignBlocks, 3828*0fca6ea1SDimitry Andric SavedLiveIns, MOutLocs, MInLocs, vlocs, MF, *TPC); 3829d56accc7SDimitry Andric } 3830d56accc7SDimitry Andric 3831e8d8bef9SDimitry Andric delete MTracker; 3832e8d8bef9SDimitry Andric delete TTracker; 3833e8d8bef9SDimitry Andric MTracker = nullptr; 3834e8d8bef9SDimitry Andric VTracker = nullptr; 3835e8d8bef9SDimitry Andric TTracker = nullptr; 3836e8d8bef9SDimitry Andric 3837e8d8bef9SDimitry Andric ArtificialBlocks.clear(); 3838e8d8bef9SDimitry Andric OrderToBB.clear(); 3839e8d8bef9SDimitry Andric BBToOrder.clear(); 3840e8d8bef9SDimitry Andric BBNumToRPO.clear(); 3841e8d8bef9SDimitry Andric DebugInstrNumToInstr.clear(); 3842fe6060f1SDimitry Andric DebugPHINumToValue.clear(); 38434824e7fdSDimitry Andric OverlapFragments.clear(); 38444824e7fdSDimitry Andric SeenFragments.clear(); 3845d56accc7SDimitry Andric SeenDbgPHIs.clear(); 3846bdd1243dSDimitry Andric DbgOpStore.clear(); 3847*0fca6ea1SDimitry Andric DVMap.clear(); 3848e8d8bef9SDimitry Andric 3849e8d8bef9SDimitry Andric return Changed; 3850e8d8bef9SDimitry Andric } 3851e8d8bef9SDimitry Andric 3852e8d8bef9SDimitry Andric LDVImpl *llvm::makeInstrRefBasedLiveDebugValues() { 3853e8d8bef9SDimitry Andric return new InstrRefBasedLDV(); 3854e8d8bef9SDimitry Andric } 3855fe6060f1SDimitry Andric 3856fe6060f1SDimitry Andric namespace { 3857fe6060f1SDimitry Andric class LDVSSABlock; 3858fe6060f1SDimitry Andric class LDVSSAUpdater; 3859fe6060f1SDimitry Andric 3860fe6060f1SDimitry Andric // Pick a type to identify incoming block values as we construct SSA. We 3861fe6060f1SDimitry Andric // can't use anything more robust than an integer unfortunately, as SSAUpdater 3862fe6060f1SDimitry Andric // expects to zero-initialize the type. 3863fe6060f1SDimitry Andric typedef uint64_t BlockValueNum; 3864fe6060f1SDimitry Andric 3865fe6060f1SDimitry Andric /// Represents an SSA PHI node for the SSA updater class. Contains the block 3866fe6060f1SDimitry Andric /// this PHI is in, the value number it would have, and the expected incoming 3867fe6060f1SDimitry Andric /// values from parent blocks. 3868fe6060f1SDimitry Andric class LDVSSAPhi { 3869fe6060f1SDimitry Andric public: 3870fe6060f1SDimitry Andric SmallVector<std::pair<LDVSSABlock *, BlockValueNum>, 4> IncomingValues; 3871fe6060f1SDimitry Andric LDVSSABlock *ParentBlock; 3872fe6060f1SDimitry Andric BlockValueNum PHIValNum; 3873fe6060f1SDimitry Andric LDVSSAPhi(BlockValueNum PHIValNum, LDVSSABlock *ParentBlock) 3874fe6060f1SDimitry Andric : ParentBlock(ParentBlock), PHIValNum(PHIValNum) {} 3875fe6060f1SDimitry Andric 3876fe6060f1SDimitry Andric LDVSSABlock *getParent() { return ParentBlock; } 3877fe6060f1SDimitry Andric }; 3878fe6060f1SDimitry Andric 3879fe6060f1SDimitry Andric /// Thin wrapper around a block predecessor iterator. Only difference from a 3880fe6060f1SDimitry Andric /// normal block iterator is that it dereferences to an LDVSSABlock. 3881fe6060f1SDimitry Andric class LDVSSABlockIterator { 3882fe6060f1SDimitry Andric public: 3883fe6060f1SDimitry Andric MachineBasicBlock::pred_iterator PredIt; 3884fe6060f1SDimitry Andric LDVSSAUpdater &Updater; 3885fe6060f1SDimitry Andric 3886fe6060f1SDimitry Andric LDVSSABlockIterator(MachineBasicBlock::pred_iterator PredIt, 3887fe6060f1SDimitry Andric LDVSSAUpdater &Updater) 3888fe6060f1SDimitry Andric : PredIt(PredIt), Updater(Updater) {} 3889fe6060f1SDimitry Andric 3890fe6060f1SDimitry Andric bool operator!=(const LDVSSABlockIterator &OtherIt) const { 3891fe6060f1SDimitry Andric return OtherIt.PredIt != PredIt; 3892fe6060f1SDimitry Andric } 3893fe6060f1SDimitry Andric 3894fe6060f1SDimitry Andric LDVSSABlockIterator &operator++() { 3895fe6060f1SDimitry Andric ++PredIt; 3896fe6060f1SDimitry Andric return *this; 3897fe6060f1SDimitry Andric } 3898fe6060f1SDimitry Andric 3899fe6060f1SDimitry Andric LDVSSABlock *operator*(); 3900fe6060f1SDimitry Andric }; 3901fe6060f1SDimitry Andric 3902fe6060f1SDimitry Andric /// Thin wrapper around a block for SSA Updater interface. Necessary because 3903fe6060f1SDimitry Andric /// we need to track the PHI value(s) that we may have observed as necessary 3904fe6060f1SDimitry Andric /// in this block. 3905fe6060f1SDimitry Andric class LDVSSABlock { 3906fe6060f1SDimitry Andric public: 3907fe6060f1SDimitry Andric MachineBasicBlock &BB; 3908fe6060f1SDimitry Andric LDVSSAUpdater &Updater; 3909fe6060f1SDimitry Andric using PHIListT = SmallVector<LDVSSAPhi, 1>; 3910fe6060f1SDimitry Andric /// List of PHIs in this block. There should only ever be one. 3911fe6060f1SDimitry Andric PHIListT PHIList; 3912fe6060f1SDimitry Andric 3913fe6060f1SDimitry Andric LDVSSABlock(MachineBasicBlock &BB, LDVSSAUpdater &Updater) 3914fe6060f1SDimitry Andric : BB(BB), Updater(Updater) {} 3915fe6060f1SDimitry Andric 3916fe6060f1SDimitry Andric LDVSSABlockIterator succ_begin() { 3917fe6060f1SDimitry Andric return LDVSSABlockIterator(BB.succ_begin(), Updater); 3918fe6060f1SDimitry Andric } 3919fe6060f1SDimitry Andric 3920fe6060f1SDimitry Andric LDVSSABlockIterator succ_end() { 3921fe6060f1SDimitry Andric return LDVSSABlockIterator(BB.succ_end(), Updater); 3922fe6060f1SDimitry Andric } 3923fe6060f1SDimitry Andric 3924fe6060f1SDimitry Andric /// SSAUpdater has requested a PHI: create that within this block record. 3925fe6060f1SDimitry Andric LDVSSAPhi *newPHI(BlockValueNum Value) { 3926fe6060f1SDimitry Andric PHIList.emplace_back(Value, this); 3927fe6060f1SDimitry Andric return &PHIList.back(); 3928fe6060f1SDimitry Andric } 3929fe6060f1SDimitry Andric 3930fe6060f1SDimitry Andric /// SSAUpdater wishes to know what PHIs already exist in this block. 3931fe6060f1SDimitry Andric PHIListT &phis() { return PHIList; } 3932fe6060f1SDimitry Andric }; 3933fe6060f1SDimitry Andric 3934fe6060f1SDimitry Andric /// Utility class for the SSAUpdater interface: tracks blocks, PHIs and values 3935fe6060f1SDimitry Andric /// while SSAUpdater is exploring the CFG. It's passed as a handle / baton to 3936fe6060f1SDimitry Andric // SSAUpdaterTraits<LDVSSAUpdater>. 3937fe6060f1SDimitry Andric class LDVSSAUpdater { 3938fe6060f1SDimitry Andric public: 3939fe6060f1SDimitry Andric /// Map of value numbers to PHI records. 3940fe6060f1SDimitry Andric DenseMap<BlockValueNum, LDVSSAPhi *> PHIs; 3941fe6060f1SDimitry Andric /// Map of which blocks generate Undef values -- blocks that are not 3942fe6060f1SDimitry Andric /// dominated by any Def. 3943*0fca6ea1SDimitry Andric DenseMap<MachineBasicBlock *, BlockValueNum> PoisonMap; 3944fe6060f1SDimitry Andric /// Map of machine blocks to our own records of them. 3945fe6060f1SDimitry Andric DenseMap<MachineBasicBlock *, LDVSSABlock *> BlockMap; 3946fe6060f1SDimitry Andric /// Machine location where any PHI must occur. 3947fe6060f1SDimitry Andric LocIdx Loc; 3948fe6060f1SDimitry Andric /// Table of live-in machine value numbers for blocks / locations. 39495f757f3fSDimitry Andric const FuncValueTable &MLiveIns; 3950fe6060f1SDimitry Andric 39515f757f3fSDimitry Andric LDVSSAUpdater(LocIdx L, const FuncValueTable &MLiveIns) 395281ad6265SDimitry Andric : Loc(L), MLiveIns(MLiveIns) {} 3953fe6060f1SDimitry Andric 3954fe6060f1SDimitry Andric void reset() { 3955fe6060f1SDimitry Andric for (auto &Block : BlockMap) 3956fe6060f1SDimitry Andric delete Block.second; 3957fe6060f1SDimitry Andric 3958fe6060f1SDimitry Andric PHIs.clear(); 3959*0fca6ea1SDimitry Andric PoisonMap.clear(); 3960fe6060f1SDimitry Andric BlockMap.clear(); 3961fe6060f1SDimitry Andric } 3962fe6060f1SDimitry Andric 3963fe6060f1SDimitry Andric ~LDVSSAUpdater() { reset(); } 3964fe6060f1SDimitry Andric 3965fe6060f1SDimitry Andric /// For a given MBB, create a wrapper block for it. Stores it in the 3966fe6060f1SDimitry Andric /// LDVSSAUpdater block map. 3967fe6060f1SDimitry Andric LDVSSABlock *getSSALDVBlock(MachineBasicBlock *BB) { 3968fe6060f1SDimitry Andric auto it = BlockMap.find(BB); 3969fe6060f1SDimitry Andric if (it == BlockMap.end()) { 3970fe6060f1SDimitry Andric BlockMap[BB] = new LDVSSABlock(*BB, *this); 3971fe6060f1SDimitry Andric it = BlockMap.find(BB); 3972fe6060f1SDimitry Andric } 3973fe6060f1SDimitry Andric return it->second; 3974fe6060f1SDimitry Andric } 3975fe6060f1SDimitry Andric 3976fe6060f1SDimitry Andric /// Find the live-in value number for the given block. Looks up the value at 3977fe6060f1SDimitry Andric /// the PHI location on entry. 3978fe6060f1SDimitry Andric BlockValueNum getValue(LDVSSABlock *LDVBB) { 3979cb14a3feSDimitry Andric return MLiveIns[LDVBB->BB][Loc.asU64()].asU64(); 3980fe6060f1SDimitry Andric } 3981fe6060f1SDimitry Andric }; 3982fe6060f1SDimitry Andric 3983fe6060f1SDimitry Andric LDVSSABlock *LDVSSABlockIterator::operator*() { 3984fe6060f1SDimitry Andric return Updater.getSSALDVBlock(*PredIt); 3985fe6060f1SDimitry Andric } 3986fe6060f1SDimitry Andric 3987fe6060f1SDimitry Andric #ifndef NDEBUG 3988fe6060f1SDimitry Andric 3989fe6060f1SDimitry Andric raw_ostream &operator<<(raw_ostream &out, const LDVSSAPhi &PHI) { 3990fe6060f1SDimitry Andric out << "SSALDVPHI " << PHI.PHIValNum; 3991fe6060f1SDimitry Andric return out; 3992fe6060f1SDimitry Andric } 3993fe6060f1SDimitry Andric 3994fe6060f1SDimitry Andric #endif 3995fe6060f1SDimitry Andric 3996fe6060f1SDimitry Andric } // namespace 3997fe6060f1SDimitry Andric 3998fe6060f1SDimitry Andric namespace llvm { 3999fe6060f1SDimitry Andric 4000fe6060f1SDimitry Andric /// Template specialization to give SSAUpdater access to CFG and value 4001fe6060f1SDimitry Andric /// information. SSAUpdater calls methods in these traits, passing in the 4002fe6060f1SDimitry Andric /// LDVSSAUpdater object, to learn about blocks and the values they define. 4003fe6060f1SDimitry Andric /// It also provides methods to create PHI nodes and track them. 4004fe6060f1SDimitry Andric template <> class SSAUpdaterTraits<LDVSSAUpdater> { 4005fe6060f1SDimitry Andric public: 4006fe6060f1SDimitry Andric using BlkT = LDVSSABlock; 4007fe6060f1SDimitry Andric using ValT = BlockValueNum; 4008fe6060f1SDimitry Andric using PhiT = LDVSSAPhi; 4009fe6060f1SDimitry Andric using BlkSucc_iterator = LDVSSABlockIterator; 4010fe6060f1SDimitry Andric 4011fe6060f1SDimitry Andric // Methods to access block successors -- dereferencing to our wrapper class. 4012fe6060f1SDimitry Andric static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); } 4013fe6060f1SDimitry Andric static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); } 4014fe6060f1SDimitry Andric 4015fe6060f1SDimitry Andric /// Iterator for PHI operands. 4016fe6060f1SDimitry Andric class PHI_iterator { 4017fe6060f1SDimitry Andric private: 4018fe6060f1SDimitry Andric LDVSSAPhi *PHI; 4019fe6060f1SDimitry Andric unsigned Idx; 4020fe6060f1SDimitry Andric 4021fe6060f1SDimitry Andric public: 4022fe6060f1SDimitry Andric explicit PHI_iterator(LDVSSAPhi *P) // begin iterator 4023fe6060f1SDimitry Andric : PHI(P), Idx(0) {} 4024fe6060f1SDimitry Andric PHI_iterator(LDVSSAPhi *P, bool) // end iterator 4025fe6060f1SDimitry Andric : PHI(P), Idx(PHI->IncomingValues.size()) {} 4026fe6060f1SDimitry Andric 4027fe6060f1SDimitry Andric PHI_iterator &operator++() { 4028fe6060f1SDimitry Andric Idx++; 4029fe6060f1SDimitry Andric return *this; 4030fe6060f1SDimitry Andric } 4031fe6060f1SDimitry Andric bool operator==(const PHI_iterator &X) const { return Idx == X.Idx; } 4032fe6060f1SDimitry Andric bool operator!=(const PHI_iterator &X) const { return !operator==(X); } 4033fe6060f1SDimitry Andric 4034fe6060f1SDimitry Andric BlockValueNum getIncomingValue() { return PHI->IncomingValues[Idx].second; } 4035fe6060f1SDimitry Andric 4036fe6060f1SDimitry Andric LDVSSABlock *getIncomingBlock() { return PHI->IncomingValues[Idx].first; } 4037fe6060f1SDimitry Andric }; 4038fe6060f1SDimitry Andric 4039fe6060f1SDimitry Andric static inline PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); } 4040fe6060f1SDimitry Andric 4041fe6060f1SDimitry Andric static inline PHI_iterator PHI_end(PhiT *PHI) { 4042fe6060f1SDimitry Andric return PHI_iterator(PHI, true); 4043fe6060f1SDimitry Andric } 4044fe6060f1SDimitry Andric 4045fe6060f1SDimitry Andric /// FindPredecessorBlocks - Put the predecessors of BB into the Preds 4046fe6060f1SDimitry Andric /// vector. 4047fe6060f1SDimitry Andric static void FindPredecessorBlocks(LDVSSABlock *BB, 4048fe6060f1SDimitry Andric SmallVectorImpl<LDVSSABlock *> *Preds) { 4049349cc55cSDimitry Andric for (MachineBasicBlock *Pred : BB->BB.predecessors()) 4050349cc55cSDimitry Andric Preds->push_back(BB->Updater.getSSALDVBlock(Pred)); 4051fe6060f1SDimitry Andric } 4052fe6060f1SDimitry Andric 4053*0fca6ea1SDimitry Andric /// GetPoisonVal - Normally creates an IMPLICIT_DEF instruction with a new 4054fe6060f1SDimitry Andric /// register. For LiveDebugValues, represents a block identified as not having 4055fe6060f1SDimitry Andric /// any DBG_PHI predecessors. 4056*0fca6ea1SDimitry Andric static BlockValueNum GetPoisonVal(LDVSSABlock *BB, LDVSSAUpdater *Updater) { 4057fe6060f1SDimitry Andric // Create a value number for this block -- it needs to be unique and in the 4058*0fca6ea1SDimitry Andric // "poison" collection, so that we know it's not real. Use a number 4059fe6060f1SDimitry Andric // representing a PHI into this block. 4060fe6060f1SDimitry Andric BlockValueNum Num = ValueIDNum(BB->BB.getNumber(), 0, Updater->Loc).asU64(); 4061*0fca6ea1SDimitry Andric Updater->PoisonMap[&BB->BB] = Num; 4062fe6060f1SDimitry Andric return Num; 4063fe6060f1SDimitry Andric } 4064fe6060f1SDimitry Andric 4065fe6060f1SDimitry Andric /// CreateEmptyPHI - Create a (representation of a) PHI in the given block. 4066fe6060f1SDimitry Andric /// SSAUpdater will populate it with information about incoming values. The 4067fe6060f1SDimitry Andric /// value number of this PHI is whatever the machine value number problem 4068fe6060f1SDimitry Andric /// solution determined it to be. This includes non-phi values if SSAUpdater 4069fe6060f1SDimitry Andric /// tries to create a PHI where the incoming values are identical. 4070fe6060f1SDimitry Andric static BlockValueNum CreateEmptyPHI(LDVSSABlock *BB, unsigned NumPreds, 4071fe6060f1SDimitry Andric LDVSSAUpdater *Updater) { 4072fe6060f1SDimitry Andric BlockValueNum PHIValNum = Updater->getValue(BB); 4073fe6060f1SDimitry Andric LDVSSAPhi *PHI = BB->newPHI(PHIValNum); 4074fe6060f1SDimitry Andric Updater->PHIs[PHIValNum] = PHI; 4075fe6060f1SDimitry Andric return PHIValNum; 4076fe6060f1SDimitry Andric } 4077fe6060f1SDimitry Andric 4078fe6060f1SDimitry Andric /// AddPHIOperand - Add the specified value as an operand of the PHI for 4079fe6060f1SDimitry Andric /// the specified predecessor block. 4080fe6060f1SDimitry Andric static void AddPHIOperand(LDVSSAPhi *PHI, BlockValueNum Val, LDVSSABlock *Pred) { 4081fe6060f1SDimitry Andric PHI->IncomingValues.push_back(std::make_pair(Pred, Val)); 4082fe6060f1SDimitry Andric } 4083fe6060f1SDimitry Andric 4084fe6060f1SDimitry Andric /// ValueIsPHI - Check if the instruction that defines the specified value 4085fe6060f1SDimitry Andric /// is a PHI instruction. 4086fe6060f1SDimitry Andric static LDVSSAPhi *ValueIsPHI(BlockValueNum Val, LDVSSAUpdater *Updater) { 408706c3fb27SDimitry Andric return Updater->PHIs.lookup(Val); 4088fe6060f1SDimitry Andric } 4089fe6060f1SDimitry Andric 4090fe6060f1SDimitry Andric /// ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source 4091fe6060f1SDimitry Andric /// operands, i.e., it was just added. 4092fe6060f1SDimitry Andric static LDVSSAPhi *ValueIsNewPHI(BlockValueNum Val, LDVSSAUpdater *Updater) { 4093fe6060f1SDimitry Andric LDVSSAPhi *PHI = ValueIsPHI(Val, Updater); 4094fe6060f1SDimitry Andric if (PHI && PHI->IncomingValues.size() == 0) 4095fe6060f1SDimitry Andric return PHI; 4096fe6060f1SDimitry Andric return nullptr; 4097fe6060f1SDimitry Andric } 4098fe6060f1SDimitry Andric 4099fe6060f1SDimitry Andric /// GetPHIValue - For the specified PHI instruction, return the value 4100fe6060f1SDimitry Andric /// that it defines. 4101fe6060f1SDimitry Andric static BlockValueNum GetPHIValue(LDVSSAPhi *PHI) { return PHI->PHIValNum; } 4102fe6060f1SDimitry Andric }; 4103fe6060f1SDimitry Andric 4104fe6060f1SDimitry Andric } // end namespace llvm 4105fe6060f1SDimitry Andric 4106bdd1243dSDimitry Andric std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIs( 41075f757f3fSDimitry Andric MachineFunction &MF, const FuncValueTable &MLiveOuts, 41085f757f3fSDimitry Andric const FuncValueTable &MLiveIns, MachineInstr &Here, uint64_t InstrNum) { 4109d56accc7SDimitry Andric // This function will be called twice per DBG_INSTR_REF, and might end up 4110d56accc7SDimitry Andric // computing lots of SSA information: memoize it. 4111bdd1243dSDimitry Andric auto SeenDbgPHIIt = SeenDbgPHIs.find(std::make_pair(&Here, InstrNum)); 4112d56accc7SDimitry Andric if (SeenDbgPHIIt != SeenDbgPHIs.end()) 4113d56accc7SDimitry Andric return SeenDbgPHIIt->second; 4114d56accc7SDimitry Andric 4115bdd1243dSDimitry Andric std::optional<ValueIDNum> Result = 4116d56accc7SDimitry Andric resolveDbgPHIsImpl(MF, MLiveOuts, MLiveIns, Here, InstrNum); 4117bdd1243dSDimitry Andric SeenDbgPHIs.insert({std::make_pair(&Here, InstrNum), Result}); 4118d56accc7SDimitry Andric return Result; 4119d56accc7SDimitry Andric } 4120d56accc7SDimitry Andric 4121bdd1243dSDimitry Andric std::optional<ValueIDNum> InstrRefBasedLDV::resolveDbgPHIsImpl( 41225f757f3fSDimitry Andric MachineFunction &MF, const FuncValueTable &MLiveOuts, 41235f757f3fSDimitry Andric const FuncValueTable &MLiveIns, MachineInstr &Here, uint64_t InstrNum) { 4124fe6060f1SDimitry Andric // Pick out records of DBG_PHI instructions that have been observed. If there 4125fe6060f1SDimitry Andric // are none, then we cannot compute a value number. 4126fe6060f1SDimitry Andric auto RangePair = std::equal_range(DebugPHINumToValue.begin(), 4127fe6060f1SDimitry Andric DebugPHINumToValue.end(), InstrNum); 4128fe6060f1SDimitry Andric auto LowerIt = RangePair.first; 4129fe6060f1SDimitry Andric auto UpperIt = RangePair.second; 4130fe6060f1SDimitry Andric 4131fe6060f1SDimitry Andric // No DBG_PHI means there can be no location. 4132fe6060f1SDimitry Andric if (LowerIt == UpperIt) 4133bdd1243dSDimitry Andric return std::nullopt; 4134fe6060f1SDimitry Andric 413581ad6265SDimitry Andric // If any DBG_PHIs referred to a location we didn't understand, don't try to 413681ad6265SDimitry Andric // compute a value. There might be scenarios where we could recover a value 413781ad6265SDimitry Andric // for some range of DBG_INSTR_REFs, but at this point we can have high 413881ad6265SDimitry Andric // confidence that we've seen a bug. 413981ad6265SDimitry Andric auto DBGPHIRange = make_range(LowerIt, UpperIt); 414081ad6265SDimitry Andric for (const DebugPHIRecord &DBG_PHI : DBGPHIRange) 414181ad6265SDimitry Andric if (!DBG_PHI.ValueRead) 4142bdd1243dSDimitry Andric return std::nullopt; 414381ad6265SDimitry Andric 4144fe6060f1SDimitry Andric // If there's only one DBG_PHI, then that is our value number. 4145fe6060f1SDimitry Andric if (std::distance(LowerIt, UpperIt) == 1) 414681ad6265SDimitry Andric return *LowerIt->ValueRead; 4147fe6060f1SDimitry Andric 4148fe6060f1SDimitry Andric // Pick out the location (physreg, slot) where any PHIs must occur. It's 4149fe6060f1SDimitry Andric // technically possible for us to merge values in different registers in each 4150fe6060f1SDimitry Andric // block, but highly unlikely that LLVM will generate such code after register 4151fe6060f1SDimitry Andric // allocation. 415281ad6265SDimitry Andric LocIdx Loc = *LowerIt->ReadLoc; 4153fe6060f1SDimitry Andric 4154fe6060f1SDimitry Andric // We have several DBG_PHIs, and a use position (the Here inst). All each 4155fe6060f1SDimitry Andric // DBG_PHI does is identify a value at a program position. We can treat each 4156fe6060f1SDimitry Andric // DBG_PHI like it's a Def of a value, and the use position is a Use of a 4157fe6060f1SDimitry Andric // value, just like SSA. We use the bulk-standard LLVM SSA updater class to 4158fe6060f1SDimitry Andric // determine which Def is used at the Use, and any PHIs that happen along 4159fe6060f1SDimitry Andric // the way. 4160fe6060f1SDimitry Andric // Adapted LLVM SSA Updater: 4161fe6060f1SDimitry Andric LDVSSAUpdater Updater(Loc, MLiveIns); 4162fe6060f1SDimitry Andric // Map of which Def or PHI is the current value in each block. 4163fe6060f1SDimitry Andric DenseMap<LDVSSABlock *, BlockValueNum> AvailableValues; 4164fe6060f1SDimitry Andric // Set of PHIs that we have created along the way. 4165fe6060f1SDimitry Andric SmallVector<LDVSSAPhi *, 8> CreatedPHIs; 4166fe6060f1SDimitry Andric 4167fe6060f1SDimitry Andric // Each existing DBG_PHI is a Def'd value under this model. Record these Defs 4168fe6060f1SDimitry Andric // for the SSAUpdater. 4169fe6060f1SDimitry Andric for (const auto &DBG_PHI : DBGPHIRange) { 4170fe6060f1SDimitry Andric LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB); 417181ad6265SDimitry Andric const ValueIDNum &Num = *DBG_PHI.ValueRead; 4172fe6060f1SDimitry Andric AvailableValues.insert(std::make_pair(Block, Num.asU64())); 4173fe6060f1SDimitry Andric } 4174fe6060f1SDimitry Andric 4175fe6060f1SDimitry Andric LDVSSABlock *HereBlock = Updater.getSSALDVBlock(Here.getParent()); 4176fe6060f1SDimitry Andric const auto &AvailIt = AvailableValues.find(HereBlock); 4177fe6060f1SDimitry Andric if (AvailIt != AvailableValues.end()) { 4178fe6060f1SDimitry Andric // Actually, we already know what the value is -- the Use is in the same 4179fe6060f1SDimitry Andric // block as the Def. 4180fe6060f1SDimitry Andric return ValueIDNum::fromU64(AvailIt->second); 4181fe6060f1SDimitry Andric } 4182fe6060f1SDimitry Andric 4183fe6060f1SDimitry Andric // Otherwise, we must use the SSA Updater. It will identify the value number 4184fe6060f1SDimitry Andric // that we are to use, and the PHIs that must happen along the way. 4185fe6060f1SDimitry Andric SSAUpdaterImpl<LDVSSAUpdater> Impl(&Updater, &AvailableValues, &CreatedPHIs); 4186fe6060f1SDimitry Andric BlockValueNum ResultInt = Impl.GetValue(Updater.getSSALDVBlock(Here.getParent())); 4187fe6060f1SDimitry Andric ValueIDNum Result = ValueIDNum::fromU64(ResultInt); 4188fe6060f1SDimitry Andric 4189fe6060f1SDimitry Andric // We have the number for a PHI, or possibly live-through value, to be used 4190fe6060f1SDimitry Andric // at this Use. There are a number of things we have to check about it though: 4191fe6060f1SDimitry Andric // * Does any PHI use an 'Undef' (like an IMPLICIT_DEF) value? If so, this 4192fe6060f1SDimitry Andric // Use was not completely dominated by DBG_PHIs and we should abort. 4193fe6060f1SDimitry Andric // * Are the Defs or PHIs clobbered in a block? SSAUpdater isn't aware that 4194fe6060f1SDimitry Andric // we've left SSA form. Validate that the inputs to each PHI are the 4195fe6060f1SDimitry Andric // expected values. 4196fe6060f1SDimitry Andric // * Is a PHI we've created actually a merging of values, or are all the 4197fe6060f1SDimitry Andric // predecessor values the same, leading to a non-PHI machine value number? 4198fe6060f1SDimitry Andric // (SSAUpdater doesn't know that either). Remap validated PHIs into the 4199fe6060f1SDimitry Andric // the ValidatedValues collection below to sort this out. 4200fe6060f1SDimitry Andric DenseMap<LDVSSABlock *, ValueIDNum> ValidatedValues; 4201fe6060f1SDimitry Andric 4202fe6060f1SDimitry Andric // Define all the input DBG_PHI values in ValidatedValues. 4203fe6060f1SDimitry Andric for (const auto &DBG_PHI : DBGPHIRange) { 4204fe6060f1SDimitry Andric LDVSSABlock *Block = Updater.getSSALDVBlock(DBG_PHI.MBB); 420581ad6265SDimitry Andric const ValueIDNum &Num = *DBG_PHI.ValueRead; 4206fe6060f1SDimitry Andric ValidatedValues.insert(std::make_pair(Block, Num)); 4207fe6060f1SDimitry Andric } 4208fe6060f1SDimitry Andric 4209fe6060f1SDimitry Andric // Sort PHIs to validate into RPO-order. 4210fe6060f1SDimitry Andric SmallVector<LDVSSAPhi *, 8> SortedPHIs; 4211fe6060f1SDimitry Andric for (auto &PHI : CreatedPHIs) 4212fe6060f1SDimitry Andric SortedPHIs.push_back(PHI); 4213fe6060f1SDimitry Andric 4214fcaf7f86SDimitry Andric llvm::sort(SortedPHIs, [&](LDVSSAPhi *A, LDVSSAPhi *B) { 4215fe6060f1SDimitry Andric return BBToOrder[&A->getParent()->BB] < BBToOrder[&B->getParent()->BB]; 4216fe6060f1SDimitry Andric }); 4217fe6060f1SDimitry Andric 4218fe6060f1SDimitry Andric for (auto &PHI : SortedPHIs) { 4219cb14a3feSDimitry Andric ValueIDNum ThisBlockValueNum = MLiveIns[PHI->ParentBlock->BB][Loc.asU64()]; 4220fe6060f1SDimitry Andric 4221fe6060f1SDimitry Andric // Are all these things actually defined? 4222fe6060f1SDimitry Andric for (auto &PHIIt : PHI->IncomingValues) { 4223fe6060f1SDimitry Andric // Any undef input means DBG_PHIs didn't dominate the use point. 4224*0fca6ea1SDimitry Andric if (Updater.PoisonMap.contains(&PHIIt.first->BB)) 4225bdd1243dSDimitry Andric return std::nullopt; 4226fe6060f1SDimitry Andric 4227fe6060f1SDimitry Andric ValueIDNum ValueToCheck; 4228cb14a3feSDimitry Andric const ValueTable &BlockLiveOuts = MLiveOuts[PHIIt.first->BB]; 4229fe6060f1SDimitry Andric 4230fe6060f1SDimitry Andric auto VVal = ValidatedValues.find(PHIIt.first); 4231fe6060f1SDimitry Andric if (VVal == ValidatedValues.end()) { 4232fe6060f1SDimitry Andric // We cross a loop, and this is a backedge. LLVMs tail duplication 4233fe6060f1SDimitry Andric // happens so late that DBG_PHI instructions should not be able to 4234fe6060f1SDimitry Andric // migrate into loops -- meaning we can only be live-through this 4235fe6060f1SDimitry Andric // loop. 4236fe6060f1SDimitry Andric ValueToCheck = ThisBlockValueNum; 4237fe6060f1SDimitry Andric } else { 4238fe6060f1SDimitry Andric // Does the block have as a live-out, in the location we're examining, 4239fe6060f1SDimitry Andric // the value that we expect? If not, it's been moved or clobbered. 4240fe6060f1SDimitry Andric ValueToCheck = VVal->second; 4241fe6060f1SDimitry Andric } 4242fe6060f1SDimitry Andric 4243fe6060f1SDimitry Andric if (BlockLiveOuts[Loc.asU64()] != ValueToCheck) 4244bdd1243dSDimitry Andric return std::nullopt; 4245fe6060f1SDimitry Andric } 4246fe6060f1SDimitry Andric 4247fe6060f1SDimitry Andric // Record this value as validated. 4248fe6060f1SDimitry Andric ValidatedValues.insert({PHI->ParentBlock, ThisBlockValueNum}); 4249fe6060f1SDimitry Andric } 4250fe6060f1SDimitry Andric 4251fe6060f1SDimitry Andric // All the PHIs are valid: we can return what the SSAUpdater said our value 4252fe6060f1SDimitry Andric // number was. 4253fe6060f1SDimitry Andric return Result; 4254fe6060f1SDimitry Andric } 4255