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