[RegisterCoalescer] Fixed inconsistent followCopyChain with subreg
authorTim Renouf <tpr.llvm@botech.co.uk>
Thu, 26 Jul 2018 21:27:34 +0000 (21:27 +0000)
committerTim Renouf <tpr.llvm@botech.co.uk>
Thu, 26 Jul 2018 21:27:34 +0000 (21:27 +0000)
Summary:
The behavior of followCopyChain with a subreg depends on the order in
which subranges appear in a live interval, which is bad.

This commit fixes that, and allows the copy chain to continue only if
all matching subranges that are not undefined take us to the same def.

I don't have a test for this; the reproducer I had on my branch with
various other local changes does not reproduce the problem on upstream
llvm. Also that reproducer was an ll test; attempting to convert it to a
mir test made the subranges appear in a different order and hid the
problem.

However I would argue that the old behavior was obviously wrong
and needs fixing.

Subscribers: MatzeB, qcolombet, llvm-commits

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

Change-Id: Iee7936ef305918f3b498ac432e2cf651ae5cc2df
llvm-svn: 338070

llvm/lib/CodeGen/RegisterCoalescer.cpp

index 5c5f8dc..cad13a6 100644 (file)
@@ -2280,7 +2280,8 @@ std::pair<const VNInfo*, unsigned> JoinVals::followCopyChain(
       LiveQueryResult LRQ = LI.Query(Def);
       ValueIn = LRQ.valueIn();
     } else {
-      // Query subranges. Pick the first matching one.
+      // Query subranges. Ensure that all matching ones take us to the same def
+      // (allowing some of them to be undef).
       ValueIn = nullptr;
       for (const LiveInterval::SubRange &S : LI.subranges()) {
         // Transform lanemask to a mask in the joined live interval.
@@ -2288,8 +2289,12 @@ std::pair<const VNInfo*, unsigned> JoinVals::followCopyChain(
         if ((SMask & LaneMask).none())
           continue;
         LiveQueryResult LRQ = S.Query(Def);
-        ValueIn = LRQ.valueIn();
-        break;
+        if (!ValueIn) {
+          ValueIn = LRQ.valueIn();
+          continue;
+        }
+        if (LRQ.valueIn() && ValueIn != LRQ.valueIn())
+          return std::make_pair(VNI, TrackReg);
       }
     }
     if (ValueIn == nullptr) {