-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[AArch64][SME] Make getRegAllocationHints more specific for multi-vector loads #123081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
f9d4ac8
68e65db
7635e0e
81c3d47
607e3df
65e937d
a651b43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,7 @@ | |
| #include "MCTargetDesc/AArch64InstPrinter.h" | ||
| #include "llvm/ADT/BitVector.h" | ||
| #include "llvm/BinaryFormat/Dwarf.h" | ||
| #include "llvm/CodeGen/LiveRegMatrix.h" | ||
| #include "llvm/CodeGen/MachineFrameInfo.h" | ||
| #include "llvm/CodeGen/MachineInstrBuilder.h" | ||
| #include "llvm/CodeGen/MachineRegisterInfo.h" | ||
|
|
@@ -1099,6 +1100,11 @@ bool AArch64RegisterInfo::getRegAllocationHints( | |
| const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const { | ||
| const MachineRegisterInfo &MRI = MF.getRegInfo(); | ||
|
|
||
| auto &ST = MF.getSubtarget<AArch64Subtarget>(); | ||
| if (!ST.hasSME() || !ST.isStreaming()) | ||
| return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, | ||
| VRM); | ||
|
|
||
| // The SVE calling convention preserves registers Z8-Z23. As a result, there | ||
| // are no ZPR2Strided or ZPR4Strided registers that do not overlap with the | ||
| // callee-saved registers and so by default these will be pushed to the back | ||
|
|
@@ -1108,25 +1114,82 @@ bool AArch64RegisterInfo::getRegAllocationHints( | |
| // instructions over reducing the number of clobbered callee-save registers, | ||
| // so we add the strided registers as a hint. | ||
| unsigned RegID = MRI.getRegClass(VirtReg)->getID(); | ||
| // Look through uses of the register for FORM_TRANSPOSED_REG_TUPLE. | ||
| if ((RegID == AArch64::ZPR2StridedOrContiguousRegClassID || | ||
| RegID == AArch64::ZPR4StridedOrContiguousRegClassID) && | ||
| any_of(MRI.use_nodbg_instructions(VirtReg), [](const MachineInstr &Use) { | ||
| return Use.getOpcode() == | ||
| AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO || | ||
| Use.getOpcode() == AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO; | ||
| })) { | ||
| const TargetRegisterClass *StridedRC = | ||
| RegID == AArch64::ZPR2StridedOrContiguousRegClassID | ||
| ? &AArch64::ZPR2StridedRegClass | ||
| : &AArch64::ZPR4StridedRegClass; | ||
|
|
||
| for (MCPhysReg Reg : Order) | ||
| if (StridedRC->contains(Reg)) | ||
| Hints.push_back(Reg); | ||
| if (RegID == AArch64::ZPR2StridedOrContiguousRegClassID || | ||
| RegID == AArch64::ZPR4StridedOrContiguousRegClassID) { | ||
|
|
||
| // Look through uses of the register for FORM_TRANSPOSED_REG_TUPLE. | ||
| for (const MachineInstr &Use : MRI.use_nodbg_instructions(VirtReg)) { | ||
| if (Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO && | ||
| Use.getOpcode() != AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO) | ||
| continue; | ||
|
|
||
| unsigned LdOps = Use.getNumOperands() - 1; | ||
|
||
| const TargetRegisterClass *StridedRC = | ||
| LdOps == 2 ? &AArch64::ZPR2StridedRegClass | ||
| : &AArch64::ZPR4StridedRegClass; | ||
|
|
||
| SmallVector<MCPhysReg, 4> StridedOrder; | ||
| for (MCPhysReg Reg : Order) | ||
| if (StridedRC->contains(Reg)) | ||
| StridedOrder.push_back(Reg); | ||
|
|
||
| int OpIdx = Use.findRegisterUseOperandIdx(VirtReg, this); | ||
| assert(OpIdx != -1 && "Expected operand index from register use."); | ||
|
|
||
| unsigned TupleID = MRI.getRegClass(Use.getOperand(0).getReg())->getID(); | ||
| bool IsMulZPR = TupleID == AArch64::ZPR2Mul2RegClassID || | ||
| TupleID == AArch64::ZPR4Mul4RegClassID; | ||
|
|
||
| const MachineOperand *AssignedRegOp = llvm::find_if( | ||
| make_range(Use.operands_begin() + 1, Use.operands_end()), | ||
| [&VRM](const MachineOperand &Op) { | ||
| return VRM->hasPhys(Op.getReg()); | ||
| }); | ||
|
|
||
| if (AssignedRegOp == Use.operands_end()) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think an example would be useful here. |
||
| // There are no registers already assigned to any of the pseudo | ||
| // operands. Look for a valid starting register for the group. | ||
| for (unsigned I = 0; I < StridedOrder.size(); ++I) { | ||
| MCPhysReg Reg = StridedOrder[I]; | ||
| SmallVector<MCPhysReg> Regs; | ||
| unsigned FirstStridedReg = Reg - OpIdx + 1; | ||
|
||
|
|
||
| // If the FORM_TRANSPOSE nodes use the ZPRMul classes, the starting | ||
| // register of the first load should be a multiple of 2 or 4. | ||
| unsigned FirstSubReg = getSubReg(FirstStridedReg, AArch64::zsub0); | ||
| if (IsMulZPR && (FirstSubReg - AArch64::Z0) % LdOps != 0) | ||
| continue; | ||
|
|
||
| for (unsigned Op = 0; Op < LdOps; ++Op) { | ||
| if (!is_contained(StridedOrder, FirstStridedReg + Op) || | ||
| getSubReg(FirstStridedReg + Op, AArch64::zsub0) != | ||
| FirstSubReg + Op) | ||
| break; | ||
| Regs.push_back(FirstStridedReg + Op); | ||
| } | ||
|
|
||
| if (Regs.size() == LdOps && all_of(Regs, [&](MCPhysReg R) { | ||
| return !Matrix->isPhysRegUsed(R); | ||
| })) | ||
|
||
| Hints.push_back(FirstStridedReg + OpIdx - 1); | ||
| } | ||
| } else { | ||
| // At least one operand already has a physical register assigned. | ||
| // Find the starting sub-register of this and use it to work out the | ||
| // correct strided register to suggest based on the current op index. | ||
| MCPhysReg TargetStartReg = | ||
| getSubReg(VRM->getPhys(AssignedRegOp->getReg()), AArch64::zsub0) + | ||
| (OpIdx - AssignedRegOp->getOperandNo()); | ||
|
|
||
| for (unsigned I = 0; I < StridedOrder.size(); ++I) | ||
| if (getSubReg(StridedOrder[I], AArch64::zsub0) == TargetStartReg) | ||
| Hints.push_back(StridedOrder[I]); | ||
| } | ||
|
|
||
| return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, | ||
| VRM); | ||
| if (!Hints.empty()) | ||
| return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, | ||
| MF, VRM); | ||
| } | ||
| } | ||
|
|
||
| for (MachineInstr &MI : MRI.def_instructions(VirtReg)) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this can be moved down (after the if(..) condition)