Skip to content

Commit 3f8380f

Browse files
authored
[AArch64] Factor out the emission of MOV and MOVZ/MOVK instructions (#110017)
Throughout the AArch64AsmPrinter implementation, there are a few common instructions emitted at many places: ORRXrs as an alias of "mov Xd, Xm" and movz/movk for materialization of constants. This commit introduces utility functions for emission of these three instructions.
1 parent 5e98136 commit 3f8380f

File tree

1 file changed

+70
-135
lines changed

1 file changed

+70
-135
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 70 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class AArch64AsmPrinter : public AsmPrinter {
164164
/// pseudo instructions.
165165
bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
166166

167+
void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
168+
167169
void emitInstruction(const MachineInstr *MI) override;
168170

169171
void emitFunctionHeaderComment() override;
@@ -229,6 +231,10 @@ class AArch64AsmPrinter : public AsmPrinter {
229231
/// Emit the LOHs contained in AArch64FI.
230232
void emitLOHs();
231233

234+
void emitMovXReg(Register Dest, Register Src);
235+
void emitMOVZ(Register Dest, uint64_t Imm, unsigned Shift);
236+
void emitMOVK(Register Dest, uint64_t Imm, unsigned Shift);
237+
232238
/// Emit instruction to set float register to zero.
233239
void emitFMov0(const MachineInstr &MI);
234240

@@ -409,16 +415,6 @@ void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI,
409415
auto &O = *OutStreamer;
410416
MCSymbol *CurSled = OutContext.createTempSymbol("xray_sled_", true);
411417
O.emitLabel(CurSled);
412-
MCInst MovX0Op0 = MCInstBuilder(AArch64::ORRXrs)
413-
.addReg(AArch64::X0)
414-
.addReg(AArch64::XZR)
415-
.addReg(MI.getOperand(0).getReg())
416-
.addImm(0);
417-
MCInst MovX1Op1 = MCInstBuilder(AArch64::ORRXrs)
418-
.addReg(AArch64::X1)
419-
.addReg(AArch64::XZR)
420-
.addReg(MI.getOperand(1).getReg())
421-
.addImm(0);
422418
bool MachO = TM.getTargetTriple().isOSBinFormatMachO();
423419
auto *Sym = MCSymbolRefExpr::create(
424420
OutContext.getOrCreateSymbol(
@@ -438,13 +434,9 @@ void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI,
438434
.addReg(AArch64::X2)
439435
.addReg(AArch64::SP)
440436
.addImm(2));
441-
EmitToStreamer(O, MovX0Op0);
442-
EmitToStreamer(O, MovX1Op1);
443-
EmitToStreamer(O, MCInstBuilder(AArch64::ORRXrs)
444-
.addReg(AArch64::X2)
445-
.addReg(AArch64::XZR)
446-
.addReg(MI.getOperand(2).getReg())
447-
.addImm(0));
437+
emitMovXReg(AArch64::X0, MI.getOperand(0).getReg());
438+
emitMovXReg(AArch64::X1, MI.getOperand(1).getReg());
439+
emitMovXReg(AArch64::X2, MI.getOperand(2).getReg());
448440
EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
449441
EmitToStreamer(O, MCInstBuilder(AArch64::LDRXui)
450442
.addReg(AArch64::X2)
@@ -468,8 +460,8 @@ void AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI,
468460
.addReg(AArch64::X1)
469461
.addReg(AArch64::SP)
470462
.addImm(-2));
471-
EmitToStreamer(O, MovX0Op0);
472-
EmitToStreamer(O, MovX1Op1);
463+
emitMovXReg(AArch64::X0, MI.getOperand(0).getReg());
464+
emitMovXReg(AArch64::X1, MI.getOperand(1).getReg());
473465
EmitToStreamer(O, MCInstBuilder(AArch64::BL).addExpr(Sym));
474466
O.AddComment("End XRay custom event");
475467
EmitToStreamer(O, MCInstBuilder(AArch64::LDPXpost)
@@ -497,11 +489,7 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
497489
// Checking XZR makes no sense. Instead of emitting a load, zero
498490
// ScratchRegs[0] and use it for the ESR AddrIndex below.
499491
AddrReg = getXRegFromWReg(ScratchRegs[0]);
500-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
501-
.addReg(AddrReg)
502-
.addReg(AArch64::XZR)
503-
.addReg(AArch64::XZR)
504-
.addImm(0));
492+
emitMovXReg(AddrReg, AArch64::XZR);
505493
} else {
506494
// If one of the scratch registers is used for the call target (e.g.
507495
// with AArch64::TCRETURNriBTI), we can clobber another caller-saved
@@ -534,16 +522,8 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
534522

535523
// Load the expected type hash.
536524
const int64_t Type = MI.getOperand(1).getImm();
537-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKWi)
538-
.addReg(ScratchRegs[1])
539-
.addReg(ScratchRegs[1])
540-
.addImm(Type & 0xFFFF)
541-
.addImm(0));
542-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKWi)
543-
.addReg(ScratchRegs[1])
544-
.addReg(ScratchRegs[1])
545-
.addImm((Type >> 16) & 0xFFFF)
546-
.addImm(16));
525+
emitMOVK(ScratchRegs[1], Type & 0xFFFF, 0);
526+
emitMOVK(ScratchRegs[1], (Type >> 16) & 0xFFFF, 16);
547527

