ExecutionDomainFix.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- 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. //
  14. /// \file Execution Domain Fix pass.
  15. ///
  16. /// Some X86 SSE instructions like mov, and, or, xor are available in different
  17. /// variants for different operand types. These variant instructions are
  18. /// equivalent, but on Nehalem and newer cpus there is extra latency
  19. /// transferring data between integer and floating point domains. ARM cores
  20. /// have similar issues when they are configured with both VFP and NEON
  21. /// pipelines.
  22. ///
  23. /// This pass changes the variant instructions to minimize domain crossings.
  24. //
  25. //===----------------------------------------------------------------------===//
  26. #ifndef LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
  27. #define LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
  28. #include "llvm/ADT/SmallVector.h"
  29. #include "llvm/CodeGen/LoopTraversal.h"
  30. #include "llvm/CodeGen/MachineFunctionPass.h"
  31. #include "llvm/CodeGen/ReachingDefAnalysis.h"
  32. #include "llvm/CodeGen/TargetRegisterInfo.h"
  33. namespace llvm {
  34. class MachineInstr;
  35. class TargetInstrInfo;
  36. /// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
  37. /// of execution domains.
  38. ///
  39. /// An open DomainValue represents a set of instructions that can still switch
  40. /// execution domain. Multiple registers may refer to the same open
  41. /// DomainValue - they will eventually be collapsed to the same execution
  42. /// domain.
  43. ///
  44. /// A collapsed DomainValue represents a single register that has been forced
  45. /// into one of more execution domains. There is a separate collapsed
  46. /// DomainValue for each register, but it may contain multiple execution
  47. /// domains. A register value is initially created in a single execution
  48. /// domain, but if we were forced to pay the penalty of a domain crossing, we
  49. /// keep track of the fact that the register is now available in multiple
  50. /// domains.
  51. struct DomainValue {
  52. /// Basic reference counting.
  53. unsigned Refs = 0;
  54. /// Bitmask of available domains. For an open DomainValue, it is the still
  55. /// possible domains for collapsing. For a collapsed DomainValue it is the
  56. /// domains where the register is available for free.
  57. unsigned AvailableDomains;
  58. /// Pointer to the next DomainValue in a chain. When two DomainValues are
  59. /// merged, Victim.Next is set to point to Victor, so old DomainValue
  60. /// references can be updated by following the chain.
  61. DomainValue *Next;
  62. /// Twiddleable instructions using or defining these registers.
  63. SmallVector<MachineInstr *, 8> Instrs;
  64. DomainValue() { clear(); }
  65. /// A collapsed DomainValue has no instructions to twiddle - it simply keeps
  66. /// track of the domains where the registers are already available.
  67. bool isCollapsed() const { return Instrs.empty(); }
  68. /// Is domain available?
  69. bool hasDomain(unsigned domain) const {
  70. assert(domain <
  71. static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
  72. "undefined behavior");
  73. return AvailableDomains & (1u << domain);
  74. }
  75. /// Mark domain as available.
  76. void addDomain(unsigned domain) {
  77. assert(domain <
  78. static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
  79. "undefined behavior");
  80. AvailableDomains |= 1u << domain;
  81. }
  82. // Restrict to a single domain available.
  83. void setSingleDomain(unsigned domain) {
  84. assert(domain <
  85. static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
  86. "undefined behavior");
  87. AvailableDomains = 1u << domain;
  88. }
  89. /// Return bitmask of domains that are available and in mask.
  90. unsigned getCommonDomains(unsigned mask) const {
  91. return AvailableDomains & mask;
  92. }
  93. /// First domain available.
  94. unsigned getFirstDomain() const {
  95. return countTrailingZeros(AvailableDomains);
  96. }
  97. /// Clear this DomainValue and point to next which has all its data.
  98. void clear() {
  99. AvailableDomains = 0;
  100. Next = nullptr;
  101. Instrs.clear();
  102. }
  103. };
  104. class ExecutionDomainFix : public MachineFunctionPass {
  105. SpecificBumpPtrAllocator<DomainValue> Allocator;
  106. SmallVector<DomainValue *, 16> Avail;
  107. const TargetRegisterClass *const RC;
  108. MachineFunction *MF;
  109. const TargetInstrInfo *TII;
  110. const TargetRegisterInfo *TRI;
  111. std::vector<SmallVector<int, 1>> AliasMap;
  112. const unsigned NumRegs;
  113. /// Value currently in each register, or NULL when no value is being tracked.
  114. /// This counts as a DomainValue reference.
  115. using LiveRegsDVInfo = std::vector<DomainValue *>;
  116. LiveRegsDVInfo LiveRegs;
  117. /// Keeps domain information for all registers. Note that this
  118. /// is different from the usual definition notion of liveness. The CPU
  119. /// doesn't care whether or not we consider a register killed.
  120. using OutRegsInfoMap = SmallVector<LiveRegsDVInfo, 4>;
  121. OutRegsInfoMap MBBOutRegsInfos;
  122. ReachingDefAnalysis *RDA;
  123. public:
  124. ExecutionDomainFix(char &PassID, const TargetRegisterClass &RC)
  125. : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
  126. void getAnalysisUsage(AnalysisUsage &AU) const override {
  127. AU.setPreservesAll();
  128. AU.addRequired<ReachingDefAnalysis>();
  129. MachineFunctionPass::getAnalysisUsage(AU);
  130. }
  131. bool runOnMachineFunction(MachineFunction &MF) override;
  132. MachineFunctionProperties getRequiredProperties() const override {
  133. return MachineFunctionProperties().set(
  134. MachineFunctionProperties::Property::NoVRegs);
  135. }
  136. private:
  137. /// Translate TRI register number to a list of indices into our smaller tables
  138. /// of interesting registers.
  139. iterator_range<SmallVectorImpl<int>::const_iterator>
  140. regIndices(unsigned Reg) const;
  141. /// DomainValue allocation.
  142. DomainValue *alloc(int domain = -1);
  143. /// Add reference to DV.
  144. DomainValue *retain(DomainValue *DV) {
  145. if (DV)
  146. ++DV->Refs;
  147. return DV;
  148. }
  149. /// Release a reference to DV. When the last reference is released,
  150. /// collapse if needed.
  151. void release(DomainValue *);
  152. /// Follow the chain of dead DomainValues until a live DomainValue is reached.
  153. /// Update the referenced pointer when necessary.
  154. DomainValue *resolve(DomainValue *&);
  155. /// Set LiveRegs[rx] = dv, updating reference counts.
  156. void setLiveReg(int rx, DomainValue *DV);
  157. /// Kill register rx, recycle or collapse any DomainValue.
  158. void kill(int rx);
  159. /// Force register rx into domain.
  160. void force(int rx, unsigned domain);
  161. /// Collapse open DomainValue into given domain. If there are multiple
  162. /// registers using dv, they each get a unique collapsed DomainValue.
  163. void collapse(DomainValue *dv, unsigned domain);
  164. /// All instructions and registers in B are moved to A, and B is released.
  165. bool merge(DomainValue *A, DomainValue *B);
  166. /// Set up LiveRegs by merging predecessor live-out values.
  167. void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
  168. /// Update live-out values.
  169. void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
  170. /// Process he given basic block.
  171. void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
  172. /// Visit given insturcion.
  173. bool visitInstr(MachineInstr *);
  174. /// Update def-ages for registers defined by MI.
  175. /// If Kill is set, also kill off DomainValues clobbered by the defs.
  176. void processDefs(MachineInstr *, bool Kill);
  177. /// A soft instruction can be changed to work in other domains given by mask.
  178. void visitSoftInstr(MachineInstr *, unsigned mask);
  179. /// A hard instruction only works in one domain. All input registers will be
  180. /// forced into that domain.
  181. void visitHardInstr(MachineInstr *, unsigned domain);
  182. };
  183. } // namespace llvm
  184. #endif // LLVM_CODEGEN_EXECUTIONDOMAINFIX_H
  185. #ifdef __GNUC__
  186. #pragma GCC diagnostic pop
  187. #endif