]> granicus.if.org Git - llvm/commitdiff
Create a PHI value when merging with a known undef live-in
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 27 Jun 2017 21:30:46 +0000 (21:30 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 27 Jun 2017 21:30:46 +0000 (21:30 +0000)
Differential Revision: https://reviews.llvm.org/D34640

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306466 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/LiveRangeCalc.cpp
test/CodeGen/Hexagon/regalloc-liveout-undef.mir [new file with mode: 0644]

index 65448937e4ce2a88dcfd04169901157177430394..2455a714c5800f0941548fb699792fd3ad85b489 100644 (file)
@@ -20,6 +20,9 @@ using namespace llvm;
 
 #define DEBUG_TYPE "regalloc"
 
+// Reserve an address that indicates a value that is known to be "undef".
+static VNInfo UndefVNI(0xbad, SlotIndex());
+
 void LiveRangeCalc::resetLiveOutMap() {
   unsigned NumBlocks = MF->getNumBlockIDs();
   Seen.clear();
@@ -283,8 +286,11 @@ bool LiveRangeCalc::isDefOnEntry(LiveRange &LR, ArrayRef<SlotIndex> Undefs,
     // Determine if the exit from the block is reached by some def.
     unsigned N = WorkList[i];
     MachineBasicBlock &B = *MF->getBlockNumbered(N);
-    if (Seen[N] && Map[&B].first != nullptr)
-      return MarkDefined(B);
+    if (Seen[N]) {
+      const LiveOutPair &LOB = Map[&B];
+      if (LOB.first != nullptr && LOB.first != &UndefVNI)
+        return MarkDefined(B);
+    }
     SlotIndex Begin, End;
     std::tie(Begin, End) = Indexes->getMBBRange(&B);
     // Treat End as not belonging to B.
@@ -387,7 +393,7 @@ bool LiveRangeCalc::findReachingDefs(LiveRange &LR, MachineBasicBlock &UseMBB,
        auto EP = LR.extendInBlock(Undefs, Start, End);
        VNInfo *VNI = EP.first;
        FoundUndef |= EP.second;
-       setLiveOutValue(Pred, VNI);
+       setLiveOutValue(Pred, EP.second ? &UndefVNI : VNI);
        if (VNI) {
          if (TheVNI && TheVNI != VNI)
            UniqueVNI = false;
@@ -417,7 +423,7 @@ bool LiveRangeCalc::findReachingDefs(LiveRange &LR, MachineBasicBlock &UseMBB,
 
   // If a unique reaching def was found, blit in the live ranges immediately.
   if (UniqueVNI) {
-    assert(TheVNI != nullptr);
+    assert(TheVNI != nullptr && TheVNI != &UndefVNI);
     LiveRangeUpdater Updater(&LR);
     for (unsigned BN : WorkList) {
       SlotIndex Start, End;
@@ -494,15 +500,20 @@ void LiveRangeCalc::updateSSA() {
         IDomValue = Map[IDom->getBlock()];
 
         // Cache the DomTree node that defined the value.
-        if (IDomValue.first && !IDomValue.second)
-          Map[IDom->getBlock()].second = IDomValue.second =
-            DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def));
+        if (IDomValue.first && IDomValue.first != &UndefVNI)
+          if (!IDomValue.second)
+            Map[IDom->getBlock()].second = IDomValue.second =
+              DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def));
 
         for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
                PE = MBB->pred_end(); PI != PE; ++PI) {
           LiveOutPair &Value = Map[*PI];
           if (!Value.first || Value.first == IDomValue.first)
             continue;
+          if (Value.first == &UndefVNI) {
+            needPHI = true;
+            break;
+          }
 
           // Cache the DomTree node that defined the value.
           if (!Value.second)
@@ -545,7 +556,7 @@ void LiveRangeCalc::updateSSA() {
             LR.addSegment(LiveInterval::Segment(Start, End, VNI));
           LOP = LiveOutPair(VNI, Node);
         }
-      } else if (IDomValue.first) {
+      } else if (IDomValue.first && IDomValue.first != &UndefVNI) {
         // No phi-def here. Remember incoming value.
         I.Value = IDomValue.first;
 
diff --git a/test/CodeGen/Hexagon/regalloc-liveout-undef.mir b/test/CodeGen/Hexagon/regalloc-liveout-undef.mir
new file mode 100644 (file)
index 0000000..6a41514
--- /dev/null
@@ -0,0 +1,35 @@
+# RUN: llc -march=hexagon -run-pass liveintervals -run-pass machineverifier -run-pass simple-register-coalescing %s -o - | FileCheck %s
+#
+# If there is no consumer of the live intervals, the live intervals pass
+# will be freed immediately after it runs, before the verifier. Add a
+# user (register coalescer in this case), so that the verification will
+# cover live intervals as well.
+#
+# Make sure that this compiles successfully.
+# CHECK: undef %1.isub_lo = A2_addi %1.isub_lo, 1
+
+---
+name: fred
+tracksRegLiveness: true
+
+registers:
+  - { id: 0, class: intregs }
+  - { id: 1, class: doubleregs }
+  - { id: 2, class: predregs }
+  - { id: 3, class: doubleregs }
+body: |
+  bb.0:
+    liveins: %d0
+    successors: %bb.1
+        %0 = IMPLICIT_DEF
+        %1 = COPY %d0
+
+  bb.1:
+    successors: %bb.1
+        %2 = C2_cmpgt %0, %1.isub_lo
+        %3 = COPY %1
+        %1 = COPY %3
+        undef %1.isub_lo = A2_addi %1.isub_lo, 1
+        J2_jump %bb.1, implicit-def %pc
+...
+