Hello, I am a beginner to LLVM. I am trying to develop a new backend for our target. I run into an error about register allocation: there are not enough registers. Reading the debug output of llc, I noticed the following:
...
Coalescing: %4:gr32_acc = COPY %0:gr32_acc
*** to: %6:gr32_acc = ADDB %4:gr32_acc(tied-def 0), %5:gr32_acc
Coalescing: %10:gr32_acc = COPY %7:gr32_acc
*** to: CMPL %10:gr32_acc, %0:gr32_acc, implicit-def $sr0
...
which is generated by the MachineCSE pass.
Later in the debug output, there shows a Register Coalescer pass, which outputs lines like:
...
240B %14:gr32 = COPY %9:gr32_acc
Considering merging to GR32_ACC with %9 in %14
RHS = %9 [192r,240r:0) 0@192r weight:0.000000e+00
LHS = %14 [240r,256B:1)[272r,288B:0)[288B,304r:2) 0@272r 1@240r 2@288B-phi weight:0.000000e+00
merge %14:1@240r into %9:0@192r --> @192r
erased: 240r %14:gr32 = COPY %9:gr32_acc
...
For the success of register allocation, I want to disable some register coalescing (about the GR32_ACC register class, which has but one ACC register in it). The Register Coalescer pass provides the TargetRegisterInfo a chance to do this:
bool RegisterCoalescer::joinCopy(MachineInstr *CopyMI, bool &Again) {
Again = false;
LLVM_DEBUG(dbgs() << LIS->getInstructionIndex(*CopyMI) << '\t' << *CopyMI);
...
if (!TRI->shouldCoalesce(CopyMI, SrcRC, SrcIdx, DstRC, DstIdx,
CP.getNewRC(), *LIS)) {
LLVM_DEBUG(dbgs() << "\tSubtarget bailed on coalescing.\n");
return false;
}
}
...
}
But this hook is not called in MachineCSE:
bool MachineCSE::PerformTrivialCopyPropagation(MachineInstr *MI,
MachineBasicBlock *MBB) {
bool Changed = false;
for (MachineOperand &MO : MI->all_uses()) {
Register Reg = MO.getReg();
if (!Reg.isVirtual())
continue;
bool OnlyOneUse = MRI->hasOneNonDBGUse(Reg);
MachineInstr *DefMI = MRI->getVRegDef(Reg);
if (!DefMI->isCopy())
continue;
Register SrcReg = DefMI->getOperand(1).getReg();
if (!SrcReg.isVirtual())
continue;
if (DefMI->getOperand(0).getSubReg())
continue;
// FIXME: We should trivially coalesce subregister copies to expose CSE
// opportunities on instructions with truncated operands (see
// cse-add-with-overflow.ll). This can be done here as follows:
// if (SrcSubReg)
// RC = TRI->getMatchingSuperRegClass(MRI->getRegClass(SrcReg), RC,
// SrcSubReg);
// MO.substVirtReg(SrcReg, SrcSubReg, *TRI);
//
// The 2-addr pass has been updated to handle coalesced subregs. However,
// some machine-specific code still can't handle it.
// To handle it properly we also need a way find a constrained subregister
// class given a super-reg class and subreg index.
if (DefMI->getOperand(1).getSubReg())
continue;
if (!MRI->constrainRegAttrs(SrcReg, Reg))
continue;
LLVM_DEBUG(dbgs() << "Coalescing: " << *DefMI);
LLVM_DEBUG(dbgs() << "*** to: " << *MI);
// Propagate SrcReg of copies to MI.
MO.setReg(SrcReg);
MRI->clearKillFlags(SrcReg);
// Coalesce single use copies.
if (OnlyOneUse) {
// If (and only if) we've eliminated all uses of the copy, also
// copy-propagate to any debug-users of MI, or they'll be left using
// an undefined value.
DefMI->changeDebugValuesDefReg(SrcReg);
DefMI->eraseFromParent();
++NumCoalesces;
}
Changed = true;
}
return Changed;
}
Could someone please tell me the reason why this hook is not called in MachineCSE? Could/Should it be added? Or, is there any other method to prevent MachineCSE from coalescing some registers?
Thank you.