Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -114,7 +114,9 @@ BitVector regsReserved; RegSet regsLive; RegVector regsDefined, regsDead, regsKilled; + SmallVector expectedLiveOuts; RegMaskVector regMasks; + BitVector PristineRegs; SlotIndex lastIndex; @@ -249,6 +251,7 @@ void report_context(SlotIndex Pos) const; void report_context_liverange(const LiveRange &LR) const; void report_context_lanemask(LaneBitmask LaneMask) const; + void report_context_reg(unsigned Reg) const; void report_context_vreg(unsigned VReg) const; void report_context_vreg_regunit(unsigned VRegOrRegUnit) const; @@ -527,6 +530,10 @@ errs() << "- liverange: " << LR << '\n'; } +void MachineVerifier::report_context_reg(unsigned Reg) const { + errs() << "- register: " << PrintReg(Reg, TRI) << '\n'; +} + void MachineVerifier::report_context_vreg(unsigned VReg) const { errs() << "- v. register: " << PrintReg(VReg, TRI) << '\n'; } @@ -581,6 +588,9 @@ if (!MF->empty()) verifyStackFrame(); + + const MachineFrameInfo &MFI = MF->getFrameInfo(); + PristineRegs = MFI.getPristineRegs(*MF); } // Does iterator point to a and b as the first two elements? @@ -775,8 +785,10 @@ regsLive.clear(); if (MRI->tracksLiveness()) { for (const auto &LI : MBB->liveins()) { - if (!TargetRegisterInfo::isPhysicalRegister(LI.PhysReg)) { + unsigned Reg = LI.PhysReg; + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) { report("MBB live-in list contains non-physical register", MBB); + report_context_reg(Reg); continue; } for (MCSubRegIterator SubRegs(LI.PhysReg, TRI, /*IncludeSelf=*/true); @@ -785,9 +797,7 @@ } } - const MachineFrameInfo &MFI = MF->getFrameInfo(); - BitVector PR = MFI.getPristineRegs(*MF); - for (unsigned I : PR.set_bits()) { + for (unsigned I : PristineRegs.set_bits()) { for (MCSubRegIterator SubRegs(I, TRI, /*IncludeSelf=*/true); SubRegs.isValid(); ++SubRegs) regsLive.insert(*SubRegs); @@ -1520,7 +1530,6 @@ void MachineVerifier::visitMachineBasicBlockAfter(const MachineBasicBlock *MBB) { MBBInfoMap[MBB].regsLiveOut = regsLive; - regsLive.clear(); if (Indexes) { SlotIndex stop = Indexes->getMBBEndIdx(MBB); @@ -1531,6 +1540,61 @@ } lastIndex = stop; } + + // Now that we now the liveness at the end of this basic block, we can + // verify that it matches the successors live-in lists or our expectations + // for return blocks. + if (MRI->tracksLiveness()) { + expectedLiveOuts.clear(); + if (MBB->isReturnBlock() && !MBB->back().isCall()) { + // Note: We excluded tailcalls here as we do not care about CSR after the + // call. TODO: We should check CSRs before the tailcall instead. + + const MachineFrameInfo &MFI = MF->getFrameInfo(); + if (MFI.isCalleeSavedInfoValid()) { + for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) { + if (!Info.isRestored()) + continue; + MCPhysReg Reg = Info.getReg(); + if (MRI->isReserved(Reg)) + continue; + expectedLiveOuts.push_back(Reg); + } + } + } else { + for (const MachineBasicBlock *Succ : MBB->successors()) { + // Don't add anything for EHPads. They have live-ins that are the result + // of the unwind/personality function that are not live-out of the + // predecessor and we don't know which is which. + if (Succ->isEHPad()) + break; + for (const auto &LI : Succ->liveins()) { + MCPhysReg Reg = LI.PhysReg; + if (TargetRegisterInfo::isPhysicalRegister(Reg) && + !MRI->isReserved(Reg)) + expectedLiveOuts.push_back(Reg); + } + } + } + + for (MCPhysReg Reg : expectedLiveOuts) { + /* At least any of the subregisters should be live. */ + bool IsLive = false; + for (MCSubRegIterator SR(Reg, TRI, true); SR.isValid(); ++SR) { + if (regsLive.count(*SR)) { + IsLive = true; + break; + } + } + if (!IsLive) { + report("Expected register to be live at end of MBB", MBB); + report_context_reg(Reg); + } + } + expectedLiveOuts.clear(); + } + + regsLive.clear(); } // Calculate the largest possible vregsPassed sets. These are the registers that Index: test/CodeGen/AArch64/machine-copy-remove.mir =================================================================== --- test/CodeGen/AArch64/machine-copy-remove.mir +++ test/CodeGen/AArch64/machine-copy-remove.mir @@ -204,7 +204,7 @@ tracksRegLiveness: true body: | bb.0: - liveins: %x0, %x1 + liveins: %x0, %x1, %x2 %x1 = COPY %x0 CBNZX %x1, %bb.2 @@ -236,7 +236,7 @@ tracksRegLiveness: true body: | bb.0: - liveins: %x0, %x1 + liveins: %x0, %x1, %x2 CBNZX %x0, %bb.2 @@ -247,7 +247,7 @@ B %bb.3 bb.2: - liveins: %x1 + liveins: %x1, %x2 %x0 = LDRXui %x1, 0 Index: test/CodeGen/AArch64/machine-zero-copy-remove.mir =================================================================== --- test/CodeGen/AArch64/machine-zero-copy-remove.mir +++ test/CodeGen/AArch64/machine-zero-copy-remove.mir @@ -7,7 +7,7 @@ name: test1 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %x1, %x2 %w0 = ANDSWri %w0, 1, implicit-def %nzcv @@ -31,7 +31,7 @@ name: test2 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2 %x0 = ANDSXri %x0, 1, implicit-def %nzcv @@ -55,7 +55,7 @@ name: test3 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %x1, %x2 %w0 = ADDSWri %w0, 1, 0, implicit-def %nzcv @@ -79,7 +79,7 @@ name: test4 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2 %x0 = ADDSXri %x0, 1, 0, implicit-def %nzcv @@ -103,7 +103,7 @@ name: test5 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %x1, %x2 %w0 = SUBSWri %w0, 1, 0, implicit-def %nzcv @@ -127,7 +127,7 @@ name: test6 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2 %x0 = SUBSXri %x0, 1, 0, implicit-def %nzcv @@ -151,7 +151,7 @@ name: test7 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = ADDSWrr %w0, %w1, implicit-def %nzcv @@ -175,7 +175,7 @@ name: test8 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = ADDSXrr %x0, %x1, implicit-def %nzcv @@ -199,7 +199,7 @@ name: test9 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = ANDSWrr %w0, %w1, implicit-def %nzcv @@ -223,7 +223,7 @@ name: test10 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = ANDSXrr %x0, %x1, implicit-def %nzcv @@ -247,7 +247,7 @@ name: test11 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = BICSWrr %w0, %w1, implicit-def %nzcv @@ -271,7 +271,7 @@ name: test12 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = BICSXrr %x0, %x1, implicit-def %nzcv @@ -295,7 +295,7 @@ name: test13 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = SUBSWrr %w0, %w1, implicit-def %nzcv @@ -319,7 +319,7 @@ name: test14 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = SUBSXrr %x0, %x1, implicit-def %nzcv @@ -343,7 +343,7 @@ name: test15 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = ADDSWrs %w0, %w1, 0, implicit-def %nzcv @@ -367,7 +367,7 @@ name: test16 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = ADDSXrs %x0, %x1, 0, implicit-def %nzcv @@ -391,7 +391,7 @@ name: test17 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = ANDSWrs %w0, %w1, 0, implicit-def %nzcv @@ -415,7 +415,7 @@ name: test18 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2, %x3 %x0 = ANDSXrs %x0, %x1, 0, implicit-def %nzcv @@ -439,7 +439,7 @@ name: test19 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %w1, %x2, %x3 %w0 = BICSWrs %w0, %w1, 0, implicit-def %nzcv @@ -465,7 +465,7 @@ name: test20 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w1, %x2 %w0 = SUBSWri %w1, 1, 0, implicit-def %nzcv @@ -492,7 +492,7 @@ name: test21 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %x1, %x2 %w0 = ANDSWri %w0, 1, implicit-def %nzcv @@ -519,7 +519,7 @@ name: test22 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %x0, %x1, %x2 %x0 = SUBSXri %x0, 1, 0, implicit-def %nzcv @@ -544,22 +544,23 @@ name: test23 tracksRegLiveness: true body: | - bb.0.entry: + bb.0: liveins: %w0, %x1, %x2 %w0 = ADDSWri %w0, 1, 0, implicit-def %nzcv STRWui killed %w0, killed %x1, 0 - Bcc 1, %bb.2, implicit killed %nzcv - B %bb.1 - - bb.3: - B %bb.1 + Bcc 1, %bb.3, implicit killed %nzcv + B %bb.2 bb.1: liveins: %x2 + B %bb.2 + + bb.2: + liveins: %x2 %w0 = COPY %wzr STRWui killed %w0, killed %x2, 0 - bb.2: + bb.3: RET_ReallyLR Index: test/CodeGen/Hexagon/livephysregs-lane-masks.mir =================================================================== --- test/CodeGen/Hexagon/livephysregs-lane-masks.mir +++ test/CodeGen/Hexagon/livephysregs-lane-masks.mir @@ -18,7 +18,7 @@ body: | bb.0: - liveins: %r16 + liveins: %r16, %r0 successors: %bb.1, %bb.2 %p0 = C2_cmpeqi %r16, 0 J2_jumpt %p0, %bb.2, implicit-def %pc Index: test/CodeGen/Hexagon/livephysregs-lane-masks2.mir =================================================================== --- test/CodeGen/Hexagon/livephysregs-lane-masks2.mir +++ test/CodeGen/Hexagon/livephysregs-lane-masks2.mir @@ -13,7 +13,7 @@ body: | bb.0: - liveins: %p0:0x1, %p2, %r0 + liveins: %p0:0x1, %p2, %r0, %r18, %r19 successors: %bb.1, %bb.2 J2_jumpt killed %p2, %bb.1, implicit-def %pc J2_jump %bb.2, implicit-def %pc Index: test/CodeGen/MIR/ARM/cfi-same-value.mir =================================================================== --- test/CodeGen/MIR/ARM/cfi-same-value.mir +++ test/CodeGen/MIR/ARM/cfi-same-value.mir @@ -23,7 +23,7 @@ stack: - { id: 0, name: mem, offset: -48, size: 40, alignment: 4 } - { id: 1, type: spill-slot, offset: -4, size: 4, alignment: 4, - callee-saved-register: '%lr' } + callee-saved-register: '%lr', callee-saved-restored: false } - { id: 2, type: spill-slot, offset: -8, size: 4, alignment: 4, callee-saved-register: '%r11' } body: | @@ -65,7 +65,7 @@ ; CHECK-NEXT: CFI_INSTRUCTION same_value %r5 CFI_INSTRUCTION same_value %r4 CFI_INSTRUCTION same_value %r5 - %sp = frame-setup STMDB_UPD %sp, 14, _, killed %r11, killed %lr + %sp = frame-setup STMDB_UPD %sp, 14, _, %r11, killed %lr frame-setup CFI_INSTRUCTION def_cfa_offset 8 frame-setup CFI_INSTRUCTION offset %lr, -4 frame-setup CFI_INSTRUCTION offset %r11, -8 Index: test/CodeGen/X86/block-placement.mir =================================================================== --- test/CodeGen/X86/block-placement.mir +++ test/CodeGen/X86/block-placement.mir @@ -46,7 +46,7 @@ - { reg: '%rdi' } - { reg: '%esi' } -# CHECK: %eax = FAULTING_OP 1, %bb.3.null, 1684, killed %rdi, 1, _, 0, _ :: (load 4 from %ir.ptr) +# CHECK: %eax = FAULTING_OP 1, %bb.3.null, 1684, %rdi, 1, _, 0, _ :: (load 4 from %ir.ptr) # CHECK-NEXT: JMP_1 %bb.2.not_null # CHECK: bb.3.null: # CHECK: bb.4.right: @@ -66,7 +66,7 @@ successors: %bb.2.null(0x7ffff800), %bb.4.not_null(0x00000800) liveins: %rdi - %eax = FAULTING_OP 1, %bb.2.null, 1684, killed %rdi, 1, _, 0, _ :: (load 4 from %ir.ptr) + %eax = FAULTING_OP 1, %bb.2.null, 1684, %rdi, 1, _, 0, _ :: (load 4 from %ir.ptr) JMP_1 %bb.4.not_null bb.4.not_null: Index: test/CodeGen/X86/implicit-null-checks.mir =================================================================== --- test/CodeGen/X86/implicit-null-checks.mir +++ test/CodeGen/X86/implicit-null-checks.mir @@ -456,7 +456,7 @@ %eax = MOV32ri 200 bb.3.is_null: - liveins: %eax, %ah, %al, %ax, %bh, %bl, %bp, %bpl, %bx, %eax, %ebp, %ebx, %rax, %rbp, %rbx, %r12, %r13, %r14, %r15, %r12b, %r13b, %r14b, %r15b, %r12d, %r13d, %r14d, %r15d, %r12w, %r13w, %r14w, %r15w + liveins: %eax RETQ %eax