548528
// Compare the hashes and trap if there's a mismatch.
549529
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSWrs)
@@ -627,6 +607,7 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
627607
std::unique_ptr<MCSubtargetInfo> STI(
628608
TM.getTarget().createMCSubtargetInfo(TT.str(), "", ""));
629609
assert(STI && "Unable to create subtarget info");
610+
this->STI = static_cast<const AArch64Subtarget *>(&*STI);
630611

631612
MCSymbol *HwasanTagMismatchV1Sym =
632613
OutContext.getOrCreateSymbol("__hwasan_tag_mismatch");
@@ -679,11 +660,7 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
679660
// Fortuitously, kShadowBaseAlignment == 32, so we use the 32-bit
680661
// left-shift option in the MOV instruction. Combined with the 16-bit
681662
// immediate, this is enough to represent any offset up to 2**48.
682-
OutStreamer->emitInstruction(MCInstBuilder(AArch64::MOVZXi)
683-
.addReg(AArch64::X17)
684-
.addImm(FixedShadowOffset >> 32)
685-
.addImm(32),
686-
*STI);
663+
emitMOVZ(AArch64::X17, FixedShadowOffset >> 32, 32);
687664
OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRBBroX)
688665
.addReg(AArch64::W16)
689666
.addReg(AArch64::X17)
@@ -823,18 +800,8 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
823800
*STI);
824801

825802
if (Reg != AArch64::X0)
826-
OutStreamer->emitInstruction(MCInstBuilder(AArch64::ORRXrs)
827-
.addReg(AArch64::X0)
828-
.addReg(AArch64::XZR)
829-
.addReg(Reg)
830-
.addImm(0),
831-
*STI);
832-
OutStreamer->emitInstruction(
833-
MCInstBuilder(AArch64::MOVZXi)
834-
.addReg(AArch64::X1)
835-
.addImm(AccessInfo & HWASanAccessInfo::RuntimeMask)
836-
.addImm(0),
837-
*STI);
803+
emitMovXReg(AArch64::X0, Reg);
804+
emitMOVZ(AArch64::X1, AccessInfo & HWASanAccessInfo::RuntimeMask, 0);
838805

839806
if (CompileKernel) {
840807
// The Linux kernel's dynamic loader doesn't support GOT relative
@@ -865,6 +832,7 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
865832
MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
866833
}
867834
}
835+
this->STI = nullptr;
868836
}
869837

