|  | //==- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- 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 | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file implements the AggressiveAntiDepBreaker class, which | 
|  | // implements register anti-dependence breaking during post-RA | 
|  | // scheduling. It attempts to break all anti-dependencies within a | 
|  | // block. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H | 
|  | #define LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H | 
|  |  | 
|  | #include "AntiDepBreaker.h" | 
|  | #include "llvm/ADT/BitVector.h" | 
|  | #include "llvm/CodeGen/TargetSubtargetInfo.h" | 
|  | #include "llvm/Support/Compiler.h" | 
|  | #include <map> | 
|  | #include <set> | 
|  | #include <vector> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class MachineBasicBlock; | 
|  | class MachineFunction; | 
|  | class MachineInstr; | 
|  | class MachineOperand; | 
|  | class MachineRegisterInfo; | 
|  | class RegisterClassInfo; | 
|  | class TargetInstrInfo; | 
|  | class TargetRegisterClass; | 
|  | class TargetRegisterInfo; | 
|  |  | 
|  | /// Contains all the state necessary for anti-dep breaking. | 
|  | class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepState { | 
|  | public: | 
|  | /// Information about a register reference within a liverange | 
|  | struct RegisterReference { | 
|  | /// The registers operand | 
|  | MachineOperand *Operand; | 
|  |  | 
|  | /// The register class | 
|  | const TargetRegisterClass *RC; | 
|  | }; | 
|  |  | 
|  | private: | 
|  | /// Number of non-virtual target registers (i.e. TRI->getNumRegs()). | 
|  | const unsigned NumTargetRegs; | 
|  |  | 
|  | /// Implements a disjoint-union data structure to | 
|  | /// form register groups. A node is represented by an index into | 
|  | /// the vector. A node can "point to" itself to indicate that it | 
|  | /// is the parent of a group, or point to another node to indicate | 
|  | /// that it is a member of the same group as that node. | 
|  | std::vector<unsigned> GroupNodes; | 
|  |  | 
|  | /// For each register, the index of the GroupNode | 
|  | /// currently representing the group that the register belongs to. | 
|  | /// Register 0 is always represented by the 0 group, a group | 
|  | /// composed of registers that are not eligible for anti-aliasing. | 
|  | std::vector<unsigned> GroupNodeIndices; | 
|  |  | 
|  | /// Map registers to all their references within a live range. | 
|  | std::multimap<unsigned, RegisterReference> RegRefs; | 
|  |  | 
|  | /// The index of the most recent kill (proceeding bottom-up), | 
|  | /// or ~0u if the register is not live. | 
|  | std::vector<unsigned> KillIndices; | 
|  |  | 
|  | /// The index of the most recent complete def (proceeding bottom | 
|  | /// up), or ~0u if the register is live. | 
|  | std::vector<unsigned> DefIndices; | 
|  |  | 
|  | public: | 
|  | AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB); | 
|  |  | 
|  | /// Return the kill indices. | 
|  | std::vector<unsigned> &GetKillIndices() { return KillIndices; } | 
|  |  | 
|  | /// Return the define indices. | 
|  | std::vector<unsigned> &GetDefIndices() { return DefIndices; } | 
|  |  | 
|  | /// Return the RegRefs map. | 
|  | std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; } | 
|  |  | 
|  | // Get the group for a register. The returned value is | 
|  | // the index of the GroupNode representing the group. | 
|  | unsigned GetGroup(unsigned Reg); | 
|  |  | 
|  | // Return a vector of the registers belonging to a group. | 
|  | // If RegRefs is non-NULL then only included referenced registers. | 
|  | void GetGroupRegs( | 
|  | unsigned Group, | 
|  | std::vector<unsigned> &Regs, | 
|  | std::multimap<unsigned, | 
|  | AggressiveAntiDepState::RegisterReference> *RegRefs); | 
|  |  | 
|  | // Union Reg1's and Reg2's groups to form a new group. | 
|  | // Return the index of the GroupNode representing the group. | 
|  | unsigned UnionGroups(unsigned Reg1, unsigned Reg2); | 
|  |  | 
|  | // Remove a register from its current group and place | 
|  | // it alone in its own group. Return the index of the GroupNode | 
|  | // representing the registers new group. | 
|  | unsigned LeaveGroup(unsigned Reg); | 
|  |  | 
|  | /// Return true if Reg is live. | 
|  | bool IsLive(unsigned Reg); | 
|  | }; | 
|  |  | 
|  | class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepBreaker | 
|  | : public AntiDepBreaker { | 
|  | MachineFunction &MF; | 
|  | MachineRegisterInfo &MRI; | 
|  | const TargetInstrInfo *TII; | 
|  | const TargetRegisterInfo *TRI; | 
|  | const RegisterClassInfo &RegClassInfo; | 
|  |  | 
|  | /// The set of registers that should only be | 
|  | /// renamed if they are on the critical path. | 
|  | BitVector CriticalPathSet; | 
|  |  | 
|  | /// The state used to identify and rename anti-dependence registers. | 
|  | AggressiveAntiDepState *State = nullptr; | 
|  |  | 
|  | public: | 
|  | AggressiveAntiDepBreaker(MachineFunction &MFi, | 
|  | const RegisterClassInfo &RCI, | 
|  | TargetSubtargetInfo::RegClassVector& CriticalPathRCs); | 
|  | ~AggressiveAntiDepBreaker() override; | 
|  |  | 
|  | /// Initialize anti-dep breaking for a new basic block. | 
|  | void StartBlock(MachineBasicBlock *BB) override; | 
|  |  | 
|  | /// Identifiy anti-dependencies along the critical path | 
|  | /// of the ScheduleDAG and break them by renaming registers. | 
|  | unsigned BreakAntiDependencies(const std::vector<SUnit> &SUnits, | 
|  | MachineBasicBlock::iterator Begin, | 
|  | MachineBasicBlock::iterator End, | 
|  | unsigned InsertPosIndex, | 
|  | DbgValueVector &DbgValues) override; | 
|  |  | 
|  | /// Update liveness information to account for the current | 
|  | /// instruction, which will not be scheduled. | 
|  | void Observe(MachineInstr &MI, unsigned Count, | 
|  | unsigned InsertPosIndex) override; | 
|  |  | 
|  | /// Finish anti-dep breaking for a basic block. | 
|  | void FinishBlock() override; | 
|  |  | 
|  | private: | 
|  | /// Keep track of a position in the allocation order for each regclass. | 
|  | using RenameOrderType = std::map<const TargetRegisterClass *, unsigned>; | 
|  |  | 
|  | /// Return true if MO represents a register | 
|  | /// that is both implicitly used and defined in MI | 
|  | bool IsImplicitDefUse(MachineInstr &MI, MachineOperand &MO); | 
|  |  | 
|  | /// If MI implicitly def/uses a register, then | 
|  | /// return that register and all subregisters. | 
|  | void GetPassthruRegs(MachineInstr &MI, std::set<unsigned> &PassthruRegs); | 
|  |  | 
|  | void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag, | 
|  | const char *header = nullptr, | 
|  | const char *footer = nullptr); | 
|  |  | 
|  | void PrescanInstruction(MachineInstr &MI, unsigned Count, | 
|  | std::set<unsigned> &PassthruRegs); | 
|  | void ScanInstruction(MachineInstr &MI, unsigned Count); | 
|  | BitVector GetRenameRegisters(unsigned Reg); | 
|  | bool FindSuitableFreeRegisters(unsigned AntiDepGroupIndex, | 
|  | RenameOrderType& RenameOrder, | 
|  | std::map<unsigned, unsigned> &RenameMap); | 
|  | }; | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H |