Recommit "[MachineVerifier] Improve verification of live-in lists."
authorJonas Paulsson <paulsson@linux.vnet.ibm.com>
Tue, 19 Nov 2019 11:34:49 +0000 (12:34 +0100)
committerJonas Paulsson <paulsson@linux.vnet.ibm.com>
Thu, 9 Jan 2020 00:58:54 +0000 (16:58 -0800)
MachineVerifier::visitMachineFunctionAfter() is extended to check the
live-through case for live-in lists. This is only done for registers without
aliases and that are neither allocatable or reserved, such as the SystemZ::CC
register.

The MachineVerifier earlier only catched the case of a live-in use without an
entry in the live-in list (as "using an undefined physical register").

A comment in LivePhysRegs.h has been added stating a guarantee that
addLiveOuts() can be trusted for a full register both before and after
register allocation.

Review: Quentin Colombet

Differential Revision: https://reviews.llvm.org/D68267

llvm/include/llvm/CodeGen/LivePhysRegs.h
llvm/lib/CodeGen/MachineVerifier.cpp
llvm/test/MachineVerifier/live-ins-01.mir [new file with mode: 0644]
llvm/test/MachineVerifier/live-ins-02.mir [new file with mode: 0644]
llvm/test/MachineVerifier/live-ins-03.mir [new file with mode: 0644]

index 50da0b3..0858934 100644 (file)
@@ -137,6 +137,9 @@ public:
   /// Live out registers are the union of the live-in registers of the successor
   /// blocks and pristine registers. Live out registers of the end block are the
   /// callee saved registers.
+  /// If a register is not added by this method, it is guaranteed to not be
+  /// live out from MBB, although a sub-register may be. This is true
+  /// both before and after regalloc.
   void addLiveOuts(const MachineBasicBlock &MBB);
 
   /// Adds all live-out registers of basic block \p MBB but skips pristine
index ca57e51..b2534c2 100644 (file)
@@ -2312,6 +2312,32 @@ void MachineVerifier::visitMachineFunctionAfter() {
   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 (const MachineBasicBlock *Pred : MBB.predecessors()) {
+          BBInfo &PInfo = MBBInfoMap[Pred];
+          if (!PInfo.regsLiveOut.count(LiveInReg)) {
+            report("Live in register not found to be live out from predecessor.",
+                   &MBB);
+            errs() << TRI->getName(LiveInReg)
+                   << " not found to be live out from "
+                   << printMBBReference(*Pred) << "\n";
+          }
+        }
+      }
+
   for (auto CSInfo : MF->getCallSitesInfo())
     if (!CSInfo.first->isCall())
       report("Call site info referencing instruction that is not call", MF);
diff --git a/llvm/test/MachineVerifier/live-ins-01.mir b/llvm/test/MachineVerifier/live-ins-01.mir
new file mode 100644 (file)
index 0000000..51c05da
--- /dev/null
@@ -0,0 +1,57 @@
+# RUN: not llc -o - %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass none 2>&1 | FileCheck %s
+# REQUIRES: systemz-registered-target
+
+# Test that a the machine verifier reports an error when a register in
+# liveins is not liveout from predecessor.
+
+---
+name:            f1
+tracksRegLiveness: true
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $r2l, $r3l
+  
+    %1:gr32bit = COPY $r3l
+    %0:gr32bit = COPY $r2l
+    CHIMux %0, 0, implicit-def $cc
+
+  bb.1:
+    liveins: $cc
+
+  bb.2:
+    liveins: $cc
+
+    %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc
+    $r2l = COPY %2
+    Return implicit $r2l
+...
+
+# CHECK: *** Bad machine code: Live in register not found to be live out from predecessor. ***
+# CHECK:- function:    f2
+# CHECK:- basic block: %bb.2
+# CHECK:CC not found to be live out from %bb.1
+---
+name:            f2
+tracksRegLiveness: true
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $r2l, $r3l
+  
+    %1:gr32bit = COPY $r3l
+    %0:gr32bit = COPY $r2l
+    CHIMux %0, 0, implicit-def $cc
+
+  bb.1:
+    liveins: $cc
+    KILL killed $cc
+
+  bb.2:
+    liveins: $cc
+
+    %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc
+    $r2l = COPY %2
+    Return implicit $r2l
+
+...
diff --git a/llvm/test/MachineVerifier/live-ins-02.mir b/llvm/test/MachineVerifier/live-ins-02.mir
new file mode 100644 (file)
index 0000000..d76325c
--- /dev/null
@@ -0,0 +1,32 @@
+# RUN: not llc -o - %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass none 2>&1 | FileCheck %s
+# REQUIRES: systemz-registered-target
+
+# Test that a the machine verifier reports an error when a register in
+# liveins is not liveout from predecessor.
+
+---
+name:            f1
+tracksRegLiveness: true
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $r2l, $r3l
+  
+    %1:gr32bit = COPY $r3l
+    %0:gr32bit = COPY $r2l
+    CHIMux %0, 0, implicit-def $cc
+
+  bb.1:
+
+  bb.2:
+    liveins: $cc
+
+    %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc
+    $r2l = COPY %2
+    Return implicit $r2l
+...
+
+# CHECK: *** Bad machine code: Live in register not found to be live out from predecessor. ***
+# CHECK:- function:    f1
+# CHECK:- basic block: %bb.2
+# CHECK:CC not found to be live out from %bb.1
diff --git a/llvm/test/MachineVerifier/live-ins-03.mir b/llvm/test/MachineVerifier/live-ins-03.mir
new file mode 100644 (file)
index 0000000..b5345cc
--- /dev/null
@@ -0,0 +1,36 @@
+# RUN: not llc -o - %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass none 2>&1 | FileCheck %s
+# REQUIRES: systemz-registered-target
+
+# Test that a the machine verifier reports an error when a register in
+# liveins is not liveout from predecessor.
+
+---
+name:            f1
+tracksRegLiveness: true
+machineFunctionInfo: {}
+body:             |
+  bb.0:
+    liveins: $r2l, $r3l
+  
+    %1:gr32bit = COPY $r3l
+    %0:gr32bit = COPY $r2l
+    CHIMux %0, 0, implicit-def $cc
+
+  bb.1:
+    liveins: $cc
+    BRC 14, 8, %bb.3, implicit $cc
+
+  bb.2:
+
+  bb.3:
+    liveins: $cc
+
+    %2:grx32bit = LOCRMux %1, %0, 14, 8, implicit $cc
+    $r2l = COPY %2
+    Return implicit $r2l
+...
+
+# CHECK: *** Bad machine code: Live in register not found to be live out from predecessor. ***
+# CHECK:- function:    f1
+# CHECK:- basic block: %bb.3
+# CHECK:CC not found to be live out from %bb.2