MVETailPredUtils.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //===-- MVETailPredUtils.h - Tail predication utility functions -*- C++-*-===//
  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. // This file contains utility functions for low overhead and tail predicated
  10. // loops, shared between the ARMLowOverheadLoops pass and anywhere else that
  11. // needs them.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H
  15. #define LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H
  16. #include "llvm/CodeGen/MachineInstr.h"
  17. #include "llvm/CodeGen/MachineInstrBuilder.h"
  18. #include "llvm/CodeGen/MachineOperand.h"
  19. #include "llvm/CodeGen/TargetInstrInfo.h"
  20. namespace llvm {
  21. static inline unsigned VCTPOpcodeToLSTP(unsigned Opcode, bool IsDoLoop) {
  22. switch (Opcode) {
  23. default:
  24. llvm_unreachable("unhandled vctp opcode");
  25. break;
  26. case ARM::MVE_VCTP8:
  27. return IsDoLoop ? ARM::MVE_DLSTP_8 : ARM::MVE_WLSTP_8;
  28. case ARM::MVE_VCTP16:
  29. return IsDoLoop ? ARM::MVE_DLSTP_16 : ARM::MVE_WLSTP_16;
  30. case ARM::MVE_VCTP32:
  31. return IsDoLoop ? ARM::MVE_DLSTP_32 : ARM::MVE_WLSTP_32;
  32. case ARM::MVE_VCTP64:
  33. return IsDoLoop ? ARM::MVE_DLSTP_64 : ARM::MVE_WLSTP_64;
  34. }
  35. return 0;
  36. }
  37. static inline unsigned getTailPredVectorWidth(unsigned Opcode) {
  38. switch (Opcode) {
  39. default:
  40. llvm_unreachable("unhandled vctp opcode");
  41. case ARM::MVE_VCTP8:
  42. return 16;
  43. case ARM::MVE_VCTP16:
  44. return 8;
  45. case ARM::MVE_VCTP32:
  46. return 4;
  47. case ARM::MVE_VCTP64:
  48. return 2;
  49. }
  50. return 0;
  51. }
  52. static inline bool isVCTP(const MachineInstr *MI) {
  53. switch (MI->getOpcode()) {
  54. default:
  55. break;
  56. case ARM::MVE_VCTP8:
  57. case ARM::MVE_VCTP16:
  58. case ARM::MVE_VCTP32:
  59. case ARM::MVE_VCTP64:
  60. return true;
  61. }
  62. return false;
  63. }
  64. static inline bool isDoLoopStart(const MachineInstr &MI) {
  65. return MI.getOpcode() == ARM::t2DoLoopStart ||
  66. MI.getOpcode() == ARM::t2DoLoopStartTP;
  67. }
  68. static inline bool isWhileLoopStart(const MachineInstr &MI) {
  69. return MI.getOpcode() == ARM::t2WhileLoopStart ||
  70. MI.getOpcode() == ARM::t2WhileLoopStartLR ||
  71. MI.getOpcode() == ARM::t2WhileLoopStartTP;
  72. }
  73. static inline bool isLoopStart(const MachineInstr &MI) {
  74. return isDoLoopStart(MI) || isWhileLoopStart(MI);
  75. }
  76. // Return the TargetBB stored in a t2WhileLoopStartLR/t2WhileLoopStartTP.
  77. inline MachineBasicBlock *getWhileLoopStartTargetBB(const MachineInstr &MI) {
  78. assert(isWhileLoopStart(MI) && "Expected WhileLoopStart!");
  79. unsigned Op = MI.getOpcode() == ARM::t2WhileLoopStartTP ? 3 : 2;
  80. return MI.getOperand(Op).getMBB();
  81. }
  82. // WhileLoopStart holds the exit block, so produce a subs Op0, Op1, 0 and then a
  83. // beq that branches to the exit branch.
  84. // If UseCmp is true, this will create a t2CMP instead of a t2SUBri, meaning the
  85. // value of LR into the loop will not be setup. This is used if the LR setup is
  86. // done via another means (via a t2DoLoopStart, for example).
  87. inline void RevertWhileLoopStartLR(MachineInstr *MI, const TargetInstrInfo *TII,
  88. unsigned BrOpc = ARM::t2Bcc,
  89. bool UseCmp = false) {
  90. MachineBasicBlock *MBB = MI->getParent();
  91. assert((MI->getOpcode() == ARM::t2WhileLoopStartLR ||
  92. MI->getOpcode() == ARM::t2WhileLoopStartTP) &&
  93. "Only expected a t2WhileLoopStartLR/TP in RevertWhileLoopStartLR!");
  94. // Subs/Cmp
  95. if (UseCmp) {
  96. MachineInstrBuilder MIB =
  97. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
  98. MIB.add(MI->getOperand(1));
  99. MIB.addImm(0);
  100. MIB.addImm(ARMCC::AL);
  101. MIB.addReg(ARM::NoRegister);
  102. } else {
  103. MachineInstrBuilder MIB =
  104. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri));
  105. MIB.add(MI->getOperand(0));
  106. MIB.add(MI->getOperand(1));
  107. MIB.addImm(0);
  108. MIB.addImm(ARMCC::AL);
  109. MIB.addReg(ARM::NoRegister);
  110. MIB.addReg(ARM::CPSR, RegState::Define);
  111. }
  112. // Branch
  113. MachineInstrBuilder MIB =
  114. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
  115. MIB.addMBB(getWhileLoopStartTargetBB(*MI)); // branch target
  116. MIB.addImm(ARMCC::EQ); // condition code
  117. MIB.addReg(ARM::CPSR);
  118. MI->eraseFromParent();
  119. }
  120. inline void RevertDoLoopStart(MachineInstr *MI, const TargetInstrInfo *TII) {
  121. MachineBasicBlock *MBB = MI->getParent();
  122. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::tMOVr))
  123. .add(MI->getOperand(0))
  124. .add(MI->getOperand(1))
  125. .add(predOps(ARMCC::AL));
  126. MI->eraseFromParent();
  127. }
  128. inline void RevertLoopDec(MachineInstr *MI, const TargetInstrInfo *TII,
  129. bool SetFlags = false) {
  130. MachineBasicBlock *MBB = MI->getParent();
  131. MachineInstrBuilder MIB =
  132. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri));
  133. MIB.add(MI->getOperand(0));
  134. MIB.add(MI->getOperand(1));
  135. MIB.add(MI->getOperand(2));
  136. MIB.addImm(ARMCC::AL);
  137. MIB.addReg(0);
  138. if (SetFlags) {
  139. MIB.addReg(ARM::CPSR);
  140. MIB->getOperand(5).setIsDef(true);
  141. } else
  142. MIB.addReg(0);
  143. MI->eraseFromParent();
  144. }
  145. // Generate a subs, or sub and cmp, and a branch instead of an LE.
  146. inline void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII,
  147. unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) {
  148. MachineBasicBlock *MBB = MI->getParent();
  149. // Create cmp
  150. if (!SkipCmp) {
  151. MachineInstrBuilder MIB =
  152. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
  153. MIB.add(MI->getOperand(0));
  154. MIB.addImm(0);
  155. MIB.addImm(ARMCC::AL);
  156. MIB.addReg(ARM::NoRegister);
  157. }
  158. // Create bne
  159. MachineInstrBuilder MIB =
  160. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
  161. MIB.add(MI->getOperand(1)); // branch target
  162. MIB.addImm(ARMCC::NE); // condition code
  163. MIB.addReg(ARM::CPSR);
  164. MI->eraseFromParent();
  165. }
  166. } // end namespace llvm
  167. #endif // LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H