1*0b57cec5SDimitry Andric //==- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-==// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the AggressiveAntiDepBreaker class, which 10*0b57cec5SDimitry Andric // implements register anti-dependence breaking during post-RA 11*0b57cec5SDimitry Andric // scheduling. It attempts to break all anti-dependencies within a 12*0b57cec5SDimitry Andric // block. 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 17*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric #include "AntiDepBreaker.h" 20*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 23*0b57cec5SDimitry Andric #include <map> 24*0b57cec5SDimitry Andric #include <set> 25*0b57cec5SDimitry Andric #include <vector> 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric namespace llvm { 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric class MachineBasicBlock; 30*0b57cec5SDimitry Andric class MachineFunction; 31*0b57cec5SDimitry Andric class MachineInstr; 32*0b57cec5SDimitry Andric class MachineOperand; 33*0b57cec5SDimitry Andric class MachineRegisterInfo; 34*0b57cec5SDimitry Andric class RegisterClassInfo; 35*0b57cec5SDimitry Andric class TargetInstrInfo; 36*0b57cec5SDimitry Andric class TargetRegisterClass; 37*0b57cec5SDimitry Andric class TargetRegisterInfo; 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric /// Contains all the state necessary for anti-dep breaking. 40*0b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepState { 41*0b57cec5SDimitry Andric public: 42*0b57cec5SDimitry Andric /// Information about a register reference within a liverange 43*0b57cec5SDimitry Andric struct RegisterReference { 44*0b57cec5SDimitry Andric /// The registers operand 45*0b57cec5SDimitry Andric MachineOperand *Operand; 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric /// The register class 48*0b57cec5SDimitry Andric const TargetRegisterClass *RC; 49*0b57cec5SDimitry Andric }; 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric private: 52*0b57cec5SDimitry Andric /// Number of non-virtual target registers (i.e. TRI->getNumRegs()). 53*0b57cec5SDimitry Andric const unsigned NumTargetRegs; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric /// Implements a disjoint-union data structure to 56*0b57cec5SDimitry Andric /// form register groups. A node is represented by an index into 57*0b57cec5SDimitry Andric /// the vector. A node can "point to" itself to indicate that it 58*0b57cec5SDimitry Andric /// is the parent of a group, or point to another node to indicate 59*0b57cec5SDimitry Andric /// that it is a member of the same group as that node. 60*0b57cec5SDimitry Andric std::vector<unsigned> GroupNodes; 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric /// For each register, the index of the GroupNode 63*0b57cec5SDimitry Andric /// currently representing the group that the register belongs to. 64*0b57cec5SDimitry Andric /// Register 0 is always represented by the 0 group, a group 65*0b57cec5SDimitry Andric /// composed of registers that are not eligible for anti-aliasing. 66*0b57cec5SDimitry Andric std::vector<unsigned> GroupNodeIndices; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric /// Map registers to all their references within a live range. 69*0b57cec5SDimitry Andric std::multimap<unsigned, RegisterReference> RegRefs; 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric /// The index of the most recent kill (proceeding bottom-up), 72*0b57cec5SDimitry Andric /// or ~0u if the register is not live. 73*0b57cec5SDimitry Andric std::vector<unsigned> KillIndices; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric /// The index of the most recent complete def (proceeding bottom 76*0b57cec5SDimitry Andric /// up), or ~0u if the register is live. 77*0b57cec5SDimitry Andric std::vector<unsigned> DefIndices; 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric public: 80*0b57cec5SDimitry Andric AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB); 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric /// Return the kill indices. 83*0b57cec5SDimitry Andric std::vector<unsigned> &GetKillIndices() { return KillIndices; } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric /// Return the define indices. 86*0b57cec5SDimitry Andric std::vector<unsigned> &GetDefIndices() { return DefIndices; } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric /// Return the RegRefs map. 89*0b57cec5SDimitry Andric std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; } 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric // Get the group for a register. The returned value is 92*0b57cec5SDimitry Andric // the index of the GroupNode representing the group. 93*0b57cec5SDimitry Andric unsigned GetGroup(unsigned Reg); 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric // Return a vector of the registers belonging to a group. 96*0b57cec5SDimitry Andric // If RegRefs is non-NULL then only included referenced registers. 97*0b57cec5SDimitry Andric void GetGroupRegs( 98*0b57cec5SDimitry Andric unsigned Group, 99*0b57cec5SDimitry Andric std::vector<unsigned> &Regs, 100*0b57cec5SDimitry Andric std::multimap<unsigned, 101*0b57cec5SDimitry Andric AggressiveAntiDepState::RegisterReference> *RegRefs); 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric // Union Reg1's and Reg2's groups to form a new group. 104*0b57cec5SDimitry Andric // Return the index of the GroupNode representing the group. 105*0b57cec5SDimitry Andric unsigned UnionGroups(unsigned Reg1, unsigned Reg2); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric // Remove a register from its current group and place 108*0b57cec5SDimitry Andric // it alone in its own group. Return the index of the GroupNode 109*0b57cec5SDimitry Andric // representing the registers new group. 110*0b57cec5SDimitry Andric unsigned LeaveGroup(unsigned Reg); 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric /// Return true if Reg is live. 113*0b57cec5SDimitry Andric bool IsLive(unsigned Reg); 114*0b57cec5SDimitry Andric }; 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepBreaker 117*0b57cec5SDimitry Andric : public AntiDepBreaker { 118*0b57cec5SDimitry Andric MachineFunction &MF; 119*0b57cec5SDimitry Andric MachineRegisterInfo &MRI; 120*0b57cec5SDimitry Andric const TargetInstrInfo *TII; 121*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 122*0b57cec5SDimitry Andric const RegisterClassInfo &RegClassInfo; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric /// The set of registers that should only be 125*0b57cec5SDimitry Andric /// renamed if they are on the critical path. 126*0b57cec5SDimitry Andric BitVector CriticalPathSet; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric /// The state used to identify and rename anti-dependence registers. 129*0b57cec5SDimitry Andric AggressiveAntiDepState *State = nullptr; 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric public: 132*0b57cec5SDimitry Andric AggressiveAntiDepBreaker(MachineFunction &MFi, 133*0b57cec5SDimitry Andric const RegisterClassInfo &RCI, 134*0b57cec5SDimitry Andric TargetSubtargetInfo::RegClassVector& CriticalPathRCs); 135*0b57cec5SDimitry Andric ~AggressiveAntiDepBreaker() override; 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric /// Initialize anti-dep breaking for a new basic block. 138*0b57cec5SDimitry Andric void StartBlock(MachineBasicBlock *BB) override; 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric /// Identifiy anti-dependencies along the critical path 141*0b57cec5SDimitry Andric /// of the ScheduleDAG and break them by renaming registers. 142*0b57cec5SDimitry Andric unsigned BreakAntiDependencies(const std::vector<SUnit> &SUnits, 143*0b57cec5SDimitry Andric MachineBasicBlock::iterator Begin, 144*0b57cec5SDimitry Andric MachineBasicBlock::iterator End, 145*0b57cec5SDimitry Andric unsigned InsertPosIndex, 146*0b57cec5SDimitry Andric DbgValueVector &DbgValues) override; 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric /// Update liveness information to account for the current 149*0b57cec5SDimitry Andric /// instruction, which will not be scheduled. 150*0b57cec5SDimitry Andric void Observe(MachineInstr &MI, unsigned Count, 151*0b57cec5SDimitry Andric unsigned InsertPosIndex) override; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric /// Finish anti-dep breaking for a basic block. 154*0b57cec5SDimitry Andric void FinishBlock() override; 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric private: 157*0b57cec5SDimitry Andric /// Keep track of a position in the allocation order for each regclass. 158*0b57cec5SDimitry Andric using RenameOrderType = std::map<const TargetRegisterClass *, unsigned>; 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric /// Return true if MO represents a register 161*0b57cec5SDimitry Andric /// that is both implicitly used and defined in MI 162*0b57cec5SDimitry Andric bool IsImplicitDefUse(MachineInstr &MI, MachineOperand &MO); 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric /// If MI implicitly def/uses a register, then 165*0b57cec5SDimitry Andric /// return that register and all subregisters. 166*0b57cec5SDimitry Andric void GetPassthruRegs(MachineInstr &MI, std::set<unsigned> &PassthruRegs); 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag, 169*0b57cec5SDimitry Andric const char *header = nullptr, 170*0b57cec5SDimitry Andric const char *footer = nullptr); 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric void PrescanInstruction(MachineInstr &MI, unsigned Count, 173*0b57cec5SDimitry Andric std::set<unsigned> &PassthruRegs); 174*0b57cec5SDimitry Andric void ScanInstruction(MachineInstr &MI, unsigned Count); 175*0b57cec5SDimitry Andric BitVector GetRenameRegisters(unsigned Reg); 176*0b57cec5SDimitry Andric bool FindSuitableFreeRegisters(unsigned AntiDepGroupIndex, 177*0b57cec5SDimitry Andric RenameOrderType& RenameOrder, 178*0b57cec5SDimitry Andric std::map<unsigned, unsigned> &RenameMap); 179*0b57cec5SDimitry Andric }; 180*0b57cec5SDimitry Andric 181*0b57cec5SDimitry Andric } // end namespace llvm 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 184