diff options
Diffstat (limited to 'llvm/lib/Target/ARM/MVETailPredUtils.h')
-rw-r--r-- | llvm/lib/Target/ARM/MVETailPredUtils.h | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/MVETailPredUtils.h b/llvm/lib/Target/ARM/MVETailPredUtils.h new file mode 100644 index 000000000000..9ab5d92729fe --- /dev/null +++ b/llvm/lib/Target/ARM/MVETailPredUtils.h @@ -0,0 +1,157 @@ +//===-- MVETailPredUtils.h - Tail predication utility functions -*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions for low overhead and tail predicated +// loops, shared between the ARMLowOverheadLoops pass and anywhere else that +// needs them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H +#define LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +namespace llvm { + +static inline unsigned VCTPOpcodeToLSTP(unsigned Opcode, bool IsDoLoop) { + switch (Opcode) { + default: + llvm_unreachable("unhandled vctp opcode"); + break; + case ARM::MVE_VCTP8: + return IsDoLoop ? ARM::MVE_DLSTP_8 : ARM::MVE_WLSTP_8; + case ARM::MVE_VCTP16: + return IsDoLoop ? ARM::MVE_DLSTP_16 : ARM::MVE_WLSTP_16; + case ARM::MVE_VCTP32: + return IsDoLoop ? ARM::MVE_DLSTP_32 : ARM::MVE_WLSTP_32; + case ARM::MVE_VCTP64: + return IsDoLoop ? ARM::MVE_DLSTP_64 : ARM::MVE_WLSTP_64; + } + return 0; +} + +static inline unsigned getTailPredVectorWidth(unsigned Opcode) { + switch (Opcode) { + default: + llvm_unreachable("unhandled vctp opcode"); + case ARM::MVE_VCTP8: + return 16; + case ARM::MVE_VCTP16: + return 8; + case ARM::MVE_VCTP32: + return 4; + case ARM::MVE_VCTP64: + return 2; + } + return 0; +} + +static inline bool isVCTP(const MachineInstr *MI) { + switch (MI->getOpcode()) { + default: + break; + case ARM::MVE_VCTP8: + case ARM::MVE_VCTP16: + case ARM::MVE_VCTP32: + case ARM::MVE_VCTP64: + return true; + } + return false; +} + +static inline bool isLoopStart(MachineInstr &MI) { + return MI.getOpcode() == ARM::t2DoLoopStart || + MI.getOpcode() == ARM::t2DoLoopStartTP || + MI.getOpcode() == ARM::t2WhileLoopStart; +} + +// WhileLoopStart holds the exit block, so produce a cmp lr, 0 and then a +// beq that branches to the exit branch. +inline void RevertWhileLoopStart(MachineInstr *MI, const TargetInstrInfo *TII, + unsigned BrOpc = ARM::t2Bcc) { + MachineBasicBlock *MBB = MI->getParent(); + + // Cmp + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri)); + MIB.add(MI->getOperand(0)); + MIB.addImm(0); + MIB.addImm(ARMCC::AL); + MIB.addReg(ARM::NoRegister); + + // Branch + MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc)); + MIB.add(MI->getOperand(1)); // branch target + MIB.addImm(ARMCC::EQ); // condition code + MIB.addReg(ARM::CPSR); + + MI->eraseFromParent(); +} + +inline void RevertDoLoopStart(MachineInstr *MI, const TargetInstrInfo *TII) { + MachineBasicBlock *MBB = MI->getParent(); + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::tMOVr)) + .add(MI->getOperand(0)) + .add(MI->getOperand(1)) + .add(predOps(ARMCC::AL)); + + MI->eraseFromParent(); +} + +inline void RevertLoopDec(MachineInstr *MI, const TargetInstrInfo *TII, + bool SetFlags = false) { + MachineBasicBlock *MBB = MI->getParent(); + + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri)); + MIB.add(MI->getOperand(0)); + MIB.add(MI->getOperand(1)); + MIB.add(MI->getOperand(2)); + MIB.addImm(ARMCC::AL); + MIB.addReg(0); + + if (SetFlags) { + MIB.addReg(ARM::CPSR); + MIB->getOperand(5).setIsDef(true); + } else + MIB.addReg(0); + + MI->eraseFromParent(); +} + +// Generate a subs, or sub and cmp, and a branch instead of an LE. +inline void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII, + unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) { + MachineBasicBlock *MBB = MI->getParent(); + + // Create cmp + if (!SkipCmp) { + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2CMPri)); + MIB.add(MI->getOperand(0)); + MIB.addImm(0); + MIB.addImm(ARMCC::AL); + MIB.addReg(ARM::NoRegister); + } + + // Create bne + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc)); + MIB.add(MI->getOperand(1)); // branch target + MIB.addImm(ARMCC::NE); // condition code + MIB.addReg(ARM::CPSR); + MI->eraseFromParent(); +} + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_ARM_MVETAILPREDUTILS_H |