870838
static void emitAuthenticatedPointer(MCStreamer &OutStreamer,
@@ -1438,24 +1406,16 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) {
14381406
.addImm(0));
14391407
++InstsEmitted;
14401408
} else {
1441-
EmitToStreamer(*OutStreamer,
1442-
MCInstBuilder(AArch64::MOVZXi)
1443-
.addReg(AArch64::X17)
1444-
.addImm(static_cast<uint16_t>(MaxTableEntry))
1445-
.addImm(0));
1409+
emitMOVZ(AArch64::X17, static_cast<uint16_t>(MaxTableEntry), 0);
14461410
++InstsEmitted;
14471411
// It's sad that we have to manually materialize instructions, but we can't
14481412
// trivially reuse the main pseudo expansion logic.
14491413
// A MOVK sequence is easy enough to generate and handles the general case.
14501414
for (int Offset = 16; Offset < 64; Offset += 16) {
14511415
if ((MaxTableEntry >> Offset) == 0)
14521416
break;
1453-
EmitToStreamer(*OutStreamer,
1454-
MCInstBuilder(AArch64::MOVKXi)
1455-
.addReg(AArch64::X17)
1456-
.addReg(AArch64::X17)
1457-
.addImm(static_cast<uint16_t>(MaxTableEntry >> Offset))
1458-
.addImm(Offset));
1417+
emitMOVK(AArch64::X17, static_cast<uint16_t>(MaxTableEntry >> Offset),
1418+
Offset);
14591419
++InstsEmitted;
14601420
}
14611421
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs)
@@ -1615,20 +1575,9 @@ void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
16151575
Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
16161576
EncodedBytes = 16;
16171577
// Materialize the jump address:
1618-
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
1619-
.addReg(ScratchReg)
1620-
.addImm((CallTarget >> 32) & 0xFFFF)
1621-
.addImm(32));
1622-
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
1623-
.addReg(ScratchReg)
1624-
.addReg(ScratchReg)
1625-
.addImm((CallTarget >> 16) & 0xFFFF)
1626-
.addImm(16));
1627-
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
1628-
.addReg(ScratchReg)
1629-
.addReg(ScratchReg)
1630-
.addImm(CallTarget & 0xFFFF)
1631-
.addImm(0));
1578+
emitMOVZ(ScratchReg, (CallTarget >> 32) & 0xFFFF, 32);
1579+
emitMOVK(ScratchReg, (CallTarget >> 16) & 0xFFFF, 16);
1580+
emitMOVK(ScratchReg, CallTarget & 0xFFFF, 0);
16321581
EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
16331582
}
16341583
// Emit padding.
@@ -1717,6 +1666,33 @@ void AArch64AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI) {
17171666
OutStreamer->emitInstruction(MI, getSubtargetInfo());
17181667
}
17191668

1669+
void AArch64AsmPrinter::emitMovXReg(Register Dest, Register Src) {
1670+
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1671+
.addReg(Dest)
1672+
.addReg(AArch64::XZR)
1673+
.addReg(Src)
1674+
.addImm(0));
1675+
}
1676+
1677+
void AArch64AsmPrinter::emitMOVZ(Register Dest, uint64_t Imm, unsigned Shift) {
1678+
bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1679+
EmitToStreamer(*OutStreamer,
1680+
MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi)
1681+
.addReg(Dest)
1682+
.addImm(Imm)
1683+
.addImm(Shift));
1684+
}
1685+
1686+
void AArch64AsmPrinter::emitMOVK(Register Dest, uint64_t Imm, unsigned Shift) {
1687+
bool Is64Bit = AArch64::GPR64RegClass.contains(Dest);
1688+
EmitToStreamer(*OutStreamer,
1689+
MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi)
1690+
.addReg(Dest)
1691+
.addReg(Dest)
1692+
.addImm(Imm)
1693+
.addImm(Shift));
1694+
}
1695+
17201696
void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) {
17211697
Register DestReg = MI.getOperand(0).getReg();
17221698
if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() &&
@@ -1774,26 +1750,15 @@ unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc,
17741750

17751751
// If there's only a constant discriminator, MOV it into x17.
17761752
if (AddrDisc == AArch64::XZR) {
1777-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi)
1778-
.addReg(AArch64::X17)
1779-
.addImm(Disc)
1780-
.addImm(/*shift=*/0));
1753+
emitMOVZ(AArch64::X17, Disc, 0);
17811754
++InstsEmitted;
17821755
return AArch64::X17;
17831756
}
17841757

17851758
// If there are both, emit a blend into x17.
1786-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1787-
.addReg(AArch64::X17)
1788-
.addReg(AArch64::XZR)
1789-
.addReg(AddrDisc)
1790-
.addImm(0));
1759+
emitMovXReg(AArch64::X17, AddrDisc);
17911760
++InstsEmitted;
1792-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi)
1793-
.addReg(AArch64::X17)
1794-
.addReg(AArch64::X17)
1795-
.addImm(Disc)
1796-
.addImm(/*shift=*/48));
1761+
emitMOVK(AArch64::X17, Disc, 48);
17971762
++InstsEmitted;
17981763
return AArch64::X17;
17991764
}
@@ -1914,11 +1879,7 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
19141879

