1 //===- AArch64ExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
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
7 //===----------------------------------------------------------------------===//
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
14 //===----------------------------------------------------------------------===//
16 #include "AArch64ExpandImm.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64MachineFunctionInfo.h"
19 #include "AArch64Subtarget.h"
20 #include "MCTargetDesc/AArch64AddressingModes.h"
21 #include "Utils/AArch64BaseInfo.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/Triple.h"
24 #include "llvm/CodeGen/LivePhysRegs.h"
25 #include "llvm/CodeGen/MachineBasicBlock.h"
26 #include "llvm/CodeGen/MachineFunction.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineInstrBuilder.h"
30 #include "llvm/CodeGen/MachineOperand.h"
31 #include "llvm/CodeGen/TargetSubtargetInfo.h"
32 #include "llvm/IR/DebugLoc.h"
33 #include "llvm/MC/MCInstrDesc.h"
34 #include "llvm/Pass.h"
35 #include "llvm/Support/CodeGen.h"
36 #include "llvm/Support/MathExtras.h"
37 #include "llvm/Target/TargetMachine.h"
46 #define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
50 class AArch64ExpandPseudo
: public MachineFunctionPass
{
52 const AArch64InstrInfo
*TII
;
56 AArch64ExpandPseudo() : MachineFunctionPass(ID
) {
57 initializeAArch64ExpandPseudoPass(*PassRegistry::getPassRegistry());
60 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
62 StringRef
getPassName() const override
{ return AARCH64_EXPAND_PSEUDO_NAME
; }
65 bool expandMBB(MachineBasicBlock
&MBB
);
66 bool expandMI(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
67 MachineBasicBlock::iterator
&NextMBBI
);
68 bool expandMOVImm(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
71 bool expandCMP_SWAP(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
72 unsigned LdarOp
, unsigned StlrOp
, unsigned CmpOp
,
73 unsigned ExtendImm
, unsigned ZeroReg
,
74 MachineBasicBlock::iterator
&NextMBBI
);
75 bool expandCMP_SWAP_128(MachineBasicBlock
&MBB
,
76 MachineBasicBlock::iterator MBBI
,
77 MachineBasicBlock::iterator
&NextMBBI
);
78 bool expandSetTagLoop(MachineBasicBlock
&MBB
,
79 MachineBasicBlock::iterator MBBI
,
80 MachineBasicBlock::iterator
&NextMBBI
);
83 } // end anonymous namespace
85 char AArch64ExpandPseudo::ID
= 0;
87 INITIALIZE_PASS(AArch64ExpandPseudo
, "aarch64-expand-pseudo",
88 AARCH64_EXPAND_PSEUDO_NAME
, false, false)
90 /// Transfer implicit operands on the pseudo instruction to the
91 /// instructions created from the expansion.
92 static void transferImpOps(MachineInstr
&OldMI
, MachineInstrBuilder
&UseMI
,
93 MachineInstrBuilder
&DefMI
) {
94 const MCInstrDesc
&Desc
= OldMI
.getDesc();
95 for (unsigned i
= Desc
.getNumOperands(), e
= OldMI
.getNumOperands(); i
!= e
;
97 const MachineOperand
&MO
= OldMI
.getOperand(i
);
98 assert(MO
.isReg() && MO
.getReg());
106 /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
107 /// real move-immediate instructions to synthesize the immediate.
108 bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock
&MBB
,
109 MachineBasicBlock::iterator MBBI
,
111 MachineInstr
&MI
= *MBBI
;
112 Register DstReg
= MI
.getOperand(0).getReg();
113 uint64_t Imm
= MI
.getOperand(1).getImm();
115 if (DstReg
== AArch64::XZR
|| DstReg
== AArch64::WZR
) {
116 // Useless def, and we don't want to risk creating an invalid ORR (which
117 // would really write to sp).
118 MI
.eraseFromParent();
122 SmallVector
<AArch64_IMM::ImmInsnModel
, 4> Insn
;
123 AArch64_IMM::expandMOVImm(Imm
, BitSize
, Insn
);
124 assert(Insn
.size() != 0);
126 SmallVector
<MachineInstrBuilder
, 4> MIBS
;
127 for (auto I
= Insn
.begin(), E
= Insn
.end(); I
!= E
; ++I
) {
128 bool LastItem
= std::next(I
) == E
;
131 default: llvm_unreachable("unhandled!"); break;
133 case AArch64::ORRWri
:
134 case AArch64::ORRXri
:
135 MIBS
.push_back(BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(I
->Opcode
))
136 .add(MI
.getOperand(0))
137 .addReg(BitSize
== 32 ? AArch64::WZR
: AArch64::XZR
)
140 case AArch64::MOVNWi
:
141 case AArch64::MOVNXi
:
142 case AArch64::MOVZWi
:
143 case AArch64::MOVZXi
: {
144 bool DstIsDead
= MI
.getOperand(0).isDead();
145 MIBS
.push_back(BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(I
->Opcode
))
146 .addReg(DstReg
, RegState::Define
|
147 getDeadRegState(DstIsDead
&& LastItem
))
151 case AArch64::MOVKWi
:
152 case AArch64::MOVKXi
: {
153 Register DstReg
= MI
.getOperand(0).getReg();
154 bool DstIsDead
= MI
.getOperand(0).isDead();
155 MIBS
.push_back(BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(I
->Opcode
))
158 getDeadRegState(DstIsDead
&& LastItem
))
165 transferImpOps(MI
, MIBS
.front(), MIBS
.back());
166 MI
.eraseFromParent();
170 bool AArch64ExpandPseudo::expandCMP_SWAP(
171 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
, unsigned LdarOp
,
172 unsigned StlrOp
, unsigned CmpOp
, unsigned ExtendImm
, unsigned ZeroReg
,
173 MachineBasicBlock::iterator
&NextMBBI
) {
174 MachineInstr
&MI
= *MBBI
;
175 DebugLoc DL
= MI
.getDebugLoc();
176 const MachineOperand
&Dest
= MI
.getOperand(0);
177 Register StatusReg
= MI
.getOperand(1).getReg();
178 bool StatusDead
= MI
.getOperand(1).isDead();
179 // Duplicating undef operands into 2 instructions does not guarantee the same
180 // value on both; However undef should be replaced by xzr anyway.
181 assert(!MI
.getOperand(2).isUndef() && "cannot handle undef");
182 Register AddrReg
= MI
.getOperand(2).getReg();
183 Register DesiredReg
= MI
.getOperand(3).getReg();
184 Register NewReg
= MI
.getOperand(4).getReg();
186 MachineFunction
*MF
= MBB
.getParent();
187 auto LoadCmpBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
188 auto StoreBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
189 auto DoneBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
191 MF
->insert(++MBB
.getIterator(), LoadCmpBB
);
192 MF
->insert(++LoadCmpBB
->getIterator(), StoreBB
);
193 MF
->insert(++StoreBB
->getIterator(), DoneBB
);
197 // ldaxr xDest, [xAddr]
198 // cmp xDest, xDesired
201 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::MOVZWi
), StatusReg
)
202 .addImm(0).addImm(0);
203 BuildMI(LoadCmpBB
, DL
, TII
->get(LdarOp
), Dest
.getReg())
205 BuildMI(LoadCmpBB
, DL
, TII
->get(CmpOp
), ZeroReg
)
206 .addReg(Dest
.getReg(), getKillRegState(Dest
.isDead()))
209 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::Bcc
))
210 .addImm(AArch64CC::NE
)
212 .addReg(AArch64::NZCV
, RegState::Implicit
| RegState::Kill
);
213 LoadCmpBB
->addSuccessor(DoneBB
);
214 LoadCmpBB
->addSuccessor(StoreBB
);
217 // stlxr wStatus, xNew, [xAddr]
218 // cbnz wStatus, .Lloadcmp
219 BuildMI(StoreBB
, DL
, TII
->get(StlrOp
), StatusReg
)
222 BuildMI(StoreBB
, DL
, TII
->get(AArch64::CBNZW
))
223 .addReg(StatusReg
, getKillRegState(StatusDead
))
225 StoreBB
->addSuccessor(LoadCmpBB
);
226 StoreBB
->addSuccessor(DoneBB
);
228 DoneBB
->splice(DoneBB
->end(), &MBB
, MI
, MBB
.end());
229 DoneBB
->transferSuccessors(&MBB
);
231 MBB
.addSuccessor(LoadCmpBB
);
233 NextMBBI
= MBB
.end();
234 MI
.eraseFromParent();
236 // Recompute livein lists.
237 LivePhysRegs LiveRegs
;
238 computeAndAddLiveIns(LiveRegs
, *DoneBB
);
239 computeAndAddLiveIns(LiveRegs
, *StoreBB
);
240 computeAndAddLiveIns(LiveRegs
, *LoadCmpBB
);
241 // Do an extra pass around the loop to get loop carried registers right.
242 StoreBB
->clearLiveIns();
243 computeAndAddLiveIns(LiveRegs
, *StoreBB
);
244 LoadCmpBB
->clearLiveIns();
245 computeAndAddLiveIns(LiveRegs
, *LoadCmpBB
);
250 bool AArch64ExpandPseudo::expandCMP_SWAP_128(
251 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
252 MachineBasicBlock::iterator
&NextMBBI
) {
253 MachineInstr
&MI
= *MBBI
;
254 DebugLoc DL
= MI
.getDebugLoc();
255 MachineOperand
&DestLo
= MI
.getOperand(0);
256 MachineOperand
&DestHi
= MI
.getOperand(1);
257 Register StatusReg
= MI
.getOperand(2).getReg();
258 bool StatusDead
= MI
.getOperand(2).isDead();
259 // Duplicating undef operands into 2 instructions does not guarantee the same
260 // value on both; However undef should be replaced by xzr anyway.
261 assert(!MI
.getOperand(3).isUndef() && "cannot handle undef");
262 Register AddrReg
= MI
.getOperand(3).getReg();
263 Register DesiredLoReg
= MI
.getOperand(4).getReg();
264 Register DesiredHiReg
= MI
.getOperand(5).getReg();
265 Register NewLoReg
= MI
.getOperand(6).getReg();
266 Register NewHiReg
= MI
.getOperand(7).getReg();
268 MachineFunction
*MF
= MBB
.getParent();
269 auto LoadCmpBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
270 auto StoreBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
271 auto DoneBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
273 MF
->insert(++MBB
.getIterator(), LoadCmpBB
);
274 MF
->insert(++LoadCmpBB
->getIterator(), StoreBB
);
275 MF
->insert(++StoreBB
->getIterator(), DoneBB
);
278 // ldaxp xDestLo, xDestHi, [xAddr]
279 // cmp xDestLo, xDesiredLo
280 // sbcs xDestHi, xDesiredHi
282 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::LDAXPX
))
283 .addReg(DestLo
.getReg(), RegState::Define
)
284 .addReg(DestHi
.getReg(), RegState::Define
)
286 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::SUBSXrs
), AArch64::XZR
)
287 .addReg(DestLo
.getReg(), getKillRegState(DestLo
.isDead()))
288 .addReg(DesiredLoReg
)
290 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::CSINCWr
), StatusReg
)
291 .addUse(AArch64::WZR
)
292 .addUse(AArch64::WZR
)
293 .addImm(AArch64CC::EQ
);
294 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::SUBSXrs
), AArch64::XZR
)
295 .addReg(DestHi
.getReg(), getKillRegState(DestHi
.isDead()))
296 .addReg(DesiredHiReg
)
298 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::CSINCWr
), StatusReg
)
299 .addUse(StatusReg
, RegState::Kill
)
300 .addUse(StatusReg
, RegState::Kill
)
301 .addImm(AArch64CC::EQ
);
302 BuildMI(LoadCmpBB
, DL
, TII
->get(AArch64::CBNZW
))
303 .addUse(StatusReg
, getKillRegState(StatusDead
))
305 LoadCmpBB
->addSuccessor(DoneBB
);
306 LoadCmpBB
->addSuccessor(StoreBB
);
309 // stlxp wStatus, xNewLo, xNewHi, [xAddr]
310 // cbnz wStatus, .Lloadcmp
311 BuildMI(StoreBB
, DL
, TII
->get(AArch64::STLXPX
), StatusReg
)
315 BuildMI(StoreBB
, DL
, TII
->get(AArch64::CBNZW
))
316 .addReg(StatusReg
, getKillRegState(StatusDead
))
318 StoreBB
->addSuccessor(LoadCmpBB
);
319 StoreBB
->addSuccessor(DoneBB
);
321 DoneBB
->splice(DoneBB
->end(), &MBB
, MI
, MBB
.end());
322 DoneBB
->transferSuccessors(&MBB
);
324 MBB
.addSuccessor(LoadCmpBB
);
326 NextMBBI
= MBB
.end();
327 MI
.eraseFromParent();
329 // Recompute liveness bottom up.
330 LivePhysRegs LiveRegs
;
331 computeAndAddLiveIns(LiveRegs
, *DoneBB
);
332 computeAndAddLiveIns(LiveRegs
, *StoreBB
);
333 computeAndAddLiveIns(LiveRegs
, *LoadCmpBB
);
334 // Do an extra pass in the loop to get the loop carried dependencies right.
335 StoreBB
->clearLiveIns();
336 computeAndAddLiveIns(LiveRegs
, *StoreBB
);
337 LoadCmpBB
->clearLiveIns();
338 computeAndAddLiveIns(LiveRegs
, *LoadCmpBB
);
343 bool AArch64ExpandPseudo::expandSetTagLoop(
344 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
345 MachineBasicBlock::iterator
&NextMBBI
) {
346 MachineInstr
&MI
= *MBBI
;
347 DebugLoc DL
= MI
.getDebugLoc();
348 Register SizeReg
= MI
.getOperand(2).getReg();
349 Register AddressReg
= MI
.getOperand(3).getReg();
351 MachineFunction
*MF
= MBB
.getParent();
353 bool ZeroData
= MI
.getOpcode() == AArch64::STZGloop
;
354 const unsigned OpCode
=
355 ZeroData
? AArch64::STZ2GPostIndex
: AArch64::ST2GPostIndex
;
357 auto LoopBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
358 auto DoneBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
360 MF
->insert(++MBB
.getIterator(), LoopBB
);
361 MF
->insert(++LoopBB
->getIterator(), DoneBB
);
363 BuildMI(LoopBB
, DL
, TII
->get(OpCode
))
369 .setMIFlags(MI
.getFlags());
370 BuildMI(LoopBB
, DL
, TII
->get(AArch64::SUBXri
))
375 BuildMI(LoopBB
, DL
, TII
->get(AArch64::CBNZX
)).addUse(SizeReg
).addMBB(LoopBB
);
377 LoopBB
->addSuccessor(LoopBB
);
378 LoopBB
->addSuccessor(DoneBB
);
380 DoneBB
->splice(DoneBB
->end(), &MBB
, MI
, MBB
.end());
381 DoneBB
->transferSuccessors(&MBB
);
383 MBB
.addSuccessor(LoopBB
);
385 NextMBBI
= MBB
.end();
386 MI
.eraseFromParent();
387 // Recompute liveness bottom up.
388 LivePhysRegs LiveRegs
;
389 computeAndAddLiveIns(LiveRegs
, *DoneBB
);
390 computeAndAddLiveIns(LiveRegs
, *LoopBB
);
391 // Do an extra pass in the loop to get the loop carried dependencies right.
392 // FIXME: is this necessary?
393 LoopBB
->clearLiveIns();
394 computeAndAddLiveIns(LiveRegs
, *LoopBB
);
395 DoneBB
->clearLiveIns();
396 computeAndAddLiveIns(LiveRegs
, *DoneBB
);
401 /// If MBBI references a pseudo instruction that should be expanded here,
402 /// do the expansion and return true. Otherwise return false.
403 bool AArch64ExpandPseudo::expandMI(MachineBasicBlock
&MBB
,
404 MachineBasicBlock::iterator MBBI
,
405 MachineBasicBlock::iterator
&NextMBBI
) {
406 MachineInstr
&MI
= *MBBI
;
407 unsigned Opcode
= MI
.getOpcode();
412 case AArch64::ADDWrr
:
413 case AArch64::SUBWrr
:
414 case AArch64::ADDXrr
:
415 case AArch64::SUBXrr
:
416 case AArch64::ADDSWrr
:
417 case AArch64::SUBSWrr
:
418 case AArch64::ADDSXrr
:
419 case AArch64::SUBSXrr
:
420 case AArch64::ANDWrr
:
421 case AArch64::ANDXrr
:
422 case AArch64::BICWrr
:
423 case AArch64::BICXrr
:
424 case AArch64::ANDSWrr
:
425 case AArch64::ANDSXrr
:
426 case AArch64::BICSWrr
:
427 case AArch64::BICSXrr
:
428 case AArch64::EONWrr
:
429 case AArch64::EONXrr
:
430 case AArch64::EORWrr
:
431 case AArch64::EORXrr
:
432 case AArch64::ORNWrr
:
433 case AArch64::ORNXrr
:
434 case AArch64::ORRWrr
:
435 case AArch64::ORRXrr
: {
437 switch (MI
.getOpcode()) {
440 case AArch64::ADDWrr
: Opcode
= AArch64::ADDWrs
; break;
441 case AArch64::SUBWrr
: Opcode
= AArch64::SUBWrs
; break;
442 case AArch64::ADDXrr
: Opcode
= AArch64::ADDXrs
; break;
443 case AArch64::SUBXrr
: Opcode
= AArch64::SUBXrs
; break;
444 case AArch64::ADDSWrr
: Opcode
= AArch64::ADDSWrs
; break;
445 case AArch64::SUBSWrr
: Opcode
= AArch64::SUBSWrs
; break;
446 case AArch64::ADDSXrr
: Opcode
= AArch64::ADDSXrs
; break;
447 case AArch64::SUBSXrr
: Opcode
= AArch64::SUBSXrs
; break;
448 case AArch64::ANDWrr
: Opcode
= AArch64::ANDWrs
; break;
449 case AArch64::ANDXrr
: Opcode
= AArch64::ANDXrs
; break;
450 case AArch64::BICWrr
: Opcode
= AArch64::BICWrs
; break;
451 case AArch64::BICXrr
: Opcode
= AArch64::BICXrs
; break;
452 case AArch64::ANDSWrr
: Opcode
= AArch64::ANDSWrs
; break;
453 case AArch64::ANDSXrr
: Opcode
= AArch64::ANDSXrs
; break;
454 case AArch64::BICSWrr
: Opcode
= AArch64::BICSWrs
; break;
455 case AArch64::BICSXrr
: Opcode
= AArch64::BICSXrs
; break;
456 case AArch64::EONWrr
: Opcode
= AArch64::EONWrs
; break;
457 case AArch64::EONXrr
: Opcode
= AArch64::EONXrs
; break;
458 case AArch64::EORWrr
: Opcode
= AArch64::EORWrs
; break;
459 case AArch64::EORXrr
: Opcode
= AArch64::EORXrs
; break;
460 case AArch64::ORNWrr
: Opcode
= AArch64::ORNWrs
; break;
461 case AArch64::ORNXrr
: Opcode
= AArch64::ORNXrs
; break;
462 case AArch64::ORRWrr
: Opcode
= AArch64::ORRWrs
; break;
463 case AArch64::ORRXrr
: Opcode
= AArch64::ORRXrs
; break;
465 MachineInstrBuilder MIB1
=
466 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(Opcode
),
467 MI
.getOperand(0).getReg())
468 .add(MI
.getOperand(1))
469 .add(MI
.getOperand(2))
470 .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL
, 0));
471 transferImpOps(MI
, MIB1
, MIB1
);
472 MI
.eraseFromParent();
476 case AArch64::LOADgot
: {
477 MachineFunction
*MF
= MBB
.getParent();
478 Register DstReg
= MI
.getOperand(0).getReg();
479 const MachineOperand
&MO1
= MI
.getOperand(1);
480 unsigned Flags
= MO1
.getTargetFlags();
482 if (MF
->getTarget().getCodeModel() == CodeModel::Tiny
) {
483 // Tiny codemodel expand to LDR
484 MachineInstrBuilder MIB
= BuildMI(MBB
, MBBI
, MI
.getDebugLoc(),
485 TII
->get(AArch64::LDRXl
), DstReg
);
487 if (MO1
.isGlobal()) {
488 MIB
.addGlobalAddress(MO1
.getGlobal(), 0, Flags
);
489 } else if (MO1
.isSymbol()) {
490 MIB
.addExternalSymbol(MO1
.getSymbolName(), Flags
);
492 assert(MO1
.isCPI() &&
493 "Only expect globals, externalsymbols, or constant pools");
494 MIB
.addConstantPoolIndex(MO1
.getIndex(), MO1
.getOffset(), Flags
);
497 // Small codemodel expand into ADRP + LDR.
498 MachineFunction
&MF
= *MI
.getParent()->getParent();
499 DebugLoc DL
= MI
.getDebugLoc();
500 MachineInstrBuilder MIB1
=
501 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::ADRP
), DstReg
);
503 MachineInstrBuilder MIB2
;
504 if (MF
.getSubtarget
<AArch64Subtarget
>().isTargetILP32()) {
505 auto TRI
= MBB
.getParent()->getSubtarget().getRegisterInfo();
506 unsigned Reg32
= TRI
->getSubReg(DstReg
, AArch64::sub_32
);
507 unsigned DstFlags
= MI
.getOperand(0).getTargetFlags();
508 MIB2
= BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::LDRWui
))
510 .addReg(DstReg
, RegState::Kill
)
511 .addReg(DstReg
, DstFlags
| RegState::Implicit
);
513 unsigned DstReg
= MI
.getOperand(0).getReg();
514 MIB2
= BuildMI(MBB
, MBBI
, DL
, TII
->get(AArch64::LDRXui
))
515 .add(MI
.getOperand(0))
516 .addUse(DstReg
, RegState::Kill
);
519 if (MO1
.isGlobal()) {
520 MIB1
.addGlobalAddress(MO1
.getGlobal(), 0, Flags
| AArch64II::MO_PAGE
);
521 MIB2
.addGlobalAddress(MO1
.getGlobal(), 0,
522 Flags
| AArch64II::MO_PAGEOFF
| AArch64II::MO_NC
);
523 } else if (MO1
.isSymbol()) {
524 MIB1
.addExternalSymbol(MO1
.getSymbolName(), Flags
| AArch64II::MO_PAGE
);
525 MIB2
.addExternalSymbol(MO1
.getSymbolName(), Flags
|
526 AArch64II::MO_PAGEOFF
|
529 assert(MO1
.isCPI() &&
530 "Only expect globals, externalsymbols, or constant pools");
531 MIB1
.addConstantPoolIndex(MO1
.getIndex(), MO1
.getOffset(),
532 Flags
| AArch64II::MO_PAGE
);
533 MIB2
.addConstantPoolIndex(MO1
.getIndex(), MO1
.getOffset(),
534 Flags
| AArch64II::MO_PAGEOFF
|
538 transferImpOps(MI
, MIB1
, MIB2
);
540 MI
.eraseFromParent();
544 case AArch64::MOVaddr
:
545 case AArch64::MOVaddrJT
:
546 case AArch64::MOVaddrCP
:
547 case AArch64::MOVaddrBA
:
548 case AArch64::MOVaddrTLS
:
549 case AArch64::MOVaddrEXT
: {
550 // Expand into ADRP + ADD.
551 Register DstReg
= MI
.getOperand(0).getReg();
552 MachineInstrBuilder MIB1
=
553 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::ADRP
), DstReg
)
554 .add(MI
.getOperand(1));
556 if (MI
.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED
) {
557 // MO_TAGGED on the page indicates a tagged address. Set the tag now.
558 // We do so by creating a MOVK that sets bits 48-63 of the register to
559 // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
560 // the small code model so we can assume a binary size of <= 4GB, which
561 // makes the untagged PC relative offset positive. The binary must also be
562 // loaded into address range [0, 2^48). Both of these properties need to
563 // be ensured at runtime when using tagged addresses.
564 auto Tag
= MI
.getOperand(1);
565 Tag
.setTargetFlags(AArch64II::MO_PREL
| AArch64II::MO_G3
);
566 Tag
.setOffset(0x100000000);
567 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::MOVKXi
), DstReg
)
573 MachineInstrBuilder MIB2
=
574 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::ADDXri
))
575 .add(MI
.getOperand(0))
577 .add(MI
.getOperand(2))
580 transferImpOps(MI
, MIB1
, MIB2
);
581 MI
.eraseFromParent();
584 case AArch64::ADDlowTLS
:
585 // Produce a plain ADD
586 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::ADDXri
))
587 .add(MI
.getOperand(0))
588 .add(MI
.getOperand(1))
589 .add(MI
.getOperand(2))
591 MI
.eraseFromParent();
594 case AArch64::MOVbaseTLS
: {
595 Register DstReg
= MI
.getOperand(0).getReg();
596 auto SysReg
= AArch64SysReg::TPIDR_EL0
;
597 MachineFunction
*MF
= MBB
.getParent();
598 if (MF
->getTarget().getTargetTriple().isOSFuchsia() &&
599 MF
->getTarget().getCodeModel() == CodeModel::Kernel
)
600 SysReg
= AArch64SysReg::TPIDR_EL1
;
601 else if (MF
->getSubtarget
<AArch64Subtarget
>().useEL3ForTP())
602 SysReg
= AArch64SysReg::TPIDR_EL3
;
603 else if (MF
->getSubtarget
<AArch64Subtarget
>().useEL2ForTP())
604 SysReg
= AArch64SysReg::TPIDR_EL2
;
605 else if (MF
->getSubtarget
<AArch64Subtarget
>().useEL1ForTP())
606 SysReg
= AArch64SysReg::TPIDR_EL1
;
607 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::MRS
), DstReg
)
609 MI
.eraseFromParent();
613 case AArch64::MOVi32imm
:
614 return expandMOVImm(MBB
, MBBI
, 32);
615 case AArch64::MOVi64imm
:
616 return expandMOVImm(MBB
, MBBI
, 64);
617 case AArch64::RET_ReallyLR
: {
618 // Hiding the LR use with RET_ReallyLR may lead to extra kills in the
619 // function and missing live-ins. We are fine in practice because callee
620 // saved register handling ensures the register value is restored before
621 // RET, but we need the undef flag here to appease the MachineVerifier
623 MachineInstrBuilder MIB
=
624 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::RET
))
625 .addReg(AArch64::LR
, RegState::Undef
);
626 transferImpOps(MI
, MIB
, MIB
);
627 MI
.eraseFromParent();
630 case AArch64::CMP_SWAP_8
:
631 return expandCMP_SWAP(MBB
, MBBI
, AArch64::LDAXRB
, AArch64::STLXRB
,
633 AArch64_AM::getArithExtendImm(AArch64_AM::UXTB
, 0),
634 AArch64::WZR
, NextMBBI
);
635 case AArch64::CMP_SWAP_16
:
636 return expandCMP_SWAP(MBB
, MBBI
, AArch64::LDAXRH
, AArch64::STLXRH
,
638 AArch64_AM::getArithExtendImm(AArch64_AM::UXTH
, 0),
639 AArch64::WZR
, NextMBBI
);
640 case AArch64::CMP_SWAP_32
:
641 return expandCMP_SWAP(MBB
, MBBI
, AArch64::LDAXRW
, AArch64::STLXRW
,
643 AArch64_AM::getShifterImm(AArch64_AM::LSL
, 0),
644 AArch64::WZR
, NextMBBI
);
645 case AArch64::CMP_SWAP_64
:
646 return expandCMP_SWAP(MBB
, MBBI
,
647 AArch64::LDAXRX
, AArch64::STLXRX
, AArch64::SUBSXrs
,
648 AArch64_AM::getShifterImm(AArch64_AM::LSL
, 0),
649 AArch64::XZR
, NextMBBI
);
650 case AArch64::CMP_SWAP_128
:
651 return expandCMP_SWAP_128(MBB
, MBBI
, NextMBBI
);
653 case AArch64::AESMCrrTied
:
654 case AArch64::AESIMCrrTied
: {
655 MachineInstrBuilder MIB
=
656 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(),
657 TII
->get(Opcode
== AArch64::AESMCrrTied
? AArch64::AESMCrr
:
659 .add(MI
.getOperand(0))
660 .add(MI
.getOperand(1));
661 transferImpOps(MI
, MIB
, MIB
);
662 MI
.eraseFromParent();
665 case AArch64::IRGstack
: {
666 MachineFunction
&MF
= *MBB
.getParent();
667 const AArch64FunctionInfo
*AFI
= MF
.getInfo
<AArch64FunctionInfo
>();
668 const AArch64FrameLowering
*TFI
=
669 MF
.getSubtarget
<AArch64Subtarget
>().getFrameLowering();
671 // IRG does not allow immediate offset. getTaggedBasePointerOffset should
672 // almost always point to SP-after-prologue; if not, emit a longer
673 // instruction sequence.
674 int BaseOffset
= -AFI
->getTaggedBasePointerOffset();
676 StackOffset FrameRegOffset
= TFI
->resolveFrameOffsetReference(
677 MF
, BaseOffset
, false /*isFixed*/, false /*isSVE*/, FrameReg
,
680 Register SrcReg
= FrameReg
;
681 if (FrameRegOffset
) {
682 // Use output register as temporary.
683 SrcReg
= MI
.getOperand(0).getReg();
684 emitFrameOffset(MBB
, &MI
, MI
.getDebugLoc(), SrcReg
, FrameReg
,
685 FrameRegOffset
, TII
);
687 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::IRG
))
688 .add(MI
.getOperand(0))
690 .add(MI
.getOperand(2));
691 MI
.eraseFromParent();
694 case AArch64::TAGPstack
: {
695 BuildMI(MBB
, MBBI
, MI
.getDebugLoc(), TII
->get(AArch64::ADDG
))
696 .add(MI
.getOperand(0))
697 .add(MI
.getOperand(1))
698 .add(MI
.getOperand(2))
699 .add(MI
.getOperand(4));
700 MI
.eraseFromParent();
703 case AArch64::STGloop
:
704 case AArch64::STZGloop
:
705 return expandSetTagLoop(MBB
, MBBI
, NextMBBI
);
710 /// Iterate over the instructions in basic block MBB and expand any
711 /// pseudo instructions. Return true if anything was modified.
712 bool AArch64ExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
713 bool Modified
= false;
715 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
717 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
718 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
725 bool AArch64ExpandPseudo::runOnMachineFunction(MachineFunction
&MF
) {
726 TII
= static_cast<const AArch64InstrInfo
*>(MF
.getSubtarget().getInstrInfo());
728 bool Modified
= false;
730 Modified
|= expandMBB(MBB
);
734 /// Returns an instance of the pseudo instruction expansion pass.
735 FunctionPass
*llvm::createAArch64ExpandPseudoPass() {
736 return new AArch64ExpandPseudo();