10b57cec5SDimitry Andric //==- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the AggressiveAntiDepBreaker class, which 100b57cec5SDimitry Andric // implements register anti-dependence breaking during post-RA 110b57cec5SDimitry Andric // scheduling. It attempts to break all anti-dependencies within a 120b57cec5SDimitry Andric // block. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 170b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 205ffd83dbSDimitry Andric #include "llvm/CodeGen/AntiDepBreaker.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 220b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 230b57cec5SDimitry Andric #include <map> 240b57cec5SDimitry Andric #include <set> 250b57cec5SDimitry Andric #include <vector> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace llvm { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class MachineBasicBlock; 300b57cec5SDimitry Andric class MachineFunction; 310b57cec5SDimitry Andric class MachineInstr; 320b57cec5SDimitry Andric class MachineOperand; 330b57cec5SDimitry Andric class MachineRegisterInfo; 340b57cec5SDimitry Andric class RegisterClassInfo; 350b57cec5SDimitry Andric class TargetInstrInfo; 360b57cec5SDimitry Andric class TargetRegisterClass; 370b57cec5SDimitry Andric class TargetRegisterInfo; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// Contains all the state necessary for anti-dep breaking. 400b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepState { 410b57cec5SDimitry Andric public: 420b57cec5SDimitry Andric /// Information about a register reference within a liverange 430b57cec5SDimitry Andric struct RegisterReference { 440b57cec5SDimitry Andric /// The registers operand 450b57cec5SDimitry Andric MachineOperand *Operand; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric /// The register class 480b57cec5SDimitry Andric const TargetRegisterClass *RC; 490b57cec5SDimitry Andric }; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric private: 520b57cec5SDimitry Andric /// Number of non-virtual target registers (i.e. TRI->getNumRegs()). 530b57cec5SDimitry Andric const unsigned NumTargetRegs; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// Implements a disjoint-union data structure to 560b57cec5SDimitry Andric /// form register groups. A node is represented by an index into 570b57cec5SDimitry Andric /// the vector. A node can "point to" itself to indicate that it 580b57cec5SDimitry Andric /// is the parent of a group, or point to another node to indicate 590b57cec5SDimitry Andric /// that it is a member of the same group as that node. 600b57cec5SDimitry Andric std::vector<unsigned> GroupNodes; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// For each register, the index of the GroupNode 630b57cec5SDimitry Andric /// currently representing the group that the register belongs to. 640b57cec5SDimitry Andric /// Register 0 is always represented by the 0 group, a group 650b57cec5SDimitry Andric /// composed of registers that are not eligible for anti-aliasing. 660b57cec5SDimitry Andric std::vector<unsigned> GroupNodeIndices; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric /// Map registers to all their references within a live range. 690b57cec5SDimitry Andric std::multimap<unsigned, RegisterReference> RegRefs; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// The index of the most recent kill (proceeding bottom-up), 720b57cec5SDimitry Andric /// or ~0u if the register is not live. 730b57cec5SDimitry Andric std::vector<unsigned> KillIndices; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric /// The index of the most recent complete def (proceeding bottom 760b57cec5SDimitry Andric /// up), or ~0u if the register is live. 770b57cec5SDimitry Andric std::vector<unsigned> DefIndices; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric public: 800b57cec5SDimitry Andric AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric /// Return the kill indices. GetKillIndices()830b57cec5SDimitry Andric std::vector<unsigned> &GetKillIndices() { return KillIndices; } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Return the define indices. GetDefIndices()860b57cec5SDimitry Andric std::vector<unsigned> &GetDefIndices() { return DefIndices; } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// Return the RegRefs map. GetRegRefs()890b57cec5SDimitry Andric std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // Get the group for a register. The returned value is 920b57cec5SDimitry Andric // the index of the GroupNode representing the group. 930b57cec5SDimitry Andric unsigned GetGroup(unsigned Reg); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // Return a vector of the registers belonging to a group. 960b57cec5SDimitry Andric // If RegRefs is non-NULL then only included referenced registers. 970b57cec5SDimitry Andric void GetGroupRegs( 980b57cec5SDimitry Andric unsigned Group, 990b57cec5SDimitry Andric std::vector<unsigned> &Regs, 1000b57cec5SDimitry Andric std::multimap<unsigned, 1010b57cec5SDimitry Andric AggressiveAntiDepState::RegisterReference> *RegRefs); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Union Reg1's and Reg2's groups to form a new group. 1040b57cec5SDimitry Andric // Return the index of the GroupNode representing the group. 1050b57cec5SDimitry Andric unsigned UnionGroups(unsigned Reg1, unsigned Reg2); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Remove a register from its current group and place 1080b57cec5SDimitry Andric // it alone in its own group. Return the index of the GroupNode 1090b57cec5SDimitry Andric // representing the registers new group. 1100b57cec5SDimitry Andric unsigned LeaveGroup(unsigned Reg); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric /// Return true if Reg is live. 1130b57cec5SDimitry Andric bool IsLive(unsigned Reg); 1140b57cec5SDimitry Andric }; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepBreaker 1170b57cec5SDimitry Andric : public AntiDepBreaker { 1180b57cec5SDimitry Andric MachineFunction &MF; 1190b57cec5SDimitry Andric MachineRegisterInfo &MRI; 1200b57cec5SDimitry Andric const TargetInstrInfo *TII; 1210b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 1220b57cec5SDimitry Andric const RegisterClassInfo &RegClassInfo; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric /// The set of registers that should only be 1250b57cec5SDimitry Andric /// renamed if they are on the critical path. 1260b57cec5SDimitry Andric BitVector CriticalPathSet; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric /// The state used to identify and rename anti-dependence registers. 1290b57cec5SDimitry Andric AggressiveAntiDepState *State = nullptr; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric public: 1320b57cec5SDimitry Andric AggressiveAntiDepBreaker(MachineFunction &MFi, 1330b57cec5SDimitry Andric const RegisterClassInfo &RCI, 1340b57cec5SDimitry Andric TargetSubtargetInfo::RegClassVector& CriticalPathRCs); 13506c3fb27SDimitry Andric AggressiveAntiDepBreaker & 13606c3fb27SDimitry Andric operator=(const AggressiveAntiDepBreaker &other) = delete; 13706c3fb27SDimitry Andric AggressiveAntiDepBreaker(const AggressiveAntiDepBreaker &other) = delete; 1380b57cec5SDimitry Andric ~AggressiveAntiDepBreaker() override; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric /// Initialize anti-dep breaking for a new basic block. 1410b57cec5SDimitry Andric void StartBlock(MachineBasicBlock *BB) override; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// Identifiy anti-dependencies along the critical path 1440b57cec5SDimitry Andric /// of the ScheduleDAG and break them by renaming registers. 1450b57cec5SDimitry Andric unsigned BreakAntiDependencies(const std::vector<SUnit> &SUnits, 1460b57cec5SDimitry Andric MachineBasicBlock::iterator Begin, 1470b57cec5SDimitry Andric MachineBasicBlock::iterator End, 1480b57cec5SDimitry Andric unsigned InsertPosIndex, 1490b57cec5SDimitry Andric DbgValueVector &DbgValues) override; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /// Update liveness information to account for the current 1520b57cec5SDimitry Andric /// instruction, which will not be scheduled. 1530b57cec5SDimitry Andric void Observe(MachineInstr &MI, unsigned Count, 1540b57cec5SDimitry Andric unsigned InsertPosIndex) override; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /// Finish anti-dep breaking for a basic block. 1570b57cec5SDimitry Andric void FinishBlock() override; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric private: 1600b57cec5SDimitry Andric /// Keep track of a position in the allocation order for each regclass. 1610b57cec5SDimitry Andric using RenameOrderType = std::map<const TargetRegisterClass *, unsigned>; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Return true if MO represents a register 1640b57cec5SDimitry Andric /// that is both implicitly used and defined in MI 1650b57cec5SDimitry Andric bool IsImplicitDefUse(MachineInstr &MI, MachineOperand &MO); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric /// If MI implicitly def/uses a register, then 1680b57cec5SDimitry Andric /// return that register and all subregisters. 1690b57cec5SDimitry Andric void GetPassthruRegs(MachineInstr &MI, std::set<unsigned> &PassthruRegs); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag, 1720b57cec5SDimitry Andric const char *header = nullptr, 1730b57cec5SDimitry Andric const char *footer = nullptr); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void PrescanInstruction(MachineInstr &MI, unsigned Count, 1760b57cec5SDimitry Andric std::set<unsigned> &PassthruRegs); 1770b57cec5SDimitry Andric void ScanInstruction(MachineInstr &MI, unsigned Count); 1780b57cec5SDimitry Andric BitVector GetRenameRegisters(unsigned Reg); 179*5f757f3fSDimitry Andric bool FindSuitableFreeRegisters(unsigned SuperReg, 180*5f757f3fSDimitry Andric unsigned AntiDepGroupIndex, 1810b57cec5SDimitry Andric RenameOrderType &RenameOrder, 1820b57cec5SDimitry Andric std::map<unsigned, unsigned> &RenameMap); 1830b57cec5SDimitry Andric }; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric } // end namespace llvm 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric #endif // LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H 188