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