[llvm] r183174 - Fix a defect in code-layout pass, improving Benchmarks/Olden/em3d/em3d by about 30%
Shuxin Yang
shuxin.llvm at gmail.com
Tue Jun 4 10:17:37 PDT 2013
>Also, you *must* provide test cases for this kind of change. It is far
too subtle otherwise, and will just break in the future.
I wish I could, but it is really difficult to fabricate one.
>
> rdar://13966341
>
> Modified:
> llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp
>
> Modified: llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp?rev=183174&r1=183173&r2=183174&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp (original)
> +++ llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp Mon Jun 3
> 20:00:57 2013
> @@ -991,6 +991,28 @@ void MachineBlockPlacement::buildCFGChai
> Cond.clear();
> MachineBasicBlock *TBB = 0, *FBB = 0; // For AnalyzeBranch.
> if (!TII->AnalyzeBranch(*PrevBB, TBB, FBB, Cond)) {
> + // The "PrevBB" is not yet updated to reflect current code
> layout, so,
> + // o. it may fall-through to a block without explict
> "goto" instruction
> + // before layout, and no longer fall-through it after
> layout; or
> + // o. just opposite.
>
>
> Yes, and my memory of AnalyzeBranch from when I wrote this code is
> that it explicitly had logic (at least for x86) to handle these cases.
> We need it to handle them because updateTerminator (the routine which
> fixes the terminator to not have the broken properties you observe in
> PrevBB) can only be called when the branch is analyzable. See the
> FIXME comment just a few lines up.
The problem is we cannot blindly call updateTerminator(); it will
complains if the branch is not analyzable.
> + //
> + // AnalyzeBranch() may return erroneous value for FBB when
> these two
> + // situations take place. For the first scenario FBB is
> mistakenly set
> + // NULL; for the 2nd scenario, the FBB, which is expected
> to be NULL,
> + // is mistakenly pointing to "*BI".
>
>
> This is either a bug in AnalyzeBranch, or a bug in us calling
> AnalyzeBranch. I suspect it is a bug in one target's implementation of
> AnalyzeBranch, but the API and behavior for that routine is so
> *incredibly* convoluted and poorly specified that I could believe
> either one. However, the fix should not be here! Instead we should fix
> updateTerminator and AnalyzeBranch to work in a more sane way.
This is the bug in the placement pass -- AnalyzeBranch() is fed with
stale parameter.
That is why the change is at code layout side.
You may argue AnalyzeBranch() should return non-NULL two branch target
no matter if it has
explicit "goto" instruction or not. I think it is better interface,
however, I don't feel like to
change AnalyzeBranch() this way, as we need to update all its callers.
>
> Let me see if I understand the problem correctly:
>
> + //
> + bool needUpdateBr = true;
> + if (!Cond.empty() && (!FBB || FBB == *BI)) {
> + PrevBB->updateTerminator();
>
>
> OK, so the goal is that:
>
> 1) If the branch is analyzable, but
> 2) We get garbage back from the analysis, then
> 3) We update the terminators, and
> 4) Re-analyze the branch in order to actually make the terminator
> reversal decision correctly, and then
> 5) Re-update the terminator?
>
Yes. It can be simplified into following if we can blindly call
updateTerminator() without triggering assertion.
1) updateTerminator() blindly
2) analyzeBranch().
> If I've understood the problem correctly, then I think there are two
> possible correct solutions, but both look somewhat different from this:
>
> A) We could solve in essentially the same way you have here, but more
> cleanly. This would be done by teaching updateTerminator to work even
> in the cases where AnalyzeBranch actually fails, so that rather than
> asserting, it simply bails out. With this change, we could write much
> simpler code:
>
> PrevBB->updateTerminator();
>
> if (TII->AnalyzeBranch(...)) {
> if (/* existing code to check for a profitable reversal case */) {
> // reverse the branch and condition
> PrevBB->updateTerminator(); // because we monkeyed with it
> }
> }
>
> Does that make sense? It seems much more clear than the current code
> sequence.
That was exactly my 1st fix, and later on I realize updateTerminator()
cannot be blindly called because
assertion will be triggered if the branch is not analyzable. I don't
want to remove the assertion as it make sense
to me.
My current fix is slightly different from this one. It just let
updateTerminator() guarded by AnalyzeBranch(),
I add extra few lines of code to make it efficient --- AnalyzeBranch()
and updateTerminator() dosen't seem to be
very expensive; one cycle saved, one cycle earned.
if (TII->AnalyzeBranch(PrevBB) {
PrevBB->updateTerminator().
TII->AnalyzeBranch(PrevBB); // analyze one more time.
...
reverse etc ...
...
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130604/4e8bd8e8/attachment.html>
More information about the llvm-commits
mailing list