LLVM 23.0.0git
ARMExpandPseudoInsts.cpp
Go to the documentation of this file.
1//===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//
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 a pass that expands pseudo instructions into target
10// instructions to allow proper scheduling, if-conversion, and other late
11// optimizations. This pass should be run after register allocation but before
12// the post-regalloc scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "ARM.h"
17#include "ARMBaseInstrInfo.h"
18#include "ARMBaseRegisterInfo.h"
21#include "ARMSubtarget.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/Support/Debug.h"
29
30#include <atomic>
31
32using namespace llvm;
33
34#define DEBUG_TYPE "arm-pseudo"
35
36static cl::opt<bool>
37VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden,
38 cl::desc("Verify machine code after expanding ARM pseudos"));
39
40#define ARM_EXPAND_PSEUDO_NAME "ARM pseudo instruction expansion pass"
41
42namespace {
43 class ARMExpandPseudo : public MachineFunctionPass {
44 public:
45 static char ID;
46 ARMExpandPseudo() : MachineFunctionPass(ID) {}
47
48 const ARMBaseInstrInfo *TII;
50 const ARMSubtarget *STI;
51 ARMFunctionInfo *AFI;
52
53 bool runOnMachineFunction(MachineFunction &Fn) override;
54
55 MachineFunctionProperties getRequiredProperties() const override {
56 return MachineFunctionProperties().setNoVRegs();
57 }
58
59 StringRef getPassName() const override {
61 }
62
63 private:
64 bool ExpandMI(MachineBasicBlock &MBB,
67 bool ExpandMBB(MachineBasicBlock &MBB);
68 void ExpandVLD(MachineBasicBlock::iterator &MBBI);
69 void ExpandVST(MachineBasicBlock::iterator &MBBI);
70 void ExpandLaneOp(MachineBasicBlock::iterator &MBBI);
71 void ExpandVTBL(MachineBasicBlock::iterator &MBBI,
72 unsigned Opc, bool IsExt);
73 void ExpandMQQPRLoadStore(MachineBasicBlock::iterator &MBBI);
74 void ExpandTMOV32BitImm(MachineBasicBlock &MBB,
76 void ExpandMOV32BitImm(MachineBasicBlock &MBB,
78 void CMSEClearGPRegs(MachineBasicBlock &MBB,
80 const SmallVectorImpl<unsigned> &ClearRegs,
81 unsigned ClobberReg);
82 MachineBasicBlock &CMSEClearFPRegs(MachineBasicBlock &MBB,
84 MachineBasicBlock &CMSEClearFPRegsV8(MachineBasicBlock &MBB,
86 const BitVector &ClearRegs);
87 MachineBasicBlock &CMSEClearFPRegsV81(MachineBasicBlock &MBB,
89 const BitVector &ClearRegs);
90 void CMSESaveClearFPRegs(MachineBasicBlock &MBB,
93 SmallVectorImpl<unsigned> &AvailableRegs);
94 void CMSESaveClearFPRegsV8(MachineBasicBlock &MBB,
97 SmallVectorImpl<unsigned> &ScratchRegs);
98 void CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,
100 const LivePhysRegs &LiveRegs);
101 void CMSERestoreFPRegs(MachineBasicBlock &MBB,
103 SmallVectorImpl<unsigned> &AvailableRegs);
104 void CMSERestoreFPRegsV8(MachineBasicBlock &MBB,
106 SmallVectorImpl<unsigned> &AvailableRegs);
107 void CMSERestoreFPRegsV81(MachineBasicBlock &MBB,
109 SmallVectorImpl<unsigned> &AvailableRegs);
110 bool ExpandCMP_SWAP(MachineBasicBlock &MBB,
111 MachineBasicBlock::iterator MBBI, unsigned LdrexOp,
112 unsigned StrexOp, unsigned UxtOp,
114
115 bool ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
118 };
119 char ARMExpandPseudo::ID = 0;
120}
121
123 false)
124
125namespace {
126 // Constants for register spacing in NEON load/store instructions.
127 // For quad-register load-lane and store-lane pseudo instructors, the
128 // spacing is initially assumed to be EvenDblSpc, and that is changed to
129 // OddDblSpc depending on the lane number operand.
130 enum NEONRegSpacing {
131 SingleSpc,
132 SingleLowSpc , // Single spacing, low registers, three and four vectors.
133 SingleHighQSpc, // Single spacing, high registers, four vectors.
134 SingleHighTSpc, // Single spacing, high registers, three vectors.
135 EvenDblSpc,
136 OddDblSpc
137 };
138
139 // Entries for NEON load/store information table. The table is sorted by
140 // PseudoOpc for fast binary-search lookups.
141 struct NEONLdStTableEntry {
142 uint16_t PseudoOpc;
143 uint16_t RealOpc;
144 bool IsLoad;
145 bool isUpdating;
146 bool hasWritebackOperand;
147 uint8_t RegSpacing; // One of type NEONRegSpacing
148 uint8_t NumRegs; // D registers loaded or stored
149 uint8_t RegElts; // elements per D register; used for lane ops
150 // FIXME: Temporary flag to denote whether the real instruction takes
151 // a single register (like the encoding) or all of the registers in
152 // the list (like the asm syntax and the isel DAG). When all definitions
153 // are converted to take only the single encoded register, this will
154 // go away.
155 bool copyAllListRegs;
156
157 // Comparison methods for binary search of the table.
158 bool operator<(const NEONLdStTableEntry &TE) const {
159 return PseudoOpc < TE.PseudoOpc;
160 }
161 friend bool operator<(const NEONLdStTableEntry &TE, unsigned PseudoOpc) {
162 return TE.PseudoOpc < PseudoOpc;
163 }
164 [[maybe_unused]] friend bool operator<(unsigned PseudoOpc,
165 const NEONLdStTableEntry &TE) {
166 return PseudoOpc < TE.PseudoOpc;
167 }
168 };
169}
170
171static const NEONLdStTableEntry NEONLdStTable[] = {
172{ ARM::VLD1LNq16Pseudo, ARM::VLD1LNd16, true, false, false, EvenDblSpc, 1, 4 ,true},
173{ ARM::VLD1LNq16Pseudo_UPD, ARM::VLD1LNd16_UPD, true, true, true, EvenDblSpc, 1, 4 ,true},
174{ ARM::VLD1LNq32Pseudo, ARM::VLD1LNd32, true, false, false, EvenDblSpc, 1, 2 ,true},
175{ ARM::VLD1LNq32Pseudo_UPD, ARM::VLD1LNd32_UPD, true, true, true, EvenDblSpc, 1, 2 ,true},
176{ ARM::VLD1LNq8Pseudo, ARM::VLD1LNd8, true, false, false, EvenDblSpc, 1, 8 ,true},
177{ ARM::VLD1LNq8Pseudo_UPD, ARM::VLD1LNd8_UPD, true, true, true, EvenDblSpc, 1, 8 ,true},
178
179{ ARM::VLD1d16QPseudo, ARM::VLD1d16Q, true, false, false, SingleSpc, 4, 4 ,false},
180{ ARM::VLD1d16QPseudoWB_fixed, ARM::VLD1d16Qwb_fixed, true, true, false, SingleSpc, 4, 4 ,false},
181{ ARM::VLD1d16QPseudoWB_register, ARM::VLD1d16Qwb_register, true, true, true, SingleSpc, 4, 4 ,false},
182{ ARM::VLD1d16TPseudo, ARM::VLD1d16T, true, false, false, SingleSpc, 3, 4 ,false},
183{ ARM::VLD1d16TPseudoWB_fixed, ARM::VLD1d16Twb_fixed, true, true, false, SingleSpc, 3, 4 ,false},
184{ ARM::VLD1d16TPseudoWB_register, ARM::VLD1d16Twb_register, true, true, true, SingleSpc, 3, 4 ,false},
185
186{ ARM::VLD1d32QPseudo, ARM::VLD1d32Q, true, false, false, SingleSpc, 4, 2 ,false},
187{ ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d32Qwb_fixed, true, true, false, SingleSpc, 4, 2 ,false},
188{ ARM::VLD1d32QPseudoWB_register, ARM::VLD1d32Qwb_register, true, true, true, SingleSpc, 4, 2 ,false},
189{ ARM::VLD1d32TPseudo, ARM::VLD1d32T, true, false, false, SingleSpc, 3, 2 ,false},
190{ ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d32Twb_fixed, true, true, false, SingleSpc, 3, 2 ,false},
191{ ARM::VLD1d32TPseudoWB_register, ARM::VLD1d32Twb_register, true, true, true, SingleSpc, 3, 2 ,false},
192
193{ ARM::VLD1d64QPseudo, ARM::VLD1d64Q, true, false, false, SingleSpc, 4, 1 ,false},
194{ ARM::VLD1d64QPseudoWB_fixed, ARM::VLD1d64Qwb_fixed, true, true, false, SingleSpc, 4, 1 ,false},
195{ ARM::VLD1d64QPseudoWB_register, ARM::VLD1d64Qwb_register, true, true, true, SingleSpc, 4, 1 ,false},
196{ ARM::VLD1d64TPseudo, ARM::VLD1d64T, true, false, false, SingleSpc, 3, 1 ,false},
197{ ARM::VLD1d64TPseudoWB_fixed, ARM::VLD1d64Twb_fixed, true, true, false, SingleSpc, 3, 1 ,false},
198{ ARM::VLD1d64TPseudoWB_register, ARM::VLD1d64Twb_register, true, true, true, SingleSpc, 3, 1 ,false},
199
200{ ARM::VLD1d8QPseudo, ARM::VLD1d8Q, true, false, false, SingleSpc, 4, 8 ,false},
201{ ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d8Qwb_fixed, true, true, false, SingleSpc, 4, 8 ,false},
202{ ARM::VLD1d8QPseudoWB_register, ARM::VLD1d8Qwb_register, true, true, true, SingleSpc, 4, 8 ,false},
203{ ARM::VLD1d8TPseudo, ARM::VLD1d8T, true, false, false, SingleSpc, 3, 8 ,false},
204{ ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d8Twb_fixed, true, true, false, SingleSpc, 3, 8 ,false},
205{ ARM::VLD1d8TPseudoWB_register, ARM::VLD1d8Twb_register, true, true, true, SingleSpc, 3, 8 ,false},
206
207{ ARM::VLD1q16HighQPseudo, ARM::VLD1d16Q, true, false, false, SingleHighQSpc, 4, 4 ,false},
208{ ARM::VLD1q16HighQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleHighQSpc, 4, 4 ,false},
209{ ARM::VLD1q16HighTPseudo, ARM::VLD1d16T, true, false, false, SingleHighTSpc, 3, 4 ,false},
210{ ARM::VLD1q16HighTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleHighTSpc, 3, 4 ,false},
211{ ARM::VLD1q16LowQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleLowSpc, 4, 4 ,false},
212{ ARM::VLD1q16LowTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleLowSpc, 3, 4 ,false},
213
214{ ARM::VLD1q32HighQPseudo, ARM::VLD1d32Q, true, false, false, SingleHighQSpc, 4, 2 ,false},
215{ ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleHighQSpc, 4, 2 ,false},
216{ ARM::VLD1q32HighTPseudo, ARM::VLD1d32T, true, false, false, SingleHighTSpc, 3, 2 ,false},
217{ ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleHighTSpc, 3, 2 ,false},
218{ ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleLowSpc, 4, 2 ,false},
219{ ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleLowSpc, 3, 2 ,false},
220
221{ ARM::VLD1q64HighQPseudo, ARM::VLD1d64Q, true, false, false, SingleHighQSpc, 4, 1 ,false},
222{ ARM::VLD1q64HighQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleHighQSpc, 4, 1 ,false},
223{ ARM::VLD1q64HighTPseudo, ARM::VLD1d64T, true, false, false, SingleHighTSpc, 3, 1 ,false},
224{ ARM::VLD1q64HighTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleHighTSpc, 3, 1 ,false},
225{ ARM::VLD1q64LowQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleLowSpc, 4, 1 ,false},
226{ ARM::VLD1q64LowTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleLowSpc, 3, 1 ,false},
227
228{ ARM::VLD1q8HighQPseudo, ARM::VLD1d8Q, true, false, false, SingleHighQSpc, 4, 8 ,false},
229{ ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleHighQSpc, 4, 8 ,false},
230{ ARM::VLD1q8HighTPseudo, ARM::VLD1d8T, true, false, false, SingleHighTSpc, 3, 8 ,false},
231{ ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleHighTSpc, 3, 8 ,false},
232{ ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleLowSpc, 4, 8 ,false},
233{ ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleLowSpc, 3, 8 ,false},
234
235{ ARM::VLD2DUPq16EvenPseudo, ARM::VLD2DUPd16x2, true, false, false, EvenDblSpc, 2, 4 ,false},
236{ ARM::VLD2DUPq16OddPseudo, ARM::VLD2DUPd16x2, true, false, false, OddDblSpc, 2, 4 ,false},
237{ ARM::VLD2DUPq16OddPseudoWB_fixed, ARM::VLD2DUPd16x2wb_fixed, true, true, false, OddDblSpc, 2, 4 ,false},
238{ ARM::VLD2DUPq16OddPseudoWB_register, ARM::VLD2DUPd16x2wb_register, true, true, true, OddDblSpc, 2, 4 ,false},
239{ ARM::VLD2DUPq32EvenPseudo, ARM::VLD2DUPd32x2, true, false, false, EvenDblSpc, 2, 2 ,false},
240{ ARM::VLD2DUPq32OddPseudo, ARM::VLD2DUPd32x2, true, false, false, OddDblSpc, 2, 2 ,false},
241{ ARM::VLD2DUPq32OddPseudoWB_fixed, ARM::VLD2DUPd32x2wb_fixed, true, true, false, OddDblSpc, 2, 2 ,false},
242{ ARM::VLD2DUPq32OddPseudoWB_register, ARM::VLD2DUPd32x2wb_register, true, true, true, OddDblSpc, 2, 2 ,false},
243{ ARM::VLD2DUPq8EvenPseudo, ARM::VLD2DUPd8x2, true, false, false, EvenDblSpc, 2, 8 ,false},
244{ ARM::VLD2DUPq8OddPseudo, ARM::VLD2DUPd8x2, true, false, false, OddDblSpc, 2, 8 ,false},
245{ ARM::VLD2DUPq8OddPseudoWB_fixed, ARM::VLD2DUPd8x2wb_fixed, true, true, false, OddDblSpc, 2, 8 ,false},
246{ ARM::VLD2DUPq8OddPseudoWB_register, ARM::VLD2DUPd8x2wb_register, true, true, true, OddDblSpc, 2, 8 ,false},
247
248{ ARM::VLD2LNd16Pseudo, ARM::VLD2LNd16, true, false, false, SingleSpc, 2, 4 ,true},
249{ ARM::VLD2LNd16Pseudo_UPD, ARM::VLD2LNd16_UPD, true, true, true, SingleSpc, 2, 4 ,true},
250{ ARM::VLD2LNd32Pseudo, ARM::VLD2LNd32, true, false, false, SingleSpc, 2, 2 ,true},
251{ ARM::VLD2LNd32Pseudo_UPD, ARM::VLD2LNd32_UPD, true, true, true, SingleSpc, 2, 2 ,true},
252{ ARM::VLD2LNd8Pseudo, ARM::VLD2LNd8, true, false, false, SingleSpc, 2, 8 ,true},
253{ ARM::VLD2LNd8Pseudo_UPD, ARM::VLD2LNd8_UPD, true, true, true, SingleSpc, 2, 8 ,true},
254{ ARM::VLD2LNq16Pseudo, ARM::VLD2LNq16, true, false, false, EvenDblSpc, 2, 4 ,true},
255{ ARM::VLD2LNq16Pseudo_UPD, ARM::VLD2LNq16_UPD, true, true, true, EvenDblSpc, 2, 4 ,true},
256{ ARM::VLD2LNq32Pseudo, ARM::VLD2LNq32, true, false, false, EvenDblSpc, 2, 2 ,true},
257{ ARM::VLD2LNq32Pseudo_UPD, ARM::VLD2LNq32_UPD, true, true, true, EvenDblSpc, 2, 2 ,true},
258
259{ ARM::VLD2q16Pseudo, ARM::VLD2q16, true, false, false, SingleSpc, 4, 4 ,false},
260{ ARM::VLD2q16PseudoWB_fixed, ARM::VLD2q16wb_fixed, true, true, false, SingleSpc, 4, 4 ,false},
261{ ARM::VLD2q16PseudoWB_register, ARM::VLD2q16wb_register, true, true, true, SingleSpc, 4, 4 ,false},
262{ ARM::VLD2q32Pseudo, ARM::VLD2q32, true, false, false, SingleSpc, 4, 2 ,false},
263{ ARM::VLD2q32PseudoWB_fixed, ARM::VLD2q32wb_fixed, true, true, false, SingleSpc, 4, 2 ,false},
264{ ARM::VLD2q32PseudoWB_register, ARM::VLD2q32wb_register, true, true, true, SingleSpc, 4, 2 ,false},
265{ ARM::VLD2q8Pseudo, ARM::VLD2q8, true, false, false, SingleSpc, 4, 8 ,false},
266{ ARM::VLD2q8PseudoWB_fixed, ARM::VLD2q8wb_fixed, true, true, false, SingleSpc, 4, 8 ,false},
267{ ARM::VLD2q8PseudoWB_register, ARM::VLD2q8wb_register, true, true, true, SingleSpc, 4, 8 ,false},
268
269{ ARM::VLD3DUPd16Pseudo, ARM::VLD3DUPd16, true, false, false, SingleSpc, 3, 4,true},
270{ ARM::VLD3DUPd16Pseudo_UPD, ARM::VLD3DUPd16_UPD, true, true, true, SingleSpc, 3, 4,true},
271{ ARM::VLD3DUPd32Pseudo, ARM::VLD3DUPd32, true, false, false, SingleSpc, 3, 2,true},
272{ ARM::VLD3DUPd32Pseudo_UPD, ARM::VLD3DUPd32_UPD, true, true, true, SingleSpc, 3, 2,true},
273{ ARM::VLD3DUPd8Pseudo, ARM::VLD3DUPd8, true, false, false, SingleSpc, 3, 8,true},
274{ ARM::VLD3DUPd8Pseudo_UPD, ARM::VLD3DUPd8_UPD, true, true, true, SingleSpc, 3, 8,true},
275{ ARM::VLD3DUPq16EvenPseudo, ARM::VLD3DUPq16, true, false, false, EvenDblSpc, 3, 4 ,true},
276{ ARM::VLD3DUPq16OddPseudo, ARM::VLD3DUPq16, true, false, false, OddDblSpc, 3, 4 ,true},
277{ ARM::VLD3DUPq16OddPseudo_UPD, ARM::VLD3DUPq16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},
278{ ARM::VLD3DUPq32EvenPseudo, ARM::VLD3DUPq32, true, false, false, EvenDblSpc, 3, 2 ,true},
279{ ARM::VLD3DUPq32OddPseudo, ARM::VLD3DUPq32, true, false, false, OddDblSpc, 3, 2 ,true},
280{ ARM::VLD3DUPq32OddPseudo_UPD, ARM::VLD3DUPq32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},
281{ ARM::VLD3DUPq8EvenPseudo, ARM::VLD3DUPq8, true, false, false, EvenDblSpc, 3, 8 ,true},
282{ ARM::VLD3DUPq8OddPseudo, ARM::VLD3DUPq8, true, false, false, OddDblSpc, 3, 8 ,true},
283{ ARM::VLD3DUPq8OddPseudo_UPD, ARM::VLD3DUPq8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},
284
285{ ARM::VLD3LNd16Pseudo, ARM::VLD3LNd16, true, false, false, SingleSpc, 3, 4 ,true},
286{ ARM::VLD3LNd16Pseudo_UPD, ARM::VLD3LNd16_UPD, true, true, true, SingleSpc, 3, 4 ,true},
287{ ARM::VLD3LNd32Pseudo, ARM::VLD3LNd32, true, false, false, SingleSpc, 3, 2 ,true},
288{ ARM::VLD3LNd32Pseudo_UPD, ARM::VLD3LNd32_UPD, true, true, true, SingleSpc, 3, 2 ,true},
289{ ARM::VLD3LNd8Pseudo, ARM::VLD3LNd8, true, false, false, SingleSpc, 3, 8 ,true},
290{ ARM::VLD3LNd8Pseudo_UPD, ARM::VLD3LNd8_UPD, true, true, true, SingleSpc, 3, 8 ,true},
291{ ARM::VLD3LNq16Pseudo, ARM::VLD3LNq16, true, false, false, EvenDblSpc, 3, 4 ,true},
292{ ARM::VLD3LNq16Pseudo_UPD, ARM::VLD3LNq16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},
293{ ARM::VLD3LNq32Pseudo, ARM::VLD3LNq32, true, false, false, EvenDblSpc, 3, 2 ,true},
294{ ARM::VLD3LNq32Pseudo_UPD, ARM::VLD3LNq32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},
295
296{ ARM::VLD3d16Pseudo, ARM::VLD3d16, true, false, false, SingleSpc, 3, 4 ,true},
297{ ARM::VLD3d16Pseudo_UPD, ARM::VLD3d16_UPD, true, true, true, SingleSpc, 3, 4 ,true},
298{ ARM::VLD3d32Pseudo, ARM::VLD3d32, true, false, false, SingleSpc, 3, 2 ,true},
299{ ARM::VLD3d32Pseudo_UPD, ARM::VLD3d32_UPD, true, true, true, SingleSpc, 3, 2 ,true},
300{ ARM::VLD3d8Pseudo, ARM::VLD3d8, true, false, false, SingleSpc, 3, 8 ,true},
301{ ARM::VLD3d8Pseudo_UPD, ARM::VLD3d8_UPD, true, true, true, SingleSpc, 3, 8 ,true},
302
303{ ARM::VLD3q16Pseudo_UPD, ARM::VLD3q16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},
304{ ARM::VLD3q16oddPseudo, ARM::VLD3q16, true, false, false, OddDblSpc, 3, 4 ,true},
305{ ARM::VLD3q16oddPseudo_UPD, ARM::VLD3q16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},
306{ ARM::VLD3q32Pseudo_UPD, ARM::VLD3q32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},
307{ ARM::VLD3q32oddPseudo, ARM::VLD3q32, true, false, false, OddDblSpc, 3, 2 ,true},
308{ ARM::VLD3q32oddPseudo_UPD, ARM::VLD3q32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},
309{ ARM::VLD3q8Pseudo_UPD, ARM::VLD3q8_UPD, true, true, true, EvenDblSpc, 3, 8 ,true},
310{ ARM::VLD3q8oddPseudo, ARM::VLD3q8, true, false, false, OddDblSpc, 3, 8 ,true},
311{ ARM::VLD3q8oddPseudo_UPD, ARM::VLD3q8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},
312
313{ ARM::VLD4DUPd16Pseudo, ARM::VLD4DUPd16, true, false, false, SingleSpc, 4, 4,true},
314{ ARM::VLD4DUPd16Pseudo_UPD, ARM::VLD4DUPd16_UPD, true, true, true, SingleSpc, 4, 4,true},
315{ ARM::VLD4DUPd32Pseudo, ARM::VLD4DUPd32, true, false, false, SingleSpc, 4, 2,true},
316{ ARM::VLD4DUPd32Pseudo_UPD, ARM::VLD4DUPd32_UPD, true, true, true, SingleSpc, 4, 2,true},
317{ ARM::VLD4DUPd8Pseudo, ARM::VLD4DUPd8, true, false, false, SingleSpc, 4, 8,true},
318{ ARM::VLD4DUPd8Pseudo_UPD, ARM::VLD4DUPd8_UPD, true, true, true, SingleSpc, 4, 8,true},
319{ ARM::VLD4DUPq16EvenPseudo, ARM::VLD4DUPq16, true, false, false, EvenDblSpc, 4, 4 ,true},
320{ ARM::VLD4DUPq16OddPseudo, ARM::VLD4DUPq16, true, false, false, OddDblSpc, 4, 4 ,true},
321{ ARM::VLD4DUPq16OddPseudo_UPD, ARM::VLD4DUPq16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},
322{ ARM::VLD4DUPq32EvenPseudo, ARM::VLD4DUPq32, true, false, false, EvenDblSpc, 4, 2 ,true},
323{ ARM::VLD4DUPq32OddPseudo, ARM::VLD4DUPq32, true, false, false, OddDblSpc, 4, 2 ,true},
324{ ARM::VLD4DUPq32OddPseudo_UPD, ARM::VLD4DUPq32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},
325{ ARM::VLD4DUPq8EvenPseudo, ARM::VLD4DUPq8, true, false, false, EvenDblSpc, 4, 8 ,true},
326{ ARM::VLD4DUPq8OddPseudo, ARM::VLD4DUPq8, true, false, false, OddDblSpc, 4, 8 ,true},
327{ ARM::VLD4DUPq8OddPseudo_UPD, ARM::VLD4DUPq8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},
328
329{ ARM::VLD4LNd16Pseudo, ARM::VLD4LNd16, true, false, false, SingleSpc, 4, 4 ,true},
330{ ARM::VLD4LNd16Pseudo_UPD, ARM::VLD4LNd16_UPD, true, true, true, SingleSpc, 4, 4 ,true},
331{ ARM::VLD4LNd32Pseudo, ARM::VLD4LNd32, true, false, false, SingleSpc, 4, 2 ,true},
332{ ARM::VLD4LNd32Pseudo_UPD, ARM::VLD4LNd32_UPD, true, true, true, SingleSpc, 4, 2 ,true},
333{ ARM::VLD4LNd8Pseudo, ARM::VLD4LNd8, true, false, false, SingleSpc, 4, 8 ,true},
334{ ARM::VLD4LNd8Pseudo_UPD, ARM::VLD4LNd8_UPD, true, true, true, SingleSpc, 4, 8 ,true},
335{ ARM::VLD4LNq16Pseudo, ARM::VLD4LNq16, true, false, false, EvenDblSpc, 4, 4 ,true},
336{ ARM::VLD4LNq16Pseudo_UPD, ARM::VLD4LNq16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},
337{ ARM::VLD4LNq32Pseudo, ARM::VLD4LNq32, true, false, false, EvenDblSpc, 4, 2 ,true},
338{ ARM::VLD4LNq32Pseudo_UPD, ARM::VLD4LNq32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},
339
340{ ARM::VLD4d16Pseudo, ARM::VLD4d16, true, false, false, SingleSpc, 4, 4 ,true},
341{ ARM::VLD4d16Pseudo_UPD, ARM::VLD4d16_UPD, true, true, true, SingleSpc, 4, 4 ,true},
342{ ARM::VLD4d32Pseudo, ARM::VLD4d32, true, false, false, SingleSpc, 4, 2 ,true},
343{ ARM::VLD4d32Pseudo_UPD, ARM::VLD4d32_UPD, true, true, true, SingleSpc, 4, 2 ,true},
344{ ARM::VLD4d8Pseudo, ARM::VLD4d8, true, false, false, SingleSpc, 4, 8 ,true},
345{ ARM::VLD4d8Pseudo_UPD, ARM::VLD4d8_UPD, true, true, true, SingleSpc, 4, 8 ,true},
346
347{ ARM::VLD4q16Pseudo_UPD, ARM::VLD4q16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},
348{ ARM::VLD4q16oddPseudo, ARM::VLD4q16, true, false, false, OddDblSpc, 4, 4 ,true},
349{ ARM::VLD4q16oddPseudo_UPD, ARM::VLD4q16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},
350{ ARM::VLD4q32Pseudo_UPD, ARM::VLD4q32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},
351{ ARM::VLD4q32oddPseudo, ARM::VLD4q32, true, false, false, OddDblSpc, 4, 2 ,true},
352{ ARM::VLD4q32oddPseudo_UPD, ARM::VLD4q32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},
353{ ARM::VLD4q8Pseudo_UPD, ARM::VLD4q8_UPD, true, true, true, EvenDblSpc, 4, 8 ,true},
354{ ARM::VLD4q8oddPseudo, ARM::VLD4q8, true, false, false, OddDblSpc, 4, 8 ,true},
355{ ARM::VLD4q8oddPseudo_UPD, ARM::VLD4q8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},
356
357{ ARM::VST1LNq16Pseudo, ARM::VST1LNd16, false, false, false, EvenDblSpc, 1, 4 ,true},
358{ ARM::VST1LNq16Pseudo_UPD, ARM::VST1LNd16_UPD, false, true, true, EvenDblSpc, 1, 4 ,true},
359{ ARM::VST1LNq32Pseudo, ARM::VST1LNd32, false, false, false, EvenDblSpc, 1, 2 ,true},
360{ ARM::VST1LNq32Pseudo_UPD, ARM::VST1LNd32_UPD, false, true, true, EvenDblSpc, 1, 2 ,true},
361{ ARM::VST1LNq8Pseudo, ARM::VST1LNd8, false, false, false, EvenDblSpc, 1, 8 ,true},
362{ ARM::VST1LNq8Pseudo_UPD, ARM::VST1LNd8_UPD, false, true, true, EvenDblSpc, 1, 8 ,true},
363
364{ ARM::VST1d16QPseudo, ARM::VST1d16Q, false, false, false, SingleSpc, 4, 4 ,false},
365{ ARM::VST1d16QPseudoWB_fixed, ARM::VST1d16Qwb_fixed, false, true, false, SingleSpc, 4, 4 ,false},
366{ ARM::VST1d16QPseudoWB_register, ARM::VST1d16Qwb_register, false, true, true, SingleSpc, 4, 4 ,false},
367{ ARM::VST1d16TPseudo, ARM::VST1d16T, false, false, false, SingleSpc, 3, 4 ,false},
368{ ARM::VST1d16TPseudoWB_fixed, ARM::VST1d16Twb_fixed, false, true, false, SingleSpc, 3, 4 ,false},
369{ ARM::VST1d16TPseudoWB_register, ARM::VST1d16Twb_register, false, true, true, SingleSpc, 3, 4 ,false},
370
371{ ARM::VST1d32QPseudo, ARM::VST1d32Q, false, false, false, SingleSpc, 4, 2 ,false},
372{ ARM::VST1d32QPseudoWB_fixed, ARM::VST1d32Qwb_fixed, false, true, false, SingleSpc, 4, 2 ,false},
373{ ARM::VST1d32QPseudoWB_register, ARM::VST1d32Qwb_register, false, true, true, SingleSpc, 4, 2 ,false},
374{ ARM::VST1d32TPseudo, ARM::VST1d32T, false, false, false, SingleSpc, 3, 2 ,false},
375{ ARM::VST1d32TPseudoWB_fixed, ARM::VST1d32Twb_fixed, false, true, false, SingleSpc, 3, 2 ,false},
376{ ARM::VST1d32TPseudoWB_register, ARM::VST1d32Twb_register, false, true, true, SingleSpc, 3, 2 ,false},
377
378{ ARM::VST1d64QPseudo, ARM::VST1d64Q, false, false, false, SingleSpc, 4, 1 ,false},
379{ ARM::VST1d64QPseudoWB_fixed, ARM::VST1d64Qwb_fixed, false, true, false, SingleSpc, 4, 1 ,false},
380{ ARM::VST1d64QPseudoWB_register, ARM::VST1d64Qwb_register, false, true, true, SingleSpc, 4, 1 ,false},
381{ ARM::VST1d64TPseudo, ARM::VST1d64T, false, false, false, SingleSpc, 3, 1 ,false},
382{ ARM::VST1d64TPseudoWB_fixed, ARM::VST1d64Twb_fixed, false, true, false, SingleSpc, 3, 1 ,false},
383{ ARM::VST1d64TPseudoWB_register, ARM::VST1d64Twb_register, false, true, true, SingleSpc, 3, 1 ,false},
384
385{ ARM::VST1d8QPseudo, ARM::VST1d8Q, false, false, false, SingleSpc, 4, 8 ,false},
386{ ARM::VST1d8QPseudoWB_fixed, ARM::VST1d8Qwb_fixed, false, true, false, SingleSpc, 4, 8 ,false},
387{ ARM::VST1d8QPseudoWB_register, ARM::VST1d8Qwb_register, false, true, true, SingleSpc, 4, 8 ,false},
388{ ARM::VST1d8TPseudo, ARM::VST1d8T, false, false, false, SingleSpc, 3, 8 ,false},
389{ ARM::VST1d8TPseudoWB_fixed, ARM::VST1d8Twb_fixed, false, true, false, SingleSpc, 3, 8 ,false},
390{ ARM::VST1d8TPseudoWB_register, ARM::VST1d8Twb_register, false, true, true, SingleSpc, 3, 8 ,false},
391
392{ ARM::VST1q16HighQPseudo, ARM::VST1d16Q, false, false, false, SingleHighQSpc, 4, 4 ,false},
393{ ARM::VST1q16HighQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},
394{ ARM::VST1q16HighTPseudo, ARM::VST1d16T, false, false, false, SingleHighTSpc, 3, 4 ,false},
395{ ARM::VST1q16HighTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleHighTSpc, 3, 4 ,false},
396{ ARM::VST1q16LowQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleLowSpc, 4, 4 ,false},
397{ ARM::VST1q16LowTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleLowSpc, 3, 4 ,false},
398
399{ ARM::VST1q32HighQPseudo, ARM::VST1d32Q, false, false, false, SingleHighQSpc, 4, 2 ,false},
400{ ARM::VST1q32HighQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},
401{ ARM::VST1q32HighTPseudo, ARM::VST1d32T, false, false, false, SingleHighTSpc, 3, 2 ,false},
402{ ARM::VST1q32HighTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleHighTSpc, 3, 2 ,false},
403{ ARM::VST1q32LowQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleLowSpc, 4, 2 ,false},
404{ ARM::VST1q32LowTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleLowSpc, 3, 2 ,false},
405
406{ ARM::VST1q64HighQPseudo, ARM::VST1d64Q, false, false, false, SingleHighQSpc, 4, 1 ,false},
407{ ARM::VST1q64HighQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},
408{ ARM::VST1q64HighTPseudo, ARM::VST1d64T, false, false, false, SingleHighTSpc, 3, 1 ,false},
409{ ARM::VST1q64HighTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleHighTSpc, 3, 1 ,false},
410{ ARM::VST1q64LowQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleLowSpc, 4, 1 ,false},
411{ ARM::VST1q64LowTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleLowSpc, 3, 1 ,false},
412
413{ ARM::VST1q8HighQPseudo, ARM::VST1d8Q, false, false, false, SingleHighQSpc, 4, 8 ,false},
414{ ARM::VST1q8HighQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},
415{ ARM::VST1q8HighTPseudo, ARM::VST1d8T, false, false, false, SingleHighTSpc, 3, 8 ,false},
416{ ARM::VST1q8HighTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleHighTSpc, 3, 8 ,false},
417{ ARM::VST1q8LowQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleLowSpc, 4, 8 ,false},
418{ ARM::VST1q8LowTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleLowSpc, 3, 8 ,false},
419
420{ ARM::VST2LNd16Pseudo, ARM::VST2LNd16, false, false, false, SingleSpc, 2, 4 ,true},
421{ ARM::VST2LNd16Pseudo_UPD, ARM::VST2LNd16_UPD, false, true, true, SingleSpc, 2, 4 ,true},
422{ ARM::VST2LNd32Pseudo, ARM::VST2LNd32, false, false, false, SingleSpc, 2, 2 ,true},
423{ ARM::VST2LNd32Pseudo_UPD, ARM::VST2LNd32_UPD, false, true, true, SingleSpc, 2, 2 ,true},
424{ ARM::VST2LNd8Pseudo, ARM::VST2LNd8, false, false, false, SingleSpc, 2, 8 ,true},
425{ ARM::VST2LNd8Pseudo_UPD, ARM::VST2LNd8_UPD, false, true, true, SingleSpc, 2, 8 ,true},
426{ ARM::VST2LNq16Pseudo, ARM::VST2LNq16, false, false, false, EvenDblSpc, 2, 4,true},
427{ ARM::VST2LNq16Pseudo_UPD, ARM::VST2LNq16_UPD, false, true, true, EvenDblSpc, 2, 4,true},
428{ ARM::VST2LNq32Pseudo, ARM::VST2LNq32, false, false, false, EvenDblSpc, 2, 2,true},
429{ ARM::VST2LNq32Pseudo_UPD, ARM::VST2LNq32_UPD, false, true, true, EvenDblSpc, 2, 2,true},
430
431{ ARM::VST2q16Pseudo, ARM::VST2q16, false, false, false, SingleSpc, 4, 4 ,false},
432{ ARM::VST2q16PseudoWB_fixed, ARM::VST2q16wb_fixed, false, true, false, SingleSpc, 4, 4 ,false},
433{ ARM::VST2q16PseudoWB_register, ARM::VST2q16wb_register, false, true, true, SingleSpc, 4, 4 ,false},
434{ ARM::VST2q32Pseudo, ARM::VST2q32, false, false, false, SingleSpc, 4, 2 ,false},
435{ ARM::VST2q32PseudoWB_fixed, ARM::VST2q32wb_fixed, false, true, false, SingleSpc, 4, 2 ,false},
436{ ARM::VST2q32PseudoWB_register, ARM::VST2q32wb_register, false, true, true, SingleSpc, 4, 2 ,false},
437{ ARM::VST2q8Pseudo, ARM::VST2q8, false, false, false, SingleSpc, 4, 8 ,false},
438{ ARM::VST2q8PseudoWB_fixed, ARM::VST2q8wb_fixed, false, true, false, SingleSpc, 4, 8 ,false},
439{ ARM::VST2q8PseudoWB_register, ARM::VST2q8wb_register, false, true, true, SingleSpc, 4, 8 ,false},
440
441{ ARM::VST3LNd16Pseudo, ARM::VST3LNd16, false, false, false, SingleSpc, 3, 4 ,true},
442{ ARM::VST3LNd16Pseudo_UPD, ARM::VST3LNd16_UPD, false, true, true, SingleSpc, 3, 4 ,true},
443{ ARM::VST3LNd32Pseudo, ARM::VST3LNd32, false, false, false, SingleSpc, 3, 2 ,true},
444{ ARM::VST3LNd32Pseudo_UPD, ARM::VST3LNd32_UPD, false, true, true, SingleSpc, 3, 2 ,true},
445{ ARM::VST3LNd8Pseudo, ARM::VST3LNd8, false, false, false, SingleSpc, 3, 8 ,true},
446{ ARM::VST3LNd8Pseudo_UPD, ARM::VST3LNd8_UPD, false, true, true, SingleSpc, 3, 8 ,true},
447{ ARM::VST3LNq16Pseudo, ARM::VST3LNq16, false, false, false, EvenDblSpc, 3, 4,true},
448{ ARM::VST3LNq16Pseudo_UPD, ARM::VST3LNq16_UPD, false, true, true, EvenDblSpc, 3, 4,true},
449{ ARM::VST3LNq32Pseudo, ARM::VST3LNq32, false, false, false, EvenDblSpc, 3, 2,true},
450{ ARM::VST3LNq32Pseudo_UPD, ARM::VST3LNq32_UPD, false, true, true, EvenDblSpc, 3, 2,true},
451
452{ ARM::VST3d16Pseudo, ARM::VST3d16, false, false, false, SingleSpc, 3, 4 ,true},
453{ ARM::VST3d16Pseudo_UPD, ARM::VST3d16_UPD, false, true, true, SingleSpc, 3, 4 ,true},
454{ ARM::VST3d32Pseudo, ARM::VST3d32, false, false, false, SingleSpc, 3, 2 ,true},
455{ ARM::VST3d32Pseudo_UPD, ARM::VST3d32_UPD, false, true, true, SingleSpc, 3, 2 ,true},
456{ ARM::VST3d8Pseudo, ARM::VST3d8, false, false, false, SingleSpc, 3, 8 ,true},
457{ ARM::VST3d8Pseudo_UPD, ARM::VST3d8_UPD, false, true, true, SingleSpc, 3, 8 ,true},
458
459{ ARM::VST3q16Pseudo_UPD, ARM::VST3q16_UPD, false, true, true, EvenDblSpc, 3, 4 ,true},
460{ ARM::VST3q16oddPseudo, ARM::VST3q16, false, false, false, OddDblSpc, 3, 4 ,true},
461{ ARM::VST3q16oddPseudo_UPD, ARM::VST3q16_UPD, false, true, true, OddDblSpc, 3, 4 ,true},
462{ ARM::VST3q32Pseudo_UPD, ARM::VST3q32_UPD, false, true, true, EvenDblSpc, 3, 2 ,true},
463{ ARM::VST3q32oddPseudo, ARM::VST3q32, false, false, false, OddDblSpc, 3, 2 ,true},
464{ ARM::VST3q32oddPseudo_UPD, ARM::VST3q32_UPD, false, true, true, OddDblSpc, 3, 2 ,true},
465{ ARM::VST3q8Pseudo_UPD, ARM::VST3q8_UPD, false, true, true, EvenDblSpc, 3, 8 ,true},
466{ ARM::VST3q8oddPseudo, ARM::VST3q8, false, false, false, OddDblSpc, 3, 8 ,true},
467{ ARM::VST3q8oddPseudo_UPD, ARM::VST3q8_UPD, false, true, true, OddDblSpc, 3, 8 ,true},
468
469{ ARM::VST4LNd16Pseudo, ARM::VST4LNd16, false, false, false, SingleSpc, 4, 4 ,true},
470{ ARM::VST4LNd16Pseudo_UPD, ARM::VST4LNd16_UPD, false, true, true, SingleSpc, 4, 4 ,true},
471{ ARM::VST4LNd32Pseudo, ARM::VST4LNd32, false, false, false, SingleSpc, 4, 2 ,true},
472{ ARM::VST4LNd32Pseudo_UPD, ARM::VST4LNd32_UPD, false, true, true, SingleSpc, 4, 2 ,true},
473{ ARM::VST4LNd8Pseudo, ARM::VST4LNd8, false, false, false, SingleSpc, 4, 8 ,true},
474{ ARM::VST4LNd8Pseudo_UPD, ARM::VST4LNd8_UPD, false, true, true, SingleSpc, 4, 8 ,true},
475{ ARM::VST4LNq16Pseudo, ARM::VST4LNq16, false, false, false, EvenDblSpc, 4, 4,true},
476{ ARM::VST4LNq16Pseudo_UPD, ARM::VST4LNq16_UPD, false, true, true, EvenDblSpc, 4, 4,true},
477{ ARM::VST4LNq32Pseudo, ARM::VST4LNq32, false, false, false, EvenDblSpc, 4, 2,true},
478{ ARM::VST4LNq32Pseudo_UPD, ARM::VST4LNq32_UPD, false, true, true, EvenDblSpc, 4, 2,true},
479
480{ ARM::VST4d16Pseudo, ARM::VST4d16, false, false, false, SingleSpc, 4, 4 ,true},
481{ ARM::VST4d16Pseudo_UPD, ARM::VST4d16_UPD, false, true, true, SingleSpc, 4, 4 ,true},
482{ ARM::VST4d32Pseudo, ARM::VST4d32, false, false, false, SingleSpc, 4, 2 ,true},
483{ ARM::VST4d32Pseudo_UPD, ARM::VST4d32_UPD, false, true, true, SingleSpc, 4, 2 ,true},
484{ ARM::VST4d8Pseudo, ARM::VST4d8, false, false, false, SingleSpc, 4, 8 ,true},
485{ ARM::VST4d8Pseudo_UPD, ARM::VST4d8_UPD, false, true, true, SingleSpc, 4, 8 ,true},
486
487{ ARM::VST4q16Pseudo_UPD, ARM::VST4q16_UPD, false, true, true, EvenDblSpc, 4, 4 ,true},
488{ ARM::VST4q16oddPseudo, ARM::VST4q16, false, false, false, OddDblSpc, 4, 4 ,true},
489{ ARM::VST4q16oddPseudo_UPD, ARM::VST4q16_UPD, false, true, true, OddDblSpc, 4, 4 ,true},
490{ ARM::VST4q32Pseudo_UPD, ARM::VST4q32_UPD, false, true, true, EvenDblSpc, 4, 2 ,true},
491{ ARM::VST4q32oddPseudo, ARM::VST4q32, false, false, false, OddDblSpc, 4, 2 ,true},
492{ ARM::VST4q32oddPseudo_UPD, ARM::VST4q32_UPD, false, true, true, OddDblSpc, 4, 2 ,true},
493{ ARM::VST4q8Pseudo_UPD, ARM::VST4q8_UPD, false, true, true, EvenDblSpc, 4, 8 ,true},
494{ ARM::VST4q8oddPseudo, ARM::VST4q8, false, false, false, OddDblSpc, 4, 8 ,true},
495{ ARM::VST4q8oddPseudo_UPD, ARM::VST4q8_UPD, false, true, true, OddDblSpc, 4, 8 ,true}
496};
497
498/// LookupNEONLdSt - Search the NEONLdStTable for information about a NEON
499/// load or store pseudo instruction.
500static const NEONLdStTableEntry *LookupNEONLdSt(unsigned Opcode) {
501#ifndef NDEBUG
502 // Make sure the table is sorted.
503 static std::atomic<bool> TableChecked(false);
504 if (!TableChecked.load(std::memory_order_relaxed)) {
505 assert(llvm::is_sorted(NEONLdStTable) && "NEONLdStTable is not sorted!");
506 TableChecked.store(true, std::memory_order_relaxed);
507 }
508#endif
509
510 auto I = llvm::lower_bound(NEONLdStTable, Opcode);
511 if (I != std::end(NEONLdStTable) && I->PseudoOpc == Opcode)
512 return I;
513 return nullptr;
514}
515
516/// GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register,
517/// corresponding to the specified register spacing. Not all of the results
518/// are necessarily valid, e.g., a Q register only has 2 D subregisters.
519static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc,
521 MCRegister &D1, MCRegister &D2, MCRegister &D3) {
522 if (RegSpc == SingleSpc || RegSpc == SingleLowSpc) {
523 D0 = TRI->getSubReg(Reg, ARM::dsub_0);
524 D1 = TRI->getSubReg(Reg, ARM::dsub_1);
525 D2 = TRI->getSubReg(Reg, ARM::dsub_2);
526 D3 = TRI->getSubReg(Reg, ARM::dsub_3);
527 } else if (RegSpc == SingleHighQSpc) {
528 D0 = TRI->getSubReg(Reg, ARM::dsub_4);
529 D1 = TRI->getSubReg(Reg, ARM::dsub_5);
530 D2 = TRI->getSubReg(Reg, ARM::dsub_6);
531 D3 = TRI->getSubReg(Reg, ARM::dsub_7);
532 } else if (RegSpc == SingleHighTSpc) {
533 D0 = TRI->getSubReg(Reg, ARM::dsub_3);
534 D1 = TRI->getSubReg(Reg, ARM::dsub_4);
535 D2 = TRI->getSubReg(Reg, ARM::dsub_5);
536 D3 = TRI->getSubReg(Reg, ARM::dsub_6);
537 } else if (RegSpc == EvenDblSpc) {
538 D0 = TRI->getSubReg(Reg, ARM::dsub_0);
539 D1 = TRI->getSubReg(Reg, ARM::dsub_2);
540 D2 = TRI->getSubReg(Reg, ARM::dsub_4);
541 D3 = TRI->getSubReg(Reg, ARM::dsub_6);
542 } else {
543 assert(RegSpc == OddDblSpc && "unknown register spacing");
544 D0 = TRI->getSubReg(Reg, ARM::dsub_1);
545 D1 = TRI->getSubReg(Reg, ARM::dsub_3);
546 D2 = TRI->getSubReg(Reg, ARM::dsub_5);
547 D3 = TRI->getSubReg(Reg, ARM::dsub_7);
548 }
549}
550
551/// ExpandVLD - Translate VLD pseudo instructions with Q, QQ or QQQQ register
552/// operands to real VLD instructions with D register operands.
553void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) {
554 MachineInstr &MI = *MBBI;
555 MachineBasicBlock &MBB = *MI.getParent();
556 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
557
558 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
559 assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed");
560 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
561 unsigned NumRegs = TableEntry->NumRegs;
562
563 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
564 TII->get(TableEntry->RealOpc));
565 unsigned OpIdx = 0;
566
567 bool DstIsDead = MI.getOperand(OpIdx).isDead();
568 Register DstReg = MI.getOperand(OpIdx++).getReg();
569
570 bool IsVLD2DUP = TableEntry->RealOpc == ARM::VLD2DUPd8x2 ||
571 TableEntry->RealOpc == ARM::VLD2DUPd16x2 ||
572 TableEntry->RealOpc == ARM::VLD2DUPd32x2 ||
573 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||
574 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||
575 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed ||
576 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_register ||
577 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_register ||
578 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_register;
579
580 if (IsVLD2DUP) {
581 unsigned SubRegIndex;
582 if (RegSpc == EvenDblSpc) {
583 SubRegIndex = ARM::dsub_0;
584 } else {
585 assert(RegSpc == OddDblSpc && "Unexpected spacing!");
586 SubRegIndex = ARM::dsub_1;
587 }
588 Register SubReg = TRI->getSubReg(DstReg, SubRegIndex);
589 MCRegister DstRegPair =
590 TRI->getMatchingSuperReg(SubReg, ARM::dsub_0, &ARM::DPairSpcRegClass);
591 MIB.addReg(DstRegPair, RegState::Define | getDeadRegState(DstIsDead));
592 } else {
593 MCRegister D0, D1, D2, D3;
594 GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
595 MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));
596 if (NumRegs > 1 && TableEntry->copyAllListRegs)
597 MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
598 if (NumRegs > 2 && TableEntry->copyAllListRegs)
599 MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
600 if (NumRegs > 3 && TableEntry->copyAllListRegs)
601 MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
602 }
603
604 if (TableEntry->isUpdating)
605 MIB.add(MI.getOperand(OpIdx++));
606
607 // Copy the addrmode6 operands.
608 MIB.add(MI.getOperand(OpIdx++));
609 MIB.add(MI.getOperand(OpIdx++));
610
611 // Copy the am6offset operand.
612 if (TableEntry->hasWritebackOperand) {
613 // TODO: The writing-back pseudo instructions we translate here are all
614 // defined to take am6offset nodes that are capable to represent both fixed
615 // and register forms. Some real instructions, however, do not rely on
616 // am6offset and have separate definitions for such forms. When this is the
617 // case, fixed forms do not take any offset nodes, so here we skip them for
618 // such instructions. Once all real and pseudo writing-back instructions are
619 // rewritten without use of am6offset nodes, this code will go away.
620 const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);
621 if (TableEntry->RealOpc == ARM::VLD1d8Qwb_fixed ||
622 TableEntry->RealOpc == ARM::VLD1d16Qwb_fixed ||
623 TableEntry->RealOpc == ARM::VLD1d32Qwb_fixed ||
624 TableEntry->RealOpc == ARM::VLD1d64Qwb_fixed ||
625 TableEntry->RealOpc == ARM::VLD1d8Twb_fixed ||
626 TableEntry->RealOpc == ARM::VLD1d16Twb_fixed ||
627 TableEntry->RealOpc == ARM::VLD1d32Twb_fixed ||
628 TableEntry->RealOpc == ARM::VLD1d64Twb_fixed ||
629 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||
630 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||
631 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed) {
632 assert(AM6Offset.getReg() == 0 &&
633 "A fixed writing-back pseudo instruction provides an offset "
634 "register!");
635 } else {
636 MIB.add(AM6Offset);
637 }
638 }
639
640 // For an instruction writing double-spaced subregs, the pseudo instruction
641 // has an extra operand that is a use of the super-register. Record the
642 // operand index and skip over it.
643 unsigned SrcOpIdx = 0;
644 if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc || RegSpc == SingleLowSpc ||
645 RegSpc == SingleHighQSpc || RegSpc == SingleHighTSpc)
646 SrcOpIdx = OpIdx++;
647
648 // Copy the predicate operands.
649 MIB.add(MI.getOperand(OpIdx++));
650 MIB.add(MI.getOperand(OpIdx++));
651
652 // Copy the super-register source operand used for double-spaced subregs over
653 // to the new instruction as an implicit operand.
654 if (SrcOpIdx != 0) {
655 MachineOperand MO = MI.getOperand(SrcOpIdx);
656 MO.setImplicit(true);
657 MIB.add(MO);
658 }
659 // Add an implicit def for the super-register.
660 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
661 MIB.copyImplicitOps(MI);
662
663 // Transfer memoperands.
664 MIB.cloneMemRefs(MI);
665 MI.eraseFromParent();
666 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
667}
668
669/// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register
670/// operands to real VST instructions with D register operands.
671void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) {
672 MachineInstr &MI = *MBBI;
673 MachineBasicBlock &MBB = *MI.getParent();
674 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
675
676 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
677 assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed");
678 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
679 unsigned NumRegs = TableEntry->NumRegs;
680
681 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
682 TII->get(TableEntry->RealOpc));
683 unsigned OpIdx = 0;
684 if (TableEntry->isUpdating)
685 MIB.add(MI.getOperand(OpIdx++));
686
687 // Copy the addrmode6 operands.
688 MIB.add(MI.getOperand(OpIdx++));
689 MIB.add(MI.getOperand(OpIdx++));
690
691 if (TableEntry->hasWritebackOperand) {
692 // TODO: The writing-back pseudo instructions we translate here are all
693 // defined to take am6offset nodes that are capable to represent both fixed
694 // and register forms. Some real instructions, however, do not rely on
695 // am6offset and have separate definitions for such forms. When this is the
696 // case, fixed forms do not take any offset nodes, so here we skip them for
697 // such instructions. Once all real and pseudo writing-back instructions are
698 // rewritten without use of am6offset nodes, this code will go away.
699 const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);
700 if (TableEntry->RealOpc == ARM::VST1d8Qwb_fixed ||
701 TableEntry->RealOpc == ARM::VST1d16Qwb_fixed ||
702 TableEntry->RealOpc == ARM::VST1d32Qwb_fixed ||
703 TableEntry->RealOpc == ARM::VST1d64Qwb_fixed ||
704 TableEntry->RealOpc == ARM::VST1d8Twb_fixed ||
705 TableEntry->RealOpc == ARM::VST1d16Twb_fixed ||
706 TableEntry->RealOpc == ARM::VST1d32Twb_fixed ||
707 TableEntry->RealOpc == ARM::VST1d64Twb_fixed) {
708 assert(AM6Offset.getReg() == 0 &&
709 "A fixed writing-back pseudo instruction provides an offset "
710 "register!");
711 } else {
712 MIB.add(AM6Offset);
713 }
714 }
715
716 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
717 bool SrcIsUndef = MI.getOperand(OpIdx).isUndef();
718 Register SrcReg = MI.getOperand(OpIdx++).getReg();
719 MCRegister D0, D1, D2, D3;
720 GetDSubRegs(SrcReg, RegSpc, TRI, D0, D1, D2, D3);
721 MIB.addReg(D0, getUndefRegState(SrcIsUndef));
722 if (NumRegs > 1 && TableEntry->copyAllListRegs)
723 MIB.addReg(D1, getUndefRegState(SrcIsUndef));
724 if (NumRegs > 2 && TableEntry->copyAllListRegs)
725 MIB.addReg(D2, getUndefRegState(SrcIsUndef));
726 if (NumRegs > 3 && TableEntry->copyAllListRegs)
727 MIB.addReg(D3, getUndefRegState(SrcIsUndef));
728
729 // Copy the predicate operands.
730 MIB.add(MI.getOperand(OpIdx++));
731 MIB.add(MI.getOperand(OpIdx++));
732
733 if (SrcIsKill && !SrcIsUndef) // Add an implicit kill for the super-reg.
734 MIB->addRegisterKilled(SrcReg, TRI, true);
735 else if (!SrcIsUndef)
736 MIB.addReg(SrcReg, RegState::Implicit); // Add implicit uses for src reg.
737 MIB.copyImplicitOps(MI);
738
739 // Transfer memoperands.
740 MIB.cloneMemRefs(MI);
741 MI.eraseFromParent();
742 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
743}
744
745/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ
746/// register operands to real instructions with D register operands.
747void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) {
748 MachineInstr &MI = *MBBI;
749 MachineBasicBlock &MBB = *MI.getParent();
750 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
751
752 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
753 assert(TableEntry && "NEONLdStTable lookup failed");
754 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
755 unsigned NumRegs = TableEntry->NumRegs;
756 unsigned RegElts = TableEntry->RegElts;
757
758 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
759 TII->get(TableEntry->RealOpc));
760 unsigned OpIdx = 0;
761 // The lane operand is always the 3rd from last operand, before the 2
762 // predicate operands.
763 unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();
764
765 // Adjust the lane and spacing as needed for Q registers.
766 assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");
767 if (RegSpc == EvenDblSpc && Lane >= RegElts) {
768 RegSpc = OddDblSpc;
769 Lane -= RegElts;
770 }
771 assert(Lane < RegElts && "out of range lane for VLD/VST-lane");
772
773 MCRegister D0, D1, D2, D3;
774 unsigned DstReg = 0;
775 bool DstIsDead = false;
776 if (TableEntry->IsLoad) {
777 DstIsDead = MI.getOperand(OpIdx).isDead();
778 DstReg = MI.getOperand(OpIdx++).getReg();
779 GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
780 MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));
781 if (NumRegs > 1)
782 MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
783 if (NumRegs > 2)
784 MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
785 if (NumRegs > 3)
786 MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
787 }
788
789 if (TableEntry->isUpdating)
790 MIB.add(MI.getOperand(OpIdx++));
791
792 // Copy the addrmode6 operands.
793 MIB.add(MI.getOperand(OpIdx++));
794 MIB.add(MI.getOperand(OpIdx++));
795 // Copy the am6offset operand.
796 if (TableEntry->hasWritebackOperand)
797 MIB.add(MI.getOperand(OpIdx++));
798
799 // Grab the super-register source.
800 MachineOperand MO = MI.getOperand(OpIdx++);
801 if (!TableEntry->IsLoad)
802 GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3);
803
804 // Add the subregs as sources of the new instruction.
805 RegState SrcFlags =
807 MIB.addReg(D0, SrcFlags);
808 if (NumRegs > 1)
809 MIB.addReg(D1, SrcFlags);
810 if (NumRegs > 2)
811 MIB.addReg(D2, SrcFlags);
812 if (NumRegs > 3)
813 MIB.addReg(D3, SrcFlags);
814
815 // Add the lane number operand.
816 MIB.addImm(Lane);
817 OpIdx += 1;
818
819 // Copy the predicate operands.
820 MIB.add(MI.getOperand(OpIdx++));
821 MIB.add(MI.getOperand(OpIdx++));
822
823 // Copy the super-register source to be an implicit source.
824 MO.setImplicit(true);
825 MIB.add(MO);
826 if (TableEntry->IsLoad)
827 // Add an implicit def for the super-register.
828 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
829 MIB.copyImplicitOps(MI);
830 // Transfer memoperands.
831 MIB.cloneMemRefs(MI);
832 MI.eraseFromParent();
833}
834
835/// ExpandVTBL - Translate VTBL and VTBX pseudo instructions with Q or QQ
836/// register operands to real instructions with D register operands.
837void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,
838 unsigned Opc, bool IsExt) {
839 MachineInstr &MI = *MBBI;
840 MachineBasicBlock &MBB = *MI.getParent();
841 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
842
843 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));
844 unsigned OpIdx = 0;
845
846 // Transfer the destination register operand.
847 MIB.add(MI.getOperand(OpIdx++));
848 if (IsExt) {
849 MachineOperand VdSrc(MI.getOperand(OpIdx++));
850 MIB.add(VdSrc);
851 }
852
853 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
854 Register SrcReg = MI.getOperand(OpIdx++).getReg();
855 MCRegister D0, D1, D2, D3;
856 GetDSubRegs(SrcReg, SingleSpc, TRI, D0, D1, D2, D3);
857 MIB.addReg(D0);
858
859 // Copy the other source register operand.
860 MachineOperand VmSrc(MI.getOperand(OpIdx++));
861 MIB.add(VmSrc);
862
863 // Copy the predicate operands.
864 MIB.add(MI.getOperand(OpIdx++));
865 MIB.add(MI.getOperand(OpIdx++));
866
867 // Add an implicit kill and use for the super-reg.
868 MIB.addReg(SrcReg, RegState::Implicit | getKillRegState(SrcIsKill));
869 MIB.copyImplicitOps(MI);
870 MI.eraseFromParent();
871 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
872}
873
874void ARMExpandPseudo::ExpandMQQPRLoadStore(MachineBasicBlock::iterator &MBBI) {
875 MachineInstr &MI = *MBBI;
876 MachineBasicBlock &MBB = *MI.getParent();
877 unsigned NewOpc =
878 MI.getOpcode() == ARM::MQQPRStore || MI.getOpcode() == ARM::MQQQQPRStore
879 ? ARM::VSTMDIA
880 : ARM::VLDMDIA;
881 MachineInstrBuilder MIB =
882 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
883
884 RegState Flags = getKillRegState(MI.getOperand(0).isKill()) |
885 getDefRegState(MI.getOperand(0).isDef());
886 Register SrcReg = MI.getOperand(0).getReg();
887
888 // Copy the destination register.
889 MIB.add(MI.getOperand(1));
890 MIB.add(predOps(ARMCC::AL));
891 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_0), Flags);
892 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_1), Flags);
893 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_2), Flags);
894 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_3), Flags);
895 if (MI.getOpcode() == ARM::MQQQQPRStore ||
896 MI.getOpcode() == ARM::MQQQQPRLoad) {
897 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_4), Flags);
898 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_5), Flags);
899 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_6), Flags);
900 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_7), Flags);
901 }
902
903 if (NewOpc == ARM::VSTMDIA)
904 MIB.addReg(SrcReg, RegState::Implicit);
905
906 MIB.copyImplicitOps(MI);
907 MIB.cloneMemRefs(MI);
908 MI.eraseFromParent();
909}
910
911static bool IsAnAddressOperand(const MachineOperand &MO) {
912 // This check is overly conservative. Unless we are certain that the machine
913 // operand is not a symbol reference, we return that it is a symbol reference.
914 // This is important as the load pair may not be split up Windows.
915 switch (MO.getType()) {
921 return false;
923 return true;
925 return false;
932 return true;
936 return false;
939 return true;
942 return false;
945 llvm_unreachable("should not exist post-isel");
946 }
947 llvm_unreachable("unhandled machine operand type");
948}
949
951 MachineOperand NewMO = MO;
952 NewMO.setImplicit();
953 return NewMO;
954}
955
957 unsigned TargetFlag) {
958 unsigned TF = MO.getTargetFlags() | TargetFlag;
959 switch (MO.getType()) {
961 unsigned Imm = MO.getImm();
962 switch (TargetFlag) {
964 Imm = (Imm >> 24) & 0xff;
965 break;
966 case ARMII::MO_HI_0_7:
967 Imm = (Imm >> 16) & 0xff;
968 break;
970 Imm = (Imm >> 8) & 0xff;
971 break;
972 case ARMII::MO_LO_0_7:
973 Imm = Imm & 0xff;
974 break;
975 case ARMII::MO_HI16:
976 Imm = (Imm >> 16) & 0xffff;
977 break;
978 case ARMII::MO_LO16:
979 Imm = Imm & 0xffff;
980 break;
981 default:
982 llvm_unreachable("Only HI/LO target flags are expected");
983 }
984 return MachineOperand::CreateImm(Imm);
985 }
991 return MachineOperand::CreateJTI(MO.getIndex(), TF);
992 default:
993 return MachineOperand::CreateGA(MO.getGlobal(), MO.getOffset(), TF);
994 }
995}
996
997void ARMExpandPseudo::ExpandTMOV32BitImm(MachineBasicBlock &MBB,
999 MachineInstr &MI = *MBBI;
1000 Register DstReg = MI.getOperand(0).getReg();
1001 bool DstIsDead = MI.getOperand(0).isDead();
1002 const MachineOperand &MO = MI.getOperand(1);
1003 unsigned MIFlags = MI.getFlags();
1004
1005 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
1006
1007 // Expand the mov into a sequence of mov/add+lsl of the individual bytes. We
1008 // want to avoid emitting any zero bytes, as they won't change the result, and
1009 // also don't want any pointless shifts, so instead of immediately emitting
1010 // the shift for a byte we keep track of how much we will need to shift and do
1011 // it before the next nonzero byte.
1012 unsigned PendingShift = 0;
1013 for (unsigned Byte = 0; Byte < 4; ++Byte) {
1014 unsigned Flag = Byte == 0 ? ARMII::MO_HI_8_15
1015 : Byte == 1 ? ARMII::MO_HI_0_7
1016 : Byte == 2 ? ARMII::MO_LO_8_15
1018 MachineOperand Operand = getMovOperand(MO, Flag);
1019 bool ZeroImm = Operand.isImm() && Operand.getImm() == 0;
1020 unsigned Op = PendingShift ? ARM::tADDi8 : ARM::tMOVi8;
1021
1022 // Emit the pending shift if we're going to emit this byte or if we've
1023 // reached the end.
1024 if (PendingShift && (!ZeroImm || Byte == 3)) {
1025 MachineInstr *Lsl =
1026 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tLSLri), DstReg)
1027 .add(t1CondCodeOp(true))
1028 .addReg(DstReg)
1029 .addImm(PendingShift)
1031 .setMIFlags(MIFlags);
1032 (void)Lsl;
1033 LLVM_DEBUG(dbgs() << "And: "; Lsl->dump(););
1034 PendingShift = 0;
1035 }
1036
1037 // Emit this byte if it's nonzero.
1038 if (!ZeroImm) {
1039 MachineInstrBuilder MIB =
1040 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Op), DstReg)
1041 .add(t1CondCodeOp(true));
1042 if (Op == ARM::tADDi8)
1043 MIB.addReg(DstReg);
1044 MIB.add(Operand);
1045 MIB.add(predOps(ARMCC::AL));
1046 MIB.setMIFlags(MIFlags);
1047 LLVM_DEBUG(dbgs() << (Op == ARM::tMOVi8 ? "To: " : "And:") << " ";
1048 MIB.getInstr()->dump(););
1049 }
1050
1051 // Don't accumulate the shift value if we've not yet seen a nonzero byte.
1052 if (PendingShift || !ZeroImm)
1053 PendingShift += 8;
1054 }
1055
1056 // The dest is dead on the last instruction we emitted if it was dead on the
1057 // original instruction.
1058 (--MBBI)->getOperand(0).setIsDead(DstIsDead);
1059
1060 MI.eraseFromParent();
1061}
1062
1063void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,
1065 MachineInstr &MI = *MBBI;
1066 unsigned Opcode = MI.getOpcode();
1067 Register PredReg;
1068 ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
1069 Register DstReg = MI.getOperand(0).getReg();
1070 bool DstIsDead = MI.getOperand(0).isDead();
1071 bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;
1072 const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);
1073 bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO);
1074 MachineInstrBuilder LO16, HI16;
1075 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
1076
1077 if (!STI->hasV6T2Ops() &&
1078 (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) {
1079 // FIXME Windows CE supports older ARM CPUs
1080 assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+");
1081
1082 assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!");
1083 unsigned ImmVal = (unsigned)MO.getImm();
1084 unsigned SOImmValV1 = 0, SOImmValV2 = 0;
1085
1086 if (ARM_AM::isSOImmTwoPartVal(ImmVal)) { // Expand into a movi + orr.
1087 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg);
1088 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri))
1089 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1090 .addReg(DstReg);
1091 SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
1092 SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
1093 } else { // Expand into a mvn + sub.
1094 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), DstReg);
1095 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri))
1096 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1097 .addReg(DstReg);
1098 SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(-ImmVal);
1099 SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(-ImmVal);
1100 SOImmValV1 = ~(-SOImmValV1);
1101 }
1102
1103 unsigned MIFlags = MI.getFlags();
1104 LO16 = LO16.addImm(SOImmValV1);
1105 HI16 = HI16.addImm(SOImmValV2);
1106 LO16.cloneMemRefs(MI);
1107 HI16.cloneMemRefs(MI);
1108 LO16.setMIFlags(MIFlags);
1109 HI16.setMIFlags(MIFlags);
1110 LO16.addImm(Pred).addReg(PredReg).add(condCodeOp());
1111 HI16.addImm(Pred).addReg(PredReg).add(condCodeOp());
1112 if (isCC)
1113 LO16.add(makeImplicit(MI.getOperand(1)));
1114 LO16.copyImplicitOps(MI);
1115 HI16.copyImplicitOps(MI);
1116 MI.eraseFromParent();
1117 return;
1118 }
1119
1120 unsigned LO16Opc = 0;
1121 unsigned HI16Opc = 0;
1122 unsigned MIFlags = MI.getFlags();
1123 if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {
1124 LO16Opc = ARM::t2MOVi16;
1125 HI16Opc = ARM::t2MOVTi16;
1126 } else {
1127 LO16Opc = ARM::MOVi16;
1128 HI16Opc = ARM::MOVTi16;
1129 }
1130
1131 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg);
1132 LO16.setMIFlags(MIFlags);
1134 LO16.cloneMemRefs(MI);
1135 LO16.addImm(Pred).addReg(PredReg);
1136 if (isCC)
1137 LO16.add(makeImplicit(MI.getOperand(1)));
1138 LO16.copyImplicitOps(MI);
1139 LLVM_DEBUG(dbgs() << "To: "; LO16.getInstr()->dump(););
1140
1141 MachineOperand HIOperand = getMovOperand(MO, ARMII::MO_HI16);
1142 if (!(HIOperand.isImm() && HIOperand.getImm() == 0)) {
1143 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc))
1144 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1145 .addReg(DstReg);
1146 HI16.setMIFlags(MIFlags);
1147 HI16.add(HIOperand);
1148 HI16.cloneMemRefs(MI);
1149 HI16.addImm(Pred).addReg(PredReg);
1150 HI16.copyImplicitOps(MI);
1151 LLVM_DEBUG(dbgs() << "And: "; HI16.getInstr()->dump(););
1152 } else {
1153 LO16->getOperand(0).setIsDead(DstIsDead);
1154 }
1155
1156 if (RequiresBundling)
1157 finalizeBundle(MBB, LO16->getIterator(), MBBI->getIterator());
1158
1159 MI.eraseFromParent();
1160}
1161
1162// The size of the area, accessed by that VLSTM/VLLDM
1163// S0-S31 + FPSCR + 8 more bytes (VPR + pad, or just pad)
1164static const int CMSE_FP_SAVE_SIZE = 136;
1165
1167 const std::initializer_list<unsigned> &Regs,
1168 SmallVectorImpl<unsigned> &ClearRegs) {
1170 for (const MachineOperand &Op : MI.operands()) {
1171 if (!Op.isReg() || !Op.isUse())
1172 continue;
1173 OpRegs.push_back(Op.getReg());
1174 }
1175 llvm::sort(OpRegs);
1176
1177 std::set_difference(Regs.begin(), Regs.end(), OpRegs.begin(), OpRegs.end(),
1178 std::back_inserter(ClearRegs));
1179}
1180
1181void ARMExpandPseudo::CMSEClearGPRegs(
1182 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
1183 const DebugLoc &DL, const SmallVectorImpl<unsigned> &ClearRegs,
1184 unsigned ClobberReg) {
1185
1186 if (STI->hasV8_1MMainlineOps()) {
1187 // Clear the registers using the CLRM instruction.
1188 MachineInstrBuilder CLRM =
1189 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2CLRM)).add(predOps(ARMCC::AL));
1190 for (unsigned R : ClearRegs)
1191 CLRM.addReg(R, RegState::Define);
1192 CLRM.addReg(ARM::APSR, RegState::Define);
1193 CLRM.addReg(ARM::CPSR, RegState::Define | RegState::Implicit);
1194 } else {
1195 // Clear the registers and flags by copying ClobberReg into them.
1196 // (Baseline can't do a high register clear in one instruction).
1197 for (unsigned Reg : ClearRegs) {
1198 if (Reg == ClobberReg)
1199 continue;
1200 BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVr), Reg)
1201 .addReg(ClobberReg)
1203 }
1204
1205 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2MSR_M))
1206 .addImm(STI->hasDSP() ? 0xc00 : 0x800)
1207 .addReg(ClobberReg)
1209 }
1210}
1211
1212// Find which FP registers need to be cleared. The parameter `ClearRegs` is
1213// initialised with all elements set to true, and this function resets all the
1214// bits, which correspond to register uses. Returns true if any floating point
1215// register is defined, false otherwise.
1217 BitVector &ClearRegs) {
1218 bool DefFP = false;
1219 for (const MachineOperand &Op : MI.operands()) {
1220 if (!Op.isReg())
1221 continue;
1222
1223 Register Reg = Op.getReg();
1224 if (Op.isDef()) {
1225 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||
1226 (Reg >= ARM::D0 && Reg <= ARM::D15) ||
1227 (Reg >= ARM::S0 && Reg <= ARM::S31))
1228 DefFP = true;
1229 continue;
1230 }
1231
1232 if (Reg >= ARM::Q0 && Reg <= ARM::Q7) {
1233 int R = Reg - ARM::Q0;
1234 ClearRegs.reset(R * 4, (R + 1) * 4);
1235 } else if (Reg >= ARM::D0 && Reg <= ARM::D15) {
1236 int R = Reg - ARM::D0;
1237 ClearRegs.reset(R * 2, (R + 1) * 2);
1238 } else if (Reg >= ARM::S0 && Reg <= ARM::S31) {
1239 ClearRegs[Reg - ARM::S0] = false;
1240 }
1241 }
1242 return DefFP;
1243}
1244
1245MachineBasicBlock &
1246ARMExpandPseudo::CMSEClearFPRegs(MachineBasicBlock &MBB,
1248 BitVector ClearRegs(16, true);
1249 (void)determineFPRegsToClear(*MBBI, ClearRegs);
1250
1251 if (STI->hasV8_1MMainlineOps())
1252 return CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);
1253 else
1254 return CMSEClearFPRegsV8(MBB, MBBI, ClearRegs);
1255}
1256
1257// Clear the FP registers for v8.0-M, by copying over the content
1258// of LR. Uses R12 as a scratch register.
1259MachineBasicBlock &
1260ARMExpandPseudo::CMSEClearFPRegsV8(MachineBasicBlock &MBB,
1262 const BitVector &ClearRegs) {
1263 if (!STI->hasFPRegs())
1264 return MBB;
1265
1266 auto &RetI = *MBBI;
1267 const DebugLoc &DL = RetI.getDebugLoc();
1268
1269 // If optimising for minimum size, clear FP registers unconditionally.
1270 // Otherwise, check the CONTROL.SFPA (Secure Floating-Point Active) bit and
1271 // don't clear them if they belong to the non-secure state.
1272 MachineBasicBlock *ClearBB, *DoneBB;
1273 if (STI->hasMinSize()) {
1274 ClearBB = DoneBB = &MBB;
1275 } else {
1276 MachineFunction *MF = MBB.getParent();
1277 ClearBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1279
1280 MF->insert(++MBB.getIterator(), ClearBB);
1281 MF->insert(++ClearBB->getIterator(), DoneBB);
1282
1283 DoneBB->splice(DoneBB->end(), &MBB, MBBI, MBB.end());
1284 DoneBB->transferSuccessors(&MBB);
1285 MBB.addSuccessor(ClearBB);
1286 MBB.addSuccessor(DoneBB);
1287 ClearBB->addSuccessor(DoneBB);
1288
1289 // At the new basic blocks we need to have live-in the registers, used
1290 // for the return value as well as LR, used to clear registers.
1291 for (const MachineOperand &Op : RetI.operands()) {
1292 if (!Op.isReg())
1293 continue;
1294 Register Reg = Op.getReg();
1295 if (Reg == ARM::NoRegister || Reg == ARM::LR)
1296 continue;
1297 assert(Reg.isPhysical() && "Unallocated register");
1298 ClearBB->addLiveIn(Reg);
1299 DoneBB->addLiveIn(Reg);
1300 }
1301 ClearBB->addLiveIn(ARM::LR);
1302 DoneBB->addLiveIn(ARM::LR);
1303
1304 // Read the CONTROL register.
1305 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2MRS_M), ARM::R12)
1306 .addImm(20)
1308 // Check bit 3 (SFPA).
1309 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2TSTri))
1310 .addReg(ARM::R12)
1311 .addImm(8)
1313 // If SFPA is clear, jump over ClearBB to DoneBB.
1314 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::tBcc))
1315 .addMBB(DoneBB)
1317 .addReg(ARM::CPSR, RegState::Kill);
1318 }
1319
1320 // Emit the clearing sequence
1321 for (unsigned D = 0; D < 8; D++) {
1322 // Attempt to clear as double
1323 if (ClearRegs[D * 2 + 0] && ClearRegs[D * 2 + 1]) {
1324 unsigned Reg = ARM::D0 + D;
1325 BuildMI(ClearBB, DL, TII->get(ARM::VMOVDRR), Reg)
1326 .addReg(ARM::LR)
1327 .addReg(ARM::LR)
1329 } else {
1330 // Clear first part as single
1331 if (ClearRegs[D * 2 + 0]) {
1332 unsigned Reg = ARM::S0 + D * 2;
1333 BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)
1334 .addReg(ARM::LR)
1336 }
1337 // Clear second part as single
1338 if (ClearRegs[D * 2 + 1]) {
1339 unsigned Reg = ARM::S0 + D * 2 + 1;
1340 BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)
1341 .addReg(ARM::LR)
1343 }
1344 }
1345 }
1346
1347 // Clear FPSCR bits 0-4, 7, 28-31
1348 // The other bits are program global according to the AAPCS
1349 BuildMI(ClearBB, DL, TII->get(ARM::VMRS), ARM::R12)
1351 BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)
1352 .addReg(ARM::R12)
1353 .addImm(0x0000009F)
1355 .add(condCodeOp());
1356 BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)
1357 .addReg(ARM::R12)
1358 .addImm(0xF0000000)
1360 .add(condCodeOp());
1361 BuildMI(ClearBB, DL, TII->get(ARM::VMSR))
1362 .addReg(ARM::R12)
1364
1365 return *DoneBB;
1366}
1367
1368MachineBasicBlock &
1369ARMExpandPseudo::CMSEClearFPRegsV81(MachineBasicBlock &MBB,
1371 const BitVector &ClearRegs) {
1372 auto &RetI = *MBBI;
1373
1374 // Emit a sequence of VSCCLRM <sreglist> instructions, one instruction for
1375 // each contiguous sequence of S-registers.
1376 int Start = -1, End = -1;
1377 for (int S = 0, E = ClearRegs.size(); S != E; ++S) {
1378 if (ClearRegs[S] && S == End + 1) {
1379 End = S; // extend range
1380 continue;
1381 }
1382 // Emit current range.
1383 if (Start < End) {
1384 MachineInstrBuilder VSCCLRM =
1385 BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))
1387 while (++Start <= End)
1388 VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);
1389 VSCCLRM.addReg(ARM::VPR, RegState::Define);
1390 }
1391 Start = End = S;
1392 }
1393 // Emit last range.
1394 if (Start < End) {
1395 MachineInstrBuilder VSCCLRM =
1396 BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))
1398 while (++Start <= End)
1399 VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);
1400 VSCCLRM.addReg(ARM::VPR, RegState::Define);
1401 }
1402
1403 return MBB;
1404}
1405
1406void ARMExpandPseudo::CMSESaveClearFPRegs(
1407 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,
1408 const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {
1409 if (STI->hasV8_1MMainlineOps())
1410 CMSESaveClearFPRegsV81(MBB, MBBI, DL, LiveRegs);
1411 else if (STI->hasV8MMainlineOps())
1412 CMSESaveClearFPRegsV8(MBB, MBBI, DL, LiveRegs, ScratchRegs);
1413}
1414
1415// Save and clear FP registers if present
1416void ARMExpandPseudo::CMSESaveClearFPRegsV8(
1417 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,
1418 const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {
1419
1420 // Store an available register for FPSCR clearing
1421 assert(!ScratchRegs.empty());
1422 unsigned SpareReg = ScratchRegs.front();
1423
1424 // save space on stack for VLSTM
1425 BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)
1426 .addReg(ARM::SP)
1429
1430 // Use ScratchRegs to store the fp regs
1431 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;
1432 std::vector<unsigned> NonclearedFPRegs;
1433 bool ReturnsFPReg = false;
1434 for (const MachineOperand &Op : MBBI->operands()) {
1435 if (Op.isReg() && Op.isUse()) {
1436 Register Reg = Op.getReg();
1437 assert(!ARM::DPRRegClass.contains(Reg) ||
1438 ARM::DPR_VFP2RegClass.contains(Reg));
1439 assert(!ARM::QPRRegClass.contains(Reg));
1440 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1441 if (ScratchRegs.size() >= 2) {
1442 unsigned SaveReg2 = ScratchRegs.pop_back_val();
1443 unsigned SaveReg1 = ScratchRegs.pop_back_val();
1444 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);
1445
1446 // Save the fp register to the normal registers
1447 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))
1448 .addReg(SaveReg1, RegState::Define)
1449 .addReg(SaveReg2, RegState::Define)
1450 .addReg(Reg)
1452 } else {
1453 NonclearedFPRegs.push_back(Reg);
1454 }
1455 } else if (ARM::SPRRegClass.contains(Reg)) {
1456 if (ScratchRegs.size() >= 1) {
1457 unsigned SaveReg = ScratchRegs.pop_back_val();
1458 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);
1459
1460 // Save the fp register to the normal registers
1461 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)
1462 .addReg(Reg)
1464 } else {
1465 NonclearedFPRegs.push_back(Reg);
1466 }
1467 }
1468 } else if (Op.isReg() && Op.isDef()) {
1469 Register Reg = Op.getReg();
1470 if (ARM::SPRRegClass.contains(Reg) || ARM::DPRRegClass.contains(Reg) ||
1471 ARM::QPRRegClass.contains(Reg))
1472 ReturnsFPReg = true;
1473 }
1474 }
1475
1476 bool PassesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
1477
1478 if (PassesFPReg || ReturnsFPReg)
1479 assert(STI->hasFPRegs() && "Subtarget needs fpregs");
1480
1481 // CVE-2024-7883
1482 //
1483 // The VLLDM/VLSTM instructions set up lazy state preservation, but they
1484 // execute as NOPs if the FP register file is not considered to contain
1485 // secure data, represented by the CONTROL_S.SFPA bit. This means that the
1486 // state of CONTROL_S.SFPA must be the same when these two instructions are
1487 // executed. That might not be the case if we haven't used any FP
1488 // instructions before the VLSTM, so CONTROL_S.SFPA is clear, but do have one
1489 // before the VLLDM, which sets it..
1490 //
1491 // If we can't prove that SFPA will be the same for the VLSTM and VLLDM, we
1492 // execute a "vmov s0, s0" instruction before the VLSTM to ensure that
1493 // CONTROL_S.SFPA is set for both.
1494 //
1495 // That can only happen for callees which take no FP arguments (or we'd have
1496 // inserted a VMOV above) and which return values in FP regs (so that we need
1497 // to use a VMOV to back-up the return value before the VLLDM). It also can't
1498 // happen if the call is dominated by other existing floating-point
1499 // instructions, but we don't currently check for that case.
1500 //
1501 // These conditions mean that we only emit this instruction when using the
1502 // hard-float ABI, which means we can assume that FP instructions are
1503 // available, and don't need to make it conditional like we do for the
1504 // CVE-2021-35465 workaround.
1505 if (ReturnsFPReg && !PassesFPReg) {
1506 bool S0Dead = !LiveRegs.contains(ARM::S0);
1507 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVS))
1508 .addReg(ARM::S0, RegState::Define | getDeadRegState(S0Dead))
1509 .addReg(ARM::S0, getUndefRegState(S0Dead))
1511 }
1512
1513 // Lazy store all fp registers to the stack.
1514 // This executes as NOP in the absence of floating-point support.
1515 MachineInstrBuilder VLSTM =
1516 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))
1517 .addReg(ARM::SP)
1519 .addImm(0); // Represents a pseoudo register list, has no effect on
1520 // the encoding.
1521 // Mark non-live registers as undef
1522 for (MachineOperand &MO : VLSTM->implicit_operands()) {
1523 if (MO.isReg() && !MO.isDef()) {
1524 Register Reg = MO.getReg();
1525 MO.setIsUndef(!LiveRegs.contains(Reg));
1526 }
1527 }
1528
1529 // Restore all arguments
1530 for (const auto &Regs : ClearedFPRegs) {
1531 unsigned Reg, SaveReg1, SaveReg2;
1532 std::tie(Reg, SaveReg1, SaveReg2) = Regs;
1533 if (ARM::DPR_VFP2RegClass.contains(Reg))
1534 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)
1535 .addReg(SaveReg1)
1536 .addReg(SaveReg2)
1538 else if (ARM::SPRRegClass.contains(Reg))
1539 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)
1540 .addReg(SaveReg1)
1542 }
1543
1544 for (unsigned Reg : NonclearedFPRegs) {
1545 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1546 if (STI->isLittle()) {
1547 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRD), Reg)
1548 .addReg(ARM::SP)
1549 .addImm((Reg - ARM::D0) * 2)
1551 } else {
1552 // For big-endian targets we need to load the two subregisters of Reg
1553 // manually because VLDRD would load them in wrong order
1554 MCRegister SReg0 = TRI->getSubReg(Reg, ARM::ssub_0);
1555 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0)
1556 .addReg(ARM::SP)
1557 .addImm((Reg - ARM::D0) * 2)
1559 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0 + 1)
1560 .addReg(ARM::SP)
1561 .addImm((Reg - ARM::D0) * 2 + 1)
1563 }
1564 } else if (ARM::SPRRegClass.contains(Reg)) {
1565 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), Reg)
1566 .addReg(ARM::SP)
1567 .addImm(Reg - ARM::S0)
1569 }
1570 }
1571 // restore FPSCR from stack and clear bits 0-4, 7, 28-31
1572 // The other bits are program global according to the AAPCS
1573 if (PassesFPReg) {
1574 BuildMI(MBB, MBBI, DL, TII->get(ARM::tLDRspi), SpareReg)
1575 .addReg(ARM::SP)
1576 .addImm(0x10)
1578 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)
1579 .addReg(SpareReg)
1580 .addImm(0x0000009F)
1582 .add(condCodeOp());
1583 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)
1584 .addReg(SpareReg)
1585 .addImm(0xF0000000)
1587 .add(condCodeOp());
1588 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMSR))
1589 .addReg(SpareReg)
1591 // The ldr must happen after a floating point instruction. To prevent the
1592 // post-ra scheduler to mess with the order, we create a bundle.
1594 }
1595}
1596
1597void ARMExpandPseudo::CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,
1599 DebugLoc &DL,
1600 const LivePhysRegs &LiveRegs) {
1601 BitVector ClearRegs(32, true);
1602 bool DefFP = determineFPRegsToClear(*MBBI, ClearRegs);
1603
1604 // If the instruction does not write to a FP register and no elements were
1605 // removed from the set, then no FP registers were used to pass
1606 // arguments/returns.
1607 if (!DefFP && ClearRegs.count() == ClearRegs.size()) {
1608 // save space on stack for VLSTM
1609 BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)
1610 .addReg(ARM::SP)
1613
1614 // Lazy store all FP registers to the stack
1615 MachineInstrBuilder VLSTM =
1616 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))
1617 .addReg(ARM::SP)
1619 .addImm(0); // Represents a pseoudo register list, has no effect on
1620 // the encoding.
1621 // Mark non-live registers as undef
1622 for (MachineOperand &MO : VLSTM->implicit_operands()) {
1623 if (MO.isReg() && !MO.isDef()) {
1624 Register Reg = MO.getReg();
1625 MO.setIsUndef(!LiveRegs.contains(Reg));
1626 }
1627 }
1628 } else {
1629 // Push all the callee-saved registers (s16-s31).
1630 MachineInstrBuilder VPUSH =
1631 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTMSDB_UPD), ARM::SP)
1632 .addReg(ARM::SP)
1634 for (unsigned Reg = ARM::S16; Reg <= ARM::S31; ++Reg)
1635 VPUSH.addReg(Reg);
1636
1637 // Clear FP registers with a VSCCLRM.
1638 (void)CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);
1639
1640 // Save floating-point context.
1641 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTR_FPCXTS_pre), ARM::SP)
1642 .addReg(ARM::SP)
1643 .addImm(-8)
1645 }
1646}
1647
1648// Restore FP registers if present
1649void ARMExpandPseudo::CMSERestoreFPRegs(
1650 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,
1651 SmallVectorImpl<unsigned> &AvailableRegs) {
1652 if (STI->hasV8_1MMainlineOps())
1653 CMSERestoreFPRegsV81(MBB, MBBI, DL, AvailableRegs);
1654 else if (STI->hasV8MMainlineOps())
1655 CMSERestoreFPRegsV8(MBB, MBBI, DL, AvailableRegs);
1656}
1657
1658void ARMExpandPseudo::CMSERestoreFPRegsV8(
1659 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,
1660 SmallVectorImpl<unsigned> &AvailableRegs) {
1661
1662 // Keep a scratch register for the mitigation sequence.
1663 unsigned ScratchReg = ARM::NoRegister;
1664 if (STI->fixCMSE_CVE_2021_35465())
1665 ScratchReg = AvailableRegs.pop_back_val();
1666
1667 // Use AvailableRegs to store the fp regs
1668 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;
1669 std::vector<unsigned> NonclearedFPRegs;
1670 for (const MachineOperand &Op : MBBI->operands()) {
1671 if (Op.isReg() && Op.isDef()) {
1672 Register Reg = Op.getReg();
1673 assert(!ARM::DPRRegClass.contains(Reg) ||
1674 ARM::DPR_VFP2RegClass.contains(Reg));
1675 assert(!ARM::QPRRegClass.contains(Reg));
1676 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1677 if (AvailableRegs.size() >= 2) {
1678 unsigned SaveReg2 = AvailableRegs.pop_back_val();
1679 unsigned SaveReg1 = AvailableRegs.pop_back_val();
1680 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);
1681
1682 // Save the fp register to the normal registers
1683 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))
1684 .addReg(SaveReg1, RegState::Define)
1685 .addReg(SaveReg2, RegState::Define)
1686 .addReg(Reg)
1688 } else {
1689 NonclearedFPRegs.push_back(Reg);
1690 }
1691 } else if (ARM::SPRRegClass.contains(Reg)) {
1692 if (AvailableRegs.size() >= 1) {
1693 unsigned SaveReg = AvailableRegs.pop_back_val();
1694 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);
1695
1696 // Save the fp register to the normal registers
1697 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)
1698 .addReg(Reg)
1700 } else {
1701 NonclearedFPRegs.push_back(Reg);
1702 }
1703 }
1704 }
1705 }
1706
1707 bool returnsFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
1708
1709 if (returnsFPReg)
1710 assert(STI->hasFPRegs() && "Subtarget needs fpregs");
1711
1712 // Push FP regs that cannot be restored via normal registers on the stack
1713 for (unsigned Reg : NonclearedFPRegs) {
1714 if (ARM::DPR_VFP2RegClass.contains(Reg))
1715 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRD))
1716 .addReg(Reg)
1717 .addReg(ARM::SP)
1718 .addImm((Reg - ARM::D0) * 2)
1720 else if (ARM::SPRRegClass.contains(Reg))
1721 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRS))
1722 .addReg(Reg)
1723 .addReg(ARM::SP)
1724 .addImm(Reg - ARM::S0)
1726 }
1727
1728 // Lazy load fp regs from stack.
1729 // This executes as NOP in the absence of floating-point support.
1730 MachineInstrBuilder VLLDM =
1731 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))
1732 .addReg(ARM::SP)
1734 .addImm(0); // Represents a pseoudo register list, has no effect on
1735 // the encoding.
1736
1737 if (STI->fixCMSE_CVE_2021_35465()) {
1738 auto Bundler = MIBundleBuilder(MBB, VLLDM);
1739 // Read the CONTROL register.
1740 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2MRS_M))
1741 .addReg(ScratchReg, RegState::Define)
1742 .addImm(20)
1743 .add(predOps(ARMCC::AL)));
1744 // Check bit 3 (SFPA).
1745 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2TSTri))
1746 .addReg(ScratchReg)
1747 .addImm(8)
1748 .add(predOps(ARMCC::AL)));
1749 // Emit the IT block.
1750 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2IT))
1752 .addImm(8));
1753 // If SFPA is clear jump over to VLLDM, otherwise execute an instruction
1754 // which has no functional effect apart from causing context creation:
1755 // vmovne s0, s0. In the absence of FPU we emit .inst.w 0xeeb00a40,
1756 // which is defined as NOP if not executed.
1757 if (STI->hasFPRegs())
1758 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::VMOVS))
1759 .addReg(ARM::S0, RegState::Define)
1760 .addReg(ARM::S0, RegState::Undef)
1761 .add(predOps(ARMCC::NE)));
1762 else
1763 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::INLINEASM))
1764 .addExternalSymbol(".inst.w 0xeeb00a40")
1766 finalizeBundle(MBB, Bundler.begin(), Bundler.end());
1767 }
1768
1769 // Restore all FP registers via normal registers
1770 for (const auto &Regs : ClearedFPRegs) {
1771 unsigned Reg, SaveReg1, SaveReg2;
1772 std::tie(Reg, SaveReg1, SaveReg2) = Regs;
1773 if (ARM::DPR_VFP2RegClass.contains(Reg))
1774 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)
1775 .addReg(SaveReg1)
1776 .addReg(SaveReg2)
1778 else if (ARM::SPRRegClass.contains(Reg))
1779 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)
1780 .addReg(SaveReg1)
1782 }
1783
1784 // Pop the stack space
1785 BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)
1786 .addReg(ARM::SP)
1789}
1790
1792 for (const MachineOperand &Op : MI.operands()) {
1793 if (!Op.isReg())
1794 continue;
1795 Register Reg = Op.getReg();
1796 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||
1797 (Reg >= ARM::D0 && Reg <= ARM::D15) ||
1798 (Reg >= ARM::S0 && Reg <= ARM::S31))
1799 return true;
1800 }
1801 return false;
1802}
1803
1804void ARMExpandPseudo::CMSERestoreFPRegsV81(
1805 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc &DL,
1806 SmallVectorImpl<unsigned> &AvailableRegs) {
1807 if (!definesOrUsesFPReg(*MBBI)) {
1808 if (STI->fixCMSE_CVE_2021_35465()) {
1809 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSCCLRMS))
1811 .addReg(ARM::VPR, RegState::Define);
1812 }
1813
1814 // Load FP registers from stack.
1815 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))
1816 .addReg(ARM::SP)
1818 .addImm(0); // Represents a pseoudo register list, has no effect on the
1819 // encoding.
1820
1821 // Pop the stack space
1822 BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)
1823 .addReg(ARM::SP)
1826 } else {
1827 // Restore the floating point context.
1828 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::VLDR_FPCXTS_post),
1829 ARM::SP)
1830 .addReg(ARM::SP)
1831 .addImm(8)
1833
1834 // Pop all the callee-saved registers (s16-s31).
1835 MachineInstrBuilder VPOP =
1836 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDMSIA_UPD), ARM::SP)
1837 .addReg(ARM::SP)
1839 for (unsigned Reg = ARM::S16; Reg <= ARM::S31; ++Reg)
1840 VPOP.addReg(Reg, RegState::Define);
1841 }
1842}
1843
1844/// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as
1845/// possible. This only gets used at -O0 so we don't care about efficiency of
1846/// the generated code.
1847bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
1849 unsigned LdrexOp, unsigned StrexOp,
1850 unsigned UxtOp,
1851 MachineBasicBlock::iterator &NextMBBI) {
1852 bool IsThumb = STI->isThumb();
1853 bool IsThumb1Only = STI->isThumb1Only();
1854 MachineInstr &MI = *MBBI;
1855 DebugLoc DL = MI.getDebugLoc();
1856 const MachineOperand &Dest = MI.getOperand(0);
1857 Register TempReg = MI.getOperand(1).getReg();
1858 // Duplicating undef operands into 2 instructions does not guarantee the same
1859 // value on both; However undef should be replaced by xzr anyway.
1860 assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
1861 Register AddrReg = MI.getOperand(2).getReg();
1862 Register DesiredReg = MI.getOperand(3).getReg();
1863 Register NewReg = MI.getOperand(4).getReg();
1864
1865 if (IsThumb) {
1866 assert(STI->hasV8MBaselineOps() &&
1867 "CMP_SWAP not expected to be custom expanded for Thumb1");
1868 assert((UxtOp == 0 || UxtOp == ARM::tUXTB || UxtOp == ARM::tUXTH) &&
1869 "ARMv8-M.baseline does not have t2UXTB/t2UXTH");
1870 assert((UxtOp == 0 || ARM::tGPRRegClass.contains(DesiredReg)) &&
1871 "DesiredReg used for UXT op must be tGPR");
1872 }
1873
1874 MachineFunction *MF = MBB.getParent();
1875 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1876 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1877 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1878
1879 MF->insert(++MBB.getIterator(), LoadCmpBB);
1880 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
1881 MF->insert(++StoreBB->getIterator(), DoneBB);
1882
1883 if (UxtOp) {
1884 MachineInstrBuilder MIB =
1885 BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg)
1886 .addReg(DesiredReg, RegState::Kill);
1887 if (!IsThumb)
1888 MIB.addImm(0);
1889 MIB.add(predOps(ARMCC::AL));
1890 }
1891
1892 // .Lloadcmp:
1893 // ldrex rDest, [rAddr]
1894 // cmp rDest, rDesired
1895 // bne .Ldone
1896
1897 MachineInstrBuilder MIB;
1898 MIB = BuildMI(LoadCmpBB, DL, TII->get(LdrexOp), Dest.getReg());
1899 MIB.addReg(AddrReg);
1900 if (LdrexOp == ARM::t2LDREX)
1901 MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.
1902 MIB.add(predOps(ARMCC::AL));
1903
1904 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
1905 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
1906 .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
1907 .addReg(DesiredReg)
1909 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
1910 BuildMI(LoadCmpBB, DL, TII->get(Bcc))
1911 .addMBB(DoneBB)
1913 .addReg(ARM::CPSR, RegState::Kill);
1914 LoadCmpBB->addSuccessor(DoneBB);
1915 LoadCmpBB->addSuccessor(StoreBB);
1916
1917 // .Lstore:
1918 // strex rTempReg, rNew, [rAddr]
1919 // cmp rTempReg, #0
1920 // bne .Lloadcmp
1921 MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), TempReg)
1922 .addReg(NewReg)
1923 .addReg(AddrReg);
1924 if (StrexOp == ARM::t2STREX)
1925 MIB.addImm(0); // a 32-bit Thumb strex (only) allows an offset.
1926 MIB.add(predOps(ARMCC::AL));
1927
1928 unsigned CMPri =
1929 IsThumb ? (IsThumb1Only ? ARM::tCMPi8 : ARM::t2CMPri) : ARM::CMPri;
1930 BuildMI(StoreBB, DL, TII->get(CMPri))
1931 .addReg(TempReg, RegState::Kill)
1932 .addImm(0)
1934 BuildMI(StoreBB, DL, TII->get(Bcc))
1935 .addMBB(LoadCmpBB)
1937 .addReg(ARM::CPSR, RegState::Kill);
1938 StoreBB->addSuccessor(LoadCmpBB);
1939 StoreBB->addSuccessor(DoneBB);
1940
1941 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
1942 DoneBB->transferSuccessors(&MBB);
1943
1944 MBB.addSuccessor(LoadCmpBB);
1945
1946 NextMBBI = MBB.end();
1947 MI.eraseFromParent();
1948
1949 // Recompute livein lists.
1950 LivePhysRegs LiveRegs;
1951 computeAndAddLiveIns(LiveRegs, *DoneBB);
1952 computeAndAddLiveIns(LiveRegs, *StoreBB);
1953 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
1954 // Do an extra pass around the loop to get loop carried registers right.
1955 StoreBB->clearLiveIns();
1956 computeAndAddLiveIns(LiveRegs, *StoreBB);
1957 LoadCmpBB->clearLiveIns();
1958 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
1959
1960 return true;
1961}
1962
1963/// ARM's ldrexd/strexd take a consecutive register pair (represented as a
1964/// single GPRPair register), Thumb's take two separate registers so we need to
1965/// extract the subregs from the pair.
1967 RegState Flags, bool IsThumb,
1968 const TargetRegisterInfo *TRI) {
1969 if (IsThumb) {
1970 Register RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);
1971 Register RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);
1972 MIB.addReg(RegLo, Flags);
1973 MIB.addReg(RegHi, Flags);
1974 } else
1975 MIB.addReg(Reg.getReg(), Flags);
1976}
1977
1978/// Expand a 64-bit CMP_SWAP to an ldrexd/strexd loop.
1979bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
1981 MachineBasicBlock::iterator &NextMBBI) {
1982 bool IsThumb = STI->isThumb();
1983 assert(!STI->isThumb1Only() && "CMP_SWAP_64 unsupported under Thumb1!");
1984 MachineInstr &MI = *MBBI;
1985 DebugLoc DL = MI.getDebugLoc();
1986 MachineOperand &Dest = MI.getOperand(0);
1987 // Duplicating undef operands into 2 instructions does not guarantee the same
1988 // value on both; However undef should be replaced by xzr anyway.
1989 assert(!MI.getOperand(1).isUndef() && "cannot handle undef");
1990 Register AddrAndTempReg = MI.getOperand(1).getReg();
1991 Register AddrReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_0);
1992 Register TempReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_1);
1993 assert(MI.getOperand(1).getReg() == MI.getOperand(2).getReg() &&
1994 "tied operands have different registers");
1995 Register DesiredReg = MI.getOperand(3).getReg();
1996 MachineOperand New = MI.getOperand(4);
1997 New.setIsKill(false);
1998
1999 Register DestLo = TRI->getSubReg(Dest.getReg(), ARM::gsub_0);
2000 Register DestHi = TRI->getSubReg(Dest.getReg(), ARM::gsub_1);
2001 Register DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);
2002 Register DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);
2003
2004 MachineFunction *MF = MBB.getParent();
2005 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
2006 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
2007 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
2008
2009 MF->insert(++MBB.getIterator(), LoadCmpBB);
2010 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
2011 MF->insert(++StoreBB->getIterator(), DoneBB);
2012
2013 // .Lloadcmp:
2014 // ldrexd rDestLo, rDestHi, [rAddr]
2015 // cmp rDestLo, rDesiredLo
2016 // sbcs dead rTempReg, rDestHi, rDesiredHi
2017 // bne .Ldone
2018 unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
2019 MachineInstrBuilder MIB;
2020 MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));
2021 addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
2022 MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
2023
2024 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
2025 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
2026 .addReg(DestLo, getKillRegState(Dest.isDead()))
2027 .addReg(DesiredLo)
2029
2030 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
2031 .addReg(DestHi, getKillRegState(Dest.isDead()))
2032 .addReg(DesiredHi)
2033 .addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
2034
2035 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
2036 BuildMI(LoadCmpBB, DL, TII->get(Bcc))
2037 .addMBB(DoneBB)
2039 .addReg(ARM::CPSR, RegState::Kill);
2040 LoadCmpBB->addSuccessor(DoneBB);
2041 LoadCmpBB->addSuccessor(StoreBB);
2042
2043 // .Lstore:
2044 // strexd rTempReg, rNewLo, rNewHi, [rAddr]
2045 // cmp rTempReg, #0
2046 // bne .Lloadcmp
2047 unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;
2048 MIB = BuildMI(StoreBB, DL, TII->get(STREXD), TempReg);
2049 RegState Flags = getKillRegState(New.isDead());
2050 addExclusiveRegPair(MIB, New, Flags, IsThumb, TRI);
2051 MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
2052
2053 unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
2054 BuildMI(StoreBB, DL, TII->get(CMPri))
2055 .addReg(TempReg, RegState::Kill)
2056 .addImm(0)
2058 BuildMI(StoreBB, DL, TII->get(Bcc))
2059 .addMBB(LoadCmpBB)
2061 .addReg(ARM::CPSR, RegState::Kill);
2062 StoreBB->addSuccessor(LoadCmpBB);
2063 StoreBB->addSuccessor(DoneBB);
2064
2065 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
2066 DoneBB->transferSuccessors(&MBB);
2067
2068 MBB.addSuccessor(LoadCmpBB);
2069
2070 NextMBBI = MBB.end();
2071 MI.eraseFromParent();
2072
2073 // Recompute livein lists.
2074 LivePhysRegs LiveRegs;
2075 computeAndAddLiveIns(LiveRegs, *DoneBB);
2076 computeAndAddLiveIns(LiveRegs, *StoreBB);
2077 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
2078 // Do an extra pass around the loop to get loop carried registers right.
2079 StoreBB->clearLiveIns();
2080 computeAndAddLiveIns(LiveRegs, *StoreBB);
2081 LoadCmpBB->clearLiveIns();
2082 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
2083
2084 return true;
2085}
2086
2090 Register JumpReg, const LivePhysRegs &LiveRegs,
2091 bool Thumb1Only) {
2092 const DebugLoc &DL = MBBI->getDebugLoc();
2093 if (Thumb1Only) { // push Lo and Hi regs separately
2094 MachineInstrBuilder PushMIB =
2095 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
2096 for (unsigned Reg = ARM::R4; Reg < ARM::R8; ++Reg) {
2097 PushMIB.addReg(
2098 Reg, getUndefRegState(Reg != JumpReg && !LiveRegs.contains(Reg)));
2099 }
2100
2101 // Thumb1 can only tPUSH low regs, so we copy the high regs to the low
2102 // regs that we just saved and push the low regs again, taking care to
2103 // not clobber JumpReg. If JumpReg is one of the low registers, push first
2104 // the values of r9-r11, and then r8. That would leave them ordered in
2105 // memory, and allow us to later pop them with a single instructions.
2106 // FIXME: Could also use any of r0-r3 that are free (including in the
2107 // first PUSH above).
2108 for (unsigned LoReg = ARM::R7, HiReg = ARM::R11; LoReg >= ARM::R4;
2109 --LoReg) {
2110 if (JumpReg == LoReg)
2111 continue;
2112 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)
2113 .addReg(HiReg, getUndefRegState(!LiveRegs.contains(HiReg)))
2115 --HiReg;
2116 }
2117 MachineInstrBuilder PushMIB2 =
2118 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
2119 for (unsigned Reg = ARM::R4; Reg < ARM::R8; ++Reg) {
2120 if (Reg == JumpReg)
2121 continue;
2122 PushMIB2.addReg(Reg, RegState::Kill);
2123 }
2124
2125 // If we couldn't use a low register for temporary storage (because it was
2126 // the JumpReg), use r4 or r5, whichever is not JumpReg. It has already been
2127 // saved.
2128 if (JumpReg >= ARM::R4 && JumpReg <= ARM::R7) {
2129 Register LoReg = JumpReg == ARM::R4 ? ARM::R5 : ARM::R4;
2130 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)
2131 .addReg(ARM::R8, getUndefRegState(!LiveRegs.contains(ARM::R8)))
2133 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH))
2135 .addReg(LoReg, RegState::Kill);
2136 }
2137 } else { // push Lo and Hi registers with a single instruction
2138 MachineInstrBuilder PushMIB =
2139 BuildMI(MBB, MBBI, DL, TII.get(ARM::t2STMDB_UPD), ARM::SP)
2140 .addReg(ARM::SP)
2142 for (unsigned Reg = ARM::R4; Reg < ARM::R12; ++Reg) {
2143 PushMIB.addReg(
2144 Reg, getUndefRegState(Reg != JumpReg && !LiveRegs.contains(Reg)));
2145 }
2146 }
2147}
2148
2152 bool Thumb1Only) {
2153 const DebugLoc &DL = MBBI->getDebugLoc();
2154 if (Thumb1Only) {
2155 MachineInstrBuilder PopMIB =
2156 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
2157 for (int R = 0; R < 4; ++R) {
2158 PopMIB.addReg(ARM::R4 + R, RegState::Define);
2159 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), ARM::R8 + R)
2160 .addReg(ARM::R4 + R, RegState::Kill)
2162 }
2163 MachineInstrBuilder PopMIB2 =
2164 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
2165 for (int R = 0; R < 4; ++R)
2166 PopMIB2.addReg(ARM::R4 + R, RegState::Define);
2167 } else { // pop Lo and Hi registers with a single instruction
2168 MachineInstrBuilder PopMIB =
2169 BuildMI(MBB, MBBI, DL, TII.get(ARM::t2LDMIA_UPD), ARM::SP)
2170 .addReg(ARM::SP)
2172 for (unsigned Reg = ARM::R4; Reg < ARM::R12; ++Reg)
2173 PopMIB.addReg(Reg, RegState::Define);
2174 }
2175}
2176
2177bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
2179 MachineBasicBlock::iterator &NextMBBI) {
2180 MachineInstr &MI = *MBBI;
2181 unsigned Opcode = MI.getOpcode();
2182 switch (Opcode) {
2183 default:
2184 return false;
2185
2186 case ARM::VBSPd:
2187 case ARM::VBSPq: {
2188 Register DstReg = MI.getOperand(0).getReg();
2189 if (DstReg == MI.getOperand(3).getReg()) {
2190 // Expand to VBIT
2191 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBITd : ARM::VBITq;
2192 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2193 .add(MI.getOperand(0))
2194 .add(MI.getOperand(3))
2195 .add(MI.getOperand(2))
2196 .add(MI.getOperand(1))
2197 .addImm(MI.getOperand(4).getImm())
2198 .add(MI.getOperand(5));
2199 } else if (DstReg == MI.getOperand(2).getReg()) {
2200 // Expand to VBIF
2201 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBIFd : ARM::VBIFq;
2202 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2203 .add(MI.getOperand(0))
2204 .add(MI.getOperand(2))
2205 .add(MI.getOperand(3))
2206 .add(MI.getOperand(1))
2207 .addImm(MI.getOperand(4).getImm())
2208 .add(MI.getOperand(5));
2209 } else {
2210 // Expand to VBSL
2211 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBSLd : ARM::VBSLq;
2212 if (DstReg == MI.getOperand(1).getReg()) {
2213 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2214 .add(MI.getOperand(0))
2215 .add(MI.getOperand(1))
2216 .add(MI.getOperand(2))
2217 .add(MI.getOperand(3))
2218 .addImm(MI.getOperand(4).getImm())
2219 .add(MI.getOperand(5));
2220 } else {
2221 // Use move to satisfy constraints
2222 unsigned MoveOpc = Opcode == ARM::VBSPd ? ARM::VORRd : ARM::VORRq;
2223 RegState MO1Flags = getRegState(MI.getOperand(1)) & ~RegState::Kill;
2224 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MoveOpc))
2225 .addReg(DstReg,
2226 RegState::Define |
2227 getRenamableRegState(MI.getOperand(0).isRenamable()))
2228 .addReg(MI.getOperand(1).getReg(), MO1Flags)
2229 .addReg(MI.getOperand(1).getReg(), MO1Flags)
2230 .addImm(MI.getOperand(4).getImm())
2231 .add(MI.getOperand(5));
2232 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2233 .add(MI.getOperand(0))
2234 .addReg(DstReg,
2235 RegState::Kill |
2236 getRenamableRegState(MI.getOperand(0).isRenamable()))
2237 .add(MI.getOperand(2))
2238 .add(MI.getOperand(3))
2239 .addImm(MI.getOperand(4).getImm())
2240 .add(MI.getOperand(5));
2241 }
2242 }
2243 MI.eraseFromParent();
2244 return true;
2245 }
2246
2247 case ARM::CLEANUPRET:
2248 case ARM::CATCHRET: {
2249 unsigned RetOpcode = STI->isThumb() ? ARM::tBX_RET : ARM::BX_RET;
2250 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(RetOpcode))
2252 MI.eraseFromParent();
2253 return true;
2254 }
2255 case ARM::TCRETURNdi:
2256 case ARM::TCRETURNri:
2257 case ARM::TCRETURNrinotr12: {
2259 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2260 MBBI--;
2261 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2262 MBBI--;
2263 assert(MBBI->isReturn() &&
2264 "Can only insert epilog into returning blocks");
2265 unsigned RetOpcode = MBBI->getOpcode();
2266 DebugLoc dl = MBBI->getDebugLoc();
2267 const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(
2268 MBB.getParent()->getSubtarget().getInstrInfo());
2269
2270 // Tail call return: adjust the stack pointer and jump to callee.
2272 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2273 MBBI--;
2274 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2275 MBBI--;
2276 MachineOperand &JumpTarget = MBBI->getOperand(0);
2277
2278 // Jump to label or value in register.
2279 if (RetOpcode == ARM::TCRETURNdi) {
2280 MachineFunction *MF = MBB.getParent();
2281 bool NeedsWinCFI = MF->getTarget().getMCAsmInfo().usesWindowsCFI() &&
2283 unsigned TCOpcode =
2284 STI->isThumb()
2285 ? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd
2286 : ARM::tTAILJMPdND)
2287 : ARM::TAILJMPd;
2288 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
2289 if (JumpTarget.isGlobal())
2290 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
2291 JumpTarget.getTargetFlags());
2292 else {
2293 assert(JumpTarget.isSymbol());
2294 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
2295 JumpTarget.getTargetFlags());
2296 }
2297
2298 // Add the default predicate in Thumb mode.
2299 if (STI->isThumb())
2300 MIB.add(predOps(ARMCC::AL));
2301 } else if (RetOpcode == ARM::TCRETURNri ||
2302 RetOpcode == ARM::TCRETURNrinotr12) {
2303 unsigned Opcode =
2304 STI->isThumb() ? ARM::tTAILJMPr
2305 : (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);
2306 BuildMI(MBB, MBBI, dl,
2307 TII.get(Opcode))
2308 .addReg(JumpTarget.getReg(), RegState::Kill);
2309 }
2310
2311 auto NewMI = std::prev(MBBI);
2312 for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)
2313 NewMI->addOperand(MBBI->getOperand(i));
2314
2315 NewMI->setCFIType(*MBB.getParent(), MI.getCFIType());
2316
2317 // Update call info and delete the pseudo instruction TCRETURN.
2318 if (MI.isCandidateForAdditionalCallInfo())
2319 MI.getMF()->moveAdditionalCallInfo(&MI, &*NewMI);
2320 // Copy nomerge flag over to new instruction.
2321 if (MI.getFlag(MachineInstr::NoMerge))
2322 NewMI->setFlag(MachineInstr::NoMerge);
2323 MBB.erase(MBBI);
2324
2325 MBBI = NewMI;
2326 return true;
2327 }
2328 case ARM::tBXNS_RET: {
2329 // For v8.0-M.Main we need to authenticate LR before clearing FPRs, which
2330 // uses R12 as a scratch register.
2331 if (!STI->hasV8_1MMainlineOps() && AFI->shouldSignReturnAddress())
2332 BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARM::t2AUT));
2333
2334 MachineBasicBlock &AfterBB = CMSEClearFPRegs(MBB, MBBI);
2335
2336 if (STI->hasV8_1MMainlineOps()) {
2337 // Restore the non-secure floating point context.
2338 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
2339 TII->get(ARM::VLDR_FPCXTNS_post), ARM::SP)
2340 .addReg(ARM::SP)
2341 .addImm(4)
2343
2344 if (AFI->shouldSignReturnAddress())
2345 BuildMI(AfterBB, AfterBB.end(), DebugLoc(), TII->get(ARM::t2AUT));
2346 }
2347
2348 // Clear all GPR that are not a use of the return instruction.
2349 assert(llvm::all_of(MBBI->operands(), [](const MachineOperand &Op) {
2350 return !Op.isReg() || Op.getReg() != ARM::R12;
2351 }));
2352 SmallVector<unsigned, 5> ClearRegs;
2354 *MBBI, {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R12}, ClearRegs);
2355 CMSEClearGPRegs(AfterBB, AfterBB.end(), MBBI->getDebugLoc(), ClearRegs,
2356 ARM::LR);
2357
2358 MachineInstrBuilder NewMI =
2359 BuildMI(AfterBB, AfterBB.end(), MBBI->getDebugLoc(),
2360 TII->get(ARM::tBXNS))
2361 .addReg(ARM::LR)
2363 for (const MachineOperand &Op : MI.operands())
2364 NewMI->addOperand(Op);
2365 MI.eraseFromParent();
2366 return true;
2367 }
2368 case ARM::tBLXNS_CALL: {
2369 DebugLoc DL = MBBI->getDebugLoc();
2370 Register JumpReg = MBBI->getOperand(0).getReg();
2371
2372 // Figure out which registers are live at the point immediately before the
2373 // call. When we indiscriminately push a set of registers, the live
2374 // registers are added as ordinary use operands, whereas dead registers
2375 // are "undef".
2376 LivePhysRegs LiveRegs(*TRI);
2377 LiveRegs.addLiveOuts(MBB);
2378 for (const MachineInstr &MI : make_range(MBB.rbegin(), MBBI.getReverse()))
2379 LiveRegs.stepBackward(MI);
2380 LiveRegs.stepBackward(*MBBI);
2381
2382 CMSEPushCalleeSaves(*TII, MBB, MBBI, JumpReg, LiveRegs,
2383 AFI->isThumb1OnlyFunction());
2384
2385 SmallVector<unsigned, 16> ClearRegs;
2387 {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4,
2388 ARM::R5, ARM::R6, ARM::R7, ARM::R8, ARM::R9,
2389 ARM::R10, ARM::R11, ARM::R12},
2390 ClearRegs);
2391 auto OriginalClearRegs = ClearRegs;
2392
2393 // Get the first cleared register as a scratch (to use later with tBIC).
2394 // We need to use the first so we can ensure it is a low register.
2395 unsigned ScratchReg = ClearRegs.front();
2396
2397 // Clear LSB of JumpReg
2398 if (AFI->isThumb2Function()) {
2399 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), JumpReg)
2400 .addReg(JumpReg)
2401 .addImm(1)
2403 .add(condCodeOp());
2404 } else {
2405 // We need to use an extra register to cope with 8M Baseline,
2406 // since we have saved all of the registers we are ok to trash a non
2407 // argument register here.
2408 BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVi8), ScratchReg)
2409 .add(condCodeOp())
2410 .addImm(1)
2412 BuildMI(MBB, MBBI, DL, TII->get(ARM::tBIC), JumpReg)
2413 .addReg(ARM::CPSR, RegState::Define)
2414 .addReg(JumpReg)
2415 .addReg(ScratchReg)
2417 }
2418
2419 CMSESaveClearFPRegs(MBB, MBBI, DL, LiveRegs,
2420 ClearRegs); // save+clear FP regs with ClearRegs
2421 CMSEClearGPRegs(MBB, MBBI, DL, ClearRegs, JumpReg);
2422
2423 const MachineInstrBuilder NewCall =
2424 BuildMI(MBB, MBBI, DL, TII->get(ARM::tBLXNSr))
2426 .addReg(JumpReg, RegState::Kill);
2427
2428 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
2429 NewCall->addOperand(MO);
2430 if (MI.isCandidateForAdditionalCallInfo())
2431 MI.getMF()->moveAdditionalCallInfo(&MI, NewCall.getInstr());
2432
2433 CMSERestoreFPRegs(MBB, MBBI, DL, OriginalClearRegs); // restore FP registers
2434
2436
2437 MI.eraseFromParent();
2438 return true;
2439 }
2440 case ARM::VMOVHcc:
2441 case ARM::VMOVScc:
2442 case ARM::VMOVDcc: {
2443 unsigned newOpc = Opcode != ARM::VMOVDcc ? ARM::VMOVS : ARM::VMOVD;
2444 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(newOpc),
2445 MI.getOperand(1).getReg())
2446 .add(MI.getOperand(2))
2447 .addImm(MI.getOperand(3).getImm()) // 'pred'
2448 .add(MI.getOperand(4))
2449 .add(makeImplicit(MI.getOperand(1)));
2450
2451 MI.eraseFromParent();
2452 return true;
2453 }
2454 case ARM::t2MOVCCr:
2455 case ARM::MOVCCr: {
2456 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVr : ARM::MOVr;
2457 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2458 MI.getOperand(1).getReg())
2459 .add(MI.getOperand(2))
2460 .addImm(MI.getOperand(3).getImm()) // 'pred'
2461 .add(MI.getOperand(4))
2462 .add(condCodeOp()) // 's' bit
2463 .add(makeImplicit(MI.getOperand(1)));
2464
2465 MI.eraseFromParent();
2466 return true;
2467 }
2468 case ARM::MOVCCsi: {
2469 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2470 (MI.getOperand(1).getReg()))
2471 .add(MI.getOperand(2))
2472 .addImm(MI.getOperand(3).getImm())
2473 .addImm(MI.getOperand(4).getImm()) // 'pred'
2474 .add(MI.getOperand(5))
2475 .add(condCodeOp()) // 's' bit
2476 .add(makeImplicit(MI.getOperand(1)));
2477
2478 MI.eraseFromParent();
2479 return true;
2480 }
2481 case ARM::MOVCCsr: {
2482 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr),
2483 (MI.getOperand(1).getReg()))
2484 .add(MI.getOperand(2))
2485 .add(MI.getOperand(3))
2486 .addImm(MI.getOperand(4).getImm())
2487 .addImm(MI.getOperand(5).getImm()) // 'pred'
2488 .add(MI.getOperand(6))
2489 .add(condCodeOp()) // 's' bit
2490 .add(makeImplicit(MI.getOperand(1)));
2491
2492 MI.eraseFromParent();
2493 return true;
2494 }
2495 case ARM::t2MOVCCi16:
2496 case ARM::MOVCCi16: {
2497 unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16;
2498 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
2499 MI.getOperand(1).getReg())
2500 .addImm(MI.getOperand(2).getImm())
2501 .addImm(MI.getOperand(3).getImm()) // 'pred'
2502 .add(MI.getOperand(4))
2503 .add(makeImplicit(MI.getOperand(1)));
2504 MI.eraseFromParent();
2505 return true;
2506 }
2507 case ARM::t2MOVCCi:
2508 case ARM::MOVCCi: {
2509 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVi : ARM::MOVi;
2510 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2511 MI.getOperand(1).getReg())
2512 .addImm(MI.getOperand(2).getImm())
2513 .addImm(MI.getOperand(3).getImm()) // 'pred'
2514 .add(MI.getOperand(4))
2515 .add(condCodeOp()) // 's' bit
2516 .add(makeImplicit(MI.getOperand(1)));
2517
2518 MI.eraseFromParent();
2519 return true;
2520 }
2521 case ARM::t2MVNCCi:
2522 case ARM::MVNCCi: {
2523 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MVNi : ARM::MVNi;
2524 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2525 MI.getOperand(1).getReg())
2526 .addImm(MI.getOperand(2).getImm())
2527 .addImm(MI.getOperand(3).getImm()) // 'pred'
2528 .add(MI.getOperand(4))
2529 .add(condCodeOp()) // 's' bit
2530 .add(makeImplicit(MI.getOperand(1)));
2531
2532 MI.eraseFromParent();
2533 return true;
2534 }
2535 case ARM::t2MOVCClsl:
2536 case ARM::t2MOVCClsr:
2537 case ARM::t2MOVCCasr:
2538 case ARM::t2MOVCCror: {
2539 unsigned NewOpc;
2540 switch (Opcode) {
2541 case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break;
2542 case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break;
2543 case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break;
2544 case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break;
2545 default: llvm_unreachable("unexpected conditional move");
2546 }
2547 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
2548 MI.getOperand(1).getReg())
2549 .add(MI.getOperand(2))
2550 .addImm(MI.getOperand(3).getImm())
2551 .addImm(MI.getOperand(4).getImm()) // 'pred'
2552 .add(MI.getOperand(5))
2553 .add(condCodeOp()) // 's' bit
2554 .add(makeImplicit(MI.getOperand(1)));
2555 MI.eraseFromParent();
2556 return true;
2557 }
2558 case ARM::Int_eh_sjlj_dispatchsetup: {
2559 MachineFunction &MF = *MI.getParent()->getParent();
2560 const ARMBaseRegisterInfo &RI = TII->getRegisterInfo();
2561 // For functions using a base pointer, we rematerialize it (via the frame
2562 // pointer) here since eh.sjlj.setjmp and eh.sjlj.longjmp don't do it
2563 // for us. Otherwise, expand to nothing.
2564 if (RI.hasBasePointer(MF)) {
2565 int32_t NumBytes = AFI->getFramePtrSpillOffset();
2568 "base pointer without frame pointer?");
2569
2570 if (AFI->isThumb2Function()) {
2571 emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2572 FramePtr, -NumBytes, ARMCC::AL, 0, *TII);
2573 } else if (AFI->isThumbFunction()) {
2574 emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2575 FramePtr, -NumBytes, *TII, RI);
2576 } else {
2577 emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2578 FramePtr, -NumBytes, ARMCC::AL, 0,
2579 *TII);
2580 }
2581 // If there's dynamic realignment, adjust for it.
2582 if (RI.hasStackRealignment(MF)) {
2583 MachineFrameInfo &MFI = MF.getFrameInfo();
2584 Align MaxAlign = MFI.getMaxAlign();
2585 assert (!AFI->isThumb1OnlyFunction());
2586 // Emit bic r6, r6, MaxAlign
2587 assert(MaxAlign <= Align(256) &&
2588 "The BIC instruction cannot encode "
2589 "immediates larger than 256 with all lower "
2590 "bits set.");
2591 unsigned bicOpc = AFI->isThumbFunction() ?
2592 ARM::t2BICri : ARM::BICri;
2593 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(bicOpc), ARM::R6)
2594 .addReg(ARM::R6, RegState::Kill)
2595 .addImm(MaxAlign.value() - 1)
2597 .add(condCodeOp());
2598 }
2599 }
2600 MI.eraseFromParent();
2601 return true;
2602 }
2603
2604 case ARM::LSRs1:
2605 case ARM::ASRs1: {
2606 // These are just fancy MOVs instructions.
2607 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2608 MI.getOperand(0).getReg())
2609 .add(MI.getOperand(1))
2611 (Opcode == ARM::LSRs1 ? ARM_AM::lsr : ARM_AM::asr), 1))
2613 .addReg(ARM::CPSR, RegState::Define);
2614 MI.eraseFromParent();
2615 return true;
2616 }
2617 case ARM::RRX: {
2618 // This encodes as "MOVs Rd, Rm, rrx
2619 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2620 MI.getOperand(0).getReg())
2621 .add(MI.getOperand(1))
2624 .add(condCodeOp())
2626 MI.eraseFromParent();
2627 return true;
2628 }
2629 case ARM::tTPsoft:
2630 case ARM::TPsoft: {
2631 const bool Thumb = Opcode == ARM::tTPsoft;
2632
2633 MachineInstrBuilder MIB;
2634 MachineFunction *MF = MBB.getParent();
2635 if (STI->genLongCalls()) {
2636 MachineConstantPool *MCP = MF->getConstantPool();
2637 unsigned PCLabelID = AFI->createPICLabelUId();
2638 MachineConstantPoolValue *CPV =
2640 "__aeabi_read_tp", PCLabelID, 0);
2641 Register Reg = MI.getOperand(0).getReg();
2642 MIB =
2643 BuildMI(MBB, MBBI, MI.getDebugLoc(),
2644 TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)
2646 if (!Thumb)
2647 MIB.addImm(0);
2648 MIB.add(predOps(ARMCC::AL));
2649
2650 MIB =
2651 BuildMI(MBB, MBBI, MI.getDebugLoc(),
2652 TII->get(Thumb ? gettBLXrOpcode(*MF) : getBLXOpcode(*MF)));
2653 if (Thumb)
2654 MIB.add(predOps(ARMCC::AL));
2655 MIB.addReg(Reg, RegState::Kill);
2656 } else {
2657 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
2658 TII->get(Thumb ? ARM::tBL : ARM::BL));
2659 if (Thumb)
2660 MIB.add(predOps(ARMCC::AL));
2661 MIB.addExternalSymbol("__aeabi_read_tp", 0);
2662 }
2663
2664 MIB.cloneMemRefs(MI);
2665 MIB.copyImplicitOps(MI);
2666 // Update the call info.
2667 if (MI.isCandidateForAdditionalCallInfo())
2668 MF->moveAdditionalCallInfo(&MI, &*MIB);
2669 MI.eraseFromParent();
2670 return true;
2671 }
2672 case ARM::tLDRpci_pic:
2673 case ARM::t2LDRpci_pic: {
2674 unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
2675 ? ARM::tLDRpci : ARM::t2LDRpci;
2676 Register DstReg = MI.getOperand(0).getReg();
2677 bool DstIsDead = MI.getOperand(0).isDead();
2678 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewLdOpc), DstReg)
2679 .add(MI.getOperand(1))
2683 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD))
2684 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2685 .addReg(DstReg)
2686 .add(MI.getOperand(2))
2688 MI.eraseFromParent();
2689 return true;
2690 }
2691
2692 case ARM::LDRLIT_ga_abs:
2693 case ARM::LDRLIT_ga_pcrel:
2694 case ARM::LDRLIT_ga_pcrel_ldr:
2695 case ARM::tLDRLIT_ga_abs:
2696 case ARM::t2LDRLIT_ga_pcrel:
2697 case ARM::tLDRLIT_ga_pcrel: {
2698 Register DstReg = MI.getOperand(0).getReg();
2699 bool DstIsDead = MI.getOperand(0).isDead();
2700 const MachineOperand &MO1 = MI.getOperand(1);
2701 auto Flags = MO1.getTargetFlags();
2702 const GlobalValue *GV = MO1.getGlobal();
2703 bool IsARM = Opcode != ARM::tLDRLIT_ga_pcrel &&
2704 Opcode != ARM::tLDRLIT_ga_abs &&
2705 Opcode != ARM::t2LDRLIT_ga_pcrel;
2706 bool IsPIC =
2707 Opcode != ARM::LDRLIT_ga_abs && Opcode != ARM::tLDRLIT_ga_abs;
2708 unsigned LDRLITOpc = IsARM ? ARM::LDRi12 : ARM::tLDRpci;
2709 if (Opcode == ARM::t2LDRLIT_ga_pcrel)
2710 LDRLITOpc = ARM::t2LDRpci;
2711 unsigned PICAddOpc =
2712 IsARM
2713 ? (Opcode == ARM::LDRLIT_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
2714 : ARM::tPICADD;
2715
2716 // We need a new const-pool entry to load from.
2717 MachineConstantPool *MCP = MBB.getParent()->getConstantPool();
2718 unsigned ARMPCLabelIndex = 0;
2719 MachineConstantPoolValue *CPV;
2720
2721 if (IsPIC) {
2722 unsigned PCAdj = IsARM ? 8 : 4;
2723 auto Modifier = (Flags & ARMII::MO_GOT)
2725 : ARMCP::no_modifier;
2726 ARMPCLabelIndex = AFI->createPICLabelUId();
2728 GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier,
2729 /*AddCurrentAddr*/ Modifier == ARMCP::GOT_PREL);
2730 } else
2732
2733 MachineInstrBuilder MIB =
2734 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LDRLITOpc), DstReg)
2736 if (IsARM)
2737 MIB.addImm(0);
2738 MIB.add(predOps(ARMCC::AL));
2739
2740 if (IsPIC) {
2741 MachineInstrBuilder MIB =
2742 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(PICAddOpc))
2743 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2744 .addReg(DstReg)
2745 .addImm(ARMPCLabelIndex);
2746
2747 if (IsARM)
2748 MIB.add(predOps(ARMCC::AL));
2749 }
2750
2751 MI.eraseFromParent();
2752 return true;
2753 }
2754 case ARM::MOV_ga_pcrel:
2755 case ARM::MOV_ga_pcrel_ldr:
2756 case ARM::t2MOV_ga_pcrel: {
2757 // Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode.
2758 unsigned LabelId = AFI->createPICLabelUId();
2759 Register DstReg = MI.getOperand(0).getReg();
2760 bool DstIsDead = MI.getOperand(0).isDead();
2761 const MachineOperand &MO1 = MI.getOperand(1);
2762 const GlobalValue *GV = MO1.getGlobal();
2763 unsigned TF = MO1.getTargetFlags();
2764 bool isARM = Opcode != ARM::t2MOV_ga_pcrel;
2765 unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;
2766 unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;
2767 unsigned LO16TF = TF | ARMII::MO_LO16;
2768 unsigned HI16TF = TF | ARMII::MO_HI16;
2769 unsigned PICAddOpc = isARM
2770 ? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
2771 : ARM::tPICADD;
2772 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg)
2773 .addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF)
2774 .addImm(LabelId)
2776
2777 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc), DstReg)
2778 .addReg(DstReg)
2779 .addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF)
2780 .addImm(LabelId)
2782
2783 MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
2784 TII->get(PICAddOpc))
2785 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2786 .addReg(DstReg).addImm(LabelId);
2787 if (isARM) {
2788 MIB3.add(predOps(ARMCC::AL));
2789 if (Opcode == ARM::MOV_ga_pcrel_ldr)
2790 MIB3.cloneMemRefs(MI);
2791 }
2792 MIB3.copyImplicitOps(MI);
2793 MI.eraseFromParent();
2794 return true;
2795 }
2796
2797 case ARM::MOVi32imm:
2798 case ARM::MOVCCi32imm:
2799 case ARM::t2MOVi32imm:
2800 case ARM::t2MOVCCi32imm:
2801 ExpandMOV32BitImm(MBB, MBBI);
2802 return true;
2803
2804 case ARM::tMOVi32imm:
2805 ExpandTMOV32BitImm(MBB, MBBI);
2806 return true;
2807
2808 case ARM::tLEApcrelJT:
2809 // Inline jump tables are handled in ARMAsmPrinter.
2810 if (MI.getMF()->getJumpTableInfo()->getEntryKind() ==
2812 return false;
2813
2814 // Use a 32-bit immediate move to generate the address of the jump table.
2815 assert(STI->isThumb() && "Non-inline jump tables expected only in thumb");
2816 ExpandTMOV32BitImm(MBB, MBBI);
2817 return true;
2818
2819 case ARM::SUBS_PC_LR: {
2820 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri), ARM::PC)
2821 .addReg(ARM::LR)
2822 .add(MI.getOperand(0))
2823 .add(MI.getOperand(1))
2824 .add(MI.getOperand(2))
2825 .addReg(ARM::CPSR, RegState::Undef)
2827 MI.eraseFromParent();
2828 return true;
2829 }
2830 case ARM::VLDMQIA: {
2831 unsigned NewOpc = ARM::VLDMDIA;
2832 MachineInstrBuilder MIB =
2833 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
2834 unsigned OpIdx = 0;
2835
2836 // Grab the Q register destination.
2837 bool DstIsDead = MI.getOperand(OpIdx).isDead();
2838 Register DstReg = MI.getOperand(OpIdx++).getReg();
2839
2840 // Copy the source register.
2841 MIB.add(MI.getOperand(OpIdx++));
2842
2843 // Copy the predicate operands.
2844 MIB.add(MI.getOperand(OpIdx++));
2845 MIB.add(MI.getOperand(OpIdx++));
2846
2847 // Add the destination operands (D subregs).
2848 Register D0 = TRI->getSubReg(DstReg, ARM::dsub_0);
2849 Register D1 = TRI->getSubReg(DstReg, ARM::dsub_1);
2850 MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
2851 .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
2852
2853 // Add an implicit def for the super-register.
2854 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
2855 MIB.copyImplicitOps(MI);
2856 MIB.cloneMemRefs(MI);
2857 MI.eraseFromParent();
2858 return true;
2859 }
2860
2861 case ARM::VSTMQIA: {
2862 unsigned NewOpc = ARM::VSTMDIA;
2863 MachineInstrBuilder MIB =
2864 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
2865 unsigned OpIdx = 0;
2866
2867 // Grab the Q register source.
2868 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
2869 Register SrcReg = MI.getOperand(OpIdx++).getReg();
2870
2871 // Copy the destination register.
2872 MachineOperand Dst(MI.getOperand(OpIdx++));
2873 MIB.add(Dst);
2874
2875 // Copy the predicate operands.
2876 MIB.add(MI.getOperand(OpIdx++));
2877 MIB.add(MI.getOperand(OpIdx++));
2878
2879 // Add the source operands (D subregs).
2880 Register D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
2881 Register D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
2882 MIB.addReg(D0, getKillRegState(SrcIsKill))
2883 .addReg(D1, getKillRegState(SrcIsKill));
2884
2885 if (SrcIsKill) // Add an implicit kill for the Q register.
2886 MIB->addRegisterKilled(SrcReg, TRI, true);
2887
2888 MIB.copyImplicitOps(MI);
2889 MIB.cloneMemRefs(MI);
2890 MI.eraseFromParent();
2891 return true;
2892 }
2893
2894 case ARM::VLD2q8Pseudo:
2895 case ARM::VLD2q16Pseudo:
2896 case ARM::VLD2q32Pseudo:
2897 case ARM::VLD2q8PseudoWB_fixed:
2898 case ARM::VLD2q16PseudoWB_fixed:
2899 case ARM::VLD2q32PseudoWB_fixed:
2900 case ARM::VLD2q8PseudoWB_register:
2901 case ARM::VLD2q16PseudoWB_register:
2902 case ARM::VLD2q32PseudoWB_register:
2903 case ARM::VLD3d8Pseudo:
2904 case ARM::VLD3d16Pseudo:
2905 case ARM::VLD3d32Pseudo:
2906 case ARM::VLD1d8TPseudo:
2907 case ARM::VLD1d8TPseudoWB_fixed:
2908 case ARM::VLD1d8TPseudoWB_register:
2909 case ARM::VLD1d16TPseudo:
2910 case ARM::VLD1d16TPseudoWB_fixed:
2911 case ARM::VLD1d16TPseudoWB_register:
2912 case ARM::VLD1d32TPseudo:
2913 case ARM::VLD1d32TPseudoWB_fixed:
2914 case ARM::VLD1d32TPseudoWB_register:
2915 case ARM::VLD1d64TPseudo:
2916 case ARM::VLD1d64TPseudoWB_fixed:
2917 case ARM::VLD1d64TPseudoWB_register:
2918 case ARM::VLD3d8Pseudo_UPD:
2919 case ARM::VLD3d16Pseudo_UPD:
2920 case ARM::VLD3d32Pseudo_UPD:
2921 case ARM::VLD3q8Pseudo_UPD:
2922 case ARM::VLD3q16Pseudo_UPD:
2923 case ARM::VLD3q32Pseudo_UPD:
2924 case ARM::VLD3q8oddPseudo:
2925 case ARM::VLD3q16oddPseudo:
2926 case ARM::VLD3q32oddPseudo:
2927 case ARM::VLD3q8oddPseudo_UPD:
2928 case ARM::VLD3q16oddPseudo_UPD:
2929 case ARM::VLD3q32oddPseudo_UPD:
2930 case ARM::VLD4d8Pseudo:
2931 case ARM::VLD4d16Pseudo:
2932 case ARM::VLD4d32Pseudo:
2933 case ARM::VLD1d8QPseudo:
2934 case ARM::VLD1d8QPseudoWB_fixed:
2935 case ARM::VLD1d8QPseudoWB_register:
2936 case ARM::VLD1d16QPseudo:
2937 case ARM::VLD1d16QPseudoWB_fixed:
2938 case ARM::VLD1d16QPseudoWB_register:
2939 case ARM::VLD1d32QPseudo:
2940 case ARM::VLD1d32QPseudoWB_fixed:
2941 case ARM::VLD1d32QPseudoWB_register:
2942 case ARM::VLD1d64QPseudo:
2943 case ARM::VLD1d64QPseudoWB_fixed:
2944 case ARM::VLD1d64QPseudoWB_register:
2945 case ARM::VLD1q8HighQPseudo:
2946 case ARM::VLD1q8HighQPseudo_UPD:
2947 case ARM::VLD1q8LowQPseudo_UPD:
2948 case ARM::VLD1q8HighTPseudo:
2949 case ARM::VLD1q8HighTPseudo_UPD:
2950 case ARM::VLD1q8LowTPseudo_UPD:
2951 case ARM::VLD1q16HighQPseudo:
2952 case ARM::VLD1q16HighQPseudo_UPD:
2953 case ARM::VLD1q16LowQPseudo_UPD:
2954 case ARM::VLD1q16HighTPseudo:
2955 case ARM::VLD1q16HighTPseudo_UPD:
2956 case ARM::VLD1q16LowTPseudo_UPD:
2957 case ARM::VLD1q32HighQPseudo:
2958 case ARM::VLD1q32HighQPseudo_UPD:
2959 case ARM::VLD1q32LowQPseudo_UPD:
2960 case ARM::VLD1q32HighTPseudo:
2961 case ARM::VLD1q32HighTPseudo_UPD:
2962 case ARM::VLD1q32LowTPseudo_UPD:
2963 case ARM::VLD1q64HighQPseudo:
2964 case ARM::VLD1q64HighQPseudo_UPD:
2965 case ARM::VLD1q64LowQPseudo_UPD:
2966 case ARM::VLD1q64HighTPseudo:
2967 case ARM::VLD1q64HighTPseudo_UPD:
2968 case ARM::VLD1q64LowTPseudo_UPD:
2969 case ARM::VLD4d8Pseudo_UPD:
2970 case ARM::VLD4d16Pseudo_UPD:
2971 case ARM::VLD4d32Pseudo_UPD:
2972 case ARM::VLD4q8Pseudo_UPD:
2973 case ARM::VLD4q16Pseudo_UPD:
2974 case ARM::VLD4q32Pseudo_UPD:
2975 case ARM::VLD4q8oddPseudo:
2976 case ARM::VLD4q16oddPseudo:
2977 case ARM::VLD4q32oddPseudo:
2978 case ARM::VLD4q8oddPseudo_UPD:
2979 case ARM::VLD4q16oddPseudo_UPD:
2980 case ARM::VLD4q32oddPseudo_UPD:
2981 case ARM::VLD3DUPd8Pseudo:
2982 case ARM::VLD3DUPd16Pseudo:
2983 case ARM::VLD3DUPd32Pseudo:
2984 case ARM::VLD3DUPd8Pseudo_UPD:
2985 case ARM::VLD3DUPd16Pseudo_UPD:
2986 case ARM::VLD3DUPd32Pseudo_UPD:
2987 case ARM::VLD4DUPd8Pseudo:
2988 case ARM::VLD4DUPd16Pseudo:
2989 case ARM::VLD4DUPd32Pseudo:
2990 case ARM::VLD4DUPd8Pseudo_UPD:
2991 case ARM::VLD4DUPd16Pseudo_UPD:
2992 case ARM::VLD4DUPd32Pseudo_UPD:
2993 case ARM::VLD2DUPq8EvenPseudo:
2994 case ARM::VLD2DUPq8OddPseudo:
2995 case ARM::VLD2DUPq16EvenPseudo:
2996 case ARM::VLD2DUPq16OddPseudo:
2997 case ARM::VLD2DUPq32EvenPseudo:
2998 case ARM::VLD2DUPq32OddPseudo:
2999 case ARM::VLD2DUPq8OddPseudoWB_fixed:
3000 case ARM::VLD2DUPq8OddPseudoWB_register:
3001 case ARM::VLD2DUPq16OddPseudoWB_fixed:
3002 case ARM::VLD2DUPq16OddPseudoWB_register:
3003 case ARM::VLD2DUPq32OddPseudoWB_fixed:
3004 case ARM::VLD2DUPq32OddPseudoWB_register:
3005 case ARM::VLD3DUPq8EvenPseudo:
3006 case ARM::VLD3DUPq8OddPseudo:
3007 case ARM::VLD3DUPq16EvenPseudo:
3008 case ARM::VLD3DUPq16OddPseudo:
3009 case ARM::VLD3DUPq32EvenPseudo:
3010 case ARM::VLD3DUPq32OddPseudo:
3011 case ARM::VLD3DUPq8OddPseudo_UPD:
3012 case ARM::VLD3DUPq16OddPseudo_UPD:
3013 case ARM::VLD3DUPq32OddPseudo_UPD:
3014 case ARM::VLD4DUPq8EvenPseudo:
3015 case ARM::VLD4DUPq8OddPseudo:
3016 case ARM::VLD4DUPq16EvenPseudo:
3017 case ARM::VLD4DUPq16OddPseudo:
3018 case ARM::VLD4DUPq32EvenPseudo:
3019 case ARM::VLD4DUPq32OddPseudo:
3020 case ARM::VLD4DUPq8OddPseudo_UPD:
3021 case ARM::VLD4DUPq16OddPseudo_UPD:
3022 case ARM::VLD4DUPq32OddPseudo_UPD:
3023 ExpandVLD(MBBI);
3024 return true;
3025
3026 case ARM::VST2q8Pseudo:
3027 case ARM::VST2q16Pseudo:
3028 case ARM::VST2q32Pseudo:
3029 case ARM::VST2q8PseudoWB_fixed:
3030 case ARM::VST2q16PseudoWB_fixed:
3031 case ARM::VST2q32PseudoWB_fixed:
3032 case ARM::VST2q8PseudoWB_register:
3033 case ARM::VST2q16PseudoWB_register:
3034 case ARM::VST2q32PseudoWB_register:
3035 case ARM::VST3d8Pseudo:
3036 case ARM::VST3d16Pseudo:
3037 case ARM::VST3d32Pseudo:
3038 case ARM::VST1d8TPseudo:
3039 case ARM::VST1d8TPseudoWB_fixed:
3040 case ARM::VST1d8TPseudoWB_register:
3041 case ARM::VST1d16TPseudo:
3042 case ARM::VST1d16TPseudoWB_fixed:
3043 case ARM::VST1d16TPseudoWB_register:
3044 case ARM::VST1d32TPseudo:
3045 case ARM::VST1d32TPseudoWB_fixed:
3046 case ARM::VST1d32TPseudoWB_register:
3047 case ARM::VST1d64TPseudo:
3048 case ARM::VST1d64TPseudoWB_fixed:
3049 case ARM::VST1d64TPseudoWB_register:
3050 case ARM::VST3d8Pseudo_UPD:
3051 case ARM::VST3d16Pseudo_UPD:
3052 case ARM::VST3d32Pseudo_UPD:
3053 case ARM::VST3q8Pseudo_UPD:
3054 case ARM::VST3q16Pseudo_UPD:
3055 case ARM::VST3q32Pseudo_UPD:
3056 case ARM::VST3q8oddPseudo:
3057 case ARM::VST3q16oddPseudo:
3058 case ARM::VST3q32oddPseudo:
3059 case ARM::VST3q8oddPseudo_UPD:
3060 case ARM::VST3q16oddPseudo_UPD:
3061 case ARM::VST3q32oddPseudo_UPD:
3062 case ARM::VST4d8Pseudo:
3063 case ARM::VST4d16Pseudo:
3064 case ARM::VST4d32Pseudo:
3065 case ARM::VST1d8QPseudo:
3066 case ARM::VST1d8QPseudoWB_fixed:
3067 case ARM::VST1d8QPseudoWB_register:
3068 case ARM::VST1d16QPseudo:
3069 case ARM::VST1d16QPseudoWB_fixed:
3070 case ARM::VST1d16QPseudoWB_register:
3071 case ARM::VST1d32QPseudo:
3072 case ARM::VST1d32QPseudoWB_fixed:
3073 case ARM::VST1d32QPseudoWB_register:
3074 case ARM::VST1d64QPseudo:
3075 case ARM::VST1d64QPseudoWB_fixed:
3076 case ARM::VST1d64QPseudoWB_register:
3077 case ARM::VST4d8Pseudo_UPD:
3078 case ARM::VST4d16Pseudo_UPD:
3079 case ARM::VST4d32Pseudo_UPD:
3080 case ARM::VST1q8HighQPseudo:
3081 case ARM::VST1q8LowQPseudo_UPD:
3082 case ARM::VST1q8HighTPseudo:
3083 case ARM::VST1q8LowTPseudo_UPD:
3084 case ARM::VST1q16HighQPseudo:
3085 case ARM::VST1q16LowQPseudo_UPD:
3086 case ARM::VST1q16HighTPseudo:
3087 case ARM::VST1q16LowTPseudo_UPD:
3088 case ARM::VST1q32HighQPseudo:
3089 case ARM::VST1q32LowQPseudo_UPD:
3090 case ARM::VST1q32HighTPseudo:
3091 case ARM::VST1q32LowTPseudo_UPD:
3092 case ARM::VST1q64HighQPseudo:
3093 case ARM::VST1q64LowQPseudo_UPD:
3094 case ARM::VST1q64HighTPseudo:
3095 case ARM::VST1q64LowTPseudo_UPD:
3096 case ARM::VST1q8HighTPseudo_UPD:
3097 case ARM::VST1q16HighTPseudo_UPD:
3098 case ARM::VST1q32HighTPseudo_UPD:
3099 case ARM::VST1q64HighTPseudo_UPD:
3100 case ARM::VST1q8HighQPseudo_UPD:
3101 case ARM::VST1q16HighQPseudo_UPD:
3102 case ARM::VST1q32HighQPseudo_UPD:
3103 case ARM::VST1q64HighQPseudo_UPD:
3104 case ARM::VST4q8Pseudo_UPD:
3105 case ARM::VST4q16Pseudo_UPD:
3106 case ARM::VST4q32Pseudo_UPD:
3107 case ARM::VST4q8oddPseudo:
3108 case ARM::VST4q16oddPseudo:
3109 case ARM::VST4q32oddPseudo:
3110 case ARM::VST4q8oddPseudo_UPD:
3111 case ARM::VST4q16oddPseudo_UPD:
3112 case ARM::VST4q32oddPseudo_UPD:
3113 ExpandVST(MBBI);
3114 return true;
3115
3116 case ARM::VLD1LNq8Pseudo:
3117 case ARM::VLD1LNq16Pseudo:
3118 case ARM::VLD1LNq32Pseudo:
3119 case ARM::VLD1LNq8Pseudo_UPD:
3120 case ARM::VLD1LNq16Pseudo_UPD:
3121 case ARM::VLD1LNq32Pseudo_UPD:
3122 case ARM::VLD2LNd8Pseudo:
3123 case ARM::VLD2LNd16Pseudo:
3124 case ARM::VLD2LNd32Pseudo:
3125 case ARM::VLD2LNq16Pseudo:
3126 case ARM::VLD2LNq32Pseudo:
3127 case ARM::VLD2LNd8Pseudo_UPD:
3128 case ARM::VLD2LNd16Pseudo_UPD:
3129 case ARM::VLD2LNd32Pseudo_UPD:
3130 case ARM::VLD2LNq16Pseudo_UPD:
3131 case ARM::VLD2LNq32Pseudo_UPD:
3132 case ARM::VLD3LNd8Pseudo:
3133 case ARM::VLD3LNd16Pseudo:
3134 case ARM::VLD3LNd32Pseudo:
3135 case ARM::VLD3LNq16Pseudo:
3136 case ARM::VLD3LNq32Pseudo:
3137 case ARM::VLD3LNd8Pseudo_UPD:
3138 case ARM::VLD3LNd16Pseudo_UPD:
3139 case ARM::VLD3LNd32Pseudo_UPD:
3140 case ARM::VLD3LNq16Pseudo_UPD:
3141 case ARM::VLD3LNq32Pseudo_UPD:
3142 case ARM::VLD4LNd8Pseudo:
3143 case ARM::VLD4LNd16Pseudo:
3144 case ARM::VLD4LNd32Pseudo:
3145 case ARM::VLD4LNq16Pseudo:
3146 case ARM::VLD4LNq32Pseudo:
3147 case ARM::VLD4LNd8Pseudo_UPD:
3148 case ARM::VLD4LNd16Pseudo_UPD:
3149 case ARM::VLD4LNd32Pseudo_UPD:
3150 case ARM::VLD4LNq16Pseudo_UPD:
3151 case ARM::VLD4LNq32Pseudo_UPD:
3152 case ARM::VST1LNq8Pseudo:
3153 case ARM::VST1LNq16Pseudo:
3154 case ARM::VST1LNq32Pseudo:
3155 case ARM::VST1LNq8Pseudo_UPD:
3156 case ARM::VST1LNq16Pseudo_UPD:
3157 case ARM::VST1LNq32Pseudo_UPD:
3158 case ARM::VST2LNd8Pseudo:
3159 case ARM::VST2LNd16Pseudo:
3160 case ARM::VST2LNd32Pseudo:
3161 case ARM::VST2LNq16Pseudo:
3162 case ARM::VST2LNq32Pseudo:
3163 case ARM::VST2LNd8Pseudo_UPD:
3164 case ARM::VST2LNd16Pseudo_UPD:
3165 case ARM::VST2LNd32Pseudo_UPD:
3166 case ARM::VST2LNq16Pseudo_UPD:
3167 case ARM::VST2LNq32Pseudo_UPD:
3168 case ARM::VST3LNd8Pseudo:
3169 case ARM::VST3LNd16Pseudo:
3170 case ARM::VST3LNd32Pseudo:
3171 case ARM::VST3LNq16Pseudo:
3172 case ARM::VST3LNq32Pseudo:
3173 case ARM::VST3LNd8Pseudo_UPD:
3174 case ARM::VST3LNd16Pseudo_UPD:
3175 case ARM::VST3LNd32Pseudo_UPD:
3176 case ARM::VST3LNq16Pseudo_UPD:
3177 case ARM::VST3LNq32Pseudo_UPD:
3178 case ARM::VST4LNd8Pseudo:
3179 case ARM::VST4LNd16Pseudo:
3180 case ARM::VST4LNd32Pseudo:
3181 case ARM::VST4LNq16Pseudo:
3182 case ARM::VST4LNq32Pseudo:
3183 case ARM::VST4LNd8Pseudo_UPD:
3184 case ARM::VST4LNd16Pseudo_UPD:
3185 case ARM::VST4LNd32Pseudo_UPD:
3186 case ARM::VST4LNq16Pseudo_UPD:
3187 case ARM::VST4LNq32Pseudo_UPD:
3188 ExpandLaneOp(MBBI);
3189 return true;
3190
3191 case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false); return true;
3192 case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true;
3193 case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;
3194 case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;
3195
3196 case ARM::MQQPRLoad:
3197 case ARM::MQQPRStore:
3198 case ARM::MQQQQPRLoad:
3199 case ARM::MQQQQPRStore:
3200 ExpandMQQPRLoadStore(MBBI);
3201 return true;
3202
3203 case ARM::tCMP_SWAP_8:
3204 assert(STI->isThumb());
3205 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, ARM::tUXTB,
3206 NextMBBI);
3207 case ARM::tCMP_SWAP_16:
3208 assert(STI->isThumb());
3209 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, ARM::tUXTH,
3210 NextMBBI);
3211 case ARM::tCMP_SWAP_32:
3212 assert(STI->isThumb());
3213 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0, NextMBBI);
3214
3215 case ARM::CMP_SWAP_8:
3216 assert(!STI->isThumb());
3217 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB, ARM::UXTB,
3218 NextMBBI);
3219 case ARM::CMP_SWAP_16:
3220 assert(!STI->isThumb());
3221 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH,
3222 NextMBBI);
3223 case ARM::CMP_SWAP_32:
3224 assert(!STI->isThumb());
3225 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREX, ARM::STREX, 0, NextMBBI);
3226
3227 case ARM::CMP_SWAP_64:
3228 return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);
3229
3230 case ARM::tBL_PUSHLR:
3231 case ARM::BL_PUSHLR: {
3232 const bool Thumb = Opcode == ARM::tBL_PUSHLR;
3233 Register Reg = MI.getOperand(0).getReg();
3234 assert(Reg == ARM::LR && "expect LR register!");
3235 MachineInstrBuilder MIB;
3236 if (Thumb) {
3237 // push {lr}
3238 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPUSH))
3240 .addReg(Reg);
3241
3242 // bl __gnu_mcount_nc
3243 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tBL));
3244 } else {
3245 // stmdb sp!, {lr}
3246 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::STMDB_UPD))
3247 .addReg(ARM::SP, RegState::Define)
3248 .addReg(ARM::SP)
3250 .addReg(Reg);
3251
3252 // bl __gnu_mcount_nc
3253 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::BL));
3254 }
3255 MIB.cloneMemRefs(MI);
3256 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
3257 MIB.add(MO);
3258 MI.eraseFromParent();
3259 return true;
3260 }
3261 case ARM::t2CALL_BTI: {
3262 MachineFunction &MF = *MI.getMF();
3263 MachineInstrBuilder MIB =
3264 BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::tBL));
3265 MIB.cloneMemRefs(MI);
3266 for (unsigned i = 0; i < MI.getNumOperands(); ++i)
3267 MIB.add(MI.getOperand(i));
3268 if (MI.isCandidateForAdditionalCallInfo())
3270 MIBundleBuilder Bundler(MBB, MI);
3271 Bundler.append(MIB);
3272 Bundler.append(BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::t2BTI)));
3273 finalizeBundle(MBB, Bundler.begin(), Bundler.end());
3274 MI.eraseFromParent();
3275 return true;
3276 }
3277 case ARM::LOADDUAL:
3278 case ARM::STOREDUAL: {
3279 Register PairReg = MI.getOperand(0).getReg();
3280
3281 MachineInstrBuilder MIB =
3282 BuildMI(MBB, MBBI, MI.getDebugLoc(),
3283 TII->get(Opcode == ARM::LOADDUAL ? ARM::LDRD : ARM::STRD))
3284 .addReg(TRI->getSubReg(PairReg, ARM::gsub_0),
3285 getDefRegState(Opcode == ARM::LOADDUAL))
3286 .addReg(TRI->getSubReg(PairReg, ARM::gsub_1),
3287 getDefRegState(Opcode == ARM::LOADDUAL));
3288 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
3289 MIB.add(MO);
3290 MIB.add(predOps(ARMCC::AL));
3291 MIB.cloneMemRefs(MI);
3292 MI.eraseFromParent();
3293 return true;
3294 }
3295 }
3296}
3297
3298bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
3299 bool Modified = false;
3300
3302 while (MBBI != E) {
3303 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
3304 Modified |= ExpandMI(MBB, MBBI, NMBBI);
3305 MBBI = NMBBI;
3306 }
3307
3308 return Modified;
3309}
3310
3311bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
3312 STI = &MF.getSubtarget<ARMSubtarget>();
3313 TII = STI->getInstrInfo();
3314 TRI = STI->getRegisterInfo();
3315 AFI = MF.getInfo<ARMFunctionInfo>();
3316
3317 LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"
3318 << "********** Function: " << MF.getName() << '\n');
3319
3320 bool Modified = false;
3321 for (MachineBasicBlock &MBB : MF)
3322 Modified |= ExpandMBB(MBB);
3323 if (VerifyARMPseudo)
3324 MF.verify(this, "After expanding ARM pseudo instructions.");
3325
3326 LLVM_DEBUG(dbgs() << "***************************************************\n");
3327 return Modified;
3328}
3329
3330/// createARMExpandPseudoPass - returns an instance of the pseudo instruction
3331/// expansion pass.
3333 return new ARMExpandPseudo();
3334}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool determineFPRegsToClear(const MachineInstr &MI, BitVector &ClearRegs)
static void CMSEPopCalleeSaves(const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool Thumb1Only)
static void addExclusiveRegPair(MachineInstrBuilder &MIB, MachineOperand &Reg, RegState Flags, bool IsThumb, const TargetRegisterInfo *TRI)
ARM's ldrexd/strexd take a consecutive register pair (represented as a single GPRPair register),...
static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc, const TargetRegisterInfo *TRI, MCRegister &D0, MCRegister &D1, MCRegister &D2, MCRegister &D3)
GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register, corresponding to the specified regis...
static MachineOperand getMovOperand(const MachineOperand &MO, unsigned TargetFlag)
static MachineOperand makeImplicit(const MachineOperand &MO)
static cl::opt< bool > VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden, cl::desc("Verify machine code after expanding ARM pseudos"))
static bool definesOrUsesFPReg(const MachineInstr &MI)
static void determineGPRegsToClear(const MachineInstr &MI, const std::initializer_list< unsigned > &Regs, SmallVectorImpl< unsigned > &ClearRegs)
static void CMSEPushCalleeSaves(const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register JumpReg, const LivePhysRegs &LiveRegs, bool Thumb1Only)
static bool IsAnAddressOperand(const MachineOperand &MO)
#define ARM_EXPAND_PSEUDO_NAME
static const int CMSE_FP_SAVE_SIZE
static const NEONLdStTableEntry * LookupNEONLdSt(unsigned Opcode)
LookupNEONLdSt - Search the NEONLdStTable for information about a NEON load or store pseudo instructi...
static const NEONLdStTableEntry NEONLdStTable[]
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:483
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const unsigned FramePtr
bool hasBasePointer(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
unsigned getFramePtrSpillOffset() const
bool isTargetMachO() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool isTargetWindows() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool hasMinSize() const
bool isLittle() const
BitVector & reset()
Reset all bits in the bitvector.
Definition BitVector.h:409
size_type count() const
Returns the number of bits which are set.
Definition BitVector.h:181
size_type size() const
Returns the number of bits in this bitvector.
Definition BitVector.h:178
A debug info location.
Definition DebugLoc.h:123
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:358
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
Definition Function.h:689
const HexagonRegisterInfo & getRegisterInfo() const
A set of physical registers with utility functions to track liveness when walking backward/forward th...
bool usesWindowsCFI() const
Definition MCAsmInfo.h:678
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
reverse_iterator rbegin()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Properties which a MachineFunction may have at a given point in time.
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
mop_range implicit_operands()
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
LLVM_ABI void dump() const
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MachineOperand CreateJTI(unsigned Idx, unsigned TargetFlags=0)
const char * getSymbolName() const
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
MCSymbol * getMCSymbol() const
@ MO_CFIIndex
MCCFIInstruction index.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_Predicate
Generic predicate for ISel.
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_ShuffleMask
Other IR Constant for ISel (shuffle masks)
@ MO_CImmediate
Immediate >64bit operand.
@ MO_BlockAddress
Address of a basic block.
@ MO_DbgInstrRef
Integer indices referring to an instruction+operand.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_LaneMask
Mask to represent active parts of registers.
@ MO_FrameIndex
Abstract Stack Frame Index.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_IntrinsicID
Intrinsic ID for ISel.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_TargetIndex
Target-dependent index+offset operand.
@ MO_Metadata
Metadata reference (for debug info)
@ MO_FPImmediate
Floating-point immediate operand.
@ MO_RegisterLiveOut
Mask of live-out registers.
int64_t getOffset() const
Return the offset from the symbol in this operand.
void dump() const
Definition Pass.cpp:146
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
@ MO_LO_0_7
MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...
@ MO_LO_8_15
MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...
@ MO_HI_8_15
MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
@ MO_HI_0_7
MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
unsigned getSOImmTwoPartSecond(unsigned V)
getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...
bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
unsigned getSOImmTwoPartFirst(unsigned V)
getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
Flag
These should be considered private to the implementation of the MCInstrDesc class.
@ ARM
Windows AXP64.
Definition MCAsmInfo.h:49
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1738
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
RegState
Flags to represent properties of register accesses.
@ Kill
The last use of a register.
@ Define
Register definition.
constexpr RegState getKillRegState(bool B)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr RegState getDeadRegState(bool B)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
constexpr RegState getRenamableRegState(bool B)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition STLExtras.h:1969
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2051
void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags=0)
emitThumbRegPlusImmediate - Emits a series of instructions to materialize a destreg = basereg + immed...
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
DWARFExpression::Operation Op
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
FunctionPass * createARMExpandPseudoPass()
createARMExpandPseudoPass - returns an instance of the pseudo instruction expansion pass.
unsigned gettBLXrOpcode(const MachineFunction &MF)
unsigned getBLXOpcode(const MachineFunction &MF)
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
constexpr RegState getUndefRegState(bool B)
void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77