LLVM 23.0.0git
AArch64ExpandPseudoInsts.cpp
Go to the documentation of this file.
1//===- AArch64ExpandPseudoInsts.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 and other late optimizations. This
11// pass should be run after register allocation but before the post-regalloc
12// scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AArch64ExpandImm.h"
17#include "AArch64InstrInfo.h"
19#include "AArch64Subtarget.h"
32#include "llvm/IR/DebugLoc.h"
33#include "llvm/MC/MCInstrDesc.h"
34#include "llvm/Pass.h"
38#include <cassert>
39#include <cstdint>
40#include <iterator>
41
42using namespace llvm;
43
44#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
45
46namespace {
47
48class AArch64ExpandPseudoImpl {
49public:
50 const AArch64InstrInfo *TII;
51
52 bool run(MachineFunction &MF);
53
54private:
55 bool expandMBB(MachineBasicBlock &MBB);
58 bool expandMultiVecPseudo(MachineBasicBlock &MBB,
60 TargetRegisterClass ContiguousClass,
61 TargetRegisterClass StridedClass,
62 unsigned ContiguousOpc, unsigned StridedOpc);
63 bool expandFormTuplePseudo(MachineBasicBlock &MBB,
66 unsigned Size);
68 unsigned BitSize);
69
70 bool expand_DestructiveOp(MachineInstr &MI, MachineBasicBlock &MBB,
72 bool expandSVEBitwisePseudo(MachineInstr &MI, MachineBasicBlock &MBB,
75 unsigned LdarOp, unsigned StlrOp, unsigned CmpOp,
76 unsigned ExtendImm, unsigned ZeroReg,
78 bool expandCMP_SWAP_128(MachineBasicBlock &MBB,
81 bool expandSetTagLoop(MachineBasicBlock &MBB,
84 bool expandSVESpillFill(MachineBasicBlock &MBB,
86 unsigned N);
87 bool expandCALL_RVMARKER(MachineBasicBlock &MBB,
90 bool expandStoreSwiftAsyncContext(MachineBasicBlock &MBB,
92 bool expandSTSHHAtomicStore(MachineBasicBlock &MBB,
94 struct ConditionalBlocks {
95 MachineBasicBlock &CondBB;
96 MachineBasicBlock &EndBB;
97 };
98 ConditionalBlocks expandConditionalPseudo(MachineBasicBlock &MBB,
100 DebugLoc DL,
101 MachineInstrBuilder &Branch);
102 MachineBasicBlock *expandRestoreZASave(MachineBasicBlock &MBB,
104 MachineBasicBlock *expandCommitZASave(MachineBasicBlock &MBB,
106 MachineBasicBlock *expandCondSMToggle(MachineBasicBlock &MBB,
108};
109
110class AArch64ExpandPseudoLegacy : public MachineFunctionPass {
111public:
112 static char ID;
113
114 AArch64ExpandPseudoLegacy() : MachineFunctionPass(ID) {}
115
116 bool runOnMachineFunction(MachineFunction &MF) override;
117
118 StringRef getPassName() const override { return AARCH64_EXPAND_PSEUDO_NAME; }
119};
120
121} // end anonymous namespace
122
123char AArch64ExpandPseudoLegacy::ID = 0;
124
125INITIALIZE_PASS(AArch64ExpandPseudoLegacy, "aarch64-expand-pseudo",
126 AARCH64_EXPAND_PSEUDO_NAME, false, false)
127
128/// Transfer implicit operands on the pseudo instruction to the
129/// instructions created from the expansion.
130static void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI,
132 const MCInstrDesc &Desc = OldMI.getDesc();
133 for (const MachineOperand &MO :
134 llvm::drop_begin(OldMI.operands(), Desc.getNumOperands())) {
135 assert(MO.isReg() && MO.getReg());
136 if (MO.isUse())
137 UseMI.add(MO);
138 else
139 DefMI.add(MO);
140 }
141}
142
143/// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
144/// real move-immediate instructions to synthesize the immediate.
145bool AArch64ExpandPseudoImpl::expandMOVImm(MachineBasicBlock &MBB,
147 unsigned BitSize) {
148 MachineInstr &MI = *MBBI;
149 Register DstReg = MI.getOperand(0).getReg();
150 RegState RenamableState =
151 getRenamableRegState(MI.getOperand(0).isRenamable());
152 uint64_t Imm = MI.getOperand(1).getImm();
153
154 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
155 // Useless def, and we don't want to risk creating an invalid ORR (which
156 // would really write to sp).
157 MI.eraseFromParent();
158 return true;
159 }
160
162 AArch64_IMM::expandMOVImm(Imm, BitSize, Insn);
163 assert(Insn.size() != 0);
164
165 SmallVector<MachineInstrBuilder, 4> MIBS;
166 for (auto I = Insn.begin(), E = Insn.end(); I != E; ++I) {
167 bool LastItem = std::next(I) == E;
168 switch (I->Opcode)
169 {
170 default: llvm_unreachable("unhandled!"); break;
171
172 case AArch64::ORRWri:
173 case AArch64::ORRXri:
174 case AArch64::ANDXri:
175 case AArch64::EORXri:
176 if (I->Op1 == 0) {
177 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
178 .add(MI.getOperand(0))
179 .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
180 .addImm(I->Op2));
181 } else {
182 Register DstReg = MI.getOperand(0).getReg();
183 bool DstIsDead = MI.getOperand(0).isDead();
184 MIBS.push_back(
185 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
186 .addReg(DstReg, RegState::Define |
187 getDeadRegState(DstIsDead && LastItem) |
188 RenamableState)
189 .addReg(DstReg)
190 .addImm(I->Op2));
191 }
192 break;
193 case AArch64::EONXrs:
194 case AArch64::EORXrs:
195 case AArch64::ORRWrs:
196 case AArch64::ORRXrs: {
197 Register DstReg = MI.getOperand(0).getReg();
198 bool DstIsDead = MI.getOperand(0).isDead();
199 MIBS.push_back(
200 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
201 .addReg(DstReg, RegState::Define |
202 getDeadRegState(DstIsDead && LastItem) |
203 RenamableState)
204 .addReg(DstReg)
205 .addReg(DstReg)
206 .addImm(I->Op2));
207 } break;
208 case AArch64::MOVNWi:
209 case AArch64::MOVNXi:
210 case AArch64::MOVZWi:
211 case AArch64::MOVZXi: {
212 bool DstIsDead = MI.getOperand(0).isDead();
213 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
214 .addReg(DstReg, RegState::Define |
215 getDeadRegState(DstIsDead && LastItem) |
216 RenamableState)
217 .addImm(I->Op1)
218 .addImm(I->Op2));
219 } break;
220 case AArch64::MOVKWi:
221 case AArch64::MOVKXi: {
222 Register DstReg = MI.getOperand(0).getReg();
223 bool DstIsDead = MI.getOperand(0).isDead();
224 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
225 .addReg(DstReg,
226 RegState::Define |
227 getDeadRegState(DstIsDead && LastItem) |
228 RenamableState)
229 .addReg(DstReg)
230 .addImm(I->Op1)
231 .addImm(I->Op2));
232 } break;
233 }
234 }
235 transferImpOps(MI, MIBS.front(), MIBS.back());
236 MI.eraseFromParent();
237 return true;
238}
239
240bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
241 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned LdarOp,
242 unsigned StlrOp, unsigned CmpOp, unsigned ExtendImm, unsigned ZeroReg,
243 MachineBasicBlock::iterator &NextMBBI) {
244 MachineInstr &MI = *MBBI;
245 MIMetadata MIMD(MI);
246 const MachineOperand &Dest = MI.getOperand(0);
247 Register StatusReg = MI.getOperand(1).getReg();
248 bool StatusDead = MI.getOperand(1).isDead();
249 // Duplicating undef operands into 2 instructions does not guarantee the same
250 // value on both; However undef should be replaced by xzr anyway.
251 assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
252 Register AddrReg = MI.getOperand(2).getReg();
253 Register DesiredReg = MI.getOperand(3).getReg();
254 Register NewReg = MI.getOperand(4).getReg();
255
256 MachineFunction *MF = MBB.getParent();
257 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
258 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
259 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
260
261 MF->insert(++MBB.getIterator(), LoadCmpBB);
262 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
263 MF->insert(++StoreBB->getIterator(), DoneBB);
264
265 // .Lloadcmp:
266 // mov wStatus, 0
267 // ldaxr xDest, [xAddr]
268 // cmp xDest, xDesired
269 // b.ne .Ldone
270 if (!StatusDead)
271 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::MOVZWi), StatusReg)
272 .addImm(0).addImm(0);
273 BuildMI(LoadCmpBB, MIMD, TII->get(LdarOp), Dest.getReg())
274 .addReg(AddrReg);
275 BuildMI(LoadCmpBB, MIMD, TII->get(CmpOp), ZeroReg)
276 .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
277 .addReg(DesiredReg)
278 .addImm(ExtendImm);
279 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::Bcc))
281 .addMBB(DoneBB)
282 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
283 LoadCmpBB->addSuccessor(DoneBB);
284 LoadCmpBB->addSuccessor(StoreBB);
285
286 // .Lstore:
287 // stlxr wStatus, xNew, [xAddr]
288 // cbnz wStatus, .Lloadcmp
289 BuildMI(StoreBB, MIMD, TII->get(StlrOp), StatusReg)
290 .addReg(NewReg)
291 .addReg(AddrReg);
292 BuildMI(StoreBB, MIMD, TII->get(AArch64::CBNZW))
293 .addReg(StatusReg, getKillRegState(StatusDead))
294 .addMBB(LoadCmpBB);
295 StoreBB->addSuccessor(LoadCmpBB);
296 StoreBB->addSuccessor(DoneBB);
297
298 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
299 DoneBB->transferSuccessors(&MBB);
300
301 MBB.addSuccessor(LoadCmpBB);
302
303 NextMBBI = MBB.end();
304 MI.eraseFromParent();
305
306 // Recompute livein lists.
307 LivePhysRegs LiveRegs;
308 computeAndAddLiveIns(LiveRegs, *DoneBB);
309 computeAndAddLiveIns(LiveRegs, *StoreBB);
310 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
311 // Do an extra pass around the loop to get loop carried registers right.
312 StoreBB->clearLiveIns();
313 computeAndAddLiveIns(LiveRegs, *StoreBB);
314 LoadCmpBB->clearLiveIns();
315 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
316
317 return true;
318}
319
320bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
321 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
322 MachineBasicBlock::iterator &NextMBBI) {
323 MachineInstr &MI = *MBBI;
324 MIMetadata MIMD(MI);
325 MachineOperand &DestLo = MI.getOperand(0);
326 MachineOperand &DestHi = MI.getOperand(1);
327 Register StatusReg = MI.getOperand(2).getReg();
328 bool StatusDead = MI.getOperand(2).isDead();
329 // Duplicating undef operands into 2 instructions does not guarantee the same
330 // value on both; However undef should be replaced by xzr anyway.
331 assert(!MI.getOperand(3).isUndef() && "cannot handle undef");
332 Register AddrReg = MI.getOperand(3).getReg();
333 Register DesiredLoReg = MI.getOperand(4).getReg();
334 Register DesiredHiReg = MI.getOperand(5).getReg();
335 Register NewLoReg = MI.getOperand(6).getReg();
336 Register NewHiReg = MI.getOperand(7).getReg();
337
338 unsigned LdxpOp, StxpOp;
339
340 switch (MI.getOpcode()) {
341 case AArch64::CMP_SWAP_128_MONOTONIC:
342 LdxpOp = AArch64::LDXPX;
343 StxpOp = AArch64::STXPX;
344 break;
345 case AArch64::CMP_SWAP_128_RELEASE:
346 LdxpOp = AArch64::LDXPX;
347 StxpOp = AArch64::STLXPX;
348 break;
349 case AArch64::CMP_SWAP_128_ACQUIRE:
350 LdxpOp = AArch64::LDAXPX;
351 StxpOp = AArch64::STXPX;
352 break;
353 case AArch64::CMP_SWAP_128:
354 LdxpOp = AArch64::LDAXPX;
355 StxpOp = AArch64::STLXPX;
356 break;
357 default:
358 llvm_unreachable("Unexpected opcode");
359 }
360
361 MachineFunction *MF = MBB.getParent();
362 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
363 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
364 auto FailBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
365 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
366
367 MF->insert(++MBB.getIterator(), LoadCmpBB);
368 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
369 MF->insert(++StoreBB->getIterator(), FailBB);
370 MF->insert(++FailBB->getIterator(), DoneBB);
371
372 // .Lloadcmp:
373 // ldaxp xDestLo, xDestHi, [xAddr]
374 // cmp xDestLo, xDesiredLo
375 // sbcs xDestHi, xDesiredHi
376 // b.ne .Ldone
377 BuildMI(LoadCmpBB, MIMD, TII->get(LdxpOp))
378 .addReg(DestLo.getReg(), RegState::Define)
379 .addReg(DestHi.getReg(), RegState::Define)
380 .addReg(AddrReg);
381 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::SUBSXrs), AArch64::XZR)
382 .addReg(DestLo.getReg(), getKillRegState(DestLo.isDead()))
383 .addReg(DesiredLoReg)
384 .addImm(0);
385 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CSINCWr), StatusReg)
386 .addUse(AArch64::WZR)
387 .addUse(AArch64::WZR)
389 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::SUBSXrs), AArch64::XZR)
390 .addReg(DestHi.getReg(), getKillRegState(DestHi.isDead()))
391 .addReg(DesiredHiReg)
392 .addImm(0);
393 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CSINCWr), StatusReg)
394 .addUse(StatusReg, RegState::Kill)
395 .addUse(StatusReg, RegState::Kill)
397 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CBNZW))
398 .addUse(StatusReg, getKillRegState(StatusDead))
399 .addMBB(FailBB);
400 LoadCmpBB->addSuccessor(FailBB);
401 LoadCmpBB->addSuccessor(StoreBB);
402
403 // .Lstore:
404 // stlxp wStatus, xNewLo, xNewHi, [xAddr]
405 // cbnz wStatus, .Lloadcmp
406 BuildMI(StoreBB, MIMD, TII->get(StxpOp), StatusReg)
407 .addReg(NewLoReg)
408 .addReg(NewHiReg)
409 .addReg(AddrReg);
410 BuildMI(StoreBB, MIMD, TII->get(AArch64::CBNZW))
411 .addReg(StatusReg, getKillRegState(StatusDead))
412 .addMBB(LoadCmpBB);
413 BuildMI(StoreBB, MIMD, TII->get(AArch64::B)).addMBB(DoneBB);
414 StoreBB->addSuccessor(LoadCmpBB);
415 StoreBB->addSuccessor(DoneBB);
416
417 // .Lfail:
418 // stlxp wStatus, xDestLo, xDestHi, [xAddr]
419 // cbnz wStatus, .Lloadcmp
420 BuildMI(FailBB, MIMD, TII->get(StxpOp), StatusReg)
421 .addReg(DestLo.getReg())
422 .addReg(DestHi.getReg())
423 .addReg(AddrReg);
424 BuildMI(FailBB, MIMD, TII->get(AArch64::CBNZW))
425 .addReg(StatusReg, getKillRegState(StatusDead))
426 .addMBB(LoadCmpBB);
427 FailBB->addSuccessor(LoadCmpBB);
428 FailBB->addSuccessor(DoneBB);
429
430 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
431 DoneBB->transferSuccessors(&MBB);
432
433 MBB.addSuccessor(LoadCmpBB);
434
435 NextMBBI = MBB.end();
436 MI.eraseFromParent();
437
438 // Recompute liveness bottom up.
439 LivePhysRegs LiveRegs;
440 computeAndAddLiveIns(LiveRegs, *DoneBB);
441 computeAndAddLiveIns(LiveRegs, *FailBB);
442 computeAndAddLiveIns(LiveRegs, *StoreBB);
443 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
444
445 // Do an extra pass in the loop to get the loop carried dependencies right.
446 FailBB->clearLiveIns();
447 computeAndAddLiveIns(LiveRegs, *FailBB);
448 StoreBB->clearLiveIns();
449 computeAndAddLiveIns(LiveRegs, *StoreBB);
450 LoadCmpBB->clearLiveIns();
451 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
452
453 return true;
454}
455
456/// \brief Expand Pseudos to Instructions with destructive operands.
457///
458/// This mechanism uses MOVPRFX instructions for zeroing the false lanes
459/// or for fixing relaxed register allocation conditions to comply with
460/// the instructions register constraints. The latter case may be cheaper
461/// than setting the register constraints in the register allocator,
462/// since that will insert regular MOV instructions rather than MOVPRFX.
463///
464/// Example (after register allocation):
465///
466/// FSUB_ZPZZ_ZERO_B Z0, Pg, Z1, Z0
467///
468/// * The Pseudo FSUB_ZPZZ_ZERO_B maps to FSUB_ZPmZ_B.
469/// * We cannot map directly to FSUB_ZPmZ_B because the register
470/// constraints of the instruction are not met.
471/// * Also the _ZERO specifies the false lanes need to be zeroed.
472///
473/// We first try to see if the destructive operand == result operand,
474/// if not, we try to swap the operands, e.g.
475///
476/// FSUB_ZPmZ_B Z0, Pg/m, Z0, Z1
477///
478/// But because FSUB_ZPmZ is not commutative, this is semantically
479/// different, so we need a reverse instruction:
480///
481/// FSUBR_ZPmZ_B Z0, Pg/m, Z0, Z1
482///
483/// Then we implement the zeroing of the false lanes of Z0 by adding
484/// a zeroing MOVPRFX instruction:
485///
486/// MOVPRFX_ZPzZ_B Z0, Pg/z, Z0
487/// FSUBR_ZPmZ_B Z0, Pg/m, Z0, Z1
488///
489/// Note that this can only be done for _ZERO or _UNDEF variants where
490/// we can guarantee the false lanes to be zeroed (by implementing this)
491/// or that they are undef (don't care / not used), otherwise the
492/// swapping of operands is illegal because the operation is not
493/// (or cannot be emulated to be) fully commutative.
494bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
495 MachineInstr &MI, MachineBasicBlock &MBB,
497 unsigned Opcode = AArch64::getSVEPseudoMap(MI.getOpcode());
498 uint64_t DType = TII->get(Opcode).TSFlags & AArch64::DestructiveInstTypeMask;
499 uint64_t FalseLanes = MI.getDesc().TSFlags & AArch64::FalseLanesMask;
500 bool FalseZero = FalseLanes == AArch64::FalseLanesZero;
501 Register DstReg = MI.getOperand(0).getReg();
502 bool DstIsDead = MI.getOperand(0).isDead();
503 bool UseRev = false;
504 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
505
506 switch (DType) {
509 if (DstReg == MI.getOperand(3).getReg()) {
510 // FSUB Zd, Pg, Zs1, Zd ==> FSUBR Zd, Pg/m, Zd, Zs1
511 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
512 UseRev = true;
513 break;
514 }
515 [[fallthrough]];
518 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
519 break;
521 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
522 break;
524 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
525 if (DstReg == MI.getOperand(3).getReg()) {
526 // FMLA Zd, Pg, Za, Zd, Zm ==> FMAD Zdn, Pg, Zm, Za
527 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
528 UseRev = true;
529 } else if (DstReg == MI.getOperand(4).getReg()) {
530 // FMLA Zd, Pg, Za, Zm, Zd ==> FMAD Zdn, Pg, Zm, Za
531 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
532 UseRev = true;
533 }
534 break;
536 // EXT_ZZI_CONSTRUCTIVE Zd, Zs, Imm
537 // ==> MOVPRFX Zd Zs; EXT_ZZI Zd, Zd, Zs, Imm
538 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
539 break;
540 default:
541 llvm_unreachable("Unsupported Destructive Operand type");
542 }
543
544 // MOVPRFX can only be used if the destination operand
545 // is the destructive operand, not as any other operand,
546 // so the Destructive Operand must be unique.
547 bool DOPRegIsUnique = false;
548 switch (DType) {
550 DOPRegIsUnique = DstReg != MI.getOperand(SrcIdx).getReg();
551 break;
554 DOPRegIsUnique =
555 DstReg != MI.getOperand(DOPIdx).getReg() ||
556 MI.getOperand(DOPIdx).getReg() != MI.getOperand(SrcIdx).getReg();
557 break;
561 DOPRegIsUnique = true;
562 break;
564 DOPRegIsUnique =
565 DstReg != MI.getOperand(DOPIdx).getReg() ||
566 (MI.getOperand(DOPIdx).getReg() != MI.getOperand(SrcIdx).getReg() &&
567 MI.getOperand(DOPIdx).getReg() != MI.getOperand(Src2Idx).getReg());
568 break;
569 }
570
571 // Resolve the reverse opcode
572 if (UseRev) {
573 int NewOpcode;
574 // e.g. DIV -> DIVR
575 if ((NewOpcode = AArch64::getSVERevInstr(Opcode)) != -1)
576 Opcode = NewOpcode;
577 // e.g. DIVR -> DIV
578 else if ((NewOpcode = AArch64::getSVENonRevInstr(Opcode)) != -1)
579 Opcode = NewOpcode;
580 }
581
582 // Get the right MOVPRFX
583 uint64_t ElementSize = TII->getElementSizeForOpcode(Opcode);
584 unsigned MovPrfx, LSLZero, MovPrfxZero;
585 switch (ElementSize) {
588 MovPrfx = AArch64::MOVPRFX_ZZ;
589 LSLZero = AArch64::LSL_ZPmI_B;
590 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
591 break;
593 MovPrfx = AArch64::MOVPRFX_ZZ;
594 LSLZero = AArch64::LSL_ZPmI_H;
595 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
596 break;
598 MovPrfx = AArch64::MOVPRFX_ZZ;
599 LSLZero = AArch64::LSL_ZPmI_S;
600 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
601 break;
603 MovPrfx = AArch64::MOVPRFX_ZZ;
604 LSLZero = AArch64::LSL_ZPmI_D;
605 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
606 break;
607 default:
608 llvm_unreachable("Unsupported ElementSize");
609 }
610
611 // Preserve undef state until DOP's reg is defined.
612 RegState DOPRegState = getUndefRegState(MI.getOperand(DOPIdx).isUndef());
613
614 //
615 // Create the destructive operation (if required)
616 //
617 MachineInstrBuilder PRFX, DOP;
618 if (FalseZero) {
619 // If we cannot prefix the requested instruction we'll instead emit a
620 // prefixed_zeroing_mov for DestructiveBinary.
621 assert((DOPRegIsUnique || DType == AArch64::DestructiveBinary ||
624 "The destructive operand should be unique");
625 assert(ElementSize != AArch64::ElementSizeNone &&
626 "This instruction is unpredicated");
627
628 // Merge source operand into destination register
629 PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfxZero))
630 .addReg(DstReg, RegState::Define)
631 .addReg(MI.getOperand(PredIdx).getReg())
632 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
633
634 // After the movprfx, the destructive operand is same as Dst
635 DOPIdx = 0;
636 DOPRegState = {};
637
638 // Create the additional LSL to zero the lanes when the DstReg is not
639 // unique. Zeros the lanes in z0 that aren't active in p0 with sequence
640 // movprfx z0.b, p0/z, z0.b; lsl z0.b, p0/m, z0.b, #0;
641 if ((DType == AArch64::DestructiveBinary ||
644 !DOPRegIsUnique) {
645 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LSLZero))
646 .addReg(DstReg, RegState::Define)
647 .add(MI.getOperand(PredIdx))
648 .addReg(DstReg)
649 .addImm(0);
650 }
651 } else if (DstReg != MI.getOperand(DOPIdx).getReg()) {
652 assert(DOPRegIsUnique && "The destructive operand should be unique");
653 PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfx))
654 .addReg(DstReg, RegState::Define)
655 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
656 DOPIdx = 0;
657 DOPRegState = {};
658 }
659
660 //
661 // Create the destructive operation
662 //
663 DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode))
664 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead));
665 DOPRegState = DOPRegState | RegState::Kill;
666
667 switch (DType) {
669 DOP.addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
670 .add(MI.getOperand(PredIdx))
671 .add(MI.getOperand(SrcIdx));
672 break;
677 DOP.add(MI.getOperand(PredIdx))
678 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
679 .add(MI.getOperand(SrcIdx));
680 break;
682 DOP.add(MI.getOperand(PredIdx))
683 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
684 .add(MI.getOperand(SrcIdx))
685 .add(MI.getOperand(Src2Idx));
686 break;
688 DOP.addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
689 .add(MI.getOperand(SrcIdx))
690 .add(MI.getOperand(Src2Idx));
691 break;
692 }
693
694 if (PRFX) {
695 transferImpOps(MI, PRFX, DOP);
697 } else
698 transferImpOps(MI, DOP, DOP);
699
700 MI.eraseFromParent();
701 return true;
702}
703
704bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
705 MachineInstr &MI, MachineBasicBlock &MBB,
707 MachineInstrBuilder PRFX, DOP;
708 const unsigned Opcode = MI.getOpcode();
709 const MachineOperand &Op0 = MI.getOperand(0);
710 const MachineOperand *Op1 = &MI.getOperand(1);
711 const MachineOperand *Op2 = &MI.getOperand(2);
712 const Register DOPReg = Op0.getReg();
713
714 if (DOPReg == Op2->getReg()) {
715 // Commute the operands to allow destroying the second source.
716 std::swap(Op1, Op2);
717 } else if (DOPReg != Op1->getReg()) {
718 // If not in destructive form, emit a MOVPRFX. The input should only be
719 // killed if unused by the subsequent instruction.
720 PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVPRFX_ZZ))
722 .addReg(Op1->getReg(),
724 getUndefRegState(Op1->isUndef()) |
725 getKillRegState(Op1->isKill() &&
726 Opcode == AArch64::NAND_ZZZ));
727 }
728
729 assert((DOPReg == Op1->getReg() || PRFX) && "invalid expansion");
730
731 const RegState DOPRegState = getRenamableRegState(Op0.isRenamable()) |
732 getUndefRegState(!PRFX && Op1->isUndef()) |
733 RegState::Kill;
734
735 switch (Opcode) {
736 default:
737 llvm_unreachable("unhandled opcode");
738 case AArch64::EON_ZZZ:
739 DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::BSL2N_ZZZZ))
740 .add(Op0)
741 .addReg(DOPReg, DOPRegState)
742 .add(*Op1)
743 .add(*Op2);
744 break;
745 case AArch64::NAND_ZZZ:
746 DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::NBSL_ZZZZ))
747 .add(Op0)
748 .addReg(DOPReg, DOPRegState)
749 .add(*Op2)
750 .add(*Op2);
751 break;
752 case AArch64::NOR_ZZZ:
753 DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::NBSL_ZZZZ))
754 .add(Op0)
755 .addReg(DOPReg, DOPRegState)
756 .add(*Op2)
757 .add(*Op1);
758 break;
759 }
760
761 if (PRFX) {
762 transferImpOps(MI, PRFX, DOP);
764 } else {
765 transferImpOps(MI, DOP, DOP);
766 }
767
768 MI.eraseFromParent();
769 return true;
770}
771
772bool AArch64ExpandPseudoImpl::expandSetTagLoop(
773 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
774 MachineBasicBlock::iterator &NextMBBI) {
775 MachineInstr &MI = *MBBI;
776 DebugLoc DL = MI.getDebugLoc();
777 Register SizeReg = MI.getOperand(0).getReg();
778 Register AddressReg = MI.getOperand(1).getReg();
779
780 MachineFunction *MF = MBB.getParent();
781
782 bool ZeroData = MI.getOpcode() == AArch64::STZGloop_wback;
783 const unsigned OpCode1 =
784 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
785 const unsigned OpCode2 =
786 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
787
788 unsigned Size = MI.getOperand(2).getImm();
789 assert(Size > 0 && Size % 16 == 0);
790 if (Size % (16 * 2) != 0) {
791 BuildMI(MBB, MBBI, DL, TII->get(OpCode1), AddressReg)
792 .addReg(AddressReg)
793 .addReg(AddressReg)
794 .addImm(1);
795 Size -= 16;
796 }
798 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), SizeReg)
799 .addImm(Size);
800 expandMOVImm(MBB, I, 64);
801
802 auto LoopBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
803 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
804
805 MF->insert(++MBB.getIterator(), LoopBB);
806 MF->insert(++LoopBB->getIterator(), DoneBB);
807
808 BuildMI(LoopBB, DL, TII->get(OpCode2))
809 .addDef(AddressReg)
810 .addReg(AddressReg)
811 .addReg(AddressReg)
812 .addImm(2)
814 .setMIFlags(MI.getFlags());
815 BuildMI(LoopBB, DL, TII->get(AArch64::SUBSXri))
816 .addDef(SizeReg)
817 .addReg(SizeReg)
818 .addImm(16 * 2)
819 .addImm(0);
820 BuildMI(LoopBB, DL, TII->get(AArch64::Bcc))
822 .addMBB(LoopBB)
823 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
824
825 LoopBB->addSuccessor(LoopBB);
826 LoopBB->addSuccessor(DoneBB);
827
828 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
829 DoneBB->transferSuccessors(&MBB);
830
831 MBB.addSuccessor(LoopBB);
832
833 NextMBBI = MBB.end();
834 MI.eraseFromParent();
835 // Recompute liveness bottom up.
836 LivePhysRegs LiveRegs;
837 computeAndAddLiveIns(LiveRegs, *DoneBB);
838 computeAndAddLiveIns(LiveRegs, *LoopBB);
839 // Do an extra pass in the loop to get the loop carried dependencies right.
840 // FIXME: is this necessary?
841 LoopBB->clearLiveIns();
842 computeAndAddLiveIns(LiveRegs, *LoopBB);
843 DoneBB->clearLiveIns();
844 computeAndAddLiveIns(LiveRegs, *DoneBB);
845
846 return true;
847}
848
849bool AArch64ExpandPseudoImpl::expandSVESpillFill(
850 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned Opc,
851 unsigned N) {
852 assert((Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI ||
853 Opc == AArch64::LDR_PXI || Opc == AArch64::STR_PXI) &&
854 "Unexpected opcode");
855 RegState RState =
856 getDefRegState(Opc == AArch64::LDR_ZXI || Opc == AArch64::LDR_PXI);
857 unsigned sub0 = (Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI)
858 ? AArch64::zsub0
859 : AArch64::psub0;
860 const TargetRegisterInfo *TRI =
862 MachineInstr &MI = *MBBI;
863 for (unsigned Offset = 0; Offset < N; ++Offset) {
864 int ImmOffset = MI.getOperand(2).getImm() + Offset;
865 bool Kill = (Offset + 1 == N) ? MI.getOperand(1).isKill() : false;
866 assert(ImmOffset >= -256 && ImmOffset < 256 &&
867 "Immediate spill offset out of range");
868 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
869 .addReg(TRI->getSubReg(MI.getOperand(0).getReg(), sub0 + Offset),
870 RState)
871 .addReg(MI.getOperand(1).getReg(), getKillRegState(Kill))
872 .addImm(ImmOffset);
873 }
874 MI.eraseFromParent();
875 return true;
876}
877
878// Create a call with the passed opcode and explicit operands, copying over all
879// the implicit operands from *MBBI, starting at the regmask.
882 const AArch64InstrInfo *TII,
883 unsigned Opcode,
884 ArrayRef<MachineOperand> ExplicitOps,
885 unsigned RegMaskStartIdx) {
886 // Build the MI, with explicit operands first (including the call target).
887 MachineInstr *Call = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode))
888 .add(ExplicitOps)
889 .getInstr();
890
891 // Register arguments are added during ISel, but cannot be added as explicit
892 // operands of the branch as it expects to be B <target> which is only one
893 // operand. Instead they are implicit operands used by the branch.
894 while (!MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
895 const MachineOperand &MOP = MBBI->getOperand(RegMaskStartIdx);
896 assert(MOP.isReg() && "can only add register operands");
898 MOP.getReg(), /*Def=*/false, /*Implicit=*/true, /*isKill=*/false,
899 /*isDead=*/false, /*isUndef=*/MOP.isUndef()));
900 RegMaskStartIdx++;
901 }
902 for (const MachineOperand &MO :
903 llvm::drop_begin(MBBI->operands(), RegMaskStartIdx))
904 Call->addOperand(MO);
905
906 return Call;
907}
908
909// Create a call to CallTarget, copying over all the operands from *MBBI,
910// starting at the regmask.
913 const AArch64InstrInfo *TII,
914 MachineOperand &CallTarget,
915 unsigned RegMaskStartIdx) {
916 unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
917
918 assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
919 "invalid operand for regular call");
920 return createCallWithOps(MBB, MBBI, TII, Opc, CallTarget, RegMaskStartIdx);
921}
922
923bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
924 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
925 // Expand CALL_RVMARKER pseudo to:
926 // - a branch to the call target, followed by
927 // - the special `mov x29, x29` marker, if necessary, and
928 // - another branch, to the runtime function
929 // Mark the sequence as bundle, to avoid passes moving other code in between.
930 MachineInstr &MI = *MBBI;
931 MachineOperand &RVTarget = MI.getOperand(0);
932 bool DoEmitMarker = MI.getOperand(1).getImm();
933 assert(RVTarget.isGlobal() && "invalid operand for attached call");
934
935 MachineInstr *OriginalCall = nullptr;
936
937 if (MI.getOpcode() == AArch64::BLRA_RVMARKER) {
938 // ptrauth call.
939 const MachineOperand &CallTarget = MI.getOperand(2);
940 const MachineOperand &Key = MI.getOperand(3);
941 const MachineOperand &IntDisc = MI.getOperand(4);
942 const MachineOperand &AddrDisc = MI.getOperand(5);
943
944 assert((Key.getImm() == AArch64PACKey::IA ||
945 Key.getImm() == AArch64PACKey::IB) &&
946 "Invalid auth call key");
947
948 MachineOperand Ops[] = {CallTarget, Key, IntDisc, AddrDisc};
949
950 OriginalCall = createCallWithOps(MBB, MBBI, TII, AArch64::BLRA, Ops,
951 /*RegMaskStartIdx=*/6);
952 } else {
953 assert(MI.getOpcode() == AArch64::BLR_RVMARKER && "unknown rvmarker MI");
954 OriginalCall = createCall(MBB, MBBI, TII, MI.getOperand(2),
955 // Regmask starts after the RV and call targets.
956 /*RegMaskStartIdx=*/3);
957 }
958
959 if (DoEmitMarker)
960 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
961 .addReg(AArch64::FP, RegState::Define)
962 .addReg(AArch64::XZR)
963 .addReg(AArch64::FP)
964 .addImm(0);
965
966 auto *RVCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::BL))
967 .add(RVTarget)
968 .getInstr();
969
970 if (MI.shouldUpdateAdditionalCallInfo())
971 MBB.getParent()->moveAdditionalCallInfo(&MI, OriginalCall);
972
973 MI.eraseFromParent();
974 finalizeBundle(MBB, OriginalCall->getIterator(),
975 std::next(RVCall->getIterator()));
976 return true;
977}
978
979bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &MBB,
981 // Expand CALL_BTI pseudo to:
982 // - a branch to the call target
983 // - a BTI instruction
984 // Mark the sequence as a bundle, to avoid passes moving other code in
985 // between.
986 MachineInstr &MI = *MBBI;
987 MachineInstr *Call = createCall(MBB, MBBI, TII, MI.getOperand(0),
988 // Regmask starts after the call target.
989 /*RegMaskStartIdx=*/1);
990
991 Call->setCFIType(*MBB.getParent(), MI.getCFIType());
992
993 MachineInstr *BTI =
994 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::HINT))
995 // BTI J so that setjmp can to BR to this.
996 .addImm(36)
997 .getInstr();
998
999 if (MI.shouldUpdateAdditionalCallInfo())
1001
1002 MI.eraseFromParent();
1003 finalizeBundle(MBB, Call->getIterator(), std::next(BTI->getIterator()));
1004 return true;
1005}
1006
1007bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1008 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
1009 Register CtxReg = MBBI->getOperand(0).getReg();
1010 Register BaseReg = MBBI->getOperand(1).getReg();
1011 int Offset = MBBI->getOperand(2).getImm();
1012 DebugLoc DL(MBBI->getDebugLoc());
1013 auto &STI = MBB.getParent()->getSubtarget<AArch64Subtarget>();
1014
1015 if (STI.getTargetTriple().getArchName() != "arm64e") {
1016 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
1017 .addUse(CtxReg)
1018 .addUse(BaseReg)
1019 .addImm(Offset / 8)
1022 return true;
1023 }
1024
1025 // We need to sign the context in an address-discriminated way. 0xc31a is a
1026 // fixed random value, chosen as part of the ABI.
1027 // add x16, xBase, #Offset
1028 // movk x16, #0xc31a, lsl #48
1029 // mov x17, x22/xzr
1030 // pacdb x17, x16
1031 // str x17, [xBase, #Offset]
1032 unsigned Opc = Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1033 BuildMI(MBB, MBBI, DL, TII->get(Opc), AArch64::X16)
1034 .addUse(BaseReg)
1035 .addImm(abs(Offset))
1036 .addImm(0)
1038 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X16)
1039 .addUse(AArch64::X16)
1040 .addImm(0xc31a)
1041 .addImm(48)
1043 // We're not allowed to clobber X22 (and couldn't clobber XZR if we tried), so
1044 // move it somewhere before signing.
1045 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
1046 .addUse(AArch64::XZR)
1047 .addUse(CtxReg)
1048 .addImm(0)
1050 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACDB), AArch64::X17)
1051 .addUse(AArch64::X17)
1052 .addUse(AArch64::X16)
1054 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
1055 .addUse(AArch64::X17)
1056 .addUse(BaseReg)
1057 .addImm(Offset / 8)
1059
1061 return true;
1062}
1063
1064bool AArch64ExpandPseudoImpl::expandSTSHHAtomicStore(
1065 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
1066 MachineInstr &MI = *MBBI;
1067 DebugLoc DL(MI.getDebugLoc());
1068
1069 unsigned Order = MI.getOperand(2).getImm();
1070 unsigned Policy = MI.getOperand(3).getImm();
1071 unsigned Size = MI.getOperand(4).getImm();
1072
1073 bool IsRelaxed = Order == 0;
1074 unsigned StoreOpc = 0;
1075
1076 // __ATOMIC_RELAXED uses STR. __ATOMIC_{RELEASE/SEQ_CST} use STLR.
1077 switch (Size) {
1078 case 8:
1079 StoreOpc = IsRelaxed ? AArch64::STRBBui : AArch64::STLRB;
1080 break;
1081 case 16:
1082 StoreOpc = IsRelaxed ? AArch64::STRHHui : AArch64::STLRH;
1083 break;
1084 case 32:
1085 StoreOpc = IsRelaxed ? AArch64::STRWui : AArch64::STLRW;
1086 break;
1087 case 64:
1088 StoreOpc = IsRelaxed ? AArch64::STRXui : AArch64::STLRX;
1089 break;
1090 default:
1091 llvm_unreachable("Unexpected STSHH atomic store size");
1092 }
1093
1094 // Emit the hint with the retention policy immediate.
1095 MachineInstr *Hint = BuildMI(MBB, MBBI, DL, TII->get(AArch64::STSHH))
1096 .addImm(Policy)
1097 .getInstr();
1098
1099 // Emit the associated store instruction.
1100 Register ValReg = MI.getOperand(0).getReg();
1101
1102 if (Size < 64) {
1103 const TargetRegisterInfo *TRI =
1105 Register SubReg = TRI->getSubReg(ValReg, AArch64::sub_32);
1106 if (SubReg)
1107 ValReg = SubReg;
1108 }
1109
1110 MachineInstrBuilder Store = BuildMI(MBB, MBBI, DL, TII->get(StoreOpc))
1111 .addReg(ValReg)
1112 .add(MI.getOperand(1));
1113
1114 // Relaxed uses base+imm addressing with a zero offset.
1115 if (IsRelaxed)
1116 Store.addImm(0);
1117
1118 // Preserve memory operands and any implicit uses/defs.
1119 Store->setMemRefs(*MBB.getParent(), MI.memoperands());
1120 transferImpOps(MI, Store, Store);
1121
1122 // Bundle the hint and store so they remain adjacent.
1123 finalizeBundle(MBB, Hint->getIterator(), std::next(Store->getIterator()));
1124
1125 MI.eraseFromParent();
1126 return true;
1127}
1128
1129AArch64ExpandPseudoImpl::ConditionalBlocks
1130AArch64ExpandPseudoImpl::expandConditionalPseudo(
1131 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL,
1132 MachineInstrBuilder &Branch) {
1133 assert((std::next(MBBI) != MBB.end() ||
1134 MBB.successors().begin() != MBB.successors().end()) &&
1135 "Unexpected unreachable in block");
1136
1137 // Split MBB and create two new blocks:
1138 // - MBB now contains all instructions before the conditional pseudo.
1139 // - CondBB contains the conditional pseudo instruction only.
1140 // - EndBB contains all instructions after the conditional pseudo.
1141 MachineInstr &PrevMI = *std::prev(MBBI);
1142 MachineBasicBlock *CondBB = MBB.splitAt(PrevMI, /*UpdateLiveIns*/ true);
1143 MachineBasicBlock *EndBB =
1144 std::next(MBBI) == CondBB->end()
1145 ? *CondBB->successors().begin()
1146 : CondBB->splitAt(*MBBI, /*UpdateLiveIns*/ true);
1147
1148 // Add the SMBB label to the branch instruction & create a branch to EndBB.
1149 Branch.addMBB(CondBB);
1150 BuildMI(&MBB, DL, TII->get(AArch64::B))
1151 .addMBB(EndBB);
1152 MBB.addSuccessor(EndBB);
1153
1154 // Create branch from CondBB to EndBB. Users of this helper should insert new
1155 // instructions at CondBB.back() -- i.e. before the branch.
1156 BuildMI(CondBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
1157 return {*CondBB, *EndBB};
1158}
1159
1160MachineBasicBlock *
1161AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &MBB,
1163 MachineInstr &MI = *MBBI;
1164 DebugLoc DL = MI.getDebugLoc();
1165
1166 // Compare TPIDR2_EL0 against 0. Restore ZA if TPIDR2_EL0 is zero.
1167 MachineInstrBuilder Branch =
1168 BuildMI(MBB, MBBI, DL, TII->get(AArch64::CBZX)).add(MI.getOperand(0));
1169
1170 auto [CondBB, EndBB] = expandConditionalPseudo(MBB, MBBI, DL, Branch);
1171 // Replace the pseudo with a call (BL).
1172 MachineInstrBuilder MIB =
1173 BuildMI(CondBB, CondBB.back(), DL, TII->get(AArch64::BL));
1174 // Copy operands (mainly the regmask) from the pseudo.
1175 for (unsigned I = 2; I < MI.getNumOperands(); ++I)
1176 MIB.add(MI.getOperand(I));
1177 // Mark the TPIDR2 block pointer (X0) as an implicit use.
1178 MIB.addReg(MI.getOperand(1).getReg(), RegState::Implicit);
1179
1180 MI.eraseFromParent();
1181 return &EndBB;
1182}
1183
1184static constexpr unsigned ZERO_ALL_ZA_MASK = 0b11111111;
1185
1187AArch64ExpandPseudoImpl::expandCommitZASave(MachineBasicBlock &MBB,
1189 MachineInstr &MI = *MBBI;
1190 DebugLoc DL = MI.getDebugLoc();
1191 [[maybe_unused]] auto *RI = MBB.getParent()->getSubtarget().getRegisterInfo();
1192
1193 // Compare TPIDR2_EL0 against 0. Commit ZA if TPIDR2_EL0 is non-zero.
1194 MachineInstrBuilder Branch =
1195 BuildMI(MBB, MBBI, DL, TII->get(AArch64::CBNZX)).add(MI.getOperand(0));
1196
1197 auto [CondBB, EndBB] = expandConditionalPseudo(MBB, MBBI, DL, Branch);
1198 // Replace the pseudo with a call (BL).
1200 BuildMI(CondBB, CondBB.back(), DL, TII->get(AArch64::BL));
1201 // Copy operands (mainly the regmask) from the pseudo.
1202 for (unsigned I = 3; I < MI.getNumOperands(); ++I)
1203 MIB.add(MI.getOperand(I));
1204 // Clear TPIDR2_EL0.
1205 BuildMI(CondBB, CondBB.back(), DL, TII->get(AArch64::MSR))
1206 .addImm(AArch64SysReg::TPIDR2_EL0)
1207 .addReg(AArch64::XZR);
1208 bool ZeroZA = MI.getOperand(1).getImm() != 0;
1209 bool ZeroZT0 = MI.getOperand(2).getImm() != 0;
1210 if (ZeroZA) {
1211 assert(MI.definesRegister(AArch64::ZAB0, RI) && "should define ZA!");
1212 BuildMI(CondBB, CondBB.back(), DL, TII->get(AArch64::ZERO_M))
1214 .addDef(AArch64::ZAB0, RegState::ImplicitDefine);
1215 }
1216 if (ZeroZT0) {
1217 assert(MI.definesRegister(AArch64::ZT0, RI) && "should define ZT0!");
1218 BuildMI(CondBB, CondBB.back(), DL, TII->get(AArch64::ZERO_T))
1219 .addDef(AArch64::ZT0);
1220 }
1221
1222 MI.eraseFromParent();
1223 return &EndBB;
1224}
1225
1226MachineBasicBlock *
1227AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &MBB,
1229 MachineInstr &MI = *MBBI;
1230 // In the case of a smstart/smstop before a unreachable, just remove the pseudo.
1231 // Exception handling code generated by Clang may introduce unreachables and it
1232 // seems unnecessary to restore pstate.sm when that happens. Note that it is
1233 // not just an optimisation, the code below expects a successor instruction/block
1234 // in order to split the block at MBBI.
1235 if (std::next(MBBI) == MBB.end() &&
1236 MI.getParent()->successors().begin() ==
1237 MI.getParent()->successors().end()) {
1238 MI.eraseFromParent();
1239 return &MBB;
1240 }
1241
1242 // Expand the pseudo into smstart or smstop instruction. The pseudo has the
1243 // following operands:
1244 //
1245 // MSRpstatePseudo <za|sm|both>, <0|1>, condition[, pstate.sm], <regmask>
1246 //
1247 // The pseudo is expanded into a conditional smstart/smstop, with a
1248 // check if pstate.sm (register) equals the expected value, and if not,
1249 // invokes the smstart/smstop.
1250 //
1251 // As an example, the following block contains a normal call from a
1252 // streaming-compatible function:
1253 //
1254 // OrigBB:
1255 // MSRpstatePseudo 3, 0, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTOP
1256 // bl @normal_callee
1257 // MSRpstatePseudo 3, 1, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTART
1258 //
1259 // ...which will be transformed into:
1260 //
1261 // OrigBB:
1262 // TBNZx %0:gpr64, 0, SMBB
1263 // b EndBB
1264 //
1265 // SMBB:
1266 // MSRpstatesvcrImm1 3, 0, <regmask> <- SMSTOP
1267 //
1268 // EndBB:
1269 // bl @normal_callee
1270 // MSRcond_pstatesvcrImm1 3, 1, <regmask> <- SMSTART
1271 //
1272 DebugLoc DL = MI.getDebugLoc();
1273
1274 // Create the conditional branch based on the third operand of the
1275 // instruction, which tells us if we are wrapping a normal or streaming
1276 // function.
1277 // We test the live value of pstate.sm and toggle pstate.sm if this is not the
1278 // expected value for the callee (0 for a normal callee and 1 for a streaming
1279 // callee).
1280 unsigned Opc;
1281 switch (MI.getOperand(2).getImm()) {
1282 case AArch64SME::Always:
1283 llvm_unreachable("Should have matched to instruction directly");
1285 Opc = AArch64::TBNZW;
1286 break;
1288 Opc = AArch64::TBZW;
1289 break;
1290 }
1291 auto PStateSM = MI.getOperand(3).getReg();
1293 unsigned SMReg32 = TRI->getSubReg(PStateSM, AArch64::sub_32);
1294 MachineInstrBuilder Tbx =
1295 BuildMI(MBB, MBBI, DL, TII->get(Opc)).addReg(SMReg32).addImm(0);
1296
1297 auto [CondBB, EndBB] = expandConditionalPseudo(MBB, MBBI, DL, Tbx);
1298 // Create the SMSTART/SMSTOP (MSRpstatesvcrImm1) instruction in SMBB.
1299 MachineInstrBuilder MIB = BuildMI(CondBB, CondBB.back(), MI.getDebugLoc(),
1300 TII->get(AArch64::MSRpstatesvcrImm1));
1301 // Copy all but the second and third operands of MSRcond_pstatesvcrImm1 (as
1302 // these contain the CopyFromReg for the first argument and the flag to
1303 // indicate whether the callee is streaming or normal).
1304 MIB.add(MI.getOperand(0));
1305 MIB.add(MI.getOperand(1));
1306 for (unsigned i = 4; i < MI.getNumOperands(); ++i)
1307 MIB.add(MI.getOperand(i));
1308
1309 MI.eraseFromParent();
1310 return &EndBB;
1311}
1312
1313bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1314 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
1315 TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
1316 unsigned ContiguousOp, unsigned StridedOpc) {
1317 MachineInstr &MI = *MBBI;
1318 Register Tuple = MI.getOperand(0).getReg();
1319
1320 auto ContiguousRange = ContiguousClass.getRegisters();
1321 auto StridedRange = StridedClass.getRegisters();
1322 unsigned Opc;
1323 if (llvm::is_contained(ContiguousRange, Tuple.asMCReg())) {
1324 Opc = ContiguousOp;
1325 } else if (llvm::is_contained(StridedRange, Tuple.asMCReg())) {
1326 Opc = StridedOpc;
1327 } else
1328 llvm_unreachable("Cannot expand Multi-Vector pseudo");
1329
1330 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
1331 .add(MI.getOperand(0))
1332 .add(MI.getOperand(1))
1333 .add(MI.getOperand(2))
1334 .add(MI.getOperand(3));
1335 transferImpOps(MI, MIB, MIB);
1336 MI.eraseFromParent();
1337 return true;
1338}
1339
1340bool AArch64ExpandPseudoImpl::expandFormTuplePseudo(
1341 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
1342 MachineBasicBlock::iterator &NextMBBI, unsigned Size) {
1343 assert((Size == 2 || Size == 4) && "Invalid Tuple Size");
1344 MachineInstr &MI = *MBBI;
1345 Register ReturnTuple = MI.getOperand(0).getReg();
1346
1347 const TargetRegisterInfo *TRI =
1349 for (unsigned I = 0; I < Size; ++I) {
1350 Register FormTupleOpReg = MI.getOperand(I + 1).getReg();
1351 Register ReturnTupleSubReg =
1352 TRI->getSubReg(ReturnTuple, AArch64::zsub0 + I);
1353 // Add copies to ensure the subregisters remain in the correct order
1354 // for any contigious operation they are used by.
1355 if (FormTupleOpReg != ReturnTupleSubReg)
1356 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORR_ZZZ))
1357 .addReg(ReturnTupleSubReg, RegState::Define)
1358 .addReg(FormTupleOpReg)
1359 .addReg(FormTupleOpReg);
1360 }
1361
1362 MI.eraseFromParent();
1363 return true;
1364}
1365
1366/// If MBBI references a pseudo instruction that should be expanded here,
1367/// do the expansion and return true. Otherwise return false.
1368bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB,
1370 MachineBasicBlock::iterator &NextMBBI) {
1371 MachineInstr &MI = *MBBI;
1372 unsigned Opcode = MI.getOpcode();
1373
1374 // Check if we can expand the destructive op
1375 int OrigInstr = AArch64::getSVEPseudoMap(MI.getOpcode());
1376 if (OrigInstr != -1) {
1377 auto &Orig = TII->get(OrigInstr);
1378 if ((Orig.TSFlags & AArch64::DestructiveInstTypeMask) !=
1380 return expand_DestructiveOp(MI, MBB, MBBI);
1381 }
1382 }
1383
1384 switch (Opcode) {
1385 default:
1386 break;
1387
1388 case AArch64::BSPv8i8:
1389 case AArch64::BSPv16i8: {
1390 Register DstReg = MI.getOperand(0).getReg();
1391 if (DstReg == MI.getOperand(3).getReg()) {
1392 // Expand to BIT
1393 auto I = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1394 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1395 : AArch64::BITv16i8))
1396 .add(MI.getOperand(0))
1397 .add(MI.getOperand(3))
1398 .add(MI.getOperand(2))
1399 .add(MI.getOperand(1));
1400 transferImpOps(MI, I, I);
1401 } else if (DstReg == MI.getOperand(2).getReg()) {
1402 // Expand to BIF
1403 auto I = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1404 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1405 : AArch64::BIFv16i8))
1406 .add(MI.getOperand(0))
1407 .add(MI.getOperand(2))
1408 .add(MI.getOperand(3))
1409 .add(MI.getOperand(1));
1410 transferImpOps(MI, I, I);
1411 } else {
1412 // Expand to BSL, use additional move if required
1413 if (DstReg == MI.getOperand(1).getReg()) {
1414 auto I =
1415 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1416 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1417 : AArch64::BSLv16i8))
1418 .add(MI.getOperand(0))
1419 .add(MI.getOperand(1))
1420 .add(MI.getOperand(2))
1421 .add(MI.getOperand(3));
1422 transferImpOps(MI, I, I);
1423 } else {
1425 getRenamableRegState(MI.getOperand(1).isRenamable()) |
1427 MI.getOperand(1).isKill() &&
1428 MI.getOperand(1).getReg() != MI.getOperand(2).getReg() &&
1429 MI.getOperand(1).getReg() != MI.getOperand(3).getReg());
1430 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1431 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1432 : AArch64::ORRv16i8))
1433 .addReg(DstReg,
1434 RegState::Define |
1435 getRenamableRegState(MI.getOperand(0).isRenamable()))
1436 .addReg(MI.getOperand(1).getReg(), RegState)
1437 .addReg(MI.getOperand(1).getReg(), RegState);
1438 auto I2 =
1439 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1440 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1441 : AArch64::BSLv16i8))
1442 .add(MI.getOperand(0))
1443 .addReg(DstReg,
1444 RegState::Kill | getRenamableRegState(
1445 MI.getOperand(0).isRenamable()))
1446 .add(MI.getOperand(2))
1447 .add(MI.getOperand(3));
1448 transferImpOps(MI, I2, I2);
1449 }
1450 }
1451 MI.eraseFromParent();
1452 return true;
1453 }
1454
1455 case AArch64::ADDWrr:
1456 case AArch64::SUBWrr:
1457 case AArch64::ADDXrr:
1458 case AArch64::SUBXrr:
1459 case AArch64::ADDSWrr:
1460 case AArch64::SUBSWrr:
1461 case AArch64::ADDSXrr:
1462 case AArch64::SUBSXrr:
1463 case AArch64::ANDWrr:
1464 case AArch64::ANDXrr:
1465 case AArch64::BICWrr:
1466 case AArch64::BICXrr:
1467 case AArch64::ANDSWrr:
1468 case AArch64::ANDSXrr:
1469 case AArch64::BICSWrr:
1470 case AArch64::BICSXrr:
1471 case AArch64::EONWrr:
1472 case AArch64::EONXrr:
1473 case AArch64::EORWrr:
1474 case AArch64::EORXrr:
1475 case AArch64::ORNWrr:
1476 case AArch64::ORNXrr:
1477 case AArch64::ORRWrr:
1478 case AArch64::ORRXrr: {
1479 unsigned Opcode;
1480 switch (MI.getOpcode()) {
1481 default:
1482 return false;
1483 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs; break;
1484 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs; break;
1485 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs; break;
1486 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs; break;
1487 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs; break;
1488 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs; break;
1489 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs; break;
1490 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs; break;
1491 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs; break;
1492 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs; break;
1493 case AArch64::BICWrr: Opcode = AArch64::BICWrs; break;
1494 case AArch64::BICXrr: Opcode = AArch64::BICXrs; break;
1495 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs; break;
1496 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs; break;
1497 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs; break;
1498 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs; break;
1499 case AArch64::EONWrr: Opcode = AArch64::EONWrs; break;
1500 case AArch64::EONXrr: Opcode = AArch64::EONXrs; break;
1501 case AArch64::EORWrr: Opcode = AArch64::EORWrs; break;
1502 case AArch64::EORXrr: Opcode = AArch64::EORXrs; break;
1503 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs; break;
1504 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs; break;
1505 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs; break;
1506 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs; break;
1507 }
1508 MachineFunction &MF = *MBB.getParent();
1509 // Try to create new inst without implicit operands added.
1510 MachineInstr *NewMI = MF.CreateMachineInstr(
1511 TII->get(Opcode), MI.getDebugLoc(), /*NoImplicit=*/true);
1512 MBB.insert(MBBI, NewMI);
1513 MachineInstrBuilder MIB1(MF, NewMI);
1514 MIB1->setPCSections(MF, MI.getPCSections());
1515 MIB1.addReg(MI.getOperand(0).getReg(), RegState::Define)
1516 .add(MI.getOperand(1))
1517 .add(MI.getOperand(2))
1519 transferImpOps(MI, MIB1, MIB1);
1520 if (auto DebugNumber = MI.peekDebugInstrNum())
1521 NewMI->setDebugInstrNum(DebugNumber);
1522 MI.eraseFromParent();
1523 return true;
1524 }
1525
1526 case AArch64::LOADgot: {
1527 MachineFunction *MF = MBB.getParent();
1528 Register DstReg = MI.getOperand(0).getReg();
1529 const MachineOperand &MO1 = MI.getOperand(1);
1530 unsigned Flags = MO1.getTargetFlags();
1531
1532 if (MF->getTarget().getCodeModel() == CodeModel::Tiny) {
1533 // Tiny codemodel expand to LDR
1534 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1535 TII->get(AArch64::LDRXl), DstReg);
1536
1537 if (MO1.isGlobal()) {
1538 MIB.addGlobalAddress(MO1.getGlobal(), 0, Flags);
1539 } else if (MO1.isSymbol()) {
1540 MIB.addExternalSymbol(MO1.getSymbolName(), Flags);
1541 } else {
1542 assert(MO1.isCPI() &&
1543 "Only expect globals, externalsymbols, or constant pools");
1544 MIB.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(), Flags);
1545 }
1546 } else {
1547 // Small codemodel expand into ADRP + LDR.
1548 MachineFunction &MF = *MI.getParent()->getParent();
1549 DebugLoc DL = MI.getDebugLoc();
1550 MachineInstrBuilder MIB1 =
1551 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
1552
1553 MachineInstrBuilder MIB2;
1554 if (MF.getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1556 unsigned Reg32 = TRI->getSubReg(DstReg, AArch64::sub_32);
1557 MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRWui))
1558 .addDef(Reg32)
1559 .addReg(DstReg, RegState::Kill)
1560 .addReg(DstReg, RegState::Implicit);
1561 } else {
1562 Register DstReg = MI.getOperand(0).getReg();
1563 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
1564 .add(MI.getOperand(0))
1565 .addUse(DstReg, RegState::Kill);
1566 }
1567
1568 if (MO1.isGlobal()) {
1569 MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
1570 MIB2.addGlobalAddress(MO1.getGlobal(), 0,
1572 } else if (MO1.isSymbol()) {
1574 MIB2.addExternalSymbol(MO1.getSymbolName(), Flags |
1577 } else {
1578 assert(MO1.isCPI() &&
1579 "Only expect globals, externalsymbols, or constant pools");
1580 MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
1581 Flags | AArch64II::MO_PAGE);
1582 MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
1583 Flags | AArch64II::MO_PAGEOFF |
1585 }
1586
1587 // If the LOADgot instruction has a debug-instr-number, annotate the
1588 // LDRWui instruction that it is expanded to with the same
1589 // debug-instr-number to preserve debug information.
1590 if (MI.peekDebugInstrNum() != 0)
1591 MIB2->setDebugInstrNum(MI.peekDebugInstrNum());
1592 transferImpOps(MI, MIB1, MIB2);
1593 }
1594 MI.eraseFromParent();
1595 return true;
1596 }
1597 case AArch64::MOVaddrBA: {
1598 MachineFunction &MF = *MI.getParent()->getParent();
1599 if (MF.getSubtarget<AArch64Subtarget>().isTargetMachO()) {
1600 // blockaddress expressions have to come from a constant pool because the
1601 // largest addend (and hence offset within a function) allowed for ADRP is
1602 // only 8MB.
1603 const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
1604 assert(MI.getOperand(1).getOffset() == 0 && "unexpected offset");
1605
1606 MachineConstantPool *MCP = MF.getConstantPool();
1607 unsigned CPIdx = MCP->getConstantPoolIndex(BA, Align(8));
1608
1609 Register DstReg = MI.getOperand(0).getReg();
1610 auto MIB1 =
1611 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
1613 auto MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1614 TII->get(AArch64::LDRXui), DstReg)
1615 .addUse(DstReg)
1618 transferImpOps(MI, MIB1, MIB2);
1619 MI.eraseFromParent();
1620 return true;
1621 }
1622 }
1623 [[fallthrough]];
1624 case AArch64::MOVaddr:
1625 case AArch64::MOVaddrJT:
1626 case AArch64::MOVaddrCP:
1627 case AArch64::MOVaddrTLS:
1628 case AArch64::MOVaddrEXT: {
1629 // Expand into ADRP + ADD.
1630 Register DstReg = MI.getOperand(0).getReg();
1631 assert(DstReg != AArch64::XZR);
1632 MachineInstrBuilder MIB1 =
1633 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
1634 .add(MI.getOperand(1));
1635
1636 if (MI.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED) {
1637 // MO_TAGGED on the page indicates a tagged address. Set the tag now.
1638 // We do so by creating a MOVK that sets bits 48-63 of the register to
1639 // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
1640 // the small code model so we can assume a binary size of <= 4GB, which
1641 // makes the untagged PC relative offset positive. The binary must also be
1642 // loaded into address range [0, 2^48). Both of these properties need to
1643 // be ensured at runtime when using tagged addresses.
1644 auto Tag = MI.getOperand(1);
1645 Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
1646 Tag.setOffset(0x100000000);
1647 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi), DstReg)
1648 .addReg(DstReg)
1649 .add(Tag)
1650 .addImm(48);
1651 }
1652
1653 MachineInstrBuilder MIB2 =
1654 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
1655 .add(MI.getOperand(0))
1656 .addReg(DstReg)
1657 .add(MI.getOperand(2))
1658 .addImm(0);
1659
1660 transferImpOps(MI, MIB1, MIB2);
1661 MI.eraseFromParent();
1662 return true;
1663 }
1664 case AArch64::ADDlowTLS:
1665 // Produce a plain ADD
1666 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
1667 .add(MI.getOperand(0))
1668 .add(MI.getOperand(1))
1669 .add(MI.getOperand(2))
1670 .addImm(0);
1671 MI.eraseFromParent();
1672 return true;
1673
1674 case AArch64::MOVbaseTLS: {
1675 Register DstReg = MI.getOperand(0).getReg();
1676 auto SysReg = AArch64SysReg::TPIDR_EL0;
1677 MachineFunction *MF = MBB.getParent();
1678 if (MF->getSubtarget<AArch64Subtarget>().useEL3ForTP())
1679 SysReg = AArch64SysReg::TPIDR_EL3;
1680 else if (MF->getSubtarget<AArch64Subtarget>().useEL2ForTP())
1681 SysReg = AArch64SysReg::TPIDR_EL2;
1682 else if (MF->getSubtarget<AArch64Subtarget>().useEL1ForTP())
1683 SysReg = AArch64SysReg::TPIDR_EL1;
1684 else if (MF->getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1685 SysReg = AArch64SysReg::TPIDRRO_EL0;
1686 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg)
1687 .addImm(SysReg);
1688 MI.eraseFromParent();
1689 return true;
1690 }
1691
1692 case AArch64::MOVi32imm:
1693 return expandMOVImm(MBB, MBBI, 32);
1694 case AArch64::MOVi64imm:
1695 return expandMOVImm(MBB, MBBI, 64);
1696 case AArch64::RET_ReallyLR: {
1697 // Hiding the LR use with RET_ReallyLR may lead to extra kills in the
1698 // function and missing live-ins. We are fine in practice because callee
1699 // saved register handling ensures the register value is restored before
1700 // RET, but we need the undef flag here to appease the MachineVerifier
1701 // liveness checks.
1702 MachineInstrBuilder MIB =
1703 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET))
1704 .addReg(AArch64::LR, RegState::Undef);
1705 transferImpOps(MI, MIB, MIB);
1706 MI.eraseFromParent();
1707 return true;
1708 }
1709 case AArch64::CMP_SWAP_8:
1710 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1711 AArch64::SUBSWrx,
1713 AArch64::WZR, NextMBBI);
1714 case AArch64::CMP_SWAP_16:
1715 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1716 AArch64::SUBSWrx,
1718 AArch64::WZR, NextMBBI);
1719 case AArch64::CMP_SWAP_32:
1720 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1721 AArch64::SUBSWrs,
1723 AArch64::WZR, NextMBBI);
1724 case AArch64::CMP_SWAP_64:
1725 return expandCMP_SWAP(MBB, MBBI,
1726 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1728 AArch64::XZR, NextMBBI);
1729 case AArch64::CMP_SWAP_128:
1730 case AArch64::CMP_SWAP_128_RELEASE:
1731 case AArch64::CMP_SWAP_128_ACQUIRE:
1732 case AArch64::CMP_SWAP_128_MONOTONIC:
1733 return expandCMP_SWAP_128(MBB, MBBI, NextMBBI);
1734
1735 case AArch64::AESMCrrTied:
1736 case AArch64::AESIMCrrTied: {
1737 MachineInstrBuilder MIB =
1738 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1739 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1740 AArch64::AESIMCrr))
1741 .add(MI.getOperand(0))
1742 .add(MI.getOperand(1));
1743 transferImpOps(MI, MIB, MIB);
1744 MI.eraseFromParent();
1745 return true;
1746 }
1747 case AArch64::IRGstack: {
1748 MachineFunction &MF = *MBB.getParent();
1749 const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
1750 const AArch64FrameLowering *TFI =
1751 MF.getSubtarget<AArch64Subtarget>().getFrameLowering();
1752
1753 // IRG does not allow immediate offset. getTaggedBasePointerOffset should
1754 // almost always point to SP-after-prologue; if not, emit a longer
1755 // instruction sequence.
1756 int BaseOffset = -AFI->getTaggedBasePointerOffset();
1757 Register FrameReg;
1758 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1759 MF, BaseOffset, false /*isFixed*/, TargetStackID::Default /*StackID*/,
1760 FrameReg,
1761 /*PreferFP=*/false,
1762 /*ForSimm=*/true);
1763 Register SrcReg = FrameReg;
1764 if (FrameRegOffset) {
1765 // Use output register as temporary.
1766 SrcReg = MI.getOperand(0).getReg();
1767 emitFrameOffset(MBB, &MI, MI.getDebugLoc(), SrcReg, FrameReg,
1768 FrameRegOffset, TII);
1769 }
1770 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::IRG))
1771 .add(MI.getOperand(0))
1772 .addUse(SrcReg)
1773 .add(MI.getOperand(2));
1774 MI.eraseFromParent();
1775 return true;
1776 }
1777 case AArch64::TAGPstack: {
1778 int64_t Offset = MI.getOperand(2).getImm();
1779 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1780 TII->get(Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1781 .add(MI.getOperand(0))
1782 .add(MI.getOperand(1))
1783 .addImm(std::abs(Offset))
1784 .add(MI.getOperand(4));
1785 MI.eraseFromParent();
1786 return true;
1787 }
1788 case AArch64::STGloop_wback:
1789 case AArch64::STZGloop_wback:
1790 return expandSetTagLoop(MBB, MBBI, NextMBBI);
1791 case AArch64::STGloop:
1792 case AArch64::STZGloop:
1794 "Non-writeback variants of STGloop / STZGloop should not "
1795 "survive past PrologEpilogInserter.");
1796 case AArch64::STR_ZZZZXI:
1797 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1798 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 4);
1799 case AArch64::STR_ZZZXI:
1800 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 3);
1801 case AArch64::STR_ZZXI:
1802 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1803 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 2);
1804 case AArch64::STR_PPXI:
1805 return expandSVESpillFill(MBB, MBBI, AArch64::STR_PXI, 2);
1806 case AArch64::LDR_ZZZZXI:
1807 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1808 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 4);
1809 case AArch64::LDR_ZZZXI:
1810 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 3);
1811 case AArch64::LDR_ZZXI:
1812 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1813 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 2);
1814 case AArch64::LDR_PPXI:
1815 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_PXI, 2);
1816 case AArch64::BLR_RVMARKER:
1817 case AArch64::BLRA_RVMARKER:
1818 return expandCALL_RVMARKER(MBB, MBBI);
1819 case AArch64::BLR_BTI:
1820 return expandCALL_BTI(MBB, MBBI);
1821 case AArch64::StoreSwiftAsyncContext:
1822 return expandStoreSwiftAsyncContext(MBB, MBBI);
1823 case AArch64::STSHH_ATOMIC_STORE_SZ:
1824 return expandSTSHHAtomicStore(MBB, MBBI);
1825 case AArch64::RestoreZAPseudo:
1826 case AArch64::CommitZASavePseudo:
1827 case AArch64::MSRpstatePseudo: {
1828 auto *NewMBB = [&] {
1829 switch (Opcode) {
1830 case AArch64::RestoreZAPseudo:
1831 return expandRestoreZASave(MBB, MBBI);
1832 case AArch64::CommitZASavePseudo:
1833 return expandCommitZASave(MBB, MBBI);
1834 case AArch64::MSRpstatePseudo:
1835 return expandCondSMToggle(MBB, MBBI);
1836 default:
1837 llvm_unreachable("Unexpected conditional pseudo!");
1838 }
1839 }();
1840 if (NewMBB != &MBB)
1841 NextMBBI = MBB.end(); // The NextMBBI iterator is invalidated.
1842 return true;
1843 }
1844 case AArch64::InOutZAUsePseudo:
1845 case AArch64::RequiresZASavePseudo:
1846 case AArch64::RequiresZT0SavePseudo:
1847 case AArch64::SMEStateAllocPseudo:
1848 case AArch64::COALESCER_BARRIER_FPR16:
1849 case AArch64::COALESCER_BARRIER_FPR32:
1850 case AArch64::COALESCER_BARRIER_FPR64:
1851 case AArch64::COALESCER_BARRIER_FPR128:
1852 MI.eraseFromParent();
1853 return true;
1854 case AArch64::LD1B_2Z_IMM_PSEUDO:
1855 return expandMultiVecPseudo(
1856 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1857 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1858 case AArch64::LD1H_2Z_IMM_PSEUDO:
1859 return expandMultiVecPseudo(
1860 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1861 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1862 case AArch64::LD1W_2Z_IMM_PSEUDO:
1863 return expandMultiVecPseudo(
1864 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1865 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1866 case AArch64::LD1D_2Z_IMM_PSEUDO:
1867 return expandMultiVecPseudo(
1868 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1869 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1870 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1871 return expandMultiVecPseudo(
1872 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1873 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1874 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1875 return expandMultiVecPseudo(
1876 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1877 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1878 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1879 return expandMultiVecPseudo(
1880 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1881 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1882 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1883 return expandMultiVecPseudo(
1884 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1885 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1886 case AArch64::LD1B_2Z_PSEUDO:
1887 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1888 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1889 AArch64::LD1B_2Z_STRIDED);
1890 case AArch64::LD1H_2Z_PSEUDO:
1891 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1892 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1893 AArch64::LD1H_2Z_STRIDED);
1894 case AArch64::LD1W_2Z_PSEUDO:
1895 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1896 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1897 AArch64::LD1W_2Z_STRIDED);
1898 case AArch64::LD1D_2Z_PSEUDO:
1899 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1900 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1901 AArch64::LD1D_2Z_STRIDED);
1902 case AArch64::LDNT1B_2Z_PSEUDO:
1903 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1904 AArch64::ZPR2StridedRegClass,
1905 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1906 case AArch64::LDNT1H_2Z_PSEUDO:
1907 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1908 AArch64::ZPR2StridedRegClass,
1909 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1910 case AArch64::LDNT1W_2Z_PSEUDO:
1911 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1912 AArch64::ZPR2StridedRegClass,
1913 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1914 case AArch64::LDNT1D_2Z_PSEUDO:
1915 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1916 AArch64::ZPR2StridedRegClass,
1917 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1918 case AArch64::LD1B_4Z_IMM_PSEUDO:
1919 return expandMultiVecPseudo(
1920 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1921 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1922 case AArch64::LD1H_4Z_IMM_PSEUDO:
1923 return expandMultiVecPseudo(
1924 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1925 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1926 case AArch64::LD1W_4Z_IMM_PSEUDO:
1927 return expandMultiVecPseudo(
1928 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1929 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1930 case AArch64::LD1D_4Z_IMM_PSEUDO:
1931 return expandMultiVecPseudo(
1932 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1933 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1934 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1935 return expandMultiVecPseudo(
1936 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1937 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1938 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1939 return expandMultiVecPseudo(
1940 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1941 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1942 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1943 return expandMultiVecPseudo(
1944 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1945 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1946 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1947 return expandMultiVecPseudo(
1948 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1949 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1950 case AArch64::LD1B_4Z_PSEUDO:
1951 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1952 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1953 AArch64::LD1B_4Z_STRIDED);
1954 case AArch64::LD1H_4Z_PSEUDO:
1955 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1956 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1957 AArch64::LD1H_4Z_STRIDED);
1958 case AArch64::LD1W_4Z_PSEUDO:
1959 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1960 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1961 AArch64::LD1W_4Z_STRIDED);
1962 case AArch64::LD1D_4Z_PSEUDO:
1963 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1964 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1965 AArch64::LD1D_4Z_STRIDED);
1966 case AArch64::LDNT1B_4Z_PSEUDO:
1967 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1968 AArch64::ZPR4StridedRegClass,
1969 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1970 case AArch64::LDNT1H_4Z_PSEUDO:
1971 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1972 AArch64::ZPR4StridedRegClass,
1973 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1974 case AArch64::LDNT1W_4Z_PSEUDO:
1975 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1976 AArch64::ZPR4StridedRegClass,
1977 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1978 case AArch64::LDNT1D_4Z_PSEUDO:
1979 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1980 AArch64::ZPR4StridedRegClass,
1981 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1982 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
1983 return expandFormTuplePseudo(MBB, MBBI, NextMBBI, 2);
1984 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
1985 return expandFormTuplePseudo(MBB, MBBI, NextMBBI, 4);
1986 case AArch64::EON_ZZZ:
1987 case AArch64::NAND_ZZZ:
1988 case AArch64::NOR_ZZZ:
1989 return expandSVEBitwisePseudo(MI, MBB, MBBI);
1990 }
1991 return false;
1992}
1993
1994/// Iterate over the instructions in basic block MBB and expand any
1995/// pseudo instructions. Return true if anything was modified.
1996bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &MBB) {
1997 bool Modified = false;
1998
2000 while (MBBI != E) {
2001 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
2002 Modified |= expandMI(MBB, MBBI, NMBBI);
2003 MBBI = NMBBI;
2004 }
2005
2006 return Modified;
2007}
2008
2009bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
2010 TII = MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
2011
2012 bool Modified = false;
2013 for (auto &MBB : MF)
2014 Modified |= expandMBB(MBB);
2015 return Modified;
2016}
2017
2018bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
2019 return AArch64ExpandPseudoImpl().run(MF);
2020}
2021
2022/// Returns an instance of the pseudo instruction expansion pass.
2024 return new AArch64ExpandPseudoLegacy();
2025}
2026
2030 const bool Changed = AArch64ExpandPseudoImpl().run(MF);
2031 if (!Changed)
2032 return PreservedAnalyses::all();
2035 return PA;
2036}
#define AARCH64_EXPAND_PSEUDO_NAME
MachineInstrBuilder & UseMI
static MachineInstr * createCallWithOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, unsigned Opcode, ArrayRef< MachineOperand > ExplicitOps, unsigned RegMaskStartIdx)
static constexpr unsigned ZERO_ALL_ZA_MASK
static MachineInstr * createCall(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, MachineOperand &CallTarget, unsigned RegMaskStartIdx)
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
A debug info location.
Definition DebugLoc.h:123
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Describe properties that are true of each instruction in the target description file.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
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 MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
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.
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
void setDebugInstrNum(unsigned Num)
Set instruction number of this MachineInstr.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
LLVM_ABI bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
CodeModel::Model getCodeModel() const
Returns the code model.
ArrayRef< MCPhysReg > getRegisters() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
self_iterator getIterator()
Definition ilist_node.h:123
IteratorT end() const
IteratorT begin() const
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
int32_t getSVERevInstr(uint32_t Opcode)
int32_t getSVENonRevInstr(uint32_t Opcode)
int32_t getSVEPseudoMap(uint32_t Opcode)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:532
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...
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.
constexpr RegState getKillRegState(bool B)
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition APFloat.h:1630
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr RegState getDeadRegState(bool B)
Op::Description Desc
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64ExpandPseudoLegacyPass()
Returns an instance of the pseudo instruction expansion pass.
constexpr RegState getRenamableRegState(bool B)
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
constexpr RegState getUndefRegState(bool B)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
#define N