From da5f256e7c554efcab92a8366fe79f4558215d5c Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Mon, 10 Nov 2025 20:43:25 +0000 Subject: [PATCH 1/2] [AArch64] Follow-up from #166926 Ensures the hints are only added once, and ensures that hints inserted by the register allocator take priority over hints to reduce movprfx. --- .../Target/AArch64/AArch64RegisterInfo.cpp | 33 ++++++---- .../CodeGen/AArch64/regalloc-hint-movprfx.mir | 66 +++++++++++++++++++ 2 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/regalloc-hint-movprfx.mir diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index eaf8723094797..a6f48cdc6c19a 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -1157,6 +1157,9 @@ bool AArch64RegisterInfo::getRegAllocationHints( // a movprfx. const TargetRegisterClass *RegRC = MRI.getRegClass(VirtReg); if (AArch64::ZPRRegClass.hasSubClassEq(RegRC)) { + bool ConsiderOnlyHints = TargetRegisterInfo::getRegAllocationHints( + VirtReg, Order, Hints, MF, VRM); + for (const MachineOperand &DefOp : MRI.def_operands(VirtReg)) { const MachineInstr &Def = *DefOp.getParent(); if (DefOp.isImplicit() || @@ -1168,26 +1171,33 @@ bool AArch64RegisterInfo::getRegAllocationHints( TII->get(AArch64::getSVEPseudoMap(Def.getOpcode())).TSFlags; for (MCPhysReg R : Order) { - auto AddHintIfSuitable = [&](MCPhysReg R, const MachineOperand &MO) { - // R is a suitable register hint if there exists an operand for the - // instruction that is not yet allocated a register or if R matches - // one of the other source operands. - if (!VRM->hasPhys(MO.getReg()) || VRM->getPhys(MO.getReg()) == R) + auto AddHintIfSuitable = [&](MCPhysReg R, + const MachineOperand &MO) -> bool { + // R is a suitable register hint if: + // * R is one of the source operands. + // * The register allocator has not suggested any hints and one of the + // instruction's source operands does not yet have a register + // allocated for it. + if (VRM->getPhys(MO.getReg()) == R || + (!VRM->hasPhys(MO.getReg()) && Hints.empty())) { Hints.push_back(R); + return true; + } + return false; }; switch (InstFlags & AArch64::DestructiveInstTypeMask) { default: break; case AArch64::DestructiveTernaryCommWithRev: - AddHintIfSuitable(R, Def.getOperand(2)); - AddHintIfSuitable(R, Def.getOperand(3)); - AddHintIfSuitable(R, Def.getOperand(4)); + AddHintIfSuitable(R, Def.getOperand(2)) || + AddHintIfSuitable(R, Def.getOperand(3)) || + AddHintIfSuitable(R, Def.getOperand(4)); break; case AArch64::DestructiveBinaryComm: case AArch64::DestructiveBinaryCommWithRev: - AddHintIfSuitable(R, Def.getOperand(2)); - AddHintIfSuitable(R, Def.getOperand(3)); + AddHintIfSuitable(R, Def.getOperand(2)) || + AddHintIfSuitable(R, Def.getOperand(3)); break; case AArch64::DestructiveBinary: case AArch64::DestructiveBinaryImm: @@ -1198,8 +1208,7 @@ bool AArch64RegisterInfo::getRegAllocationHints( } if (Hints.size()) - return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, - MF, VRM); + return ConsiderOnlyHints; } if (!ST.hasSME() || !ST.isStreaming()) diff --git a/llvm/test/CodeGen/AArch64/regalloc-hint-movprfx.mir b/llvm/test/CodeGen/AArch64/regalloc-hint-movprfx.mir new file mode 100644 index 0000000000000..c2d8f8e73772d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/regalloc-hint-movprfx.mir @@ -0,0 +1,66 @@ +# RUN: llc -mtriple=aarch64 -mattr=+sve -start-before=greedy -stop-after=virtregrewriter -debug-only=regalloc %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DBG + +# Check that the register allocator gets hints to reuse registers of one of it's operands. +--- +name: prioritize_movprfx_hints +tracksRegLiveness: true +isSSA: false +noVRegs: false +body: | + bb.0.entry: + liveins: $z0, $z1, $z2, $z3, $p0 + + ; DBG: Machine code for function prioritize_movprfx_hints + ; + ; DBG: selectOrSplit ZPR:%4 + ; DBG-NEXT: hints: $z0 $z1{{$}} + ; + ; DBG: selectOrSplit ZPR:%5 + ; DBG-NEXT: hints: $z2 $z3{{$}} + ; + ; DBG: [%0 -> $z3] ZPR + ; DBG: [%1 -> $z2] ZPR + ; DBG: [%2 -> $z1] ZPR + ; DBG: [%3 -> $z0] ZPR + ; DBG: [%4 -> $z0] ZPR + ; DBG: [%5 -> $z2] ZPR + ; DBG: [%6 -> $z0] ZPR + %0:zpr = COPY $z3 + %1:zpr = COPY $z2 + %2:zpr = COPY $z1 + %3:zpr = COPY $z0 + %4:zpr = SDIV_ZPZZ_D_UNDEF $p0, %3:zpr, %2:zpr + %5:zpr = MUL_ZPZZ_D_UNDEF $p0, %1:zpr, %0:zpr + %6:zpr = MUL_ZPZZ_D_UNDEF $p0, %5:zpr, %4:zpr + $z0 = COPY %6:zpr + RET_ReallyLR implicit $z0 +... + +# Check that the register allocator prioritises hints that are set by the register +# allocator itself (i.e. to use z4 for the result register). +--- +name: prioritize_regalloc_hints +isSSA: false +noVRegs: false +body: | + bb.0.entry: + %0:zpr = FDUP_ZI_S 0, implicit $vg + %1:zpr = FDUP_ZI_S 16, implicit $vg + %2:zpr = FDUP_ZI_S 32, implicit $vg + %3:ppr_3b = PTRUE_S 31, implicit $vg + + ; DBG: Machine code for function prioritize_regalloc_hints + ; + ; DBG: selectOrSplit ZPR:%4 + ; DBG-NEXT: hints: $z4{{$}} + ; + ; DBG: [%0 -> $z0] ZPR + ; DBG: [%1 -> $z1] ZPR + ; DBG: [%2 -> $z2] ZPR + ; DBG: [%3 -> $p0] PPR_3b + ; DBG: [%4 -> $z4] ZPR + + %4:zpr = FMLA_ZPZZZ_S_UNDEF %3, %0, %1, %2 + $z4 = COPY %4 + RET_ReallyLR implicit $z4 +... From bb3ba8170e65bee3bc5a31a1b696484ce6e1fb61 Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Tue, 11 Nov 2025 12:59:56 +0000 Subject: [PATCH 2/2] Remove unbound register condition --- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index a6f48cdc6c19a..1667bce402378 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -1173,17 +1173,12 @@ bool AArch64RegisterInfo::getRegAllocationHints( for (MCPhysReg R : Order) { auto AddHintIfSuitable = [&](MCPhysReg R, const MachineOperand &MO) -> bool { - // R is a suitable register hint if: - // * R is one of the source operands. - // * The register allocator has not suggested any hints and one of the - // instruction's source operands does not yet have a register - // allocated for it. - if (VRM->getPhys(MO.getReg()) == R || - (!VRM->hasPhys(MO.getReg()) && Hints.empty())) { - Hints.push_back(R); - return true; - } - return false; + // R is a suitable register hint if R can reuse one of the other + // source operands. + if (VRM->getPhys(MO.getReg()) != R) + return false; + Hints.push_back(R); + return true; }; switch (InstFlags & AArch64::DestructiveInstTypeMask) {