Index: include/llvm/CodeGen/MachineBasicBlock.h =================================================================== --- include/llvm/CodeGen/MachineBasicBlock.h +++ include/llvm/CodeGen/MachineBasicBlock.h @@ -341,6 +341,12 @@ bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = LaneBitmask::getAll()) const; + /// Return true if the specified physical register is in the live in set of + /// any of the successor blocks. If false is returned, Reg is guaranteed to + /// not be live out, although sub/super-registers are not checked. This can + /// be called both before and after regalloc. + bool isLiveOut(MCRegister PhysReg) const; + // Iteration support for live in sets. These sets are kept in sorted // order by their register number. using livein_iterator = LiveInVector::const_iterator; Index: lib/CodeGen/MachineBasicBlock.cpp =================================================================== --- lib/CodeGen/MachineBasicBlock.cpp +++ lib/CodeGen/MachineBasicBlock.cpp @@ -469,6 +469,14 @@ return I != livein_end() && (I->LaneMask & LaneMask).any(); } +bool MachineBasicBlock::isLiveOut(MCRegister PhysReg) const { + assert(PhysReg.isPhysical() && "Expected physreg"); + for (const_succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) + if ((*SI)->isLiveIn(PhysReg)) + return true; + return false; +} + void MachineBasicBlock::sortUniqueLiveIns() { llvm::sort(LiveIns, [](const RegisterMaskPair &LI0, const RegisterMaskPair &LI1) { Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -2304,6 +2304,32 @@ if (LiveInts) verifyLiveIntervals(); + // Check live-in list of each MBB. If a register is live into MBB, check + // that the register is in regsLiveOut of each predecessor block. Since + // this must come from a definition in the predecesssor or its live-in + // list, this will catch a live-through case where the predecessor does not + // have the register in its live-in list. This currently only checks + // registers that have no aliases, are not allocatable and are not + // reserved, which could mean a condition code register for instance. + if (MRI->tracksLiveness()) + for (const auto &MBB : *MF) + for (MachineBasicBlock::RegisterMaskPair P : MBB.liveins()) { + MCPhysReg LiveInReg = P.PhysReg; + bool hasAliases = MCRegAliasIterator(LiveInReg, TRI, false).isValid(); + if (hasAliases || isAllocatable(LiveInReg) || isReserved(LiveInReg)) + continue; + for (MachineBasicBlock::const_pred_iterator PrI = MBB.pred_begin(), + PrE = MBB.pred_end(); PrI != PrE; ++PrI) { + BBInfo &PInfo = MBBInfoMap[*PrI]; + if (!PInfo.regsLiveOut.count(LiveInReg)) { + Twine Msg = Twine("Live in register ") + + TRI->getName(LiveInReg) + " not found to be live out from " + + "%.bb." + Twine((*PrI)->getNumber()); + report(Msg.str().c_str(), &MBB); + } + } + } + for (auto CSInfo : MF->getCallSitesInfo()) if (!CSInfo.first->isCall()) report("Call site info referencing instruction that is not call", MF); Index: lib/Target/SystemZ/SystemZElimCompare.cpp =================================================================== --- lib/Target/SystemZ/SystemZElimCompare.cpp +++ lib/Target/SystemZ/SystemZElimCompare.cpp @@ -103,14 +103,6 @@ } // end anonymous namespace -// Return true if CC is live out of MBB. -static bool isCCLiveOut(MachineBasicBlock &MBB) { - for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) - if ((*SI)->isLiveIn(SystemZ::CC)) - return true; - return false; -} - // Returns true if MI is an instruction whose output equals the value in Reg. static bool preservesValueOf(MachineInstr &MI, unsigned Reg) { switch (MI.getOpcode()) { @@ -595,7 +587,7 @@ // Walk backwards through the block looking for comparisons, recording // all CC users as we go. The subroutines can delete Compare and // instructions before it. - bool CompleteCCUsers = !isCCLiveOut(MBB); + bool CompleteCCUsers = !MBB.isLiveOut(SystemZ::CC); SmallVector CCUsers; MachineBasicBlock::iterator MBBI = MBB.end(); while (MBBI != MBB.begin()) { Index: test/MachineVerifier/live-ins-01.mir =================================================================== --- /dev/null +++ test/MachineVerifier/live-ins-01.mir @@ -0,0 +1,60 @@ +# RUN: not llc -o - %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass none 2>&1 | FileCheck %s + +# Test that a the machine verifier reports an error when a register in +# liveins is not liveout from predecessor. + +--- | + define i32 @f1(i32 %a, i32 %b) { ret i32 %a } + define i32 @f2(i32 %a, i32 %b) { ret i32 %a } +... +--- +name: f1 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.0): + liveins: $r2l, $r3l + + %1:gr32bit = COPY $r3l + %0:gr32bit = COPY $r2l + CHIMux %0, 0, implicit-def $cc + + bb.1 (%ir-block.0): + liveins: $cc + + bb.2 (%ir-block.0): + liveins: $cc + + %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc + $r2l = COPY %2 + Return implicit $r2l +... + +# CHECK: *** Bad machine code: Live in register CC not found to be live out from %.bb.1 *** +# CHECK:- function: f2 +# CHECK:- basic block: %bb.2 + +--- +name: f2 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.0): + liveins: $r2l, $r3l + + %1:gr32bit = COPY $r3l + %0:gr32bit = COPY $r2l + CHIMux %0, 0, implicit-def $cc + + bb.1 (%ir-block.0): + liveins: $cc + KILL killed $cc + + bb.2 (%ir-block.0): + liveins: $cc + + %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc + $r2l = COPY %2 + Return implicit $r2l + +... Index: test/MachineVerifier/live-ins-02.mir =================================================================== --- /dev/null +++ test/MachineVerifier/live-ins-02.mir @@ -0,0 +1,35 @@ +# RUN: not llc -o - %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass none 2>&1 | FileCheck %s + +# Test that a the machine verifier reports an error when a register in +# liveins is not liveout from predecessor. + +--- | + define i32 @f1(i32 %a, i32 %b) { ret i32 %a } +... +--- +name: f1 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.0): + liveins: $r2l, $r3l + + %1:gr32bit = COPY $r3l + %0:gr32bit = COPY $r2l + CHIMux %0, 0, implicit-def $cc + + bb.1 (%ir-block.0): + + bb.2 (%ir-block.0): + liveins: $cc + + %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc + $r2l = COPY %2 + Return implicit $r2l +... + +# CHECK: *** Bad machine code: Live in register CC not found to be live out from %.bb.1 *** +# CHECK:- function: f1 +# CHECK:- basic block: %bb.2 + +...