1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
//==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file Reaching Defs Analysis pass.
///
/// This pass tracks for each instruction what is the "closest" reaching def of
/// a given register. It is used by BreakFalseDeps (for clearance calculation)
/// and ExecutionDomainFix (for arbitrating conflicting domains).
///
/// Note that this is different from the usual definition notion of liveness.
/// The CPU doesn't care whether or not we consider a register killed.
///
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_REACHINGDEFANALYSIS_H
#define LLVM_CODEGEN_REACHINGDEFANALYSIS_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/CodeGen/LoopTraversal.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/InitializePasses.h"
namespace llvm {
class MachineBasicBlock;
class MachineInstr;
/// Thin wrapper around "int" used to store reaching definitions,
/// using an encoding that makes it compatible with TinyPtrVector.
/// The 0th LSB is forced zero (and will be used for pointer union tagging),
/// The 1st LSB is forced one (to make sure the value is non-zero).
class ReachingDef {
uintptr_t Encoded;
friend struct PointerLikeTypeTraits<ReachingDef>;
explicit ReachingDef(uintptr_t Encoded) : Encoded(Encoded) {}
public:
ReachingDef(std::nullptr_t) : Encoded(0) {}
ReachingDef(int Instr) : Encoded(((uintptr_t) Instr << 2) | 2) {}
operator int() const { return ((int) Encoded) >> 2; }
};
template<>
struct PointerLikeTypeTraits<ReachingDef> {
static constexpr int NumLowBitsAvailable = 1;
static inline void *getAsVoidPointer(const ReachingDef &RD) {
return reinterpret_cast<void *>(RD.Encoded);
}
static inline ReachingDef getFromVoidPointer(void *P) {
return ReachingDef(reinterpret_cast<uintptr_t>(P));
}
static inline ReachingDef getFromVoidPointer(const void *P) {
return ReachingDef(reinterpret_cast<uintptr_t>(P));
}
};
/// This class provides the reaching def analysis.
class ReachingDefAnalysis : public MachineFunctionPass {
private:
MachineFunction *MF;
const TargetRegisterInfo *TRI;
LoopTraversal::TraversalOrder TraversedMBBOrder;
unsigned NumRegUnits;
/// Instruction that defined each register, relative to the beginning of the
/// current basic block. When a LiveRegsDefInfo is used to represent a
/// live-out register, this value is relative to the end of the basic block,
/// so it will be a negative number.
using LiveRegsDefInfo = std::vector<int>;
LiveRegsDefInfo LiveRegs;
/// Keeps clearance information for all registers. Note that this
/// is different from the usual definition notion of liveness. The CPU
/// doesn't care whether or not we consider a register killed.
using OutRegsInfoMap = SmallVector<LiveRegsDefInfo, 4>;
OutRegsInfoMap MBBOutRegsInfos;
/// Current instruction number.
/// The first instruction in each basic block is 0.
int CurInstr;
/// Maps instructions to their instruction Ids, relative to the beginning of
/// their basic blocks.
DenseMap<MachineInstr *, int> InstIds;
/// All reaching defs of a given RegUnit for a given MBB.
using MBBRegUnitDefs = TinyPtrVector<ReachingDef>;
/// All reaching defs of all reg units for a given MBB
using MBBDefsInfo = std::vector<MBBRegUnitDefs>;
/// All reaching defs of all reg units for a all MBBs
using MBBReachingDefsInfo = SmallVector<MBBDefsInfo, 4>;
MBBReachingDefsInfo MBBReachingDefs;
/// Default values are 'nothing happened a long time ago'.
const int ReachingDefDefaultVal = -(1 << 20);
using InstSet = SmallPtrSetImpl<MachineInstr*>;
using BlockSet = SmallPtrSetImpl<MachineBasicBlock*>;
public:
static char ID; // Pass identification, replacement for typeid
ReachingDefAnalysis() : MachineFunctionPass(ID) {
initializeReachingDefAnalysisPass(*PassRegistry::getPassRegistry());
}
void releaseMemory() override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool runOnMachineFunction(MachineFunction &MF) override;
MachineFunctionProperties getRequiredProperties() const override {
return MachineFunctionProperties().set(
MachineFunctionProperties::Property::NoVRegs).set(
MachineFunctionProperties::Property::TracksLiveness);
}
/// Re-run the analysis.
void reset();
/// Initialize data structures.
void init();
/// Traverse the machine function, mapping definitions.
void traverse();
/// Provides the instruction id of the closest reaching def instruction of
/// PhysReg that reaches MI, relative to the begining of MI's basic block.
int getReachingDef(MachineInstr *MI, MCRegister PhysReg) const;
/// Return whether A and B use the same def of PhysReg.
bool hasSameReachingDef(MachineInstr *A, MachineInstr *B,
MCRegister PhysReg) const;
/// Return whether the reaching def for MI also is live out of its parent
/// block.
bool isReachingDefLiveOut(MachineInstr *MI, MCRegister PhysReg) const;
/// Return the local MI that produces the live out value for PhysReg, or
/// nullptr for a non-live out or non-local def.
MachineInstr *getLocalLiveOutMIDef(MachineBasicBlock *MBB,
MCRegister PhysReg) const;
/// If a single MachineInstr creates the reaching definition, then return it.
/// Otherwise return null.
MachineInstr *getUniqueReachingMIDef(MachineInstr *MI,
MCRegister PhysReg) const;
/// If a single MachineInstr creates the reaching definition, for MIs operand
/// at Idx, then return it. Otherwise return null.
MachineInstr *getMIOperand(MachineInstr *MI, unsigned Idx) const;
/// If a single MachineInstr creates the reaching definition, for MIs MO,
/// then return it. Otherwise return null.
MachineInstr *getMIOperand(MachineInstr *MI, MachineOperand &MO) const;
/// Provide whether the register has been defined in the same basic block as,
/// and before, MI.
bool hasLocalDefBefore(MachineInstr *MI, MCRegister PhysReg) const;
/// Return whether the given register is used after MI, whether it's a local
/// use or a live out.
bool isRegUsedAfter(MachineInstr *MI, MCRegister PhysReg) const;
/// Return whether the given register is defined after MI.
bool isRegDefinedAfter(MachineInstr *MI, MCRegister PhysReg) const;
/// Provides the clearance - the number of instructions since the closest
/// reaching def instuction of PhysReg that reaches MI.
int getClearance(MachineInstr *MI, MCRegister PhysReg) const;
/// Provides the uses, in the same block as MI, of register that MI defines.
/// This does not consider live-outs.
void getReachingLocalUses(MachineInstr *MI, MCRegister PhysReg,
InstSet &Uses) const;
/// Search MBB for a definition of PhysReg and insert it into Defs. If no
/// definition is found, recursively search the predecessor blocks for them.
void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg, InstSet &Defs,
BlockSet &VisitedBBs) const;
void getLiveOuts(MachineBasicBlock *MBB, MCRegister PhysReg,
InstSet &Defs) const;
/// For the given block, collect the instructions that use the live-in
/// value of the provided register. Return whether the value is still
/// live on exit.
bool getLiveInUses(MachineBasicBlock *MBB, MCRegister PhysReg,
InstSet &Uses) const;
/// Collect the users of the value stored in PhysReg, which is defined
/// by MI.
void getGlobalUses(MachineInstr *MI, MCRegister PhysReg, InstSet &Uses) const;
/// Collect all possible definitions of the value stored in PhysReg, which is
/// used by MI.
void getGlobalReachingDefs(MachineInstr *MI, MCRegister PhysReg,
InstSet &Defs) const;
/// Return whether From can be moved forwards to just before To.
bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const;
/// Return whether From can be moved backwards to just after To.
bool isSafeToMoveBackwards(MachineInstr *From, MachineInstr *To) const;
/// Assuming MI is dead, recursively search the incoming operands which are
/// killed by MI and collect those that would become dead.
void collectKilledOperands(MachineInstr *MI, InstSet &Dead) const;
/// Return whether removing this instruction will have no effect on the
/// program, returning the redundant use-def chain.
bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove) const;
/// Return whether removing this instruction will have no effect on the
/// program, ignoring the possible effects on some instructions, returning
/// the redundant use-def chain.
bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove,
InstSet &Ignore) const;
/// Return whether a MachineInstr could be inserted at MI and safely define
/// the given register without affecting the program.
bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg) const;
/// Return whether a MachineInstr could be inserted at MI and safely define
/// the given register without affecting the program, ignoring any effects
/// on the provided instructions.
bool isSafeToDefRegAt(MachineInstr *MI, MCRegister PhysReg,
InstSet &Ignore) const;
private:
/// Set up LiveRegs by merging predecessor live-out values.
void enterBasicBlock(MachineBasicBlock *MBB);
/// Update live-out values.
void leaveBasicBlock(MachineBasicBlock *MBB);
/// Process he given basic block.
void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
/// Process block that is part of a loop again.
void reprocessBasicBlock(MachineBasicBlock *MBB);
/// Update def-ages for registers defined by MI.
/// Also break dependencies on partial defs and undef uses.
void processDefs(MachineInstr *);
/// Utility function for isSafeToMoveForwards/Backwards.
template<typename Iterator>
bool isSafeToMove(MachineInstr *From, MachineInstr *To) const;
/// Return whether removing this instruction will have no effect on the
/// program, ignoring the possible effects on some instructions, returning
/// the redundant use-def chain.
bool isSafeToRemove(MachineInstr *MI, InstSet &Visited,
InstSet &ToRemove, InstSet &Ignore) const;
/// Provides the MI, from the given block, corresponding to the Id or a
/// nullptr if the id does not refer to the block.
MachineInstr *getInstFromId(MachineBasicBlock *MBB, int InstId) const;
/// Provides the instruction of the closest reaching def instruction of
/// PhysReg that reaches MI, relative to the begining of MI's basic block.
MachineInstr *getReachingLocalMIDef(MachineInstr *MI,
MCRegister PhysReg) const;
};
} // namespace llvm
#endif // LLVM_CODEGEN_REACHINGDEFANALYSIS_H
|