xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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