19151880
// XPAC has tied src/dst: use x17 as a temporary copy.
19161881
// mov x17, x16
1917-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1918-
.addReg(AArch64::X17)
1919-
.addReg(AArch64::XZR)
1920-
.addReg(AArch64::X16)
1921-
.addImm(0));
1882+
emitMovXReg(AArch64::X17, AArch64::X16);
19221883
++InstsEmitted;
19231884

19241885
// xpaci x17
@@ -1955,11 +1916,7 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) {
19551916
// FIXME: can we simply return the AUT result, already in x16? without..
19561917
// ..traps this is usable as an oracle anyway, based on high bits
19571918
// mov x17, x16
1958-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
1959-
.addReg(AArch64::X16)
1960-
.addReg(AArch64::XZR)
1961-
.addReg(AArch64::X17)
1962-
.addImm(0));
1919+
emitMovXReg(AArch64::X16, AArch64::X17);
19631920
++InstsEmitted;
19641921

19651922
if (IsAUTPAC) {
@@ -2273,13 +2230,9 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
22732230
return true;
22742231
return false;
22752232
};
2276-
for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16) {
2277-
EmitAndIncrement(MCInstBuilder(AArch64::MOVKXi)
2278-
.addReg(AArch64::X17)
2279-
.addReg(AArch64::X17)
2280-
.addImm((UOffset >> BitPos) & 0xffff)
2281-
.addImm(/*shift=*/BitPos));
2282-
}
2233+
for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16)
2234+
emitMOVK(AArch64::X17, (UOffset >> BitPos) & 0xffff, BitPos);
2235+
22832236
EmitAndIncrement(MCInstBuilder(AArch64::ADDXrs)
22842237
.addReg(AArch64::X16)
22852238
.addReg(AArch64::X16)
@@ -2291,21 +2244,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
22912244
unsigned DiscReg = AddrDisc;
22922245
if (Disc != 0) {
22932246
if (AddrDisc != AArch64::XZR) {
2294-
EmitAndIncrement(MCInstBuilder(AArch64::ORRXrs)
2295-
.addReg(AArch64::X17)
2296-
.addReg(AArch64::XZR)
2297-
.addReg(AddrDisc)
2298-
.addImm(0));
2299-
EmitAndIncrement(MCInstBuilder(AArch64::MOVKXi)
2300-
.addReg(AArch64::X17)
2301-
.addReg(AArch64::X17)
2302-
.addImm(Disc)
2303-
.addImm(/*shift=*/48));
2247+
emitMovXReg(AArch64::X17, AddrDisc);
2248+
emitMOVK(AArch64::X17, Disc, 48);
23042249
} else {
2305-
EmitAndIncrement(MCInstBuilder(AArch64::MOVZXi)
2306-
.addReg(AArch64::X17)
2307-
.addImm(Disc)
2308-
.addImm(/*shift=*/0));
2250+
emitMOVZ(AArch64::X17, Disc, 0);
23092251
}
23102252
DiscReg = AArch64::X17;
23112253
}
@@ -2337,6 +2279,10 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
23372279
// instructions) auto-generated.
23382280
#include "AArch64GenMCPseudoLowering.inc"
23392281

2282+
void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
2283+
S.emitInstruction(Inst, *STI);
2284+
}
2285+
23402286
void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
23412287
AArch64_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits());
23422288

@@ -2511,21 +2457,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
25112457
if (Disc) {
25122458
if (AddrDisc != AArch64::NoRegister) {
25132459
if (ScratchReg != AddrDisc)
2514-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs)
2515-
.addReg(ScratchReg)
2516-
.addReg(AArch64::XZR)
2517-
.addReg(AddrDisc)
2518-
.addImm(0));
2519-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi)
2520-
.addReg(ScratchReg)
2521-
.addReg(ScratchReg)
2522-
.addImm(Disc)
2523-
.addImm(/*shift=*/48));
2460+
emitMovXReg(ScratchReg, AddrDisc);
2461+
emitMOVK(ScratchReg, Disc, 48);
25242462
} else {
2525-
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi)
2526-
.addReg(ScratchReg)
2527-
.addImm(Disc)
2528-
.addImm(/*shift=*/0));
2463+
emitMOVZ(ScratchReg, Disc, 0);
25292464
}
25302465
DiscReg = ScratchReg;
25312466
}

0 commit comments

Comments
 (0)