[MachineVerifier] do not use !NoPHI to check if a MF has phi nodes (#211941)

We were violating the property expressed in MachineFunction.h:

```
The properties are stated in "positive" form; i.e. a pass could require
that the property hold, but not that it does not hold.
```

Resolves a false positive "MBB has allocatable live-in, [...]" error in
our downstream target.
This commit is contained in:
Florian Mayer 2026-07-27 11:41:31 -07:00 committed by GitHub
parent 68e94c9040
commit f83fcfbdc7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 2 deletions

View file

@ -731,12 +731,19 @@ void MachineVerifier::visitMachineFunctionBefore() {
}
}
static bool hasPHIs(const MachineFunction &MF) {
return !MF.getProperties().hasNoPHIs() &&
any_of(MF, [](const MachineBasicBlock &MBB) {
return !MBB.phis().empty();
});
}
void
MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
FirstTerminator = nullptr;
FirstNonPHI = nullptr;
if (!MF->getProperties().hasNoPHIs() && MRI->tracksLiveness()) {
if (MRI->tracksLiveness() && hasPHIs(*MF)) {
// If this block has allocatable physical registers live-in, check that
// it is an entry block or landing pad.
for (const auto &LI : MBB->liveins()) {
@ -2360,7 +2367,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
if (!MI->getOperand(0).isReg() || !MI->getOperand(0).isDef())
report("Unspillable Terminator does not define a reg", MI);
Register Def = MI->getOperand(0).getReg();
if (Def.isVirtual() && !MF->getProperties().hasNoPHIs() &&
if (Def.isVirtual() && hasPHIs(*MF) &&
std::distance(MRI->use_nodbg_begin(Def), MRI->use_nodbg_end()) > 1)
report("Unspillable Terminator expected to have at most one use!", MI);
}

View file

@ -0,0 +1,21 @@
# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=machineverifier -o /dev/null %s
# Verify that the MachineVerifier does not trust a negative noPhis flag.
# As per MachineFunction.h:
# > The properties are stated in "positive" form; i.e. a pass could require
# > that the property hold, but not that it does not hold.
---
name: baz
tracksRegLiveness: true
noPhis: false
body: |
bb.0:
successors: %bb.1(0x80000000)
liveins: $rdi, $xmm0
bb.1:
successors: %bb.1(0x80000000)
liveins: $rax
RET64
...