[PATCH] D35073: [RegisterCoalescer] Fix for subrange join unreachable

Tim Renouf via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 22 05:22:10 PDT 2018


tpr added a comment.

Krzysztof's fix for another occurrence of what looks like the same problem was as follows. This cropped up in the middle of https://reviews.llvm.org/D48102.

I don't know if this fixes all our occurrences of the problem, but it's worth checking.

  --- a/lib/CodeGen/RegisterCoalescer.cpp
  +++ b/lib/CodeGen/RegisterCoalescer.cpp
  @@ -2121,7 +2117,8 @@ class JoinVals {
     LaneBitmask computeWriteLanes(const MachineInstr *DefMI, bool &Redef) const;
   
     /// Find the ultimate value that VNI was copied from.
  -  std::pair<const VNInfo*,unsigned> followCopyChain(const VNInfo *VNI) const;
  +  std::pair<const VNInfo*,unsigned> followCopyChain(const VNInfo *VNI,
  +                                                    unsigned OtherReg) const;
   
     bool valuesIdentical(VNInfo *Val0, VNInfo *Val1, const JoinVals &Other) const;
   
  @@ -2240,18 +2237,18 @@ LaneBitmask JoinVals::computeWriteLanes(const MachineInstr *DefMI, bool &Redef)
   }
   
   std::pair<const VNInfo*, unsigned> JoinVals::followCopyChain(
  -    const VNInfo *VNI) const {
  -  unsigned Reg = this->Reg;
  +    const VNInfo *VNI, unsigned OtherReg) const {
  +  unsigned TrackReg = Reg;
   
     while (!VNI->isPHIDef()) {
       SlotIndex Def = VNI->def;
       MachineInstr *MI = Indexes->getInstructionFromIndex(Def);
       assert(MI && "No defining instruction");
       if (!MI->isFullCopy())
  -      return std::make_pair(VNI, Reg);
  +      return std::make_pair(VNI, TrackReg);
       unsigned SrcReg = MI->getOperand(1).getReg();
       if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
  -      return std::make_pair(VNI, Reg);
  +      return std::make_pair(VNI, TrackReg);
   
       const LiveInterval &LI = LIS->getInterval(SrcReg);
       const VNInfo *ValueIn;
  @@ -2272,25 +2269,41 @@ std::pair<const VNInfo*, unsigned> JoinVals::followCopyChain(
           break;
         }
       }
  -    if (ValueIn == nullptr)
  +    if (ValueIn == nullptr) {
  +      // Reaching undefined value is legitimate in cases where it comes from
  +      // one of the considered registers (Reg or OtherReg).
  +      //
  +      // 1   undef %0.sub1 = ...  ;; %0.sub0 == undef
  +      // 2   %1 = COPY %0         ;; %1 is defined here.
  +      // 3   %0 = COPY %1         ;; Now %0.sub0 has a definition!
  +      // 4   ...                  ;; Here we should indicate that %0 at 3 is
  +      //                          ;; the same as %0 at 2 (%0 at 3 == %1 at 2).
  +      if (SrcReg == Reg || SrcReg == OtherReg)
  +        return std::make_pair(nullptr, SrcReg);
         break;
  +    }
       VNI = ValueIn;
  -    Reg = SrcReg;
  +    TrackReg = SrcReg;
     }
  -  return std::make_pair(VNI, Reg);
  +  return std::make_pair(VNI, TrackReg);
   }
   
   bool JoinVals::valuesIdentical(VNInfo *Value0, VNInfo *Value1,
                                  const JoinVals &Other) const {
     const VNInfo *Orig0;
     unsigned Reg0;
  -  std::tie(Orig0, Reg0) = followCopyChain(Value0);
  +  std::tie(Orig0, Reg0) = followCopyChain(Value0, Other.Reg);
     if (Orig0 == Value1 && Reg0 == Other.Reg)
       return true;
   
     const VNInfo *Orig1;
     unsigned Reg1;
  -  std::tie(Orig1, Reg1) = Other.followCopyChain(Value1);
  +  std::tie(Orig1, Reg1) = Other.followCopyChain(Value1, Reg);
  +  // If both values are undefined, and the source registers are the same
  +  // register, the values are identical. Filter out cases where only one
  +  // value is defined.
  +  if (Orig0 == nullptr || Orig1 == nullptr)
  +    return Orig0 == Orig1 && Reg0 == Reg1;
   
     // The values are equal if they are defined at the same place and use the
     // same register. Note that we cannot compare VNInfos directly as some of


https://reviews.llvm.org/D35073





More information about the llvm-commits mailing list