PPCMacroFusion.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. //===- PPCMacroFusion.cpp - PowerPC Macro Fusion --------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. /// \file This file contains the PowerPC implementation of the DAG scheduling
  10. /// mutation to pair instructions back to back.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "PPC.h"
  14. #include "PPCSubtarget.h"
  15. #include "llvm/ADT/DenseSet.h"
  16. #include "llvm/CodeGen/MacroFusion.h"
  17. using namespace llvm;
  18. namespace {
  19. class FusionFeature {
  20. public:
  21. typedef SmallDenseSet<unsigned> FusionOpSet;
  22. enum FusionKind {
  23. #define FUSION_KIND(KIND) FK_##KIND
  24. #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) \
  25. FUSION_KIND(KIND),
  26. #include "PPCMacroFusion.def"
  27. FUSION_KIND(END)
  28. };
  29. private:
  30. // Each fusion feature is assigned with one fusion kind. All the
  31. // instructions with the same fusion kind have the same fusion characteristic.
  32. FusionKind Kd;
  33. // True if this feature is enabled.
  34. bool Supported;
  35. // li rx, si
  36. // load rt, ra, rx
  37. // The dependent operand index in the second op(load). And the negative means
  38. // it could be any one.
  39. int DepOpIdx;
  40. // The first fusion op set.
  41. FusionOpSet OpSet1;
  42. // The second fusion op set.
  43. FusionOpSet OpSet2;
  44. public:
  45. FusionFeature(FusionKind Kind, bool HasFeature, int Index,
  46. const FusionOpSet &First, const FusionOpSet &Second) :
  47. Kd(Kind), Supported(HasFeature), DepOpIdx(Index), OpSet1(First),
  48. OpSet2(Second) {}
  49. bool hasOp1(unsigned Opc) const { return OpSet1.contains(Opc); }
  50. bool hasOp2(unsigned Opc) const { return OpSet2.contains(Opc); }
  51. bool isSupported() const { return Supported; }
  52. Optional<unsigned> depOpIdx() const {
  53. if (DepOpIdx < 0)
  54. return None;
  55. return DepOpIdx;
  56. }
  57. FusionKind getKind() const { return Kd; }
  58. };
  59. static bool matchingRegOps(const MachineInstr &FirstMI,
  60. int FirstMIOpIndex,
  61. const MachineInstr &SecondMI,
  62. int SecondMIOpIndex) {
  63. const MachineOperand &Op1 = FirstMI.getOperand(FirstMIOpIndex);
  64. const MachineOperand &Op2 = SecondMI.getOperand(SecondMIOpIndex);
  65. if (!Op1.isReg() || !Op2.isReg())
  66. return false;
  67. return Op1.getReg() == Op2.getReg();
  68. }
  69. // Return true if the FirstMI meets the constraints of SecondMI according to
  70. // fusion specification.
  71. static bool checkOpConstraints(FusionFeature::FusionKind Kd,
  72. const MachineInstr &FirstMI,
  73. const MachineInstr &SecondMI) {
  74. switch (Kd) {
  75. // The hardware didn't require any specific check for the fused instructions'
  76. // operands. Therefore, return true to indicate that, it is fusable.
  77. default: return true;
  78. // [addi rt,ra,si - lxvd2x xt,ra,rb] etc.
  79. case FusionFeature::FK_AddiLoad: {
  80. // lxvd2x(ra) cannot be zero
  81. const MachineOperand &RA = SecondMI.getOperand(1);
  82. if (!RA.isReg())
  83. return true;
  84. return Register::isVirtualRegister(RA.getReg()) ||
  85. (RA.getReg() != PPC::ZERO && RA.getReg() != PPC::ZERO8);
  86. }
  87. // [addis rt,ra,si - ld rt,ds(ra)] etc.
  88. case FusionFeature::FK_AddisLoad: {
  89. const MachineOperand &RT = SecondMI.getOperand(0);
  90. if (!RT.isReg())
  91. return true;
  92. // Only check it for non-virtual register.
  93. if (!Register::isVirtualRegister(RT.getReg()))
  94. // addis(rt) = ld(ra) = ld(rt)
  95. // ld(rt) cannot be zero
  96. if (!matchingRegOps(SecondMI, 0, SecondMI, 2) ||
  97. (RT.getReg() == PPC::ZERO || RT.getReg() == PPC::ZERO8))
  98. return false;
  99. // addis(si) first 12 bits must be all 1s or all 0s
  100. const MachineOperand &SI = FirstMI.getOperand(2);
  101. if (!SI.isImm())
  102. return true;
  103. int64_t Imm = SI.getImm();
  104. if (((Imm & 0xFFF0) != 0) && ((Imm & 0xFFF0) != 0xFFF0))
  105. return false;
  106. // If si = 1111111111110000 and the msb of the d/ds field of the load equals
  107. // 1, then fusion does not occur.
  108. if ((Imm & 0xFFF0) == 0xFFF0) {
  109. const MachineOperand &D = SecondMI.getOperand(1);
  110. if (!D.isImm())
  111. return true;
  112. // 14 bit for DS field, while 16 bit for D field.
  113. int MSB = 15;
  114. if (SecondMI.getOpcode() == PPC::LD)
  115. MSB = 13;
  116. return (D.getImm() & (1ULL << MSB)) == 0;
  117. }
  118. return true;
  119. }
  120. }
  121. llvm_unreachable("All the cases should have been handled");
  122. return true;
  123. }
  124. /// Check if the instr pair, FirstMI and SecondMI, should be fused together.
  125. /// Given SecondMI, when FirstMI is unspecified, then check if SecondMI may be
  126. /// part of a fused pair at all.
  127. static bool shouldScheduleAdjacent(const TargetInstrInfo &TII,
  128. const TargetSubtargetInfo &TSI,
  129. const MachineInstr *FirstMI,
  130. const MachineInstr &SecondMI) {
  131. // We use the PPC namespace to avoid the need to prefix opcodes with PPC:: in
  132. // the def file.
  133. using namespace PPC;
  134. const PPCSubtarget &ST = static_cast<const PPCSubtarget&>(TSI);
  135. static const FusionFeature FusionFeatures[] = {
  136. #define FUSION_FEATURE(KIND, HAS_FEATURE, DEP_OP_IDX, OPSET1, OPSET2) { \
  137. FusionFeature::FUSION_KIND(KIND), ST.HAS_FEATURE(), DEP_OP_IDX, { OPSET1 },\
  138. { OPSET2 } },
  139. #include "PPCMacroFusion.def"
  140. };
  141. #undef FUSION_KIND
  142. for (auto &Feature : FusionFeatures) {
  143. // Skip if the feature is not supported.
  144. if (!Feature.isSupported())
  145. continue;
  146. // Only when the SecondMI is fusable, we are starting to look for the
  147. // fusable FirstMI.
  148. if (Feature.hasOp2(SecondMI.getOpcode())) {
  149. // If FirstMI == nullptr, that means, we're only checking whether SecondMI
  150. // can be fused at all.
  151. if (!FirstMI)
  152. return true;
  153. // Checking if the FirstMI is fusable with the SecondMI.
  154. if (!Feature.hasOp1(FirstMI->getOpcode()))
  155. continue;
  156. auto DepOpIdx = Feature.depOpIdx();
  157. if (DepOpIdx.hasValue()) {
  158. // Checking if the result of the FirstMI is the desired operand of the
  159. // SecondMI if the DepOpIdx is set. Otherwise, ignore it.
  160. if (!matchingRegOps(*FirstMI, 0, SecondMI, *DepOpIdx))
  161. return false;
  162. }
  163. // Checking more on the instruction operands.
  164. if (checkOpConstraints(Feature.getKind(), *FirstMI, SecondMI))
  165. return true;
  166. }
  167. }
  168. return false;
  169. }
  170. } // end anonymous namespace
  171. namespace llvm {
  172. std::unique_ptr<ScheduleDAGMutation> createPowerPCMacroFusionDAGMutation () {
  173. return createMacroFusionDAGMutation(shouldScheduleAdjacent);
  174. }
  175. } // end namespace llvm