[PATCH] D22966: GVN-hoist: compute MSSA once per function (PR28670)

Daniel Berlin via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 19:23:30 PDT 2016


I have to stare at this.

On Fri, Jul 29, 2016, 7:10 PM Sebastian Pop <sebpop at gmail.com> wrote:

> sebpop updated this revision to Diff 66212.
> sebpop added a comment.
>
> Updated the patch as I first wrote it: I think this is the natural way to
> update an SSA variable.
>
> This fails because when invoking:
> +          MSSA->removeMemoryAccess(OldMemAcc);
>
> we go from:
> ; MemoryUse(2)
>
>   %2 = load i32, i32* %v.addr, align 4
>
> to no annotation at all:
>
>   %2 = load i32, i32* %v.addr, align 4
>
> This is because removeMemoryAccess calls removeFromLookups which does:
>
>   Value *MemoryInst;
>   if (MemoryUseOrDef *MUD = dyn_cast<MemoryUseOrDef>(MA)) {
>     MemoryInst = MUD->getMemoryInst();
>   } else {
>     MemoryInst = MA->getBlock();
>   }
>   ValueToMemoryAccess.erase(MemoryInst);
>
> and erase() removes both the new and old MemoryAccess'es leaving the
> instruction without MSSA annotation.
>

Yes, only one memory access can exist for an instruction for real.  You
can't create two at once and get the right result.


> For loads this can be fixed by first removing the OldMemoryAccess and then
> creating the NewMemoryAccess.
> This works for loads because there are no users of a MemoryUse.
> However for a store, we need to keep both the old and new MemoryAccess'es
> at the same time, to be able to rename the uses of old with new.
>

Yes, most of the hoisters are cloning, so do not have this issue.


> I think the solution would be for "MSSA->removeMemoryAccess(OldMemAcc);"
> to only invalidate and remove "OldMemAcc" without touching "NewMemAcc" that
> should remain attached to the instruction.
>

We can't make it work with two memoryacceses for the same instruction at
once.

We can probably implement either a createReplacement (that takes over the
uses of the old one) or a moveBefore/moveAfter.

>
>
> https://reviews.llvm.org/D22966
>
> Files:
>   lib/Transforms/Scalar/GVNHoist.cpp
>
> Index: lib/Transforms/Scalar/GVNHoist.cpp
> ===================================================================
> --- lib/Transforms/Scalar/GVNHoist.cpp
> +++ lib/Transforms/Scalar/GVNHoist.cpp
> @@ -193,30 +193,27 @@
>      VN.setAliasAnalysis(AA);
>      VN.setMemDep(MD);
>      bool Res = false;
> +    MemorySSA M(F, AA, DT);
> +    MSSA = &M;
>
>      // FIXME: use lazy evaluation of VN to avoid the fix-point
> computation.
>      while (1) {
> -      // FIXME: only compute MemorySSA once. We need to update the
> analysis in
> -      // the same time as transforming the code.
> -      MemorySSA M(F, AA, DT);
> -      MSSA = &M;
> -
>        // Perform DFS Numbering of instructions.
>        unsigned I = 0;
>        for (const BasicBlock *BB : depth_first(&F.getEntryBlock()))
>          for (auto &Inst: *BB)
>            DFSNumber.insert({&Inst, ++I});
>
>        auto HoistStat = hoistExpressions(F);
> -      if (HoistStat.first + HoistStat.second == 0) {
> +      if (HoistStat.first + HoistStat.second == 0)
>          return Res;
> -      }
> -      if (HoistStat.second > 0) {
> +
> +      if (HoistStat.second > 0)
>          // To address a limitation of the current GVN, we need to rerun
> the
> -        // hoisting after we hoisted loads in order to be able to hoist
> all
> -        // scalars dependent on the hoisted loads. Same for stores.
> +        // hoisting after we hoisted loads or stores in order to be able
> to
> +        // hoist all scalars dependent on the hoisted ld/st.
>          VN.clear();
> -      }
> +
>        Res = true;
>
>        // DFS numbers change when instructions are hoisted: clear and
> recompute.
> @@ -725,6 +722,8 @@
>            if (!Repl || firstInBB(I, Repl))
>              Repl = I;
>
> +      MemoryAccess *NewMemAcc = nullptr;
> +
>        if (Repl) {
>          // Repl is already in HoistPt: it remains in place.
>          assert(allOperandsAvailable(Repl, HoistPt) &&
> @@ -742,7 +741,23 @@
>              !makeGepOperandsAvailable(Repl, HoistPt, InstructionsToHoist))
>            continue;
>
> +        // Before moving the instruction, get its MSSA access.
> +        MemoryUseOrDef *OldMemAcc = nullptr;
> +        if (MemoryAccess *MA = MSSA->getMemoryAccess(Repl))
> +          OldMemAcc = dyn_cast<MemoryUseOrDef>(MA);
> +
> +        // Move the instruction at the end of HoistPt.
>          Repl->moveBefore(HoistPt->getTerminator());
> +
> +        if (OldMemAcc) {
> +          // The definition of this ld/st will not change: ld/st hoisting
> is
> +          // legal when the ld/st is not moved past its current
> definition.
> +          MemoryAccess *Def = OldMemAcc->getDefiningAccess();
> +          NewMemAcc = MSSA->createMemoryAccessInBB(Repl, Def, HoistPt,
> +                                                   MemorySSA::End);
> +          OldMemAcc->replaceAllUsesWith(NewMemAcc);
> +          MSSA->removeMemoryAccess(OldMemAcc);
> +        }
>        }
>
>        if (isa<LoadInst>(Repl))
> @@ -775,6 +790,14 @@
>            } else if (isa<CallInst>(Repl)) {
>              ++NumCallsRemoved;
>            }
> +
> +          if (NewMemAcc) {
> +            // Update the uses of the old MSSA access with NewMemAcc.
> +            MemoryAccess *OldMA = MSSA->getMemoryAccess(I);
> +            OldMA->replaceAllUsesWith(NewMemAcc);
> +            MSSA->removeMemoryAccess(OldMA);
> +          }
> +
>            Repl->intersectOptionalDataWith(I);
>            combineKnownMetadata(Repl, I);
>            I->replaceAllUsesWith(Repl);
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160730/504ddcf9/attachment.html>


More information about the llvm-commits mailing list