[PATCH] D22966: GVN-hoist: compute MSSA once per function (PR28670)
Sebastian Pop via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 29 20:30:18 PDT 2016
I think I have a patch that works around the limitation of only one
MSSA per instruction:
instead of moving the instruction that we hoist, we clone it, such
that it can have its own separate MSSA annotation.
On Fri, Jul 29, 2016 at 10:23 PM, Daniel Berlin <dberlin at dberlin.org> wrote:
> Okay, so ...
>
> you have to create before you can remove.
>
> remove is going to destroy the memory, and not much we can do about that.
> (We could split remove into remove and erase, but ... ugly)
>
> If you create first, right now, it will do the wrong thing (the annotation
> will never end up on the instruction, unless the instruction is new)
> Please try the attached, which should make it stop doing the wrong thing
> there. If that works, i'll add unit tests and commit it.
>
> verifyMemorySSA will catch if you mess it up (verifyOrdering checks that the
> accesslist and the lookups have the same number of things).
>
>
> On Fri, Jul 29, 2016 at 7:36 PM, Daniel Berlin <dberlin at dberlin.org> wrote:
>>
>> So, I think remove from lookups should check and only remove from the
>> lookup if the lookups point to that access
>>
>>
>> On Fri, Jul 29, 2016, 7:23 PM Daniel Berlin <dberlin at dberlin.org> wrote:
>>>
>>> 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);
>>>>
>>>>
>
More information about the llvm-commits
mailing list