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