Skip to content

Commit 1fc1154

Browse files
adriwebcodex
andcommitted
[Z80] more determinism: canonicalize regalloc hints for pair classes.
Make Z80/eZ80 register-allocation hints deterministic for interchangeable G*/O* pair classes by sorting target-independent hints back into canonical allocation order, while preserving the existing DE/UDE preference when frame-index-heavy code asks for it. Co-Authored-By: Codex CLI <codex@openai.com>
1 parent b063e77 commit 1fc1154

1 file changed

Lines changed: 45 additions & 2 deletions

File tree

llvm/lib/Target/Z80/Z80RegisterInfo.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/CodeGen/MachineRegisterInfo.h"
2323
#include "llvm/CodeGen/TargetFrameLowering.h"
2424
#include "llvm/CodeGen/VirtRegMap.h"
25+
#include "llvm/ADT/STLExtras.h"
2526
#include "llvm/ADT/SmallPtrSet.h"
2627
#include "llvm/Support/Debug.h"
2728
using namespace llvm;
@@ -31,6 +32,45 @@ using namespace llvm;
3132
#define GET_REGINFO_TARGET_DESC
3233
#include "Z80GenRegisterInfo.inc"
3334

35+
namespace {
36+
37+
static bool shouldCanonicalizeHintOrder(const TargetRegisterClass *RC,
38+
bool Is24Bit) {
39+
return RC == (Is24Bit ? &Z80::G24RegClass : &Z80::G16RegClass) ||
40+
RC == (Is24Bit ? &Z80::O24RegClass : &Z80::O16RegClass);
41+
}
42+
43+
static unsigned getAllocationOrderIndex(ArrayRef<MCPhysReg> Order,
44+
MCPhysReg Reg) {
45+
for (auto [Idx, PhysReg] : enumerate(Order))
46+
if (PhysReg == Reg)
47+
return Idx;
48+
llvm_unreachable("hint register must be present in allocation order");
49+
}
50+
51+
static void canonicalizeHintOrder(ArrayRef<MCPhysReg> Order,
52+
SmallVectorImpl<MCPhysReg> &Hints,
53+
MCPhysReg PreferredReg = MCPhysReg()) {
54+
if (Hints.size() < 2)
55+
return;
56+
57+
llvm::stable_sort(Hints, [&](MCPhysReg LHS, MCPhysReg RHS) {
58+
const bool LHSPref = PreferredReg && LHS == PreferredReg;
59+
const bool RHSPref = PreferredReg && RHS == PreferredReg;
60+
if (LHSPref != RHSPref)
61+
return LHSPref;
62+
63+
const unsigned LHSIdx = getAllocationOrderIndex(Order, LHS);
64+
const unsigned RHSIdx = getAllocationOrderIndex(Order, RHS);
65+
if (LHSIdx != RHSIdx)
66+
return LHSIdx < RHSIdx;
67+
68+
return LHS < RHS;
69+
});
70+
}
71+
72+
} // namespace
73+
3474
Z80RegisterInfo::Z80RegisterInfo(const Triple &TT)
3575
: Z80GenRegisterInfo(0, 0, 0, Z80::PC) {
3676
// Cache some information.
@@ -486,7 +526,7 @@ bool Z80RegisterInfo::getRegAllocationHints(
486526
}
487527

488528
bool ShouldHintDE = false;
489-
const char *HintReason = nullptr;
529+
[[maybe_unused]] const char *HintReason = nullptr;
490530

491531
// case A: PHI defined vregs are loop carried
492532
if (IsPHIDefined && HasFIInLiveBBs) {
@@ -518,8 +558,8 @@ bool Z80RegisterInfo::getRegAllocationHints(
518558
<< " => " << (ShouldHintDE ? HintReason : "NO_HINT") << "\n";
519559
});
520560

561+
MCPhysReg DE = Is24Bit ? Z80::UDE : Z80::DE;
521562
if (ShouldHintDE) {
522-
MCPhysReg DE = Is24Bit ? Z80::UDE : Z80::DE;
523563
if (is_contained(Order, DE) && !MRI->isReserved(DE) &&
524564
!is_contained(Hints, DE)) {
525565

@@ -537,5 +577,8 @@ bool Z80RegisterInfo::getRegAllocationHints(
537577
}
538578
}
539579

580+
if (shouldCanonicalizeHintOrder(RC, Is24Bit))
581+
canonicalizeHintOrder(Order, Hints, ShouldHintDE ? DE : MCPhysReg());
582+
540583
return BaseResult;
541584
}

0 commit comments

Comments
 (0)