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