LLVM 19.0.0git
MVETailPredUtils.h
Go to the documentation of this file.
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
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) {
84}
85
86// Return the TargetBB stored in a t2WhileLoopStartLR/t2WhileLoopStartTP.
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).
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) {
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 {
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
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
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))
141
142 MI->eraseFromParent();
143}
144
146 bool SetFlags = false) {
147 MachineBasicBlock *MBB = MI->getParent();
148
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.
168 unsigned BrOpc = ARM::t2Bcc, bool SkipCmp = false) {
169 MachineBasicBlock *MBB = MI->getParent();
170
171 // Create cmp
172 if (!SkipCmp) {
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
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
MachineBasicBlock & MBB
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents an Operation in the Expression.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:556
void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
TargetInstrInfo - Interface to description of machine instruction set.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Define
Register definition.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
static bool isDoLoopStart(const MachineInstr &MI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isVCTP(const MachineInstr *MI)
static unsigned getTailPredVectorWidth(unsigned Opcode)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isLoopStart(const MachineInstr &MI)
void RevertWhileLoopStartLR(MachineInstr *MI, const TargetInstrInfo *TII, unsigned BrOpc=ARM::t2Bcc, bool UseCmp=false)
static unsigned VCTPOpcodeToLSTP(unsigned Opcode, bool IsDoLoop)
void RevertLoopEnd(MachineInstr *MI, const TargetInstrInfo *TII, unsigned BrOpc=ARM::t2Bcc, bool SkipCmp=false)
void RevertLoopDec(MachineInstr *MI, const TargetInstrInfo *TII, bool SetFlags=false)
MachineBasicBlock * getWhileLoopStartTargetBB(const MachineInstr &MI)
static bool isWhileLoopStart(const MachineInstr &MI)
void RevertDoLoopStart(MachineInstr *MI, const TargetInstrInfo *TII)