DFAPacketizer.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/CodeGen/DFAPacketizer.h - DFA Packetizer for VLIW ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. // This class implements a deterministic finite automaton (DFA) based
  14. // packetizing mechanism for VLIW architectures. It provides APIs to
  15. // determine whether there exists a legal mapping of instructions to
  16. // functional unit assignments in a packet. The DFA is auto-generated from
  17. // the target's Schedule.td file.
  18. //
  19. // A DFA consists of 3 major elements: states, inputs, and transitions. For
  20. // the packetizing mechanism, the input is the set of instruction classes for
  21. // a target. The state models all possible combinations of functional unit
  22. // consumption for a given set of instructions in a packet. A transition
  23. // models the addition of an instruction to a packet. In the DFA constructed
  24. // by this class, if an instruction can be added to a packet, then a valid
  25. // transition exists from the corresponding state. Invalid transitions
  26. // indicate that the instruction cannot be added to the current packet.
  27. //
  28. //===----------------------------------------------------------------------===//
  29. #ifndef LLVM_CODEGEN_DFAPACKETIZER_H
  30. #define LLVM_CODEGEN_DFAPACKETIZER_H
  31. #include "llvm/CodeGen/MachineBasicBlock.h"
  32. #include "llvm/Support/Automaton.h"
  33. #include <cstdint>
  34. #include <map>
  35. #include <memory>
  36. #include <utility>
  37. #include <vector>
  38. namespace llvm {
  39. class DefaultVLIWScheduler;
  40. class ScheduleDAGMutation;
  41. class InstrItineraryData;
  42. class MachineFunction;
  43. class MachineInstr;
  44. class MachineLoopInfo;
  45. class MCInstrDesc;
  46. class SUnit;
  47. class TargetInstrInfo;
  48. class DFAPacketizer {
  49. private:
  50. const InstrItineraryData *InstrItins;
  51. Automaton<uint64_t> A;
  52. /// For every itinerary, an "action" to apply to the automaton. This removes
  53. /// the redundancy in actions between itinerary classes.
  54. ArrayRef<unsigned> ItinActions;
  55. public:
  56. DFAPacketizer(const InstrItineraryData *InstrItins, Automaton<uint64_t> a,
  57. ArrayRef<unsigned> ItinActions)
  58. : InstrItins(InstrItins), A(std::move(a)), ItinActions(ItinActions) {
  59. // Start off with resource tracking disabled.
  60. A.enableTranscription(false);
  61. }
  62. // Reset the current state to make all resources available.
  63. void clearResources() {
  64. A.reset();
  65. }
  66. // Set whether this packetizer should track not just whether instructions
  67. // can be packetized, but also which functional units each instruction ends up
  68. // using after packetization.
  69. void setTrackResources(bool Track) {
  70. A.enableTranscription(Track);
  71. }
  72. // Check if the resources occupied by a MCInstrDesc are available in
  73. // the current state.
  74. bool canReserveResources(const MCInstrDesc *MID);
  75. // Reserve the resources occupied by a MCInstrDesc and change the current
  76. // state to reflect that change.
  77. void reserveResources(const MCInstrDesc *MID);
  78. // Check if the resources occupied by a machine instruction are available
  79. // in the current state.
  80. bool canReserveResources(MachineInstr &MI);
  81. // Reserve the resources occupied by a machine instruction and change the
  82. // current state to reflect that change.
  83. void reserveResources(MachineInstr &MI);
  84. // Return the resources used by the InstIdx'th instruction added to this
  85. // packet. The resources are returned as a bitvector of functional units.
  86. //
  87. // Note that a bundle may be packed in multiple valid ways. This function
  88. // returns one arbitary valid packing.
  89. //
  90. // Requires setTrackResources(true) to have been called.
  91. unsigned getUsedResources(unsigned InstIdx);
  92. const InstrItineraryData *getInstrItins() const { return InstrItins; }
  93. };
  94. // VLIWPacketizerList implements a simple VLIW packetizer using DFA. The
  95. // packetizer works on machine basic blocks. For each instruction I in BB,
  96. // the packetizer consults the DFA to see if machine resources are available
  97. // to execute I. If so, the packetizer checks if I depends on any instruction
  98. // in the current packet. If no dependency is found, I is added to current
  99. // packet and the machine resource is marked as taken. If any dependency is
  100. // found, a target API call is made to prune the dependence.
  101. class VLIWPacketizerList {
  102. protected:
  103. MachineFunction &MF;
  104. const TargetInstrInfo *TII;
  105. AAResults *AA;
  106. // The VLIW Scheduler.
  107. DefaultVLIWScheduler *VLIWScheduler;
  108. // Vector of instructions assigned to the current packet.
  109. std::vector<MachineInstr*> CurrentPacketMIs;
  110. // DFA resource tracker.
  111. DFAPacketizer *ResourceTracker;
  112. // Map: MI -> SU.
  113. std::map<MachineInstr*, SUnit*> MIToSUnit;
  114. public:
  115. // The AAResults parameter can be nullptr.
  116. VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
  117. AAResults *AA);
  118. virtual ~VLIWPacketizerList();
  119. // Implement this API in the backend to bundle instructions.
  120. void PacketizeMIs(MachineBasicBlock *MBB,
  121. MachineBasicBlock::iterator BeginItr,
  122. MachineBasicBlock::iterator EndItr);
  123. // Return the ResourceTracker.
  124. DFAPacketizer *getResourceTracker() {return ResourceTracker;}
  125. // addToPacket - Add MI to the current packet.
  126. virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI) {
  127. CurrentPacketMIs.push_back(&MI);
  128. ResourceTracker->reserveResources(MI);
  129. return MI;
  130. }
  131. // End the current packet and reset the state of the packetizer.
  132. // Overriding this function allows the target-specific packetizer
  133. // to perform custom finalization.
  134. virtual void endPacket(MachineBasicBlock *MBB,
  135. MachineBasicBlock::iterator MI);
  136. // Perform initialization before packetizing an instruction. This
  137. // function is supposed to be overrided by the target dependent packetizer.
  138. virtual void initPacketizerState() {}
  139. // Check if the given instruction I should be ignored by the packetizer.
  140. virtual bool ignorePseudoInstruction(const MachineInstr &I,
  141. const MachineBasicBlock *MBB) {
  142. return false;
  143. }
  144. // Return true if instruction MI can not be packetized with any other
  145. // instruction, which means that MI itself is a packet.
  146. virtual bool isSoloInstruction(const MachineInstr &MI) { return true; }
  147. // Check if the packetizer should try to add the given instruction to
  148. // the current packet. One reasons for which it may not be desirable
  149. // to include an instruction in the current packet could be that it
  150. // would cause a stall.
  151. // If this function returns "false", the current packet will be ended,
  152. // and the instruction will be added to the next packet.
  153. virtual bool shouldAddToPacket(const MachineInstr &MI) { return true; }
  154. // Check if it is legal to packetize SUI and SUJ together.
  155. virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
  156. return false;
  157. }
  158. // Check if it is legal to prune dependece between SUI and SUJ.
  159. virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {
  160. return false;
  161. }
  162. // Add a DAG mutation to be done before the packetization begins.
  163. void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation);
  164. bool alias(const MachineInstr &MI1, const MachineInstr &MI2,
  165. bool UseTBAA = true) const;
  166. private:
  167. bool alias(const MachineMemOperand &Op1, const MachineMemOperand &Op2,
  168. bool UseTBAA = true) const;
  169. };
  170. } // end namespace llvm
  171. #endif // LLVM_CODEGEN_DFAPACKETIZER_H
  172. #ifdef __GNUC__
  173. #pragma GCC diagnostic pop
  174. #endif