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