MVETailPredUtils.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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 isLoopStart(MachineInstr &MI) {
  65. return MI.getOpcode() == ARM::t2DoLoopStart ||
  66. MI.getOpcode() == ARM::t2DoLoopStartTP ||
  67. MI.getOpcode() == ARM::t2WhileLoopStart;
  68. }
  69. // WhileLoopStart holds the exit block, so produce a cmp lr, 0 and then a
  70. // beq that branches to the exit branch.
  71. inline void RevertWhileLoopStart(MachineInstr *MI, const TargetInstrInfo *TII,
  72. unsigned BrOpc = ARM::t2Bcc) {
  73. MachineBasicBlock *MBB = MI->getParent();
  74. // Cmp
  75. MachineInstrBuilder MIB =
  76. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
  77. MIB.add(MI->getOperand(0));
  78. MIB.addImm(0);
  79. MIB.addImm(ARMCC::AL);
  80. MIB.addReg(ARM::NoRegister);
  81. // Branch
  82. MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
  83. MIB.add(MI->getOperand(1)); // branch target
  84. MIB.addImm(ARMCC::EQ); // condition code
  85. MIB.addReg(ARM::CPSR);
  86. MI->eraseFromParent();
  87. }
  88. inline void RevertDoLoopStart(MachineInstr *MI, const TargetInstrInfo *TII) {
  89. MachineBasicBlock *MBB = MI->getParent();
  90. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::tMOVr))
  91. .add(MI->getOperand(0))
  92. .add(MI->getOperand(1))
  93. .add(predOps(ARMCC::AL));
  94. MI->eraseFromParent();
  95. }
  96. inline void RevertLoopDec(MachineInstr *MI, const TargetInstrInfo *TII,
  97. bool SetFlags = false) {
  98. MachineBasicBlock *MBB = MI->getParent();
  99. MachineInstrBuilder MIB =
  100. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri));
  101. MIB.add(MI->getOperand(0));
  102. MIB.add(MI->getOperand(1));
  103. MIB.add(MI->getOperand(2));
  104. MIB.addImm(ARMCC::AL);
  105. MIB.addReg(0);
  106. if (SetFlags) {
  107. MIB.addReg(ARM::CPSR);
  108. MIB->getOperand(5).setIsDef(true);
  109. } else
  110. MIB.addReg(0);
  111. MI->eraseFromParent();
  112. }
  113. // Generate a subs, or sub and cmp, and a branch instead of an LE.
  114. inline void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII,
  115. unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) {
  116. MachineBasicBlock *MBB = MI->getParent();
  117. // Create cmp
  118. if (!SkipCmp) {
  119. MachineInstrBuilder MIB =
  120. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
  121. MIB.add(MI->getOperand(0));
  122. MIB.addImm(0);
  123. MIB.addImm(ARMCC::AL);
  124. MIB.addReg(ARM::NoRegister);
  125. }
  126. // Create bne
  127. MachineInstrBuilder MIB =
  128. BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
  129. MIB.add(MI->getOperand(1)); // branch target
  130. MIB.addImm(ARMCC::NE); // condition code
  131. MIB.addReg(ARM::CPSR);
  132. MI->eraseFromParent();
  133. }
  134. } // end namespace llvm
  135. #endif // LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H