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