[PATCH] D35475: [PATCH] [GVN] Ensure replacement instruction dominates its uses
Pedro Ferreira via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 17 08:02:11 PDT 2017
On 17/07/17 15:48, Daniel Berlin wrote:
>
>
> On Mon, Jul 17, 2017 at 2:04 AM, Pedro Ferreira via Phabricator
> <reviews at reviews.llvm.org <mailto:reviews at reviews.llvm.org>> wrote:
>
> PFerreira created this revision.
> Herald added a reviewer: dberlin.
>
> Related to bugzilla 33731
> https://bugs.llvm.org/show_bug.cgi?id=33731
> <https://bugs.llvm.org/show_bug.cgi?id=33731>
>
> This is caused by a a PRE insertion when the predecessor block
> hasn't yet been through Value Numbering (due to a back-edge).
>
>
> I'm not surprised this is buggy, sadly.
> I suspect there are a bunch of issues around this kind of thing.
>
> The PRE insertion adds a duplicate instruction at the end of the
> block, but the already-existing instruction is already used in the
> predecessor block, like so:
>
> L.LB1_346: ; preds = %L.LB1_423
>
> %7 = sext i32 %2 to i64
> %8 = mul i64 %7, 4
>
>
>
> - %.pre = sext i32 %1 to i64** ; inserted by
> GVN::performScalarPREInsertion
>
> When we then iterate over this block (later in the pass), GVN
> chooses to delete the first instance of the instruction as it is
> duplicated (instead of the later one which was created before).
>
> This sounds like an issue with findLeader/addToLeaderTable not
> checking local dominance if they are in the same block, based on the
> assumption that it will process the block in order.
I agree; there is a comment in "performScalarPREInsertion" stating
exactly that.
> addToLeaderTable always adds to the end, and so it will hit the PRE
> leader before any other.
>
> If so, the fastest fix i can think of is to number the instructions
> in the block starting at 0 as we process them. An instruction can only
> be a leader when BB = LeaderBB iff the number is < than the current
> instruction's number.
> Assign all PRE'd instructions numbers that are MAX_INT.
I'm not sure I understand - the instruction in particular has already
been numbered on a different block. That is, there are equivalent
instructions in other blocks which DO get numbered, so essentially CSE
will eventually move the instruction to a common dominator (or at least
it should).
That being said, the "%7 = sext i32 %2 to i64" already has a number. The
problem is that this particular instance has not been added to the
leader list and so PREInsertion adds one (since it assumes there isn't one).
>
> If you have two MAX_INT instructions, they are in-order already (since
> PRE will only add them in order).
>
>
>
>
> This is because "GVN::performScalarPREInsertion" will number the
> instruction as it is created (so it is in the leader-list).
>
>
> The attached patch moves the "%.pre" instruction up so that the
> replacement is valid.
>
> I am not sure this is a valid fix, but I couldn't figure out
> another solution.
>
> There are a couple other ways to fix this.
> Another would be "always check local dominance using
> OrderedInstruction in FindLeader ". This is equivalent to the above.
But wouldn't that require that the instruction exists in the leader list?
If I do check the dominance, wouldn't I have to scan the incoming block
anyway?
I do have another alternative; just before where I added the instruction
moving, we have:
Value *Repl = findLeader(I->getParent(), Num);
if (!Repl) {
// Failure, just remember this instance for future use.
addToLeaderTable(Num, I, I->getParent());
return false;
} else if (Repl == I) {
// If I was the result of a shortcut PRE, it might already be in the
table
// and the best replacement for itself. Nothing to do.
return false;
}
we could append to this if-else block:
else if (DT->dominates(I,R)) {
// Replace the existing leader since this one dominates it.
replaceOnLeaderTable(Num, Repl, I);
}
This way we'd preserve the existing instruction (instead of replacing it
with the "%.pre" one).
> I though about stoping "GVN::performScalarPREInsertion" from
> inserting the instruction by numbering the BasicBlock, but that
> might lead to infinite loops. I also tried to stop PREInsertion
> from running if the BasicBlock had not been numbered yet (by
> keeping a list of numbered blocks) but that wouldn't work since
> GVN only does one pass over the function (so this case would never
> be optimised out).
>
> The patch does fix the bug though, without adding regressions.
>
>
> https://reviews.llvm.org/D35475 <https://reviews.llvm.org/D35475>
>
> Files:
> lib/Transforms/Scalar/GVN.cpp
>
>
> Index: lib/Transforms/Scalar/GVN.cpp
> ===================================================================
> --- lib/Transforms/Scalar/GVN.cpp
> +++ lib/Transforms/Scalar/GVN.cpp
> @@ -1807,6 +1807,13 @@
> return false;
> }
>
> + // If this was a shortcut PRE, it will have been inserted at
> the end
> + // of the block; ensure that it dominates all uses of the original.
> + if (Instruction *R = dyn_cast<Instruction>(Repl)) {
> + if (DT->dominates(I, R)) {
> + R->moveBefore(I);
> + }
> + }
> // Remove it!
> patchAndReplaceAllUsesWith(I, Repl);
> if (MD && Repl->getType()->isPtrOrPtrVectorTy())
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170717/7d29c9c7/attachment.html>
More information about the llvm-commits
mailing list