193 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains utility functions for low overhead and tail predicated10// loops, shared between the ARMLowOverheadLoops pass and anywhere else that11// needs them.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H16#define LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H17 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 23namespace llvm {24 25static 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 42static 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 58static 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 71static inline bool isDoLoopStart(const MachineInstr &MI) {72 return MI.getOpcode() == ARM::t2DoLoopStart ||73 MI.getOpcode() == ARM::t2DoLoopStartTP;74}75 76static inline bool isWhileLoopStart(const MachineInstr &MI) {77 return MI.getOpcode() == ARM::t2WhileLoopStart ||78 MI.getOpcode() == ARM::t2WhileLoopStartLR ||79 MI.getOpcode() == ARM::t2WhileLoopStartTP;80}81 82static inline bool isLoopStart(const MachineInstr &MI) {83 return isDoLoopStart(MI) || isWhileLoopStart(MI);84}85 86// Return the TargetBB stored in a t2WhileLoopStartLR/t2WhileLoopStartTP.87inline 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 a94// beq that branches to the exit branch.95// If UseCmp is true, this will create a t2CMP instead of a t2SUBri, meaning the96// value of LR into the loop will not be setup. This is used if the LR setup is97// done via another means (via a t2DoLoopStart, for example).98inline 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/Cmp107 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 // Branch126 MachineInstrBuilder MIB =127 BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));128 MIB.addMBB(getWhileLoopStartTargetBB(*MI)); // branch target129 MIB.addImm(ARMCC::EQ); // condition code130 MIB.addReg(ARM::CPSR);131 132 MI->eraseFromParent();133}134 135inline 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 145inline 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 } else161 MIB.addReg(0);162 163 MI->eraseFromParent();164}165 166// Generate a subs, or sub and cmp, and a branch instead of an LE.167inline void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII,168 unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) {169 MachineBasicBlock *MBB = MI->getParent();170 171 // Create cmp172 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 bne182 MachineInstrBuilder MIB =183 BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));184 MIB.add(MI->getOperand(1)); // branch target185 MIB.addImm(ARMCC::NE); // condition code186 MIB.addReg(ARM::CPSR);187 MI->eraseFromParent();188}189 190} // end namespace llvm191 192#endif // LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H193