Home | History | Annotate | Line # | Download | only in ARM
      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          MI.getOpcode() == ARM::t2WhileLoopStartLR;
     76 }
     77 
     78 // WhileLoopStart holds the exit block, so produce a subs Op0, Op1, 0 and then a
     79 // beq that branches to the exit branch.
     80 // If UseCmp is true, this will create a t2CMP instead of a t2SUBri, meaning the
     81 // value of LR into the loop will not be setup. This is used if the LR setup is
     82 // done via another means (via a t2DoLoopStart, for example).
     83 inline void RevertWhileLoopStartLR(MachineInstr *MI, const TargetInstrInfo *TII,
     84                                    unsigned BrOpc = ARM::t2Bcc,
     85                                    bool UseCmp = false) {
     86   MachineBasicBlock *MBB = MI->getParent();
     87   assert(MI->getOpcode() == ARM::t2WhileLoopStartLR &&
     88          "Only expected a t2WhileLoopStartLR in RevertWhileLoopStartLR!");
     89 
     90   // Subs/Cmp
     91   if (UseCmp) {
     92     MachineInstrBuilder MIB =
     93         BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
     94     MIB.add(MI->getOperand(1));
     95     MIB.addImm(0);
     96     MIB.addImm(ARMCC::AL);
     97     MIB.addReg(ARM::NoRegister);
     98   } else {
     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.addImm(0);
    104     MIB.addImm(ARMCC::AL);
    105     MIB.addReg(ARM::NoRegister);
    106     MIB.addReg(ARM::CPSR, RegState::Define);
    107   }
    108 
    109   // Branch
    110   MachineInstrBuilder MIB =
    111       BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
    112   MIB.add(MI->getOperand(2)); // branch target
    113   MIB.addImm(ARMCC::EQ);      // condition code
    114   MIB.addReg(ARM::CPSR);
    115 
    116   MI->eraseFromParent();
    117 }
    118 
    119 inline void RevertDoLoopStart(MachineInstr *MI, const TargetInstrInfo *TII) {
    120   MachineBasicBlock *MBB = MI->getParent();
    121   BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::tMOVr))
    122       .add(MI->getOperand(0))
    123       .add(MI->getOperand(1))
    124       .add(predOps(ARMCC::AL));
    125 
    126   MI->eraseFromParent();
    127 }
    128 
    129 inline void RevertLoopDec(MachineInstr *MI, const TargetInstrInfo *TII,
    130                           bool SetFlags = false) {
    131   MachineBasicBlock *MBB = MI->getParent();
    132 
    133   MachineInstrBuilder MIB =
    134       BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri));
    135   MIB.add(MI->getOperand(0));
    136   MIB.add(MI->getOperand(1));
    137   MIB.add(MI->getOperand(2));
    138   MIB.addImm(ARMCC::AL);
    139   MIB.addReg(0);
    140 
    141   if (SetFlags) {
    142     MIB.addReg(ARM::CPSR);
    143     MIB->getOperand(5).setIsDef(true);
    144   } else
    145     MIB.addReg(0);
    146 
    147   MI->eraseFromParent();
    148 }
    149 
    150 // Generate a subs, or sub and cmp, and a branch instead of an LE.
    151 inline void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII,
    152                           unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) {
    153   MachineBasicBlock *MBB = MI->getParent();
    154 
    155   // Create cmp
    156   if (!SkipCmp) {
    157     MachineInstrBuilder MIB =
    158         BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri));
    159     MIB.add(MI->getOperand(0));
    160     MIB.addImm(0);
    161     MIB.addImm(ARMCC::AL);
    162     MIB.addReg(ARM::NoRegister);
    163   }
    164 
    165   // Create bne
    166   MachineInstrBuilder MIB =
    167       BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc));
    168   MIB.add(MI->getOperand(1)); // branch target
    169   MIB.addImm(ARMCC::NE);      // condition code
    170   MIB.addReg(ARM::CPSR);
    171   MI->eraseFromParent();
    172 }
    173 
    174 } // end namespace llvm
    175 
    176 #endif // LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H
    177