diff options
Diffstat (limited to 'llvm/lib/CodeGen/RegisterCoalescer.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/RegisterCoalescer.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp index 2c1bc6df37e..9a689e9a17c 100644 --- a/llvm/lib/CodeGen/RegisterCoalescer.cpp +++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -2508,8 +2508,10 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) { // We normally expect IMPLICIT_DEF values to be live only until the end // of their block. If the value is really live longer and gets pruned in // another block, this flag is cleared again. + // + // Clearing the valid lanes is deferred until it is sure this can be + // erased. V.ErasableImplicitDef = true; - V.ValidLanes &= ~V.WriteLanes; } } } @@ -2564,20 +2566,25 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) { Other.computeAssignment(V.OtherVNI->id, *this); Val &OtherV = Other.Vals[V.OtherVNI->id]; - // Check if OtherV is an IMPLICIT_DEF that extends beyond its basic block. - // This shouldn't normally happen, but ProcessImplicitDefs can leave such - // IMPLICIT_DEF instructions behind, and there is nothing wrong with it - // technically. - // - // When it happens, treat that IMPLICIT_DEF as a normal value, and don't try - // to erase the IMPLICIT_DEF instruction. - if (OtherV.ErasableImplicitDef && DefMI && - DefMI->getParent() != Indexes->getMBBFromIndex(V.OtherVNI->def)) { - LLVM_DEBUG(dbgs() << "IMPLICIT_DEF defined at " << V.OtherVNI->def - << " extends into " - << printMBBReference(*DefMI->getParent()) - << ", keeping it.\n"); - OtherV.ErasableImplicitDef = false; + if (OtherV.ErasableImplicitDef) { + // Check if OtherV is an IMPLICIT_DEF that extends beyond its basic block. + // This shouldn't normally happen, but ProcessImplicitDefs can leave such + // IMPLICIT_DEF instructions behind, and there is nothing wrong with it + // technically. + // + // When it happens, treat that IMPLICIT_DEF as a normal value, and don't try + // to erase the IMPLICIT_DEF instruction. + if (DefMI && + DefMI->getParent() != Indexes->getMBBFromIndex(V.OtherVNI->def)) { + LLVM_DEBUG(dbgs() << "IMPLICIT_DEF defined at " << V.OtherVNI->def + << " extends into " + << printMBBReference(*DefMI->getParent()) + << ", keeping it.\n"); + OtherV.ErasableImplicitDef = false; + } else { + // We deferred clearing these lanes in case we needed to save them + OtherV.ValidLanes &= ~OtherV.WriteLanes; + } } // Allow overlapping PHI values. Any real interference would show up in a @@ -2701,8 +2708,18 @@ void JoinVals::computeAssignment(unsigned ValNo, JoinVals &Other) { Val &OtherV = Other.Vals[V.OtherVNI->id]; // We cannot erase an IMPLICIT_DEF if we don't have valid values for all // its lanes. - if ((OtherV.WriteLanes & ~V.ValidLanes).any() && TrackSubRegLiveness) + if (OtherV.ErasableImplicitDef && + TrackSubRegLiveness && + (OtherV.WriteLanes & ~V.ValidLanes).any()) { + LLVM_DEBUG(dbgs() << "Cannot erase implicit_def with missing values\n"); + OtherV.ErasableImplicitDef = false; + // The valid lanes written by the implicit_def were speculatively cleared + // before, so make this more conservative. It may be better to track this, + // I haven't found a testcase where it matters. + OtherV.ValidLanes = LaneBitmask::getAll(); + } + OtherV.Pruned = true; LLVM_FALLTHROUGH; } |

