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