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