45#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
71 unsigned ContiguousOpc,
unsigned StridedOpc);
78 unsigned LdarOp,
unsigned StlrOp,
unsigned CmpOp,
79 unsigned ExtendImm,
unsigned ZeroReg,
103char AArch64ExpandPseudo::ID = 0;
115 assert(MO.isReg() && MO.getReg());
134 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
137 MI.eraseFromParent();
146 for (
auto I =
Insn.begin(), E =
Insn.end();
I != E; ++
I) {
147 bool LastItem = std::next(
I) == E;
152 case AArch64::ORRWri:
153 case AArch64::ORRXri:
156 .
add(
MI.getOperand(0))
157 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
161 bool DstIsDead =
MI.getOperand(0).isDead();
171 case AArch64::ANDXri:
172 case AArch64::EORXri:
175 .
add(
MI.getOperand(0))
176 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
180 bool DstIsDead =
MI.getOperand(0).isDead();
190 case AArch64::MOVNWi:
191 case AArch64::MOVNXi:
192 case AArch64::MOVZWi:
193 case AArch64::MOVZXi: {
194 bool DstIsDead =
MI.getOperand(0).isDead();
202 case AArch64::MOVKWi:
203 case AArch64::MOVKXi: {
205 bool DstIsDead =
MI.getOperand(0).isDead();
218 MI.eraseFromParent();
222bool AArch64ExpandPseudo::expandCMP_SWAP(
224 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
229 Register StatusReg =
MI.getOperand(1).getReg();
230 bool StatusDead =
MI.getOperand(1).isDead();
233 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
235 Register DesiredReg =
MI.getOperand(3).getReg();
244 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
245 MF->
insert(++StoreBB->getIterator(), DoneBB);
253 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
257 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
261 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
265 LoadCmpBB->addSuccessor(DoneBB);
266 LoadCmpBB->addSuccessor(StoreBB);
271 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
274 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
277 StoreBB->addSuccessor(LoadCmpBB);
278 StoreBB->addSuccessor(DoneBB);
280 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
281 DoneBB->transferSuccessors(&
MBB);
286 MI.eraseFromParent();
294 StoreBB->clearLiveIns();
296 LoadCmpBB->clearLiveIns();
302bool AArch64ExpandPseudo::expandCMP_SWAP_128(
309 Register StatusReg =
MI.getOperand(2).getReg();
310 bool StatusDead =
MI.getOperand(2).isDead();
313 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
315 Register DesiredLoReg =
MI.getOperand(4).getReg();
316 Register DesiredHiReg =
MI.getOperand(5).getReg();
317 Register NewLoReg =
MI.getOperand(6).getReg();
318 Register NewHiReg =
MI.getOperand(7).getReg();
320 unsigned LdxpOp, StxpOp;
322 switch (
MI.getOpcode()) {
323 case AArch64::CMP_SWAP_128_MONOTONIC:
324 LdxpOp = AArch64::LDXPX;
325 StxpOp = AArch64::STXPX;
327 case AArch64::CMP_SWAP_128_RELEASE:
328 LdxpOp = AArch64::LDXPX;
329 StxpOp = AArch64::STLXPX;
331 case AArch64::CMP_SWAP_128_ACQUIRE:
332 LdxpOp = AArch64::LDAXPX;
333 StxpOp = AArch64::STXPX;
335 case AArch64::CMP_SWAP_128:
336 LdxpOp = AArch64::LDAXPX;
337 StxpOp = AArch64::STLXPX;
350 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
351 MF->
insert(++StoreBB->getIterator(), FailBB);
352 MF->
insert(++FailBB->getIterator(), DoneBB);
363 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
367 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
371 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
375 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
379 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
382 LoadCmpBB->addSuccessor(FailBB);
383 LoadCmpBB->addSuccessor(StoreBB);
388 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
392 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
396 StoreBB->addSuccessor(LoadCmpBB);
397 StoreBB->addSuccessor(DoneBB);
402 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
406 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
409 FailBB->addSuccessor(LoadCmpBB);
410 FailBB->addSuccessor(DoneBB);
412 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
413 DoneBB->transferSuccessors(&
MBB);
418 MI.eraseFromParent();
428 FailBB->clearLiveIns();
430 StoreBB->clearLiveIns();
432 LoadCmpBB->clearLiveIns();
476bool AArch64ExpandPseudo::expand_DestructiveOp(
485 bool DstIsDead =
MI.getOperand(0).isDead();
487 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
492 if (DstReg ==
MI.getOperand(3).getReg()) {
494 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
501 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
504 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
507 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
508 if (DstReg ==
MI.getOperand(3).getReg()) {
510 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
512 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
514 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
525 bool DOPRegIsUnique =
false;
528 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
533 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
534 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
538 DOPRegIsUnique =
true;
542 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
543 (
MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg() &&
544 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
560 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
561 unsigned MovPrfx, LSLZero, MovPrfxZero;
562 switch (ElementSize) {
565 MovPrfx = AArch64::MOVPRFX_ZZ;
566 LSLZero = AArch64::LSL_ZPmI_B;
567 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
570 MovPrfx = AArch64::MOVPRFX_ZZ;
571 LSLZero = AArch64::LSL_ZPmI_H;
572 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
575 MovPrfx = AArch64::MOVPRFX_ZZ;
576 LSLZero = AArch64::LSL_ZPmI_S;
577 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
580 MovPrfx = AArch64::MOVPRFX_ZZ;
581 LSLZero = AArch64::LSL_ZPmI_D;
582 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
598 "The destructive operand should be unique");
600 "This instruction is unpredicated");
605 .
addReg(
MI.getOperand(PredIdx).getReg())
606 .
addReg(
MI.getOperand(DOPIdx).getReg());
620 .
add(
MI.getOperand(PredIdx))
624 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
625 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
628 .
addReg(
MI.getOperand(DOPIdx).getReg());
641 .
add(
MI.getOperand(PredIdx))
642 .
add(
MI.getOperand(SrcIdx));
648 DOP.
add(
MI.getOperand(PredIdx))
650 .
add(
MI.getOperand(SrcIdx));
653 DOP.
add(
MI.getOperand(PredIdx))
655 .
add(
MI.getOperand(SrcIdx))
656 .
add(
MI.getOperand(Src2Idx));
662 transferImpOps(
MI, PRFX, DOP);
664 transferImpOps(
MI, DOP, DOP);
666 MI.eraseFromParent();
670bool AArch64ExpandPseudo::expandSetTagLoop(
676 Register AddressReg =
MI.getOperand(1).getReg();
680 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
681 const unsigned OpCode1 =
682 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
683 const unsigned OpCode2 =
684 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
686 unsigned Size =
MI.getOperand(2).getImm();
688 if (
Size % (16 * 2) != 0) {
704 MF->
insert(++LoopBB->getIterator(), DoneBB);
723 LoopBB->addSuccessor(LoopBB);
724 LoopBB->addSuccessor(DoneBB);
726 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
727 DoneBB->transferSuccessors(&
MBB);
732 MI.eraseFromParent();
739 LoopBB->clearLiveIns();
741 DoneBB->clearLiveIns();
749 unsigned Opc,
unsigned N) {
750 assert((Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI ||
751 Opc == AArch64::LDR_PXI || Opc == AArch64::STR_PXI) &&
752 "Unexpected opcode");
753 unsigned RState = (Opc == AArch64::LDR_ZXI || Opc == AArch64::LDR_PXI)
756 unsigned sub0 = (Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI)
763 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
764 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
765 assert(ImmOffset >= -256 && ImmOffset < 256 &&
766 "Immediate spill offset out of range");
773 MI.eraseFromParent();
783 unsigned RegMaskStartIdx) {
784 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
789 "invalid operand for regular call");
790 Call->addOperand(CallTarget);
795 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
796 auto MOP =
MBBI->getOperand(RegMaskStartIdx);
797 assert(MOP.isReg() &&
"can only add register operands");
799 MOP.getReg(),
false,
true,
false,
800 false, MOP.isUndef()));
805 Call->addOperand(MO);
810bool AArch64ExpandPseudo::expandCALL_RVMARKER(
819 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
835 if (
MI.shouldUpdateCallSiteInfo())
838 MI.eraseFromParent();
840 std::next(RVCall->getIterator()));
864 if (
MI.shouldUpdateCallSiteInfo())
867 MI.eraseFromParent();
872bool AArch64ExpandPseudo::expandStoreSwiftAsyncContext(
880 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
897 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
934 MI.getParent()->successors().begin() !=
935 MI.getParent()->successors().end()) &&
936 "Unexpected unreachable in block that restores ZA");
941 .
add(
MI.getOperand(0));
963 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
964 MIB.
add(
MI.getOperand(
I));
967 MI.eraseFromParent();
981 MI.getParent()->successors().begin() ==
982 MI.getParent()->successors().end()) {
983 MI.eraseFromParent();
1026 switch (
MI.getOperand(2).getImm()) {
1030 Opc = AArch64::TBNZW;
1033 Opc = AArch64::TBZW;
1036 auto PStateSM =
MI.getOperand(3).getReg();
1038 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1060 TII->get(AArch64::MSRpstatesvcrImm1));
1064 MIB.
add(
MI.getOperand(0));
1065 MIB.
add(
MI.getOperand(1));
1066 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1067 MIB.
add(
MI.getOperand(i));
1071 MI.eraseFromParent();
1075bool AArch64ExpandPseudo::expandMultiVecPseudo(
1078 unsigned ContiguousOp,
unsigned StridedOpc) {
1093 .
add(
MI.getOperand(0))
1094 .
add(
MI.getOperand(1))
1095 .
add(
MI.getOperand(2))
1096 .
add(
MI.getOperand(3));
1097 transferImpOps(
MI, MIB, MIB);
1098 MI.eraseFromParent();
1108 unsigned Opcode =
MI.getOpcode();
1112 if (OrigInstr != -1) {
1113 auto &Orig =
TII->get(OrigInstr);
1116 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1124 case AArch64::BSPv8i8:
1125 case AArch64::BSPv16i8: {
1127 if (DstReg ==
MI.getOperand(3).getReg()) {
1130 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1131 : AArch64::BITv16i8))
1132 .
add(
MI.getOperand(0))
1133 .
add(
MI.getOperand(3))
1134 .
add(
MI.getOperand(2))
1135 .
add(
MI.getOperand(1));
1136 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1139 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1140 : AArch64::BIFv16i8))
1141 .
add(
MI.getOperand(0))
1142 .
add(
MI.getOperand(2))
1143 .
add(
MI.getOperand(3))
1144 .
add(
MI.getOperand(1));
1147 if (DstReg ==
MI.getOperand(1).getReg()) {
1149 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1150 : AArch64::BSLv16i8))
1151 .
add(
MI.getOperand(0))
1152 .
add(
MI.getOperand(1))
1153 .
add(
MI.getOperand(2))
1154 .
add(
MI.getOperand(3));
1157 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1158 : AArch64::ORRv16i8))
1162 .
add(
MI.getOperand(1))
1163 .
add(
MI.getOperand(1));
1165 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1166 : AArch64::BSLv16i8))
1167 .
add(
MI.getOperand(0))
1171 .
add(
MI.getOperand(2))
1172 .
add(
MI.getOperand(3));
1175 MI.eraseFromParent();
1179 case AArch64::ADDWrr:
1180 case AArch64::SUBWrr:
1181 case AArch64::ADDXrr:
1182 case AArch64::SUBXrr:
1183 case AArch64::ADDSWrr:
1184 case AArch64::SUBSWrr:
1185 case AArch64::ADDSXrr:
1186 case AArch64::SUBSXrr:
1187 case AArch64::ANDWrr:
1188 case AArch64::ANDXrr:
1189 case AArch64::BICWrr:
1190 case AArch64::BICXrr:
1191 case AArch64::ANDSWrr:
1192 case AArch64::ANDSXrr:
1193 case AArch64::BICSWrr:
1194 case AArch64::BICSXrr:
1195 case AArch64::EONWrr:
1196 case AArch64::EONXrr:
1197 case AArch64::EORWrr:
1198 case AArch64::EORXrr:
1199 case AArch64::ORNWrr:
1200 case AArch64::ORNXrr:
1201 case AArch64::ORRWrr:
1202 case AArch64::ORRXrr: {
1204 switch (
MI.getOpcode()) {
1207 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1208 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1209 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1210 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1211 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1212 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1213 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1214 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1215 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1216 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1217 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1218 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1219 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1220 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1221 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1222 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1223 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1224 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1225 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1226 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1227 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1228 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1229 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1230 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1235 TII->get(Opcode),
MI.getDebugLoc(),
true);
1238 MIB1->setPCSections(MF,
MI.getPCSections());
1240 .add(
MI.getOperand(1))
1241 .add(
MI.getOperand(2))
1243 transferImpOps(
MI, MIB1, MIB1);
1244 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1246 MI.eraseFromParent();
1250 case AArch64::LOADgot: {
1259 TII->get(AArch64::LDRXl), DstReg);
1267 "Only expect globals, externalsymbols, or constant pools");
1280 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1281 unsigned DstFlags =
MI.getOperand(0).getTargetFlags();
1289 .
add(
MI.getOperand(0))
1304 "Only expect globals, externalsymbols, or constant pools");
1312 transferImpOps(
MI, MIB1, MIB2);
1314 MI.eraseFromParent();
1317 case AArch64::MOVaddrBA: {
1324 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1334 TII->get(AArch64::LDRXui), DstReg)
1338 transferImpOps(
MI, MIB1, MIB2);
1339 MI.eraseFromParent();
1344 case AArch64::MOVaddr:
1345 case AArch64::MOVaddrJT:
1346 case AArch64::MOVaddrCP:
1347 case AArch64::MOVaddrTLS:
1348 case AArch64::MOVaddrEXT: {
1351 assert(DstReg != AArch64::XZR);
1354 .
add(
MI.getOperand(1));
1364 auto Tag =
MI.getOperand(1);
1366 Tag.setOffset(0x100000000);
1375 .
add(
MI.getOperand(0))
1377 .
add(
MI.getOperand(2))
1380 transferImpOps(
MI, MIB1, MIB2);
1381 MI.eraseFromParent();
1384 case AArch64::ADDlowTLS:
1387 .
add(
MI.getOperand(0))
1388 .
add(
MI.getOperand(1))
1389 .
add(
MI.getOperand(2))
1391 MI.eraseFromParent();
1394 case AArch64::MOVbaseTLS: {
1396 auto SysReg = AArch64SysReg::TPIDR_EL0;
1399 SysReg = AArch64SysReg::TPIDR_EL3;
1401 SysReg = AArch64SysReg::TPIDR_EL2;
1403 SysReg = AArch64SysReg::TPIDR_EL1;
1405 SysReg = AArch64SysReg::TPIDRRO_EL0;
1408 MI.eraseFromParent();
1412 case AArch64::MOVi32imm:
1414 case AArch64::MOVi64imm:
1416 case AArch64::RET_ReallyLR: {
1425 transferImpOps(
MI, MIB, MIB);
1426 MI.eraseFromParent();
1429 case AArch64::CMP_SWAP_8:
1430 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1433 AArch64::WZR, NextMBBI);
1434 case AArch64::CMP_SWAP_16:
1435 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1438 AArch64::WZR, NextMBBI);
1439 case AArch64::CMP_SWAP_32:
1440 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1443 AArch64::WZR, NextMBBI);
1444 case AArch64::CMP_SWAP_64:
1445 return expandCMP_SWAP(
MBB,
MBBI,
1446 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1448 AArch64::XZR, NextMBBI);
1449 case AArch64::CMP_SWAP_128:
1450 case AArch64::CMP_SWAP_128_RELEASE:
1451 case AArch64::CMP_SWAP_128_ACQUIRE:
1452 case AArch64::CMP_SWAP_128_MONOTONIC:
1453 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1455 case AArch64::AESMCrrTied:
1456 case AArch64::AESIMCrrTied: {
1459 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1461 .
add(
MI.getOperand(0))
1462 .
add(
MI.getOperand(1));
1463 transferImpOps(
MI, MIB, MIB);
1464 MI.eraseFromParent();
1467 case AArch64::IRGstack: {
1478 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1479 MF, BaseOffset,
false ,
false , FrameReg,
1483 if (FrameRegOffset) {
1485 SrcReg =
MI.getOperand(0).getReg();
1487 FrameRegOffset,
TII);
1490 .
add(
MI.getOperand(0))
1492 .
add(
MI.getOperand(2));
1493 MI.eraseFromParent();
1496 case AArch64::TAGPstack: {
1497 int64_t
Offset =
MI.getOperand(2).getImm();
1499 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1500 .
add(
MI.getOperand(0))
1501 .
add(
MI.getOperand(1))
1503 .
add(
MI.getOperand(4));
1504 MI.eraseFromParent();
1507 case AArch64::STGloop_wback:
1508 case AArch64::STZGloop_wback:
1509 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1510 case AArch64::STGloop:
1511 case AArch64::STZGloop:
1513 "Non-writeback variants of STGloop / STZGloop should not "
1514 "survive past PrologEpilogInserter.");
1515 case AArch64::STR_ZZZZXI:
1516 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1517 case AArch64::STR_ZZZXI:
1518 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1519 case AArch64::STR_ZZXI:
1520 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1521 case AArch64::STR_PPXI:
1522 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1523 case AArch64::LDR_ZZZZXI:
1524 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1525 case AArch64::LDR_ZZZXI:
1526 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1527 case AArch64::LDR_ZZXI:
1528 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1529 case AArch64::LDR_PPXI:
1530 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1531 case AArch64::BLR_RVMARKER:
1532 return expandCALL_RVMARKER(
MBB,
MBBI);
1533 case AArch64::BLR_BTI:
1534 return expandCALL_BTI(
MBB,
MBBI);
1535 case AArch64::StoreSwiftAsyncContext:
1536 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1537 case AArch64::RestoreZAPseudo: {
1538 auto *NewMBB = expandRestoreZA(
MBB,
MBBI);
1543 case AArch64::MSRpstatePseudo: {
1544 auto *NewMBB = expandCondSMToggle(
MBB,
MBBI);
1549 case AArch64::COALESCER_BARRIER_FPR16:
1550 case AArch64::COALESCER_BARRIER_FPR32:
1551 case AArch64::COALESCER_BARRIER_FPR64:
1552 case AArch64::COALESCER_BARRIER_FPR128:
1553 MI.eraseFromParent();
1555 case AArch64::LD1B_2Z_IMM_PSEUDO:
1556 return expandMultiVecPseudo(
1557 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1558 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1559 case AArch64::LD1H_2Z_IMM_PSEUDO:
1560 return expandMultiVecPseudo(
1561 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1562 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1563 case AArch64::LD1W_2Z_IMM_PSEUDO:
1564 return expandMultiVecPseudo(
1565 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1566 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1567 case AArch64::LD1D_2Z_IMM_PSEUDO:
1568 return expandMultiVecPseudo(
1569 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1570 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1571 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1572 return expandMultiVecPseudo(
1573 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1574 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1575 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1576 return expandMultiVecPseudo(
1577 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1578 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1579 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1580 return expandMultiVecPseudo(
1581 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1582 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1583 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1584 return expandMultiVecPseudo(
1585 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1586 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1587 case AArch64::LD1B_2Z_PSEUDO:
1588 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1589 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1590 AArch64::LD1B_2Z_STRIDED);
1591 case AArch64::LD1H_2Z_PSEUDO:
1592 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1593 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1594 AArch64::LD1H_2Z_STRIDED);
1595 case AArch64::LD1W_2Z_PSEUDO:
1596 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1597 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1598 AArch64::LD1W_2Z_STRIDED);
1599 case AArch64::LD1D_2Z_PSEUDO:
1600 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1601 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1602 AArch64::LD1D_2Z_STRIDED);
1603 case AArch64::LDNT1B_2Z_PSEUDO:
1604 return expandMultiVecPseudo(
1605 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1606 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1607 case AArch64::LDNT1H_2Z_PSEUDO:
1608 return expandMultiVecPseudo(
1609 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1610 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1611 case AArch64::LDNT1W_2Z_PSEUDO:
1612 return expandMultiVecPseudo(
1613 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1614 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1615 case AArch64::LDNT1D_2Z_PSEUDO:
1616 return expandMultiVecPseudo(
1617 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1618 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1619 case AArch64::LD1B_4Z_IMM_PSEUDO:
1620 return expandMultiVecPseudo(
1621 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1622 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1623 case AArch64::LD1H_4Z_IMM_PSEUDO:
1624 return expandMultiVecPseudo(
1625 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1626 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1627 case AArch64::LD1W_4Z_IMM_PSEUDO:
1628 return expandMultiVecPseudo(
1629 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1630 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1631 case AArch64::LD1D_4Z_IMM_PSEUDO:
1632 return expandMultiVecPseudo(
1633 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1634 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1635 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1636 return expandMultiVecPseudo(
1637 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1638 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1639 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1640 return expandMultiVecPseudo(
1641 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1642 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1643 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1644 return expandMultiVecPseudo(
1645 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1646 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1647 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1648 return expandMultiVecPseudo(
1649 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1650 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1651 case AArch64::LD1B_4Z_PSEUDO:
1652 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1653 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1654 AArch64::LD1B_4Z_STRIDED);
1655 case AArch64::LD1H_4Z_PSEUDO:
1656 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1657 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1658 AArch64::LD1H_4Z_STRIDED);
1659 case AArch64::LD1W_4Z_PSEUDO:
1660 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1661 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1662 AArch64::LD1W_4Z_STRIDED);
1663 case AArch64::LD1D_4Z_PSEUDO:
1664 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1665 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1666 AArch64::LD1D_4Z_STRIDED);
1667 case AArch64::LDNT1B_4Z_PSEUDO:
1668 return expandMultiVecPseudo(
1669 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1670 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1671 case AArch64::LDNT1H_4Z_PSEUDO:
1672 return expandMultiVecPseudo(
1673 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1674 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1675 case AArch64::LDNT1W_4Z_PSEUDO:
1676 return expandMultiVecPseudo(
1677 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1678 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1679 case AArch64::LDNT1D_4Z_PSEUDO:
1680 return expandMultiVecPseudo(
1681 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1682 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1706 for (
auto &
MBB : MF)
1713 return new AArch64ExpandPseudo();
#define AARCH64_EXPAND_PSEUDO_NAME
MachineInstrBuilder & UseMI
static MachineInstr * createCall(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, MachineOperand &CallTarget, unsigned RegMaskStartIdx)
MachineInstrBuilder MachineInstrBuilder & DefMI
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
unsigned getTaggedBasePointerOffset() const
bool isTargetILP32() const
bool isTargetMachO() const
The address of a basic block.
FunctionPass class - This class is used to implement most global optimizations.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Describe properties that are true of each instruction in the target description file.
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.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
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()
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
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...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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.
void moveCallSiteInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
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.
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.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
StringRef - Represent a constant reference to a string, i.e.
CodeModel::Model getCodeModel() const
Returns the code model.
ArrayRef< MCPhysReg > getRegisters() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
self_iterator getIterator()
#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...
int getSVERevInstr(uint16_t Opcode)
@ DestructiveInstTypeMask
@ DestructiveUnaryPassthru
@ DestructiveTernaryCommWithRev
@ DestructiveBinaryCommWithRev
int getSVEPseudoMap(uint16_t Opcode)
int getSVENonRevInstr(uint16_t Opcode)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Renamable
Register that may be renamed.
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
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.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
unsigned getDeadRegState(bool B)
void initializeAArch64ExpandPseudoPass(PassRegistry &)
FunctionPass * createAArch64ExpandPseudoPass()
Returns an instance of the pseudo instruction expansion pass.
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.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
unsigned getKillRegState(bool B)
unsigned getRenamableRegState(bool B)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
This struct is a compact representation of a valid (non-zero power of two) alignment.
Description of the encoding of one expression Op.