LLVM 18.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
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 (!IsVLD2DUP) {
644 if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc ||
645 RegSpc == SingleLowSpc || RegSpc == SingleHighQSpc ||
646 RegSpc == SingleHighTSpc)
647 SrcOpIdx = OpIdx++;
648 }
649
650 // Copy the predicate operands.
651 MIB.add(MI.getOperand(OpIdx++));
652 MIB.add(MI.getOperand(OpIdx++));
653
654 // Copy the super-register source operand used for double-spaced subregs over
655 // to the new instruction as an implicit operand.
656 if (SrcOpIdx != 0) {
657 MachineOperand MO = MI.getOperand(SrcOpIdx);
658 MO.setImplicit(true);
659 MIB.add(MO);
660 }
661 // Add an implicit def for the super-register.
662 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
663 MIB.copyImplicitOps(MI);
664
665 // Transfer memoperands.
666 MIB.cloneMemRefs(MI);
667 MI.eraseFromParent();
668 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
669}
670
671/// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register
672/// operands to real VST instructions with D register operands.
673void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) {
674 MachineInstr &MI = *MBBI;
675 MachineBasicBlock &MBB = *MI.getParent();
676 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
677
678 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
679 assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed");
680 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
681 unsigned NumRegs = TableEntry->NumRegs;
682
683 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
684 TII->get(TableEntry->RealOpc));
685 unsigned OpIdx = 0;
686 if (TableEntry->isUpdating)
687 MIB.add(MI.getOperand(OpIdx++));
688
689 // Copy the addrmode6 operands.
690 MIB.add(MI.getOperand(OpIdx++));
691 MIB.add(MI.getOperand(OpIdx++));
692
693 if (TableEntry->hasWritebackOperand) {
694 // TODO: The writing-back pseudo instructions we translate here are all
695 // defined to take am6offset nodes that are capable to represent both fixed
696 // and register forms. Some real instructions, however, do not rely on
697 // am6offset and have separate definitions for such forms. When this is the
698 // case, fixed forms do not take any offset nodes, so here we skip them for
699 // such instructions. Once all real and pseudo writing-back instructions are
700 // rewritten without use of am6offset nodes, this code will go away.
701 const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);
702 if (TableEntry->RealOpc == ARM::VST1d8Qwb_fixed ||
703 TableEntry->RealOpc == ARM::VST1d16Qwb_fixed ||
704 TableEntry->RealOpc == ARM::VST1d32Qwb_fixed ||
705 TableEntry->RealOpc == ARM::VST1d64Qwb_fixed ||
706 TableEntry->RealOpc == ARM::VST1d8Twb_fixed ||
707 TableEntry->RealOpc == ARM::VST1d16Twb_fixed ||
708 TableEntry->RealOpc == ARM::VST1d32Twb_fixed ||
709 TableEntry->RealOpc == ARM::VST1d64Twb_fixed) {
710 assert(AM6Offset.getReg() == 0 &&
711 "A fixed writing-back pseudo instruction provides an offset "
712 "register!");
713 } else {
714 MIB.add(AM6Offset);
715 }
716 }
717
718 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
719 bool SrcIsUndef = MI.getOperand(OpIdx).isUndef();
720 Register SrcReg = MI.getOperand(OpIdx++).getReg();
721 unsigned D0, D1, D2, D3;
722 GetDSubRegs(SrcReg, RegSpc, TRI, D0, D1, D2, D3);
723 MIB.addReg(D0, getUndefRegState(SrcIsUndef));
724 if (NumRegs > 1 && TableEntry->copyAllListRegs)
725 MIB.addReg(D1, getUndefRegState(SrcIsUndef));
726 if (NumRegs > 2 && TableEntry->copyAllListRegs)
727 MIB.addReg(D2, getUndefRegState(SrcIsUndef));
728 if (NumRegs > 3 && TableEntry->copyAllListRegs)
729 MIB.addReg(D3, getUndefRegState(SrcIsUndef));
730
731 // Copy the predicate operands.
732 MIB.add(MI.getOperand(OpIdx++));
733 MIB.add(MI.getOperand(OpIdx++));
734
735 if (SrcIsKill && !SrcIsUndef) // Add an implicit kill for the super-reg.
736 MIB->addRegisterKilled(SrcReg, TRI, true);
737 else if (!SrcIsUndef)
738 MIB.addReg(SrcReg, RegState::Implicit); // Add implicit uses for src reg.
739 MIB.copyImplicitOps(MI);
740
741 // Transfer memoperands.
742 MIB.cloneMemRefs(MI);
743 MI.eraseFromParent();
744 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
745}
746
747/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ
748/// register operands to real instructions with D register operands.
749void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) {
750 MachineInstr &MI = *MBBI;
751 MachineBasicBlock &MBB = *MI.getParent();
752 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
753
754 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
755 assert(TableEntry && "NEONLdStTable lookup failed");
756 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;
757 unsigned NumRegs = TableEntry->NumRegs;
758 unsigned RegElts = TableEntry->RegElts;
759
760 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
761 TII->get(TableEntry->RealOpc));
762 unsigned OpIdx = 0;
763 // The lane operand is always the 3rd from last operand, before the 2
764 // predicate operands.
765 unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();
766
767 // Adjust the lane and spacing as needed for Q registers.
768 assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");
769 if (RegSpc == EvenDblSpc && Lane >= RegElts) {
770 RegSpc = OddDblSpc;
771 Lane -= RegElts;
772 }
773 assert(Lane < RegElts && "out of range lane for VLD/VST-lane");
774
775 unsigned D0 = 0, D1 = 0, D2 = 0, D3 = 0;
776 unsigned DstReg = 0;
777 bool DstIsDead = false;
778 if (TableEntry->IsLoad) {
779 DstIsDead = MI.getOperand(OpIdx).isDead();
780 DstReg = MI.getOperand(OpIdx++).getReg();
781 GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
782 MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead));
783 if (NumRegs > 1)
784 MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
785 if (NumRegs > 2)
786 MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
787 if (NumRegs > 3)
788 MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
789 }
790
791 if (TableEntry->isUpdating)
792 MIB.add(MI.getOperand(OpIdx++));
793
794 // Copy the addrmode6 operands.
795 MIB.add(MI.getOperand(OpIdx++));
796 MIB.add(MI.getOperand(OpIdx++));
797 // Copy the am6offset operand.
798 if (TableEntry->hasWritebackOperand)
799 MIB.add(MI.getOperand(OpIdx++));
800
801 // Grab the super-register source.
802 MachineOperand MO = MI.getOperand(OpIdx++);
803 if (!TableEntry->IsLoad)
804 GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3);
805
806 // Add the subregs as sources of the new instruction.
807 unsigned SrcFlags = (getUndefRegState(MO.isUndef()) |
808 getKillRegState(MO.isKill()));
809 MIB.addReg(D0, SrcFlags);
810 if (NumRegs > 1)
811 MIB.addReg(D1, SrcFlags);
812 if (NumRegs > 2)
813 MIB.addReg(D2, SrcFlags);
814 if (NumRegs > 3)
815 MIB.addReg(D3, SrcFlags);
816
817 // Add the lane number operand.
818 MIB.addImm(Lane);
819 OpIdx += 1;
820
821 // Copy the predicate operands.
822 MIB.add(MI.getOperand(OpIdx++));
823 MIB.add(MI.getOperand(OpIdx++));
824
825 // Copy the super-register source to be an implicit source.
826 MO.setImplicit(true);
827 MIB.add(MO);
828 if (TableEntry->IsLoad)
829 // Add an implicit def for the super-register.
830 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
831 MIB.copyImplicitOps(MI);
832 // Transfer memoperands.
833 MIB.cloneMemRefs(MI);
834 MI.eraseFromParent();
835}
836
837/// ExpandVTBL - Translate VTBL and VTBX pseudo instructions with Q or QQ
838/// register operands to real instructions with D register operands.
839void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI,
840 unsigned Opc, bool IsExt) {
841 MachineInstr &MI = *MBBI;
842 MachineBasicBlock &MBB = *MI.getParent();
843 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
844
845 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc));
846 unsigned OpIdx = 0;
847
848 // Transfer the destination register operand.
849 MIB.add(MI.getOperand(OpIdx++));
850 if (IsExt) {
851 MachineOperand VdSrc(MI.getOperand(OpIdx++));
852 MIB.add(VdSrc);
853 }
854
855 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
856 Register SrcReg = MI.getOperand(OpIdx++).getReg();
857 unsigned D0, D1, D2, D3;
858 GetDSubRegs(SrcReg, SingleSpc, TRI, D0, D1, D2, D3);
859 MIB.addReg(D0);
860
861 // Copy the other source register operand.
862 MachineOperand VmSrc(MI.getOperand(OpIdx++));
863 MIB.add(VmSrc);
864
865 // Copy the predicate operands.
866 MIB.add(MI.getOperand(OpIdx++));
867 MIB.add(MI.getOperand(OpIdx++));
868
869 // Add an implicit kill and use for the super-reg.
870 MIB.addReg(SrcReg, RegState::Implicit | getKillRegState(SrcIsKill));
871 MIB.copyImplicitOps(MI);
872 MI.eraseFromParent();
873 LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump(););
874}
875
876void ARMExpandPseudo::ExpandMQQPRLoadStore(MachineBasicBlock::iterator &MBBI) {
877 MachineInstr &MI = *MBBI;
878 MachineBasicBlock &MBB = *MI.getParent();
879 unsigned NewOpc =
880 MI.getOpcode() == ARM::MQQPRStore || MI.getOpcode() == ARM::MQQQQPRStore
881 ? ARM::VSTMDIA
882 : ARM::VLDMDIA;
884 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
885
886 unsigned Flags = getKillRegState(MI.getOperand(0).isKill()) |
887 getDefRegState(MI.getOperand(0).isDef());
888 Register SrcReg = MI.getOperand(0).getReg();
889
890 // Copy the destination register.
891 MIB.add(MI.getOperand(1));
892 MIB.add(predOps(ARMCC::AL));
893 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_0), Flags);
894 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_1), Flags);
895 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_2), Flags);
896 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_3), Flags);
897 if (MI.getOpcode() == ARM::MQQQQPRStore ||
898 MI.getOpcode() == ARM::MQQQQPRLoad) {
899 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_4), Flags);
900 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_5), Flags);
901 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_6), Flags);
902 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_7), Flags);
903 }
904
905 if (NewOpc == ARM::VSTMDIA)
906 MIB.addReg(SrcReg, RegState::Implicit);
907
908 MIB.copyImplicitOps(MI);
909 MIB.cloneMemRefs(MI);
910 MI.eraseFromParent();
911}
912
913static bool IsAnAddressOperand(const MachineOperand &MO) {
914 // This check is overly conservative. Unless we are certain that the machine
915 // operand is not a symbol reference, we return that it is a symbol reference.
916 // This is important as the load pair may not be split up Windows.
917 switch (MO.getType()) {
923 return false;
925 return true;
927 return false;
934 return true;
937 return false;
940 return true;
943 return false;
946 llvm_unreachable("should not exist post-isel");
947 }
948 llvm_unreachable("unhandled machine operand type");
949}
950
952 MachineOperand NewMO = MO;
953 NewMO.setImplicit();
954 return NewMO;
955}
956
958 unsigned TargetFlag) {
959 unsigned TF = MO.getTargetFlags() | TargetFlag;
960 switch (MO.getType()) {
962 unsigned Imm = MO.getImm();
963 switch (TargetFlag) {
965 Imm = (Imm >> 24) & 0xff;
966 break;
967 case ARMII::MO_HI_0_7:
968 Imm = (Imm >> 16) & 0xff;
969 break;
971 Imm = (Imm >> 8) & 0xff;
972 break;
973 case ARMII::MO_LO_0_7:
974 Imm = Imm & 0xff;
975 break;
976 case ARMII::MO_HI16:
977 Imm = (Imm >> 16) & 0xffff;
978 break;
979 case ARMII::MO_LO16:
980 Imm = Imm & 0xffff;
981 break;
982 default:
983 llvm_unreachable("Only HI/LO target flags are expected");
984 }
985 return MachineOperand::CreateImm(Imm);
986 }
990 return MachineOperand::CreateJTI(MO.getIndex(), TF);
991 default:
992 return MachineOperand::CreateGA(MO.getGlobal(), MO.getOffset(), TF);
993 }
994}
995
996void ARMExpandPseudo::ExpandTMOV32BitImm(MachineBasicBlock &MBB,
998 MachineInstr &MI = *MBBI;
999 Register DstReg = MI.getOperand(0).getReg();
1000 bool DstIsDead = MI.getOperand(0).isDead();
1001 const MachineOperand &MO = MI.getOperand(1);
1002 unsigned MIFlags = MI.getFlags();
1003
1004 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
1005
1006 // Expand the mov into a sequence of mov/add+lsl of the individual bytes. We
1007 // want to avoid emitting any zero bytes, as they won't change the result, and
1008 // also don't want any pointless shifts, so instead of immediately emitting
1009 // the shift for a byte we keep track of how much we will need to shift and do
1010 // it before the next nonzero byte.
1011 unsigned PendingShift = 0;
1012 for (unsigned Byte = 0; Byte < 4; ++Byte) {
1013 unsigned Flag = Byte == 0 ? ARMII::MO_HI_8_15
1014 : Byte == 1 ? ARMII::MO_HI_0_7
1015 : Byte == 2 ? ARMII::MO_LO_8_15
1017 MachineOperand Operand = getMovOperand(MO, Flag);
1018 bool ZeroImm = Operand.isImm() && Operand.getImm() == 0;
1019 unsigned Op = PendingShift ? ARM::tADDi8 : ARM::tMOVi8;
1020
1021 // Emit the pending shift if we're going to emit this byte or if we've
1022 // reached the end.
1023 if (PendingShift && (!ZeroImm || Byte == 3)) {
1024 MachineInstr *Lsl =
1025 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tLSLri), DstReg)
1026 .add(t1CondCodeOp(true))
1027 .addReg(DstReg)
1028 .addImm(PendingShift)
1030 .setMIFlags(MIFlags);
1031 (void)Lsl;
1032 LLVM_DEBUG(dbgs() << "And: "; Lsl->dump(););
1033 PendingShift = 0;
1034 }
1035
1036 // Emit this byte if it's nonzero.
1037 if (!ZeroImm) {
1039 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Op), DstReg)
1040 .add(t1CondCodeOp(true));
1041 if (Op == ARM::tADDi8)
1042 MIB.addReg(DstReg);
1043 MIB.add(Operand);
1044 MIB.add(predOps(ARMCC::AL));
1045 MIB.setMIFlags(MIFlags);
1046 LLVM_DEBUG(dbgs() << (Op == ARM::tMOVi8 ? "To: " : "And:") << " ";
1047 MIB.getInstr()->dump(););
1048 }
1049
1050 // Don't accumulate the shift value if we've not yet seen a nonzero byte.
1051 if (PendingShift || !ZeroImm)
1052 PendingShift += 8;
1053 }
1054
1055 // The dest is dead on the last instruction we emitted if it was dead on the
1056 // original instruction.
1057 (--MBBI)->getOperand(0).setIsDead(DstIsDead);
1058
1059 MI.eraseFromParent();
1060}
1061
1062void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,
1064 MachineInstr &MI = *MBBI;
1065 unsigned Opcode = MI.getOpcode();
1066 Register PredReg;
1067 ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
1068 Register DstReg = MI.getOperand(0).getReg();
1069 bool DstIsDead = MI.getOperand(0).isDead();
1070 bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;
1071 const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);
1072 bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO);
1073 MachineInstrBuilder LO16, HI16;
1074 LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump());
1075
1076 if (!STI->hasV6T2Ops() &&
1077 (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) {
1078 // FIXME Windows CE supports older ARM CPUs
1079 assert(!STI->isTargetWindows() && "Windows on ARM requires ARMv7+");
1080
1081 assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!");
1082 unsigned ImmVal = (unsigned)MO.getImm();
1083 unsigned SOImmValV1 = 0, SOImmValV2 = 0;
1084
1085 if (ARM_AM::isSOImmTwoPartVal(ImmVal)) { // Expand into a movi + orr.
1086 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg);
1087 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri))
1088 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1089 .addReg(DstReg);
1090 SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
1091 SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
1092 } else { // Expand into a mvn + sub.
1093 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MVNi), DstReg);
1094 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri))
1095 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1096 .addReg(DstReg);
1097 SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(-ImmVal);
1098 SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(-ImmVal);
1099 SOImmValV1 = ~(-SOImmValV1);
1100 }
1101
1102 unsigned MIFlags = MI.getFlags();
1103 LO16 = LO16.addImm(SOImmValV1);
1104 HI16 = HI16.addImm(SOImmValV2);
1105 LO16.cloneMemRefs(MI);
1106 HI16.cloneMemRefs(MI);
1107 LO16.setMIFlags(MIFlags);
1108 HI16.setMIFlags(MIFlags);
1109 LO16.addImm(Pred).addReg(PredReg).add(condCodeOp());
1110 HI16.addImm(Pred).addReg(PredReg).add(condCodeOp());
1111 if (isCC)
1112 LO16.add(makeImplicit(MI.getOperand(1)));
1113 LO16.copyImplicitOps(MI);
1114 HI16.copyImplicitOps(MI);
1115 MI.eraseFromParent();
1116 return;
1117 }
1118
1119 unsigned LO16Opc = 0;
1120 unsigned HI16Opc = 0;
1121 unsigned MIFlags = MI.getFlags();
1122 if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {
1123 LO16Opc = ARM::t2MOVi16;
1124 HI16Opc = ARM::t2MOVTi16;
1125 } else {
1126 LO16Opc = ARM::MOVi16;
1127 HI16Opc = ARM::MOVTi16;
1128 }
1129
1130 LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg);
1131 LO16.setMIFlags(MIFlags);
1132 LO16.add(getMovOperand(MO, ARMII::MO_LO16));
1133 LO16.cloneMemRefs(MI);
1134 LO16.addImm(Pred).addReg(PredReg);
1135 if (isCC)
1136 LO16.add(makeImplicit(MI.getOperand(1)));
1137 LO16.copyImplicitOps(MI);
1138 LLVM_DEBUG(dbgs() << "To: "; LO16.getInstr()->dump(););
1139
1141 if (!(HIOperand.isImm() && HIOperand.getImm() == 0)) {
1142 HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc))
1143 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1144 .addReg(DstReg);
1145 HI16.setMIFlags(MIFlags);
1146 HI16.add(HIOperand);
1147 HI16.cloneMemRefs(MI);
1148 HI16.addImm(Pred).addReg(PredReg);
1149 HI16.copyImplicitOps(MI);
1150 LLVM_DEBUG(dbgs() << "And: "; HI16.getInstr()->dump(););
1151 } else {
1152 LO16->getOperand(0).setIsDead(DstIsDead);
1153 }
1154
1155 if (RequiresBundling)
1157
1158 MI.eraseFromParent();
1159}
1160
1161// The size of the area, accessed by that VLSTM/VLLDM
1162// S0-S31 + FPSCR + 8 more bytes (VPR + pad, or just pad)
1163static const int CMSE_FP_SAVE_SIZE = 136;
1164
1166 const std::initializer_list<unsigned> &Regs,
1167 SmallVectorImpl<unsigned> &ClearRegs) {
1169 for (const MachineOperand &Op : MI.operands()) {
1170 if (!Op.isReg() || !Op.isUse())
1171 continue;
1172 OpRegs.push_back(Op.getReg());
1173 }
1174 llvm::sort(OpRegs);
1175
1176 std::set_difference(Regs.begin(), Regs.end(), OpRegs.begin(), OpRegs.end(),
1177 std::back_inserter(ClearRegs));
1178}
1179
1180void ARMExpandPseudo::CMSEClearGPRegs(
1182 const DebugLoc &DL, const SmallVectorImpl<unsigned> &ClearRegs,
1183 unsigned ClobberReg) {
1184
1185 if (STI->hasV8_1MMainlineOps()) {
1186 // Clear the registers using the CLRM instruction.
1187 MachineInstrBuilder CLRM =
1188 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2CLRM)).add(predOps(ARMCC::AL));
1189 for (unsigned R : ClearRegs)
1190 CLRM.addReg(R, RegState::Define);
1191 CLRM.addReg(ARM::APSR, RegState::Define);
1192 CLRM.addReg(ARM::CPSR, RegState::Define | RegState::Implicit);
1193 } else {
1194 // Clear the registers and flags by copying ClobberReg into them.
1195 // (Baseline can't do a high register clear in one instruction).
1196 for (unsigned Reg : ClearRegs) {
1197 if (Reg == ClobberReg)
1198 continue;
1199 BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVr), Reg)
1200 .addReg(ClobberReg)
1202 }
1203
1204 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2MSR_M))
1205 .addImm(STI->hasDSP() ? 0xc00 : 0x800)
1206 .addReg(ClobberReg)
1208 }
1209}
1210
1211// Find which FP registers need to be cleared. The parameter `ClearRegs` is
1212// initialised with all elements set to true, and this function resets all the
1213// bits, which correspond to register uses. Returns true if any floating point
1214// register is defined, false otherwise.
1216 BitVector &ClearRegs) {
1217 bool DefFP = false;
1218 for (const MachineOperand &Op : MI.operands()) {
1219 if (!Op.isReg())
1220 continue;
1221
1222 Register Reg = Op.getReg();
1223 if (Op.isDef()) {
1224 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||
1225 (Reg >= ARM::D0 && Reg <= ARM::D15) ||
1226 (Reg >= ARM::S0 && Reg <= ARM::S31))
1227 DefFP = true;
1228 continue;
1229 }
1230
1231 if (Reg >= ARM::Q0 && Reg <= ARM::Q7) {
1232 int R = Reg - ARM::Q0;
1233 ClearRegs.reset(R * 4, (R + 1) * 4);
1234 } else if (Reg >= ARM::D0 && Reg <= ARM::D15) {
1235 int R = Reg - ARM::D0;
1236 ClearRegs.reset(R * 2, (R + 1) * 2);
1237 } else if (Reg >= ARM::S0 && Reg <= ARM::S31) {
1238 ClearRegs[Reg - ARM::S0] = false;
1239 }
1240 }
1241 return DefFP;
1242}
1243
1245ARMExpandPseudo::CMSEClearFPRegs(MachineBasicBlock &MBB,
1247 BitVector ClearRegs(16, true);
1248 (void)determineFPRegsToClear(*MBBI, ClearRegs);
1249
1250 if (STI->hasV8_1MMainlineOps())
1251 return CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);
1252 else
1253 return CMSEClearFPRegsV8(MBB, MBBI, ClearRegs);
1254}
1255
1256// Clear the FP registers for v8.0-M, by copying over the content
1257// of LR. Uses R12 as a scratch register.
1259ARMExpandPseudo::CMSEClearFPRegsV8(MachineBasicBlock &MBB,
1261 const BitVector &ClearRegs) {
1262 if (!STI->hasFPRegs())
1263 return MBB;
1264
1265 auto &RetI = *MBBI;
1266 const DebugLoc &DL = RetI.getDebugLoc();
1267
1268 // If optimising for minimum size, clear FP registers unconditionally.
1269 // Otherwise, check the CONTROL.SFPA (Secure Floating-Point Active) bit and
1270 // don't clear them if they belong to the non-secure state.
1271 MachineBasicBlock *ClearBB, *DoneBB;
1272 if (STI->hasMinSize()) {
1273 ClearBB = DoneBB = &MBB;
1274 } else {
1276 ClearBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1278
1279 MF->insert(++MBB.getIterator(), ClearBB);
1280 MF->insert(++ClearBB->getIterator(), DoneBB);
1281
1282 DoneBB->splice(DoneBB->end(), &MBB, MBBI, MBB.end());
1283 DoneBB->transferSuccessors(&MBB);
1284 MBB.addSuccessor(ClearBB);
1285 MBB.addSuccessor(DoneBB);
1286 ClearBB->addSuccessor(DoneBB);
1287
1288 // At the new basic blocks we need to have live-in the registers, used
1289 // for the return value as well as LR, used to clear registers.
1290 for (const MachineOperand &Op : RetI.operands()) {
1291 if (!Op.isReg())
1292 continue;
1293 Register Reg = Op.getReg();
1294 if (Reg == ARM::NoRegister || Reg == ARM::LR)
1295 continue;
1296 assert(Reg.isPhysical() && "Unallocated register");
1297 ClearBB->addLiveIn(Reg);
1298 DoneBB->addLiveIn(Reg);
1299 }
1300 ClearBB->addLiveIn(ARM::LR);
1301 DoneBB->addLiveIn(ARM::LR);
1302
1303 // Read the CONTROL register.
1304 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2MRS_M), ARM::R12)
1305 .addImm(20)
1307 // Check bit 3 (SFPA).
1308 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::t2TSTri))
1309 .addReg(ARM::R12)
1310 .addImm(8)
1312 // If SFPA is clear, jump over ClearBB to DoneBB.
1313 BuildMI(MBB, MBB.end(), DL, TII->get(ARM::tBcc))
1314 .addMBB(DoneBB)
1316 .addReg(ARM::CPSR, RegState::Kill);
1317 }
1318
1319 // Emit the clearing sequence
1320 for (unsigned D = 0; D < 8; D++) {
1321 // Attempt to clear as double
1322 if (ClearRegs[D * 2 + 0] && ClearRegs[D * 2 + 1]) {
1323 unsigned Reg = ARM::D0 + D;
1324 BuildMI(ClearBB, DL, TII->get(ARM::VMOVDRR), Reg)
1325 .addReg(ARM::LR)
1326 .addReg(ARM::LR)
1328 } else {
1329 // Clear first part as single
1330 if (ClearRegs[D * 2 + 0]) {
1331 unsigned Reg = ARM::S0 + D * 2;
1332 BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)
1333 .addReg(ARM::LR)
1335 }
1336 // Clear second part as single
1337 if (ClearRegs[D * 2 + 1]) {
1338 unsigned Reg = ARM::S0 + D * 2 + 1;
1339 BuildMI(ClearBB, DL, TII->get(ARM::VMOVSR), Reg)
1340 .addReg(ARM::LR)
1342 }
1343 }
1344 }
1345
1346 // Clear FPSCR bits 0-4, 7, 28-31
1347 // The other bits are program global according to the AAPCS
1348 BuildMI(ClearBB, DL, TII->get(ARM::VMRS), ARM::R12)
1350 BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)
1351 .addReg(ARM::R12)
1352 .addImm(0x0000009F)
1354 .add(condCodeOp());
1355 BuildMI(ClearBB, DL, TII->get(ARM::t2BICri), ARM::R12)
1356 .addReg(ARM::R12)
1357 .addImm(0xF0000000)
1359 .add(condCodeOp());
1360 BuildMI(ClearBB, DL, TII->get(ARM::VMSR))
1361 .addReg(ARM::R12)
1363
1364 return *DoneBB;
1365}
1366
1368ARMExpandPseudo::CMSEClearFPRegsV81(MachineBasicBlock &MBB,
1370 const BitVector &ClearRegs) {
1371 auto &RetI = *MBBI;
1372
1373 // Emit a sequence of VSCCLRM <sreglist> instructions, one instruction for
1374 // each contiguous sequence of S-registers.
1375 int Start = -1, End = -1;
1376 for (int S = 0, E = ClearRegs.size(); S != E; ++S) {
1377 if (ClearRegs[S] && S == End + 1) {
1378 End = S; // extend range
1379 continue;
1380 }
1381 // Emit current range.
1382 if (Start < End) {
1383 MachineInstrBuilder VSCCLRM =
1384 BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))
1386 while (++Start <= End)
1387 VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);
1388 VSCCLRM.addReg(ARM::VPR, RegState::Define);
1389 }
1390 Start = End = S;
1391 }
1392 // Emit last range.
1393 if (Start < End) {
1394 MachineInstrBuilder VSCCLRM =
1395 BuildMI(MBB, MBBI, RetI.getDebugLoc(), TII->get(ARM::VSCCLRMS))
1397 while (++Start <= End)
1398 VSCCLRM.addReg(ARM::S0 + Start, RegState::Define);
1399 VSCCLRM.addReg(ARM::VPR, RegState::Define);
1400 }
1401
1402 return MBB;
1403}
1404
1405void ARMExpandPseudo::CMSESaveClearFPRegs(
1407 const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {
1408 if (STI->hasV8_1MMainlineOps())
1409 CMSESaveClearFPRegsV81(MBB, MBBI, DL, LiveRegs);
1410 else if (STI->hasV8MMainlineOps())
1411 CMSESaveClearFPRegsV8(MBB, MBBI, DL, LiveRegs, ScratchRegs);
1412}
1413
1414// Save and clear FP registers if present
1415void ARMExpandPseudo::CMSESaveClearFPRegsV8(
1417 const LivePhysRegs &LiveRegs, SmallVectorImpl<unsigned> &ScratchRegs) {
1418
1419 // Store an available register for FPSCR clearing
1420 assert(!ScratchRegs.empty());
1421 unsigned SpareReg = ScratchRegs.front();
1422
1423 // save space on stack for VLSTM
1424 BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)
1425 .addReg(ARM::SP)
1428
1429 // Use ScratchRegs to store the fp regs
1430 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;
1431 std::vector<unsigned> NonclearedFPRegs;
1432 for (const MachineOperand &Op : MBBI->operands()) {
1433 if (Op.isReg() && Op.isUse()) {
1434 Register Reg = Op.getReg();
1435 assert(!ARM::DPRRegClass.contains(Reg) ||
1436 ARM::DPR_VFP2RegClass.contains(Reg));
1437 assert(!ARM::QPRRegClass.contains(Reg));
1438 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1439 if (ScratchRegs.size() >= 2) {
1440 unsigned SaveReg2 = ScratchRegs.pop_back_val();
1441 unsigned SaveReg1 = ScratchRegs.pop_back_val();
1442 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);
1443
1444 // Save the fp register to the normal registers
1445 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))
1446 .addReg(SaveReg1, RegState::Define)
1447 .addReg(SaveReg2, RegState::Define)
1448 .addReg(Reg)
1450 } else {
1451 NonclearedFPRegs.push_back(Reg);
1452 }
1453 } else if (ARM::SPRRegClass.contains(Reg)) {
1454 if (ScratchRegs.size() >= 1) {
1455 unsigned SaveReg = ScratchRegs.pop_back_val();
1456 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);
1457
1458 // Save the fp register to the normal registers
1459 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)
1460 .addReg(Reg)
1462 } else {
1463 NonclearedFPRegs.push_back(Reg);
1464 }
1465 }
1466 }
1467 }
1468
1469 bool passesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
1470
1471 if (passesFPReg)
1472 assert(STI->hasFPRegs() && "Subtarget needs fpregs");
1473
1474 // Lazy store all fp registers to the stack.
1475 // This executes as NOP in the absence of floating-point support.
1476 MachineInstrBuilder VLSTM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))
1477 .addReg(ARM::SP)
1479 for (auto R : {ARM::VPR, ARM::FPSCR, ARM::FPSCR_NZCV, ARM::Q0, ARM::Q1,
1480 ARM::Q2, ARM::Q3, ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7})
1481 VLSTM.addReg(R, RegState::Implicit |
1482 (LiveRegs.contains(R) ? 0 : RegState::Undef));
1483
1484 // Restore all arguments
1485 for (const auto &Regs : ClearedFPRegs) {
1486 unsigned Reg, SaveReg1, SaveReg2;
1487 std::tie(Reg, SaveReg1, SaveReg2) = Regs;
1488 if (ARM::DPR_VFP2RegClass.contains(Reg))
1489 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)
1490 .addReg(SaveReg1)
1491 .addReg(SaveReg2)
1493 else if (ARM::SPRRegClass.contains(Reg))
1494 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)
1495 .addReg(SaveReg1)
1497 }
1498
1499 for (unsigned Reg : NonclearedFPRegs) {
1500 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1501 if (STI->isLittle()) {
1502 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRD), Reg)
1503 .addReg(ARM::SP)
1504 .addImm((Reg - ARM::D0) * 2)
1506 } else {
1507 // For big-endian targets we need to load the two subregisters of Reg
1508 // manually because VLDRD would load them in wrong order
1509 unsigned SReg0 = TRI->getSubReg(Reg, ARM::ssub_0);
1510 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0)
1511 .addReg(ARM::SP)
1512 .addImm((Reg - ARM::D0) * 2)
1514 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), SReg0 + 1)
1515 .addReg(ARM::SP)
1516 .addImm((Reg - ARM::D0) * 2 + 1)
1518 }
1519 } else if (ARM::SPRRegClass.contains(Reg)) {
1520 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDRS), Reg)
1521 .addReg(ARM::SP)
1522 .addImm(Reg - ARM::S0)
1524 }
1525 }
1526 // restore FPSCR from stack and clear bits 0-4, 7, 28-31
1527 // The other bits are program global according to the AAPCS
1528 if (passesFPReg) {
1529 BuildMI(MBB, MBBI, DL, TII->get(ARM::tLDRspi), SpareReg)
1530 .addReg(ARM::SP)
1531 .addImm(0x10)
1533 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)
1534 .addReg(SpareReg)
1535 .addImm(0x0000009F)
1537 .add(condCodeOp());
1538 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), SpareReg)
1539 .addReg(SpareReg)
1540 .addImm(0xF0000000)
1542 .add(condCodeOp());
1543 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMSR))
1544 .addReg(SpareReg)
1546 // The ldr must happen after a floating point instruction. To prevent the
1547 // post-ra scheduler to mess with the order, we create a bundle.
1549 }
1550}
1551
1552void ARMExpandPseudo::CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,
1554 DebugLoc &DL,
1555 const LivePhysRegs &LiveRegs) {
1556 BitVector ClearRegs(32, true);
1557 bool DefFP = determineFPRegsToClear(*MBBI, ClearRegs);
1558
1559 // If the instruction does not write to a FP register and no elements were
1560 // removed from the set, then no FP registers were used to pass
1561 // arguments/returns.
1562 if (!DefFP && ClearRegs.count() == ClearRegs.size()) {
1563 // save space on stack for VLSTM
1564 BuildMI(MBB, MBBI, DL, TII->get(ARM::tSUBspi), ARM::SP)
1565 .addReg(ARM::SP)
1568
1569 // Lazy store all FP registers to the stack
1570 MachineInstrBuilder VLSTM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM))
1571 .addReg(ARM::SP)
1573 for (auto R : {ARM::VPR, ARM::FPSCR, ARM::FPSCR_NZCV, ARM::Q0, ARM::Q1,
1574 ARM::Q2, ARM::Q3, ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7})
1575 VLSTM.addReg(R, RegState::Implicit |
1576 (LiveRegs.contains(R) ? 0 : RegState::Undef));
1577 } else {
1578 // Push all the callee-saved registers (s16-s31).
1579 MachineInstrBuilder VPUSH =
1580 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTMSDB_UPD), ARM::SP)
1581 .addReg(ARM::SP)
1583 for (int Reg = ARM::S16; Reg <= ARM::S31; ++Reg)
1584 VPUSH.addReg(Reg);
1585
1586 // Clear FP registers with a VSCCLRM.
1587 (void)CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);
1588
1589 // Save floating-point context.
1590 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTR_FPCXTS_pre), ARM::SP)
1591 .addReg(ARM::SP)
1592 .addImm(-8)
1594 }
1595}
1596
1597// Restore FP registers if present
1598void ARMExpandPseudo::CMSERestoreFPRegs(
1600 SmallVectorImpl<unsigned> &AvailableRegs) {
1601 if (STI->hasV8_1MMainlineOps())
1602 CMSERestoreFPRegsV81(MBB, MBBI, DL, AvailableRegs);
1603 else if (STI->hasV8MMainlineOps())
1604 CMSERestoreFPRegsV8(MBB, MBBI, DL, AvailableRegs);
1605}
1606
1607void ARMExpandPseudo::CMSERestoreFPRegsV8(
1609 SmallVectorImpl<unsigned> &AvailableRegs) {
1610
1611 // Keep a scratch register for the mitigation sequence.
1612 unsigned ScratchReg = ARM::NoRegister;
1613 if (STI->fixCMSE_CVE_2021_35465())
1614 ScratchReg = AvailableRegs.pop_back_val();
1615
1616 // Use AvailableRegs to store the fp regs
1617 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;
1618 std::vector<unsigned> NonclearedFPRegs;
1619 for (const MachineOperand &Op : MBBI->operands()) {
1620 if (Op.isReg() && Op.isDef()) {
1621 Register Reg = Op.getReg();
1622 assert(!ARM::DPRRegClass.contains(Reg) ||
1623 ARM::DPR_VFP2RegClass.contains(Reg));
1624 assert(!ARM::QPRRegClass.contains(Reg));
1625 if (ARM::DPR_VFP2RegClass.contains(Reg)) {
1626 if (AvailableRegs.size() >= 2) {
1627 unsigned SaveReg2 = AvailableRegs.pop_back_val();
1628 unsigned SaveReg1 = AvailableRegs.pop_back_val();
1629 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);
1630
1631 // Save the fp register to the normal registers
1632 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRRD))
1633 .addReg(SaveReg1, RegState::Define)
1634 .addReg(SaveReg2, RegState::Define)
1635 .addReg(Reg)
1637 } else {
1638 NonclearedFPRegs.push_back(Reg);
1639 }
1640 } else if (ARM::SPRRegClass.contains(Reg)) {
1641 if (AvailableRegs.size() >= 1) {
1642 unsigned SaveReg = AvailableRegs.pop_back_val();
1643 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);
1644
1645 // Save the fp register to the normal registers
1646 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVRS), SaveReg)
1647 .addReg(Reg)
1649 } else {
1650 NonclearedFPRegs.push_back(Reg);
1651 }
1652 }
1653 }
1654 }
1655
1656 bool returnsFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
1657
1658 if (returnsFPReg)
1659 assert(STI->hasFPRegs() && "Subtarget needs fpregs");
1660
1661 // Push FP regs that cannot be restored via normal registers on the stack
1662 for (unsigned Reg : NonclearedFPRegs) {
1663 if (ARM::DPR_VFP2RegClass.contains(Reg))
1664 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRD))
1665 .addReg(Reg)
1666 .addReg(ARM::SP)
1667 .addImm((Reg - ARM::D0) * 2)
1669 else if (ARM::SPRRegClass.contains(Reg))
1670 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSTRS))
1671 .addReg(Reg)
1672 .addReg(ARM::SP)
1673 .addImm(Reg - ARM::S0)
1675 }
1676
1677 // Lazy load fp regs from stack.
1678 // This executes as NOP in the absence of floating-point support.
1679 MachineInstrBuilder VLLDM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))
1680 .addReg(ARM::SP)
1682
1683 if (STI->fixCMSE_CVE_2021_35465()) {
1684 auto Bundler = MIBundleBuilder(MBB, VLLDM);
1685 // Read the CONTROL register.
1686 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2MRS_M))
1687 .addReg(ScratchReg, RegState::Define)
1688 .addImm(20)
1689 .add(predOps(ARMCC::AL)));
1690 // Check bit 3 (SFPA).
1691 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2TSTri))
1692 .addReg(ScratchReg)
1693 .addImm(8)
1694 .add(predOps(ARMCC::AL)));
1695 // Emit the IT block.
1696 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::t2IT))
1698 .addImm(8));
1699 // If SFPA is clear jump over to VLLDM, otherwise execute an instruction
1700 // which has no functional effect apart from causing context creation:
1701 // vmovne s0, s0. In the absence of FPU we emit .inst.w 0xeeb00a40,
1702 // which is defined as NOP if not executed.
1703 if (STI->hasFPRegs())
1704 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::VMOVS))
1705 .addReg(ARM::S0, RegState::Define)
1706 .addReg(ARM::S0, RegState::Undef)
1707 .add(predOps(ARMCC::NE)));
1708 else
1709 Bundler.append(BuildMI(*MBB.getParent(), DL, TII->get(ARM::INLINEASM))
1710 .addExternalSymbol(".inst.w 0xeeb00a40")
1712 finalizeBundle(MBB, Bundler.begin(), Bundler.end());
1713 }
1714
1715 // Restore all FP registers via normal registers
1716 for (const auto &Regs : ClearedFPRegs) {
1717 unsigned Reg, SaveReg1, SaveReg2;
1718 std::tie(Reg, SaveReg1, SaveReg2) = Regs;
1719 if (ARM::DPR_VFP2RegClass.contains(Reg))
1720 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVDRR), Reg)
1721 .addReg(SaveReg1)
1722 .addReg(SaveReg2)
1724 else if (ARM::SPRRegClass.contains(Reg))
1725 BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVSR), Reg)
1726 .addReg(SaveReg1)
1728 }
1729
1730 // Pop the stack space
1731 BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)
1732 .addReg(ARM::SP)
1735}
1736
1738 for (const MachineOperand &Op : MI.operands()) {
1739 if (!Op.isReg())
1740 continue;
1741 Register Reg = Op.getReg();
1742 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||
1743 (Reg >= ARM::D0 && Reg <= ARM::D15) ||
1744 (Reg >= ARM::S0 && Reg <= ARM::S31))
1745 return true;
1746 }
1747 return false;
1748}
1749
1750void ARMExpandPseudo::CMSERestoreFPRegsV81(
1752 SmallVectorImpl<unsigned> &AvailableRegs) {
1753 if (!definesOrUsesFPReg(*MBBI)) {
1754 if (STI->fixCMSE_CVE_2021_35465()) {
1755 BuildMI(MBB, MBBI, DL, TII->get(ARM::VSCCLRMS))
1757 .addReg(ARM::VPR, RegState::Define);
1758 }
1759
1760 // Load FP registers from stack.
1761 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM))
1762 .addReg(ARM::SP)
1764
1765 // Pop the stack space
1766 BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP)
1767 .addReg(ARM::SP)
1770 } else {
1771 // Restore the floating point context.
1772 BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(ARM::VLDR_FPCXTS_post),
1773 ARM::SP)
1774 .addReg(ARM::SP)
1775 .addImm(8)
1777
1778 // Pop all the callee-saved registers (s16-s31).
1779 MachineInstrBuilder VPOP =
1780 BuildMI(MBB, MBBI, DL, TII->get(ARM::VLDMSIA_UPD), ARM::SP)
1781 .addReg(ARM::SP)
1783 for (int Reg = ARM::S16; Reg <= ARM::S31; ++Reg)
1784 VPOP.addReg(Reg, RegState::Define);
1785 }
1786}
1787
1788/// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as
1789/// possible. This only gets used at -O0 so we don't care about efficiency of
1790/// the generated code.
1791bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,
1793 unsigned LdrexOp, unsigned StrexOp,
1794 unsigned UxtOp,
1795 MachineBasicBlock::iterator &NextMBBI) {
1796 bool IsThumb = STI->isThumb();
1797 bool IsThumb1Only = STI->isThumb1Only();
1798 MachineInstr &MI = *MBBI;
1799 DebugLoc DL = MI.getDebugLoc();
1800 const MachineOperand &Dest = MI.getOperand(0);
1801 Register TempReg = MI.getOperand(1).getReg();
1802 // Duplicating undef operands into 2 instructions does not guarantee the same
1803 // value on both; However undef should be replaced by xzr anyway.
1804 assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
1805 Register AddrReg = MI.getOperand(2).getReg();
1806 Register DesiredReg = MI.getOperand(3).getReg();
1807 Register NewReg = MI.getOperand(4).getReg();
1808
1809 if (IsThumb) {
1810 assert(STI->hasV8MBaselineOps() &&
1811 "CMP_SWAP not expected to be custom expanded for Thumb1");
1812 assert((UxtOp == 0 || UxtOp == ARM::tUXTB || UxtOp == ARM::tUXTH) &&
1813 "ARMv8-M.baseline does not have t2UXTB/t2UXTH");
1814 assert((UxtOp == 0 || ARM::tGPRRegClass.contains(DesiredReg)) &&
1815 "DesiredReg used for UXT op must be tGPR");
1816 }
1817
1819 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1820 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1821 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1822
1823 MF->insert(++MBB.getIterator(), LoadCmpBB);
1824 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
1825 MF->insert(++StoreBB->getIterator(), DoneBB);
1826
1827 if (UxtOp) {
1829 BuildMI(MBB, MBBI, DL, TII->get(UxtOp), DesiredReg)
1830 .addReg(DesiredReg, RegState::Kill);
1831 if (!IsThumb)
1832 MIB.addImm(0);
1833 MIB.add(predOps(ARMCC::AL));
1834 }
1835
1836 // .Lloadcmp:
1837 // ldrex rDest, [rAddr]
1838 // cmp rDest, rDesired
1839 // bne .Ldone
1840
1842 MIB = BuildMI(LoadCmpBB, DL, TII->get(LdrexOp), Dest.getReg());
1843 MIB.addReg(AddrReg);
1844 if (LdrexOp == ARM::t2LDREX)
1845 MIB.addImm(0); // a 32-bit Thumb ldrex (only) allows an offset.
1846 MIB.add(predOps(ARMCC::AL));
1847
1848 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
1849 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
1850 .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
1851 .addReg(DesiredReg)
1853 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
1854 BuildMI(LoadCmpBB, DL, TII->get(Bcc))
1855 .addMBB(DoneBB)
1857 .addReg(ARM::CPSR, RegState::Kill);
1858 LoadCmpBB->addSuccessor(DoneBB);
1859 LoadCmpBB->addSuccessor(StoreBB);
1860
1861 // .Lstore:
1862 // strex rTempReg, rNew, [rAddr]
1863 // cmp rTempReg, #0
1864 // bne .Lloadcmp
1865 MIB = BuildMI(StoreBB, DL, TII->get(StrexOp), TempReg)
1866 .addReg(NewReg)
1867 .addReg(AddrReg);
1868 if (StrexOp == ARM::t2STREX)
1869 MIB.addImm(0); // a 32-bit Thumb strex (only) allows an offset.
1870 MIB.add(predOps(ARMCC::AL));
1871
1872 unsigned CMPri =
1873 IsThumb ? (IsThumb1Only ? ARM::tCMPi8 : ARM::t2CMPri) : ARM::CMPri;
1874 BuildMI(StoreBB, DL, TII->get(CMPri))
1875 .addReg(TempReg, RegState::Kill)
1876 .addImm(0)
1878 BuildMI(StoreBB, DL, TII->get(Bcc))
1879 .addMBB(LoadCmpBB)
1881 .addReg(ARM::CPSR, RegState::Kill);
1882 StoreBB->addSuccessor(LoadCmpBB);
1883 StoreBB->addSuccessor(DoneBB);
1884
1885 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
1886 DoneBB->transferSuccessors(&MBB);
1887
1888 MBB.addSuccessor(LoadCmpBB);
1889
1890 NextMBBI = MBB.end();
1891 MI.eraseFromParent();
1892
1893 // Recompute livein lists.
1894 LivePhysRegs LiveRegs;
1895 computeAndAddLiveIns(LiveRegs, *DoneBB);
1896 computeAndAddLiveIns(LiveRegs, *StoreBB);
1897 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
1898 // Do an extra pass around the loop to get loop carried registers right.
1899 StoreBB->clearLiveIns();
1900 computeAndAddLiveIns(LiveRegs, *StoreBB);
1901 LoadCmpBB->clearLiveIns();
1902 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
1903
1904 return true;
1905}
1906
1907/// ARM's ldrexd/strexd take a consecutive register pair (represented as a
1908/// single GPRPair register), Thumb's take two separate registers so we need to
1909/// extract the subregs from the pair.
1911 unsigned Flags, bool IsThumb,
1912 const TargetRegisterInfo *TRI) {
1913 if (IsThumb) {
1914 Register RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);
1915 Register RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);
1916 MIB.addReg(RegLo, Flags);
1917 MIB.addReg(RegHi, Flags);
1918 } else
1919 MIB.addReg(Reg.getReg(), Flags);
1920}
1921
1922/// Expand a 64-bit CMP_SWAP to an ldrexd/strexd loop.
1923bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
1925 MachineBasicBlock::iterator &NextMBBI) {
1926 bool IsThumb = STI->isThumb();
1927 assert(!STI->isThumb1Only() && "CMP_SWAP_64 unsupported under Thumb1!");
1928 MachineInstr &MI = *MBBI;
1929 DebugLoc DL = MI.getDebugLoc();
1930 MachineOperand &Dest = MI.getOperand(0);
1931 Register TempReg = MI.getOperand(1).getReg();
1932 // Duplicating undef operands into 2 instructions does not guarantee the same
1933 // value on both; However undef should be replaced by xzr anyway.
1934 assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
1935 Register AddrReg = MI.getOperand(2).getReg();
1936 Register DesiredReg = MI.getOperand(3).getReg();
1937 MachineOperand New = MI.getOperand(4);
1938 New.setIsKill(false);
1939
1940 Register DestLo = TRI->getSubReg(Dest.getReg(), ARM::gsub_0);
1941 Register DestHi = TRI->getSubReg(Dest.getReg(), ARM::gsub_1);
1942 Register DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);
1943 Register DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);
1944
1946 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1947 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1948 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
1949
1950 MF->insert(++MBB.getIterator(), LoadCmpBB);
1951 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
1952 MF->insert(++StoreBB->getIterator(), DoneBB);
1953
1954 // .Lloadcmp:
1955 // ldrexd rDestLo, rDestHi, [rAddr]
1956 // cmp rDestLo, rDesiredLo
1957 // sbcs dead rTempReg, rDestHi, rDesiredHi
1958 // bne .Ldone
1959 unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
1961 MIB = BuildMI(LoadCmpBB, DL, TII->get(LDREXD));
1962 addExclusiveRegPair(MIB, Dest, RegState::Define, IsThumb, TRI);
1963 MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
1964
1965 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;
1966 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
1967 .addReg(DestLo, getKillRegState(Dest.isDead()))
1968 .addReg(DesiredLo)
1970
1971 BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
1972 .addReg(DestHi, getKillRegState(Dest.isDead()))
1973 .addReg(DesiredHi)
1974 .addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
1975
1976 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
1977 BuildMI(LoadCmpBB, DL, TII->get(Bcc))
1978 .addMBB(DoneBB)
1980 .addReg(ARM::CPSR, RegState::Kill);
1981 LoadCmpBB->addSuccessor(DoneBB);
1982 LoadCmpBB->addSuccessor(StoreBB);
1983
1984 // .Lstore:
1985 // strexd rTempReg, rNewLo, rNewHi, [rAddr]
1986 // cmp rTempReg, #0
1987 // bne .Lloadcmp
1988 unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;
1989 MIB = BuildMI(StoreBB, DL, TII->get(STREXD), TempReg);
1990 unsigned Flags = getKillRegState(New.isDead());
1991 addExclusiveRegPair(MIB, New, Flags, IsThumb, TRI);
1992 MIB.addReg(AddrReg).add(predOps(ARMCC::AL));
1993
1994 unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;
1995 BuildMI(StoreBB, DL, TII->get(CMPri))
1996 .addReg(TempReg, RegState::Kill)
1997 .addImm(0)
1999 BuildMI(StoreBB, DL, TII->get(Bcc))
2000 .addMBB(LoadCmpBB)
2002 .addReg(ARM::CPSR, RegState::Kill);
2003 StoreBB->addSuccessor(LoadCmpBB);
2004 StoreBB->addSuccessor(DoneBB);
2005
2006 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
2007 DoneBB->transferSuccessors(&MBB);
2008
2009 MBB.addSuccessor(LoadCmpBB);
2010
2011 NextMBBI = MBB.end();
2012 MI.eraseFromParent();
2013
2014 // Recompute livein lists.
2015 LivePhysRegs LiveRegs;
2016 computeAndAddLiveIns(LiveRegs, *DoneBB);
2017 computeAndAddLiveIns(LiveRegs, *StoreBB);
2018 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
2019 // Do an extra pass around the loop to get loop carried registers right.
2020 StoreBB->clearLiveIns();
2021 computeAndAddLiveIns(LiveRegs, *StoreBB);
2022 LoadCmpBB->clearLiveIns();
2023 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
2024
2025 return true;
2026}
2027
2030 MachineBasicBlock::iterator MBBI, int JumpReg,
2031 const LivePhysRegs &LiveRegs, bool Thumb1Only) {
2032 const DebugLoc &DL = MBBI->getDebugLoc();
2033 if (Thumb1Only) { // push Lo and Hi regs separately
2034 MachineInstrBuilder PushMIB =
2035 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
2036 for (int Reg = ARM::R4; Reg < ARM::R8; ++Reg) {
2037 PushMIB.addReg(
2038 Reg, Reg == JumpReg || LiveRegs.contains(Reg) ? 0 : RegState::Undef);
2039 }
2040
2041 // Thumb1 can only tPUSH low regs, so we copy the high regs to the low
2042 // regs that we just saved and push the low regs again, taking care to
2043 // not clobber JumpReg. If JumpReg is one of the low registers, push first
2044 // the values of r9-r11, and then r8. That would leave them ordered in
2045 // memory, and allow us to later pop them with a single instructions.
2046 // FIXME: Could also use any of r0-r3 that are free (including in the
2047 // first PUSH above).
2048 for (int LoReg = ARM::R7, HiReg = ARM::R11; LoReg >= ARM::R4; --LoReg) {
2049 if (JumpReg == LoReg)
2050 continue;
2051 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)
2052 .addReg(HiReg, LiveRegs.contains(HiReg) ? 0 : RegState::Undef)
2054 --HiReg;
2055 }
2056 MachineInstrBuilder PushMIB2 =
2057 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH)).add(predOps(ARMCC::AL));
2058 for (int Reg = ARM::R4; Reg < ARM::R8; ++Reg) {
2059 if (Reg == JumpReg)
2060 continue;
2061 PushMIB2.addReg(Reg, RegState::Kill);
2062 }
2063
2064 // If we couldn't use a low register for temporary storage (because it was
2065 // the JumpReg), use r4 or r5, whichever is not JumpReg. It has already been
2066 // saved.
2067 if (JumpReg >= ARM::R4 && JumpReg <= ARM::R7) {
2068 int LoReg = JumpReg == ARM::R4 ? ARM::R5 : ARM::R4;
2069 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), LoReg)
2070 .addReg(ARM::R8, LiveRegs.contains(ARM::R8) ? 0 : RegState::Undef)
2072 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPUSH))
2074 .addReg(LoReg, RegState::Kill);
2075 }
2076 } else { // push Lo and Hi registers with a single instruction
2077 MachineInstrBuilder PushMIB =
2078 BuildMI(MBB, MBBI, DL, TII.get(ARM::t2STMDB_UPD), ARM::SP)
2079 .addReg(ARM::SP)
2081 for (int Reg = ARM::R4; Reg < ARM::R12; ++Reg) {
2082 PushMIB.addReg(
2083 Reg, Reg == JumpReg || LiveRegs.contains(Reg) ? 0 : RegState::Undef);
2084 }
2085 }
2086}
2087
2090 MachineBasicBlock::iterator MBBI, int JumpReg,
2091 bool Thumb1Only) {
2092 const DebugLoc &DL = MBBI->getDebugLoc();
2093 if (Thumb1Only) {
2094 MachineInstrBuilder PopMIB =
2095 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
2096 for (int R = 0; R < 4; ++R) {
2097 PopMIB.addReg(ARM::R4 + R, RegState::Define);
2098 BuildMI(MBB, MBBI, DL, TII.get(ARM::tMOVr), ARM::R8 + R)
2099 .addReg(ARM::R4 + R, RegState::Kill)
2101 }
2102 MachineInstrBuilder PopMIB2 =
2103 BuildMI(MBB, MBBI, DL, TII.get(ARM::tPOP)).add(predOps(ARMCC::AL));
2104 for (int R = 0; R < 4; ++R)
2105 PopMIB2.addReg(ARM::R4 + R, RegState::Define);
2106 } else { // pop Lo and Hi registers with a single instruction
2107 MachineInstrBuilder PopMIB =
2108 BuildMI(MBB, MBBI, DL, TII.get(ARM::t2LDMIA_UPD), ARM::SP)
2109 .addReg(ARM::SP)
2111 for (int Reg = ARM::R4; Reg < ARM::R12; ++Reg)
2112 PopMIB.addReg(Reg, RegState::Define);
2113 }
2114}
2115
2116bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
2118 MachineBasicBlock::iterator &NextMBBI) {
2119 MachineInstr &MI = *MBBI;
2120 unsigned Opcode = MI.getOpcode();
2121 switch (Opcode) {
2122 default:
2123 return false;
2124
2125 case ARM::VBSPd:
2126 case ARM::VBSPq: {
2127 Register DstReg = MI.getOperand(0).getReg();
2128 if (DstReg == MI.getOperand(3).getReg()) {
2129 // Expand to VBIT
2130 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBITd : ARM::VBITq;
2131 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2132 .add(MI.getOperand(0))
2133 .add(MI.getOperand(3))
2134 .add(MI.getOperand(2))
2135 .add(MI.getOperand(1))
2136 .addImm(MI.getOperand(4).getImm())
2137 .add(MI.getOperand(5));
2138 } else if (DstReg == MI.getOperand(2).getReg()) {
2139 // Expand to VBIF
2140 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBIFd : ARM::VBIFq;
2141 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2142 .add(MI.getOperand(0))
2143 .add(MI.getOperand(2))
2144 .add(MI.getOperand(3))
2145 .add(MI.getOperand(1))
2146 .addImm(MI.getOperand(4).getImm())
2147 .add(MI.getOperand(5));
2148 } else {
2149 // Expand to VBSL
2150 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBSLd : ARM::VBSLq;
2151 if (DstReg == MI.getOperand(1).getReg()) {
2152 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2153 .add(MI.getOperand(0))
2154 .add(MI.getOperand(1))
2155 .add(MI.getOperand(2))
2156 .add(MI.getOperand(3))
2157 .addImm(MI.getOperand(4).getImm())
2158 .add(MI.getOperand(5));
2159 } else {
2160 // Use move to satisfy constraints
2161 unsigned MoveOpc = Opcode == ARM::VBSPd ? ARM::VORRd : ARM::VORRq;
2162 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MoveOpc))
2163 .addReg(DstReg,
2165 getRenamableRegState(MI.getOperand(0).isRenamable()))
2166 .add(MI.getOperand(1))
2167 .add(MI.getOperand(1))
2168 .addImm(MI.getOperand(4).getImm())
2169 .add(MI.getOperand(5));
2170 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc))
2171 .add(MI.getOperand(0))
2172 .addReg(DstReg,
2174 getRenamableRegState(MI.getOperand(0).isRenamable()))
2175 .add(MI.getOperand(2))
2176 .add(MI.getOperand(3))
2177 .addImm(MI.getOperand(4).getImm())
2178 .add(MI.getOperand(5));
2179 }
2180 }
2181 MI.eraseFromParent();
2182 return true;
2183 }
2184
2185 case ARM::TCRETURNdi:
2186 case ARM::TCRETURNri: {
2188 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2189 MBBI--;
2190 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2191 MBBI--;
2192 assert(MBBI->isReturn() &&
2193 "Can only insert epilog into returning blocks");
2194 unsigned RetOpcode = MBBI->getOpcode();
2195 DebugLoc dl = MBBI->getDebugLoc();
2196 const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(
2198
2199 // Tail call return: adjust the stack pointer and jump to callee.
2201 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2202 MBBI--;
2203 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2204 MBBI--;
2205 MachineOperand &JumpTarget = MBBI->getOperand(0);
2206
2207 // Jump to label or value in register.
2208 if (RetOpcode == ARM::TCRETURNdi) {
2210 bool NeedsWinCFI = MF->getTarget().getMCAsmInfo()->usesWindowsCFI() &&
2212 unsigned TCOpcode =
2213 STI->isThumb()
2214 ? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd
2215 : ARM::tTAILJMPdND)
2216 : ARM::TAILJMPd;
2217 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
2218 if (JumpTarget.isGlobal())
2219 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
2220 JumpTarget.getTargetFlags());
2221 else {
2222 assert(JumpTarget.isSymbol());
2223 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
2224 JumpTarget.getTargetFlags());
2225 }
2226
2227 // Add the default predicate in Thumb mode.
2228 if (STI->isThumb())
2229 MIB.add(predOps(ARMCC::AL));
2230 } else if (RetOpcode == ARM::TCRETURNri) {
2231 unsigned Opcode =
2232 STI->isThumb() ? ARM::tTAILJMPr
2233 : (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);
2234 BuildMI(MBB, MBBI, dl,
2235 TII.get(Opcode))
2236 .addReg(JumpTarget.getReg(), RegState::Kill);
2237 }
2238
2239 auto NewMI = std::prev(MBBI);
2240 for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)
2241 NewMI->addOperand(MBBI->getOperand(i));
2242
2243
2244 // Update call site info and delete the pseudo instruction TCRETURN.
2245 if (MI.isCandidateForCallSiteEntry())
2246 MI.getMF()->moveCallSiteInfo(&MI, &*NewMI);
2247 // Copy nomerge flag over to new instruction.
2248 if (MI.getFlag(MachineInstr::NoMerge))
2249 NewMI->setFlag(MachineInstr::NoMerge);
2250 MBB.erase(MBBI);
2251
2252 MBBI = NewMI;
2253 return true;
2254 }
2255 case ARM::tBXNS_RET: {
2256 // For v8.0-M.Main we need to authenticate LR before clearing FPRs, which
2257 // uses R12 as a scratch register.
2258 if (!STI->hasV8_1MMainlineOps() && AFI->shouldSignReturnAddress())
2259 BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARM::t2AUT));
2260
2261 MachineBasicBlock &AfterBB = CMSEClearFPRegs(MBB, MBBI);
2262
2263 if (STI->hasV8_1MMainlineOps()) {
2264 // Restore the non-secure floating point context.
2265 BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
2266 TII->get(ARM::VLDR_FPCXTNS_post), ARM::SP)
2267 .addReg(ARM::SP)
2268 .addImm(4)
2270
2271 if (AFI->shouldSignReturnAddress())
2272 BuildMI(AfterBB, AfterBB.end(), DebugLoc(), TII->get(ARM::t2AUT));
2273 }
2274
2275 // Clear all GPR that are not a use of the return instruction.
2276 assert(llvm::all_of(MBBI->operands(), [](const MachineOperand &Op) {
2277 return !Op.isReg() || Op.getReg() != ARM::R12;
2278 }));
2279 SmallVector<unsigned, 5> ClearRegs;
2281 *MBBI, {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R12}, ClearRegs);
2282 CMSEClearGPRegs(AfterBB, AfterBB.end(), MBBI->getDebugLoc(), ClearRegs,
2283 ARM::LR);
2284
2285 MachineInstrBuilder NewMI =
2286 BuildMI(AfterBB, AfterBB.end(), MBBI->getDebugLoc(),
2287 TII->get(ARM::tBXNS))
2288 .addReg(ARM::LR)
2290 for (const MachineOperand &Op : MI.operands())
2291 NewMI->addOperand(Op);
2292 MI.eraseFromParent();
2293 return true;
2294 }
2295 case ARM::tBLXNS_CALL: {
2296 DebugLoc DL = MBBI->getDebugLoc();
2297 Register JumpReg = MBBI->getOperand(0).getReg();
2298
2299 // Figure out which registers are live at the point immediately before the
2300 // call. When we indiscriminately push a set of registers, the live
2301 // registers are added as ordinary use operands, whereas dead registers
2302 // are "undef".
2303 LivePhysRegs LiveRegs(*TRI);
2304 LiveRegs.addLiveOuts(MBB);
2305 for (const MachineInstr &MI : make_range(MBB.rbegin(), MBBI.getReverse()))
2306 LiveRegs.stepBackward(MI);
2307 LiveRegs.stepBackward(*MBBI);
2308
2309 CMSEPushCalleeSaves(*TII, MBB, MBBI, JumpReg, LiveRegs,
2310 AFI->isThumb1OnlyFunction());
2311
2312 SmallVector<unsigned, 16> ClearRegs;
2314 {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4,
2315 ARM::R5, ARM::R6, ARM::R7, ARM::R8, ARM::R9,
2316 ARM::R10, ARM::R11, ARM::R12},
2317 ClearRegs);
2318 auto OriginalClearRegs = ClearRegs;
2319
2320 // Get the first cleared register as a scratch (to use later with tBIC).
2321 // We need to use the first so we can ensure it is a low register.
2322 unsigned ScratchReg = ClearRegs.front();
2323
2324 // Clear LSB of JumpReg
2325 if (AFI->isThumb2Function()) {
2326 BuildMI(MBB, MBBI, DL, TII->get(ARM::t2BICri), JumpReg)
2327 .addReg(JumpReg)
2328 .addImm(1)
2330 .add(condCodeOp());
2331 } else {
2332 // We need to use an extra register to cope with 8M Baseline,
2333 // since we have saved all of the registers we are ok to trash a non
2334 // argument register here.
2335 BuildMI(MBB, MBBI, DL, TII->get(ARM::tMOVi8), ScratchReg)
2336 .add(condCodeOp())
2337 .addImm(1)
2339 BuildMI(MBB, MBBI, DL, TII->get(ARM::tBIC), JumpReg)
2340 .addReg(ARM::CPSR, RegState::Define)
2341 .addReg(JumpReg)
2342 .addReg(ScratchReg)
2344 }
2345
2346 CMSESaveClearFPRegs(MBB, MBBI, DL, LiveRegs,
2347 ClearRegs); // save+clear FP regs with ClearRegs
2348 CMSEClearGPRegs(MBB, MBBI, DL, ClearRegs, JumpReg);
2349
2350 const MachineInstrBuilder NewCall =
2351 BuildMI(MBB, MBBI, DL, TII->get(ARM::tBLXNSr))
2353 .addReg(JumpReg, RegState::Kill);
2354
2355 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
2356 NewCall->addOperand(MO);
2357 if (MI.isCandidateForCallSiteEntry())
2358 MI.getMF()->moveCallSiteInfo(&MI, NewCall.getInstr());
2359
2360 CMSERestoreFPRegs(MBB, MBBI, DL, OriginalClearRegs); // restore FP registers
2361
2362 CMSEPopCalleeSaves(*TII, MBB, MBBI, JumpReg, AFI->isThumb1OnlyFunction());
2363
2364 MI.eraseFromParent();
2365 return true;
2366 }
2367 case ARM::VMOVHcc:
2368 case ARM::VMOVScc:
2369 case ARM::VMOVDcc: {
2370 unsigned newOpc = Opcode != ARM::VMOVDcc ? ARM::VMOVS : ARM::VMOVD;
2371 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(newOpc),
2372 MI.getOperand(1).getReg())
2373 .add(MI.getOperand(2))
2374 .addImm(MI.getOperand(3).getImm()) // 'pred'
2375 .add(MI.getOperand(4))
2376 .add(makeImplicit(MI.getOperand(1)));
2377
2378 MI.eraseFromParent();
2379 return true;
2380 }
2381 case ARM::t2MOVCCr:
2382 case ARM::MOVCCr: {
2383 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVr : ARM::MOVr;
2384 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2385 MI.getOperand(1).getReg())
2386 .add(MI.getOperand(2))
2387 .addImm(MI.getOperand(3).getImm()) // 'pred'
2388 .add(MI.getOperand(4))
2389 .add(condCodeOp()) // 's' bit
2390 .add(makeImplicit(MI.getOperand(1)));
2391
2392 MI.eraseFromParent();
2393 return true;
2394 }
2395 case ARM::MOVCCsi: {
2396 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2397 (MI.getOperand(1).getReg()))
2398 .add(MI.getOperand(2))
2399 .addImm(MI.getOperand(3).getImm())
2400 .addImm(MI.getOperand(4).getImm()) // 'pred'
2401 .add(MI.getOperand(5))
2402 .add(condCodeOp()) // 's' bit
2403 .add(makeImplicit(MI.getOperand(1)));
2404
2405 MI.eraseFromParent();
2406 return true;
2407 }
2408 case ARM::MOVCCsr: {
2409 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr),
2410 (MI.getOperand(1).getReg()))
2411 .add(MI.getOperand(2))
2412 .add(MI.getOperand(3))
2413 .addImm(MI.getOperand(4).getImm())
2414 .addImm(MI.getOperand(5).getImm()) // 'pred'
2415 .add(MI.getOperand(6))
2416 .add(condCodeOp()) // 's' bit
2417 .add(makeImplicit(MI.getOperand(1)));
2418
2419 MI.eraseFromParent();
2420 return true;
2421 }
2422 case ARM::t2MOVCCi16:
2423 case ARM::MOVCCi16: {
2424 unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16;
2425 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
2426 MI.getOperand(1).getReg())
2427 .addImm(MI.getOperand(2).getImm())
2428 .addImm(MI.getOperand(3).getImm()) // 'pred'
2429 .add(MI.getOperand(4))
2430 .add(makeImplicit(MI.getOperand(1)));
2431 MI.eraseFromParent();
2432 return true;
2433 }
2434 case ARM::t2MOVCCi:
2435 case ARM::MOVCCi: {
2436 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MOVi : ARM::MOVi;
2437 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2438 MI.getOperand(1).getReg())
2439 .addImm(MI.getOperand(2).getImm())
2440 .addImm(MI.getOperand(3).getImm()) // 'pred'
2441 .add(MI.getOperand(4))
2442 .add(condCodeOp()) // 's' bit
2443 .add(makeImplicit(MI.getOperand(1)));
2444
2445 MI.eraseFromParent();
2446 return true;
2447 }
2448 case ARM::t2MVNCCi:
2449 case ARM::MVNCCi: {
2450 unsigned Opc = AFI->isThumbFunction() ? ARM::t2MVNi : ARM::MVNi;
2451 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc),
2452 MI.getOperand(1).getReg())
2453 .addImm(MI.getOperand(2).getImm())
2454 .addImm(MI.getOperand(3).getImm()) // 'pred'
2455 .add(MI.getOperand(4))
2456 .add(condCodeOp()) // 's' bit
2457 .add(makeImplicit(MI.getOperand(1)));
2458
2459 MI.eraseFromParent();
2460 return true;
2461 }
2462 case ARM::t2MOVCClsl:
2463 case ARM::t2MOVCClsr:
2464 case ARM::t2MOVCCasr:
2465 case ARM::t2MOVCCror: {
2466 unsigned NewOpc;
2467 switch (Opcode) {
2468 case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break;
2469 case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break;
2470 case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break;
2471 case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break;
2472 default: llvm_unreachable("unexpeced conditional move");
2473 }
2474 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc),
2475 MI.getOperand(1).getReg())
2476 .add(MI.getOperand(2))
2477 .addImm(MI.getOperand(3).getImm())
2478 .addImm(MI.getOperand(4).getImm()) // 'pred'
2479 .add(MI.getOperand(5))
2480 .add(condCodeOp()) // 's' bit
2481 .add(makeImplicit(MI.getOperand(1)));
2482 MI.eraseFromParent();
2483 return true;
2484 }
2485 case ARM::Int_eh_sjlj_dispatchsetup: {
2486 MachineFunction &MF = *MI.getParent()->getParent();
2487 const ARMBaseInstrInfo *AII =
2488 static_cast<const ARMBaseInstrInfo*>(TII);
2489 const ARMBaseRegisterInfo &RI = AII->getRegisterInfo();
2490 // For functions using a base pointer, we rematerialize it (via the frame
2491 // pointer) here since eh.sjlj.setjmp and eh.sjlj.longjmp don't do it
2492 // for us. Otherwise, expand to nothing.
2493 if (RI.hasBasePointer(MF)) {
2494 int32_t NumBytes = AFI->getFramePtrSpillOffset();
2497 "base pointer without frame pointer?");
2498
2499 if (AFI->isThumb2Function()) {
2500 emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2501 FramePtr, -NumBytes, ARMCC::AL, 0, *TII);
2502 } else if (AFI->isThumbFunction()) {
2503 emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2504 FramePtr, -NumBytes, *TII, RI);
2505 } else {
2506 emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6,
2507 FramePtr, -NumBytes, ARMCC::AL, 0,
2508 *TII);
2509 }
2510 // If there's dynamic realignment, adjust for it.
2511 if (RI.hasStackRealignment(MF)) {
2512 MachineFrameInfo &MFI = MF.getFrameInfo();
2513 Align MaxAlign = MFI.getMaxAlign();
2514 assert (!AFI->isThumb1OnlyFunction());
2515 // Emit bic r6, r6, MaxAlign
2516 assert(MaxAlign <= Align(256) &&
2517 "The BIC instruction cannot encode "
2518 "immediates larger than 256 with all lower "
2519 "bits set.");
2520 unsigned bicOpc = AFI->isThumbFunction() ?
2521 ARM::t2BICri : ARM::BICri;
2522 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(bicOpc), ARM::R6)
2523 .addReg(ARM::R6, RegState::Kill)
2524 .addImm(MaxAlign.value() - 1)
2526 .add(condCodeOp());
2527 }
2528 }
2529 MI.eraseFromParent();
2530 return true;
2531 }
2532
2533 case ARM::MOVsrl_glue:
2534 case ARM::MOVsra_glue: {
2535 // These are just fancy MOVs instructions.
2536 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2537 MI.getOperand(0).getReg())
2538 .add(MI.getOperand(1))
2540 (Opcode == ARM::MOVsrl_glue ? ARM_AM::lsr : ARM_AM::asr), 1))
2542 .addReg(ARM::CPSR, RegState::Define);
2543 MI.eraseFromParent();
2544 return true;
2545 }
2546 case ARM::RRX: {
2547 // This encodes as "MOVs Rd, Rm, rrx
2548 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi),
2549 MI.getOperand(0).getReg())
2550 .add(MI.getOperand(1))
2553 .add(condCodeOp())
2555 MI.eraseFromParent();
2556 return true;
2557 }
2558 case ARM::tTPsoft:
2559 case ARM::TPsoft: {
2560 const bool Thumb = Opcode == ARM::tTPsoft;
2561
2564 if (STI->genLongCalls()) {
2566 unsigned PCLabelID = AFI->createPICLabelUId();
2569 "__aeabi_read_tp", PCLabelID, 0);
2570 Register Reg = MI.getOperand(0).getReg();
2571 MIB =
2572 BuildMI(MBB, MBBI, MI.getDebugLoc(),
2573 TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)
2575 if (!Thumb)
2576 MIB.addImm(0);
2577 MIB.add(predOps(ARMCC::AL));
2578
2579 MIB =
2580 BuildMI(MBB, MBBI, MI.getDebugLoc(),
2581 TII->get(Thumb ? gettBLXrOpcode(*MF) : getBLXOpcode(*MF)));
2582 if (Thumb)
2583 MIB.add(predOps(ARMCC::AL));
2584 MIB.addReg(Reg, RegState::Kill);
2585 } else {
2586 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
2587 TII->get(Thumb ? ARM::tBL : ARM::BL));
2588 if (Thumb)
2589 MIB.add(predOps(ARMCC::AL));
2590 MIB.addExternalSymbol("__aeabi_read_tp", 0);
2591 }
2592
2593 MIB.cloneMemRefs(MI);
2594 MIB.copyImplicitOps(MI);
2595 // Update the call site info.
2596 if (MI.isCandidateForCallSiteEntry())
2597 MF->moveCallSiteInfo(&MI, &*MIB);
2598 MI.eraseFromParent();
2599 return true;
2600 }
2601 case ARM::tLDRpci_pic:
2602 case ARM::t2LDRpci_pic: {
2603 unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)
2604 ? ARM::tLDRpci : ARM::t2LDRpci;
2605 Register DstReg = MI.getOperand(0).getReg();
2606 bool DstIsDead = MI.getOperand(0).isDead();
2607 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewLdOpc), DstReg)
2608 .add(MI.getOperand(1))
2612 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPICADD))
2613 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2614 .addReg(DstReg)
2615 .add(MI.getOperand(2))
2617 MI.eraseFromParent();
2618 return true;
2619 }
2620
2621 case ARM::LDRLIT_ga_abs:
2622 case ARM::LDRLIT_ga_pcrel:
2623 case ARM::LDRLIT_ga_pcrel_ldr:
2624 case ARM::tLDRLIT_ga_abs:
2625 case ARM::t2LDRLIT_ga_pcrel:
2626 case ARM::tLDRLIT_ga_pcrel: {
2627 Register DstReg = MI.getOperand(0).getReg();
2628 bool DstIsDead = MI.getOperand(0).isDead();
2629 const MachineOperand &MO1 = MI.getOperand(1);
2630 auto Flags = MO1.getTargetFlags();
2631 const GlobalValue *GV = MO1.getGlobal();
2632 bool IsARM = Opcode != ARM::tLDRLIT_ga_pcrel &&
2633 Opcode != ARM::tLDRLIT_ga_abs &&
2634 Opcode != ARM::t2LDRLIT_ga_pcrel;
2635 bool IsPIC =
2636 Opcode != ARM::LDRLIT_ga_abs && Opcode != ARM::tLDRLIT_ga_abs;
2637 unsigned LDRLITOpc = IsARM ? ARM::LDRi12 : ARM::tLDRpci;
2638 if (Opcode == ARM::t2LDRLIT_ga_pcrel)
2639 LDRLITOpc = ARM::t2LDRpci;
2640 unsigned PICAddOpc =
2641 IsARM
2642 ? (Opcode == ARM::LDRLIT_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
2643 : ARM::tPICADD;
2644
2645 // We need a new const-pool entry to load from.
2647 unsigned ARMPCLabelIndex = 0;
2649
2650 if (IsPIC) {
2651 unsigned PCAdj = IsARM ? 8 : 4;
2652 auto Modifier = (Flags & ARMII::MO_GOT)
2655 ARMPCLabelIndex = AFI->createPICLabelUId();
2657 GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier,
2658 /*AddCurrentAddr*/ Modifier == ARMCP::GOT_PREL);
2659 } else
2661
2663 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LDRLITOpc), DstReg)
2664 .addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, Align(4)));
2665 if (IsARM)
2666 MIB.addImm(0);
2667 MIB.add(predOps(ARMCC::AL));
2668
2669 if (IsPIC) {
2671 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(PICAddOpc))
2672 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2673 .addReg(DstReg)
2674 .addImm(ARMPCLabelIndex);
2675
2676 if (IsARM)
2677 MIB.add(predOps(ARMCC::AL));
2678 }
2679
2680 MI.eraseFromParent();
2681 return true;
2682 }
2683 case ARM::MOV_ga_pcrel:
2684 case ARM::MOV_ga_pcrel_ldr:
2685 case ARM::t2MOV_ga_pcrel: {
2686 // Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode.
2687 unsigned LabelId = AFI->createPICLabelUId();
2688 Register DstReg = MI.getOperand(0).getReg();
2689 bool DstIsDead = MI.getOperand(0).isDead();
2690 const MachineOperand &MO1 = MI.getOperand(1);
2691 const GlobalValue *GV = MO1.getGlobal();
2692 unsigned TF = MO1.getTargetFlags();
2693 bool isARM = Opcode != ARM::t2MOV_ga_pcrel;
2694 unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;
2695 unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;
2696 unsigned LO16TF = TF | ARMII::MO_LO16;
2697 unsigned HI16TF = TF | ARMII::MO_HI16;
2698 unsigned PICAddOpc = isARM
2699 ? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)
2700 : ARM::tPICADD;
2701 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg)
2702 .addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF)
2703 .addImm(LabelId)
2705
2706 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc), DstReg)
2707 .addReg(DstReg)
2708 .addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF)
2709 .addImm(LabelId)
2711
2712 MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
2713 TII->get(PICAddOpc))
2714 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
2715 .addReg(DstReg).addImm(LabelId);
2716 if (isARM) {
2717 MIB3.add(predOps(ARMCC::AL));
2718 if (Opcode == ARM::MOV_ga_pcrel_ldr)
2719 MIB3.cloneMemRefs(MI);
2720 }
2721 MIB3.copyImplicitOps(MI);
2722 MI.eraseFromParent();
2723 return true;
2724 }
2725
2726 case ARM::MOVi32imm:
2727 case ARM::MOVCCi32imm:
2728 case ARM::t2MOVi32imm:
2729 case ARM::t2MOVCCi32imm:
2730 ExpandMOV32BitImm(MBB, MBBI);
2731 return true;
2732
2733 case ARM::tMOVi32imm:
2734 ExpandTMOV32BitImm(MBB, MBBI);
2735 return true;
2736
2737 case ARM::tLEApcrelJT:
2738 // Inline jump tables are handled in ARMAsmPrinter.
2739 if (MI.getMF()->getJumpTableInfo()->getEntryKind() ==
2741 return false;
2742
2743 // Use a 32-bit immediate move to generate the address of the jump table.
2744 assert(STI->isThumb() && "Non-inline jump tables expected only in thumb");
2745 ExpandTMOV32BitImm(MBB, MBBI);
2746 return true;
2747
2748 case ARM::SUBS_PC_LR: {
2749 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri), ARM::PC)
2750 .addReg(ARM::LR)
2751 .add(MI.getOperand(0))
2752 .add(MI.getOperand(1))
2753 .add(MI.getOperand(2))
2754 .addReg(ARM::CPSR, RegState::Undef)
2756 MI.eraseFromParent();
2757 return true;
2758 }
2759 case ARM::VLDMQIA: {
2760 unsigned NewOpc = ARM::VLDMDIA;
2762 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
2763 unsigned OpIdx = 0;
2764
2765 // Grab the Q register destination.
2766 bool DstIsDead = MI.getOperand(OpIdx).isDead();
2767 Register DstReg = MI.getOperand(OpIdx++).getReg();
2768
2769 // Copy the source register.
2770 MIB.add(MI.getOperand(OpIdx++));
2771
2772 // Copy the predicate operands.
2773 MIB.add(MI.getOperand(OpIdx++));
2774 MIB.add(MI.getOperand(OpIdx++));
2775
2776 // Add the destination operands (D subregs).
2777 Register D0 = TRI->getSubReg(DstReg, ARM::dsub_0);
2778 Register D1 = TRI->getSubReg(DstReg, ARM::dsub_1);
2779 MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
2780 .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
2781
2782 // Add an implicit def for the super-register.
2783 MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
2784 MIB.copyImplicitOps(MI);
2785 MIB.cloneMemRefs(MI);
2786 MI.eraseFromParent();
2787 return true;
2788 }
2789
2790 case ARM::VSTMQIA: {
2791 unsigned NewOpc = ARM::VSTMDIA;
2793 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc));
2794 unsigned OpIdx = 0;
2795
2796 // Grab the Q register source.
2797 bool SrcIsKill = MI.getOperand(OpIdx).isKill();
2798 Register SrcReg = MI.getOperand(OpIdx++).getReg();
2799
2800 // Copy the destination register.
2801 MachineOperand Dst(MI.getOperand(OpIdx++));
2802 MIB.add(Dst);
2803
2804 // Copy the predicate operands.
2805 MIB.add(MI.getOperand(OpIdx++));
2806 MIB.add(MI.getOperand(OpIdx++));
2807
2808 // Add the source operands (D subregs).
2809 Register D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);
2810 Register D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);
2811 MIB.addReg(D0, SrcIsKill ? RegState::Kill : 0)
2812 .addReg(D1, SrcIsKill ? RegState::Kill : 0);
2813
2814 if (SrcIsKill) // Add an implicit kill for the Q register.
2815 MIB->addRegisterKilled(SrcReg, TRI, true);
2816
2817 MIB.copyImplicitOps(MI);
2818 MIB.cloneMemRefs(MI);
2819 MI.eraseFromParent();
2820 return true;
2821 }
2822
2823 case ARM::VLD2q8Pseudo:
2824 case ARM::VLD2q16Pseudo:
2825 case ARM::VLD2q32Pseudo:
2826 case ARM::VLD2q8PseudoWB_fixed:
2827 case ARM::VLD2q16PseudoWB_fixed:
2828 case ARM::VLD2q32PseudoWB_fixed:
2829 case ARM::VLD2q8PseudoWB_register:
2830 case ARM::VLD2q16PseudoWB_register:
2831 case ARM::VLD2q32PseudoWB_register:
2832 case ARM::VLD3d8Pseudo:
2833 case ARM::VLD3d16Pseudo:
2834 case ARM::VLD3d32Pseudo:
2835 case ARM::VLD1d8TPseudo:
2836 case ARM::VLD1d8TPseudoWB_fixed:
2837 case ARM::VLD1d8TPseudoWB_register:
2838 case ARM::VLD1d16TPseudo:
2839 case ARM::VLD1d16TPseudoWB_fixed:
2840 case ARM::VLD1d16TPseudoWB_register:
2841 case ARM::VLD1d32TPseudo:
2842 case ARM::VLD1d32TPseudoWB_fixed:
2843 case ARM::VLD1d32TPseudoWB_register:
2844 case ARM::VLD1d64TPseudo:
2845 case ARM::VLD1d64TPseudoWB_fixed:
2846 case ARM::VLD1d64TPseudoWB_register:
2847 case ARM::VLD3d8Pseudo_UPD:
2848 case ARM::VLD3d16Pseudo_UPD:
2849 case ARM::VLD3d32Pseudo_UPD:
2850 case ARM::VLD3q8Pseudo_UPD:
2851 case ARM::VLD3q16Pseudo_UPD:
2852 case ARM::VLD3q32Pseudo_UPD:
2853 case ARM::VLD3q8oddPseudo:
2854 case ARM::VLD3q16oddPseudo:
2855 case ARM::VLD3q32oddPseudo:
2856 case ARM::VLD3q8oddPseudo_UPD:
2857 case ARM::VLD3q16oddPseudo_UPD:
2858 case ARM::VLD3q32oddPseudo_UPD:
2859 case ARM::VLD4d8Pseudo:
2860 case ARM::VLD4d16Pseudo:
2861 case ARM::VLD4d32Pseudo:
2862 case ARM::VLD1d8QPseudo:
2863 case ARM::VLD1d8QPseudoWB_fixed:
2864 case ARM::VLD1d8QPseudoWB_register:
2865 case ARM::VLD1d16QPseudo:
2866 case ARM::VLD1d16QPseudoWB_fixed:
2867 case ARM::VLD1d16QPseudoWB_register:
2868 case ARM::VLD1d32QPseudo:
2869 case ARM::VLD1d32QPseudoWB_fixed:
2870 case ARM::VLD1d32QPseudoWB_register:
2871 case ARM::VLD1d64QPseudo:
2872 case ARM::VLD1d64QPseudoWB_fixed:
2873 case ARM::VLD1d64QPseudoWB_register:
2874 case ARM::VLD1q8HighQPseudo:
2875 case ARM::VLD1q8HighQPseudo_UPD:
2876 case ARM::VLD1q8LowQPseudo_UPD:
2877 case ARM::VLD1q8HighTPseudo:
2878 case ARM::VLD1q8HighTPseudo_UPD:
2879 case ARM::VLD1q8LowTPseudo_UPD:
2880 case ARM::VLD1q16HighQPseudo:
2881 case ARM::VLD1q16HighQPseudo_UPD:
2882 case ARM::VLD1q16LowQPseudo_UPD:
2883 case ARM::VLD1q16HighTPseudo:
2884 case ARM::VLD1q16HighTPseudo_UPD:
2885 case ARM::VLD1q16LowTPseudo_UPD:
2886 case ARM::VLD1q32HighQPseudo:
2887 case ARM::VLD1q32HighQPseudo_UPD:
2888 case ARM::VLD1q32LowQPseudo_UPD:
2889 case ARM::VLD1q32HighTPseudo:
2890 case ARM::VLD1q32HighTPseudo_UPD:
2891 case ARM::VLD1q32LowTPseudo_UPD:
2892 case ARM::VLD1q64HighQPseudo:
2893 case ARM::VLD1q64HighQPseudo_UPD:
2894 case ARM::VLD1q64LowQPseudo_UPD:
2895 case ARM::VLD1q64HighTPseudo:
2896 case ARM::VLD1q64HighTPseudo_UPD:
2897 case ARM::VLD1q64LowTPseudo_UPD:
2898 case ARM::VLD4d8Pseudo_UPD:
2899 case ARM::VLD4d16Pseudo_UPD:
2900 case ARM::VLD4d32Pseudo_UPD:
2901 case ARM::VLD4q8Pseudo_UPD:
2902 case ARM::VLD4q16Pseudo_UPD:
2903 case ARM::VLD4q32Pseudo_UPD:
2904 case ARM::VLD4q8oddPseudo:
2905 case ARM::VLD4q16oddPseudo:
2906 case ARM::VLD4q32oddPseudo:
2907 case ARM::VLD4q8oddPseudo_UPD:
2908 case ARM::VLD4q16oddPseudo_UPD:
2909 case ARM::VLD4q32oddPseudo_UPD:
2910 case ARM::VLD3DUPd8Pseudo:
2911 case ARM::VLD3DUPd16Pseudo:
2912 case ARM::VLD3DUPd32Pseudo:
2913 case ARM::VLD3DUPd8Pseudo_UPD:
2914 case ARM::VLD3DUPd16Pseudo_UPD:
2915 case ARM::VLD3DUPd32Pseudo_UPD:
2916 case ARM::VLD4DUPd8Pseudo:
2917 case ARM::VLD4DUPd16Pseudo:
2918 case ARM::VLD4DUPd32Pseudo:
2919 case ARM::VLD4DUPd8Pseudo_UPD:
2920 case ARM::VLD4DUPd16Pseudo_UPD:
2921 case ARM::VLD4DUPd32Pseudo_UPD:
2922 case ARM::VLD2DUPq8EvenPseudo:
2923 case ARM::VLD2DUPq8OddPseudo:
2924 case ARM::VLD2DUPq16EvenPseudo:
2925 case ARM::VLD2DUPq16OddPseudo:
2926 case ARM::VLD2DUPq32EvenPseudo:
2927 case ARM::VLD2DUPq32OddPseudo:
2928 case ARM::VLD2DUPq8OddPseudoWB_fixed:
2929 case ARM::VLD2DUPq8OddPseudoWB_register:
2930 case ARM::VLD2DUPq16OddPseudoWB_fixed:
2931 case ARM::VLD2DUPq16OddPseudoWB_register:
2932 case ARM::VLD2DUPq32OddPseudoWB_fixed:
2933 case ARM::VLD2DUPq32OddPseudoWB_register:
2934 case ARM::VLD3DUPq8EvenPseudo:
2935 case ARM::VLD3DUPq8OddPseudo:
2936 case ARM::VLD3DUPq16EvenPseudo:
2937 case ARM::VLD3DUPq16OddPseudo:
2938 case ARM::VLD3DUPq32EvenPseudo:
2939 case ARM::VLD3DUPq32OddPseudo:
2940 case ARM::VLD3DUPq8OddPseudo_UPD:
2941 case ARM::VLD3DUPq16OddPseudo_UPD:
2942 case ARM::VLD3DUPq32OddPseudo_UPD:
2943 case ARM::VLD4DUPq8EvenPseudo:
2944 case ARM::VLD4DUPq8OddPseudo:
2945 case ARM::VLD4DUPq16EvenPseudo:
2946 case ARM::VLD4DUPq16OddPseudo:
2947 case ARM::VLD4DUPq32EvenPseudo:
2948 case ARM::VLD4DUPq32OddPseudo:
2949 case ARM::VLD4DUPq8OddPseudo_UPD:
2950 case ARM::VLD4DUPq16OddPseudo_UPD:
2951 case ARM::VLD4DUPq32OddPseudo_UPD:
2952 ExpandVLD(MBBI);
2953 return true;
2954
2955 case ARM::VST2q8Pseudo:
2956 case ARM::VST2q16Pseudo:
2957 case ARM::VST2q32Pseudo:
2958 case ARM::VST2q8PseudoWB_fixed:
2959 case ARM::VST2q16PseudoWB_fixed:
2960 case ARM::VST2q32PseudoWB_fixed:
2961 case ARM::VST2q8PseudoWB_register:
2962 case ARM::VST2q16PseudoWB_register:
2963 case ARM::VST2q32PseudoWB_register:
2964 case ARM::VST3d8Pseudo:
2965 case ARM::VST3d16Pseudo:
2966 case ARM::VST3d32Pseudo:
2967 case ARM::VST1d8TPseudo:
2968 case ARM::VST1d8TPseudoWB_fixed:
2969 case ARM::VST1d8TPseudoWB_register:
2970 case ARM::VST1d16TPseudo:
2971 case ARM::VST1d16TPseudoWB_fixed:
2972 case ARM::VST1d16TPseudoWB_register:
2973 case ARM::VST1d32TPseudo:
2974 case ARM::VST1d32TPseudoWB_fixed:
2975 case ARM::VST1d32TPseudoWB_register:
2976 case ARM::VST1d64TPseudo:
2977 case ARM::VST1d64TPseudoWB_fixed:
2978 case ARM::VST1d64TPseudoWB_register:
2979 case ARM::VST3d8Pseudo_UPD:
2980 case ARM::VST3d16Pseudo_UPD:
2981 case ARM::VST3d32Pseudo_UPD:
2982 case ARM::VST3q8Pseudo_UPD:
2983 case ARM::VST3q16Pseudo_UPD:
2984 case ARM::VST3q32Pseudo_UPD:
2985 case ARM::VST3q8oddPseudo:
2986 case ARM::VST3q16oddPseudo:
2987 case ARM::VST3q32oddPseudo:
2988 case ARM::VST3q8oddPseudo_UPD:
2989 case ARM::VST3q16oddPseudo_UPD:
2990 case ARM::VST3q32oddPseudo_UPD:
2991 case ARM::VST4d8Pseudo:
2992 case ARM::VST4d16Pseudo:
2993 case ARM::VST4d32Pseudo:
2994 case ARM::VST1d8QPseudo:
2995 case ARM::VST1d8QPseudoWB_fixed:
2996 case ARM::VST1d8QPseudoWB_register:
2997 case ARM::VST1d16QPseudo:
2998 case ARM::VST1d16QPseudoWB_fixed:
2999 case ARM::VST1d16QPseudoWB_register:
3000 case ARM::VST1d32QPseudo:
3001 case ARM::VST1d32QPseudoWB_fixed:
3002 case ARM::VST1d32QPseudoWB_register:
3003 case ARM::VST1d64QPseudo:
3004 case ARM::VST1d64QPseudoWB_fixed:
3005 case ARM::VST1d64QPseudoWB_register:
3006 case ARM::VST4d8Pseudo_UPD:
3007 case ARM::VST4d16Pseudo_UPD:
3008 case ARM::VST4d32Pseudo_UPD:
3009 case ARM::VST1q8HighQPseudo:
3010 case ARM::VST1q8LowQPseudo_UPD:
3011 case ARM::VST1q8HighTPseudo:
3012 case ARM::VST1q8LowTPseudo_UPD:
3013 case ARM::VST1q16HighQPseudo:
3014 case ARM::VST1q16LowQPseudo_UPD:
3015 case ARM::VST1q16HighTPseudo:
3016 case ARM::VST1q16LowTPseudo_UPD:
3017 case ARM::VST1q32HighQPseudo:
3018 case ARM::VST1q32LowQPseudo_UPD:
3019 case ARM::VST1q32HighTPseudo:
3020 case ARM::VST1q32LowTPseudo_UPD:
3021 case ARM::VST1q64HighQPseudo:
3022 case ARM::VST1q64LowQPseudo_UPD:
3023 case ARM::VST1q64HighTPseudo:
3024 case ARM::VST1q64LowTPseudo_UPD:
3025 case ARM::VST1q8HighTPseudo_UPD:
3026 case ARM::VST1q16HighTPseudo_UPD:
3027 case ARM::VST1q32HighTPseudo_UPD:
3028 case ARM::VST1q64HighTPseudo_UPD:
3029 case ARM::VST1q8HighQPseudo_UPD:
3030 case ARM::VST1q16HighQPseudo_UPD:
3031 case ARM::VST1q32HighQPseudo_UPD:
3032 case ARM::VST1q64HighQPseudo_UPD:
3033 case ARM::VST4q8Pseudo_UPD:
3034 case ARM::VST4q16Pseudo_UPD:
3035 case ARM::VST4q32Pseudo_UPD:
3036 case ARM::VST4q8oddPseudo:
3037 case ARM::VST4q16oddPseudo:
3038 case ARM::VST4q32oddPseudo:
3039 case ARM::VST4q8oddPseudo_UPD:
3040 case ARM::VST4q16oddPseudo_UPD:
3041 case ARM::VST4q32oddPseudo_UPD:
3042 ExpandVST(MBBI);
3043 return true;
3044
3045 case ARM::VLD1LNq8Pseudo:
3046 case ARM::VLD1LNq16Pseudo:
3047 case ARM::VLD1LNq32Pseudo:
3048 case ARM::VLD1LNq8Pseudo_UPD:
3049 case ARM::VLD1LNq16Pseudo_UPD:
3050 case ARM::VLD1LNq32Pseudo_UPD:
3051 case ARM::VLD2LNd8Pseudo:
3052 case ARM::VLD2LNd16Pseudo:
3053 case ARM::VLD2LNd32Pseudo:
3054 case ARM::VLD2LNq16Pseudo:
3055 case ARM::VLD2LNq32Pseudo:
3056 case ARM::VLD2LNd8Pseudo_UPD:
3057 case ARM::VLD2LNd16Pseudo_UPD:
3058 case ARM::VLD2LNd32Pseudo_UPD:
3059 case ARM::VLD2LNq16Pseudo_UPD:
3060 case ARM::VLD2LNq32Pseudo_UPD:
3061 case ARM::VLD3LNd8Pseudo:
3062 case ARM::VLD3LNd16Pseudo:
3063 case ARM::VLD3LNd32Pseudo:
3064 case ARM::VLD3LNq16Pseudo:
3065 case ARM::VLD3LNq32Pseudo:
3066 case ARM::VLD3LNd8Pseudo_UPD:
3067 case ARM::VLD3LNd16Pseudo_UPD:
3068 case ARM::VLD3LNd32Pseudo_UPD:
3069 case ARM::VLD3LNq16Pseudo_UPD:
3070 case ARM::VLD3LNq32Pseudo_UPD:
3071 case ARM::VLD4LNd8Pseudo:
3072 case ARM::VLD4LNd16Pseudo:
3073 case ARM::VLD4LNd32Pseudo:
3074 case ARM::VLD4LNq16Pseudo:
3075 case ARM::VLD4LNq32Pseudo:
3076 case ARM::VLD4LNd8Pseudo_UPD:
3077 case ARM::VLD4LNd16Pseudo_UPD:
3078 case ARM::VLD4LNd32Pseudo_UPD:
3079 case ARM::VLD4LNq16Pseudo_UPD:
3080 case ARM::VLD4LNq32Pseudo_UPD:
3081 case ARM::VST1LNq8Pseudo:
3082 case ARM::VST1LNq16Pseudo:
3083 case ARM::VST1LNq32Pseudo:
3084 case ARM::VST1LNq8Pseudo_UPD:
3085 case ARM::VST1LNq16Pseudo_UPD:
3086 case ARM::VST1LNq32Pseudo_UPD:
3087 case ARM::VST2LNd8Pseudo:
3088 case ARM::VST2LNd16Pseudo:
3089 case ARM::VST2LNd32Pseudo:
3090 case ARM::VST2LNq16Pseudo:
3091 case ARM::VST2LNq32Pseudo:
3092 case ARM::VST2LNd8Pseudo_UPD:
3093 case ARM::VST2LNd16Pseudo_UPD:
3094 case ARM::VST2LNd32Pseudo_UPD:
3095 case ARM::VST2LNq16Pseudo_UPD:
3096 case ARM::VST2LNq32Pseudo_UPD:
3097 case ARM::VST3LNd8Pseudo:
3098 case ARM::VST3LNd16Pseudo:
3099 case ARM::VST3LNd32Pseudo:
3100 case ARM::VST3LNq16Pseudo:
3101 case ARM::VST3LNq32Pseudo:
3102 case ARM::VST3LNd8Pseudo_UPD:
3103 case ARM::VST3LNd16Pseudo_UPD:
3104 case ARM::VST3LNd32Pseudo_UPD:
3105 case ARM::VST3LNq16Pseudo_UPD:
3106 case ARM::VST3LNq32Pseudo_UPD:
3107 case ARM::VST4LNd8Pseudo:
3108 case ARM::VST4LNd16Pseudo:
3109 case ARM::VST4LNd32Pseudo:
3110 case ARM::VST4LNq16Pseudo:
3111 case ARM::VST4LNq32Pseudo:
3112 case ARM::VST4LNd8Pseudo_UPD:
3113 case ARM::VST4LNd16Pseudo_UPD:
3114 case ARM::VST4LNd32Pseudo_UPD:
3115 case ARM::VST4LNq16Pseudo_UPD:
3116 case ARM::VST4LNq32Pseudo_UPD:
3117 ExpandLaneOp(MBBI);
3118 return true;
3119
3120 case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false); return true;
3121 case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true;
3122 case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;
3123 case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;
3124
3125 case ARM::MQQPRLoad:
3126 case ARM::MQQPRStore:
3127 case ARM::MQQQQPRLoad:
3128 case ARM::MQQQQPRStore:
3129 ExpandMQQPRLoadStore(MBBI);
3130 return true;
3131
3132 case ARM::tCMP_SWAP_8:
3133 assert(STI->isThumb());
3134 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, ARM::tUXTB,
3135 NextMBBI);
3136 case ARM::tCMP_SWAP_16:
3137 assert(STI->isThumb());
3138 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, ARM::tUXTH,
3139 NextMBBI);
3140 case ARM::tCMP_SWAP_32:
3141 assert(STI->isThumb());
3142 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0, NextMBBI);
3143
3144 case ARM::CMP_SWAP_8:
3145 assert(!STI->isThumb());
3146 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB, ARM::UXTB,
3147 NextMBBI);
3148 case ARM::CMP_SWAP_16:
3149 assert(!STI->isThumb());
3150 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH,
3151 NextMBBI);
3152 case ARM::CMP_SWAP_32:
3153 assert(!STI->isThumb());
3154 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREX, ARM::STREX, 0, NextMBBI);
3155
3156 case ARM::CMP_SWAP_64:
3157 return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);
3158
3159 case ARM::tBL_PUSHLR:
3160 case ARM::BL_PUSHLR: {
3161 const bool Thumb = Opcode == ARM::tBL_PUSHLR;
3162 Register Reg = MI.getOperand(0).getReg();
3163 assert(Reg == ARM::LR && "expect LR register!");
3165 if (Thumb) {
3166 // push {lr}
3167 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPUSH))
3169 .addReg(Reg);
3170
3171 // bl __gnu_mcount_nc
3172 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tBL));
3173 } else {
3174 // stmdb sp!, {lr}
3175 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::STMDB_UPD))
3176 .addReg(ARM::SP, RegState::Define)
3177 .addReg(ARM::SP)
3179 .addReg(Reg);
3180
3181 // bl __gnu_mcount_nc
3182 MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::BL));
3183 }
3184 MIB.cloneMemRefs(MI);
3185 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
3186 MIB.add(MO);
3187 MI.eraseFromParent();
3188 return true;
3189 }
3190 case ARM::t2CALL_BTI: {
3191 MachineFunction &MF = *MI.getMF();
3193 BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::tBL));
3194 MIB.cloneMemRefs(MI);
3195 for (unsigned i = 0; i < MI.getNumOperands(); ++i)
3196 MIB.add(MI.getOperand(i));
3197 if (MI.isCandidateForCallSiteEntry())
3198 MF.moveCallSiteInfo(&MI, MIB.getInstr());
3199 MIBundleBuilder Bundler(MBB, MI);
3200 Bundler.append(MIB);
3201 Bundler.append(BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::t2BTI)));
3202 finalizeBundle(MBB, Bundler.begin(), Bundler.end());
3203 MI.eraseFromParent();
3204 return true;
3205 }
3206 case ARM::LOADDUAL:
3207 case ARM::STOREDUAL: {
3208 Register PairReg = MI.getOperand(0).getReg();
3209
3211 BuildMI(MBB, MBBI, MI.getDebugLoc(),
3212 TII->get(Opcode == ARM::LOADDUAL ? ARM::LDRD : ARM::STRD))
3213 .addReg(TRI->getSubReg(PairReg, ARM::gsub_0),
3214 Opcode == ARM::LOADDUAL ? RegState::Define : 0)
3215 .addReg(TRI->getSubReg(PairReg, ARM::gsub_1),
3216 Opcode == ARM::LOADDUAL ? RegState::Define : 0);
3217 for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
3218 MIB.add(MO);
3219 MIB.add(predOps(ARMCC::AL));
3220 MIB.cloneMemRefs(MI);
3221 MI.eraseFromParent();
3222 return true;
3223 }
3224 }
3225}
3226
3227bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
3228 bool Modified = false;
3229
3231 while (MBBI != E) {
3232 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
3233 Modified |= ExpandMI(MBB, MBBI, NMBBI);
3234 MBBI = NMBBI;
3235 }
3236
3237 return Modified;
3238}
3239
3240bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
3241 STI = &MF.getSubtarget<ARMSubtarget>();
3242 TII = STI->getInstrInfo();
3243 TRI = STI->getRegisterInfo();
3244 AFI = MF.getInfo<ARMFunctionInfo>();
3245
3246 LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"
3247 << "********** Function: " << MF.getName() << '\n');
3248
3249 bool Modified = false;
3250 for (MachineBasicBlock &MBB : MF)
3251 Modified |= ExpandMBB(MBB);
3252 if (VerifyARMPseudo)
3253 MF.verify(this, "After expanding ARM pseudo instructions.");
3254
3255 LLVM_DEBUG(dbgs() << "***************************************************\n");
3256 return Modified;
3257}
3258
3259/// createARMExpandPseudoPass - returns an instance of the pseudo instruction
3260/// expansion pass.
3262 return new ARMExpandPseudo();
3263}
unsigned SubReg
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
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 void CMSEPushCalleeSaves(const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, int JumpReg, const LivePhysRegs &LiveRegs, bool Thumb1Only)
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 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[]
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:203
#define LLVM_DEBUG(X)
Definition: Debug.h:101
bool End
Definition: ELF_riscv.cpp:478
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
static constexpr uint32_t Opcode
Definition: aarch32.h:200
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:311
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:341
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
Definition: Function.h:652
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Definition: LivePhysRegs.h:50
bool contains(MCPhysReg Reg) const
Returns true if register Reg is contained in the set.
Definition: LivePhysRegs.h:107
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:805
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.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 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:68
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.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:553
@ 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
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
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:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
virtual bool hasFP(const MachineFunction &MF) const =0
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:109
#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:1726
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:1651
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:1906
unsigned getUndefRegState(bool B)
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:1945
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