[llvm-dev] RFC: Stop using redundant PHI node entries for multi-edge predecessors
Evgeny Astigeevich via llvm-dev
llvm-dev at lists.llvm.org
Tue May 2 05:36:42 PDT 2017
Hi,
I have got experience of low-level manipulations of Phi-nodes whilst I was implementing an aggressive jump threading optimization for switches.
Chandler's proposal will simplify code.
Cases I had:
1. A->B->C, A has multi-edges to B. A is redirected to C.
I had to write the code something like this:
int NumEdgesToB = changeteTerminatorTarget(A->getTerminator(), B, C);
for (phi: all Phi-nodes in C) {
V = get incoming value to C from B
for (int i = 0; i < NumEdgesToB; ++i) {
phi->addIncoming(V, A);
}
}
I also had to update phi-nodes in B like this:
for (int i = 0; i < NumEdgesToB; ++i) {
PhiInB-> removeIncomingValue (B, DontDeletePHIIfEmpty);
}
2. I needed to analyze all values incoming to B. As there can be multi-edges I had to write the code something like this:
SmallPtrSet<BasicBlock *, 8> SeenBlocks;
for (unsigned I = 0, E = CurPhi->getNumIncomingValues(); I != E; ++I) {
if (!SeenBlocks.insert(CurPhi->getIncomingBlock(I)).second) {
continue;
}
...
}
3. I copied A into A'. I needed correct phi-nodes in successors of A. I had to write code like this:
int VCount = 0;
for (unsigned Id = 0, IdE = Phi->getNumIncomingValues(); Id != IdE; ++Id) {
if (Phi->getIncomingBlock(Id) != OriginalBlock)
continue;
++VCount;
}
for (; VCount > 0; --VCount)
Phi->addIncoming(V, BlockCopy);
4. In order not to deal with duplicated incoming values I had to simplify a phi-nodes Def-Use graph by making some copy of it and removing redundant incoming values.
So in all places where we modify/access a phi-node we have to take into account redundant incoming values and preserve this feature.
> > So would this lead to a case where PHI->getNumOperands() !=
> > std::distance(pred_begin(phiblock), pred_end(phiblock))
I cannot imagine when this kind of code could be needed. When we work with phi-nodes we almost work with DFG they are part of. The code you provided is an attempt of mixing DFG and CFG. I don't this is good.
As Chandler wrote connections among phi-node values and edges are not expressed in any way.
> Also, IIUC, today deleting an edge from A to B only requires
> removeIncomingValue(A) on B's PHI nodes, but after this change you'll have
> to check if you're deleting the last edge or not.
All cases I've seen required to add/remove all multi-edges. It's interesting to see real-life cases when not all edges are changed.
Thanks,
Evgeny Astigeevich
> -----Original Message-----
> From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of
> Sanjoy Das via llvm-dev
> Sent: Monday, May 01, 2017 5:30 PM
> To: Daniel Berlin
> Cc: llvm-dev
> Subject: Re: [llvm-dev] RFC: Stop using redundant PHI node entries for multi-
> edge predecessors
>
> Hi,
>
> On Mon, May 1, 2017 at 8:47 AM, Daniel Berlin via llvm-dev <llvm-
> dev at lists.llvm.org> wrote:
> >> Today, the IR requires that if you have multiple edges from A to B
> >> (typically with a switch) any phi nodes in B must have an equal
> >> number of entries for A, but that all of them must have the same value.
> >
> >> This seems rather annoying....
> >> 1) It creates multiple uses of values in A for no apparently good
> >> reason
> >> 2) It makes updating PHI nodes using sets of predecessors incredibly
> >> hard
> >> 3) There is no correspondence between the edges and the PHI node
> >> entries other than number, making most of the code that does handle
> >> this very ad-hoc "count off N repetitions of the same thing" style
> >> code, which is brittle and hard to test effectively.
> >
> > Having written this code a few times, i'd agree.
> >
> >>
> >> 4) I suspect bugs are quite common given that
> >> PHINode::removeIncomingValue accepts a basic block but only removes
> >> the first incoming value, leaving the others in place.
> >
> >> I can't see any serious use case for this symmetry either. These
> >> aren't uses (and can't be), and there doesn't seem to be any lost
> >> functionality if we only have a single
> >> entry.http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> >>
> >> It also seems likely to open up more efficient in-memory
> >> representations if it is possible at some point to build maps of these
> things.
> >>
> >> Thoughts?
> >
> >
> >
> > So would this lead to a case where PHI->getNumOperands() !=
> > std::distance(pred_begin(phiblock), pred_end(phiblock))
> >
> > If so, that would seem problematic to handle as well.
> > :(
>
> Also, IIUC, today deleting an edge from A to B only requires
> removeIncomingValue(A) on B's PHI nodes, but after this change you'll have
> to check if you're deleting the last edge or not.
>
> Can (2), (3) and (4) be fixed by changing the API instead of the deeper IR
> change you're proposing?
>
> -- Sanjoy
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
More information about the llvm-dev
mailing list