[llvm-bugs] [Bug 40992] New: JumpThreading pass causes wrong optimization results in combination with indirect branches (indirectbr)

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Mar 7 07:05:59 PST 2019


https://bugs.llvm.org/show_bug.cgi?id=40992

            Bug ID: 40992
           Summary: JumpThreading pass causes wrong optimization results
                    in combination with indirect branches (indirectbr)
           Product: new-bugs
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: matthias.liedtke at sap.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

Created attachment 21574
  --> https://bugs.llvm.org/attachment.cgi?id=21574&action=edit
Testcase

Hi,

it seems that I have encountered a bug in the JumpThreading pass that is caused
by the fact that predecessors which terminate with an indirect branch
instruction are skipped in the pass.

I added the corresponding testcase as an attachment.

This is how the testcase works:

There is a condition "%cond" that is evaluated in the beginning. The
interesting path is the one where this condition is true.
In the true case we jump to "condTrue" where we have a select to select between
two different targets. The first target "indirectA" isn't the interesting one
but it seems to be necessary to cause the failure. The second target
"indirectB" jumps to the same block that would also be reachable if "%cond" was
false in the beginning which is labeled "condFalse".
In condFalse we have a branch on "%cond".
What happens here: The JumpThreading sees the branch and checks the
predecessors and finds out that there is one predecessor where we know that
"%cond" is false (the one if coming from basicblock "start"). The other one has
an indirect branch instruction and is skipped because of the indirect branch.
The JumpThreading thinks "Great, only one predecessor to take care of and that
one knows that %cond is false, so I can remove the block condFalse and set all
predecessors to condStillFalse."
It just doesn't notice the indirect branch that then will point to
"condStillFalse" instead of the expected result "condFalse" or "condStillTrue"
if optimization would work correctly.

I have encountered this issue on LLVM5.0 but it also exists in the current
master branch on github.

I was able to apply a fix for the problem:
In the JumpThreading there is the following coding:
    // If the predecessor ends with an indirect goto, we can't change its
    // destination. Same for CallBr.
    if (isa<IndirectBrInst>(Pred->getTerminator()) ||
        isa<CallBrInst>(Pred->getTerminator()))
      continue;

If the "continue;" is replaced by a "return false;" the problem is gone because
we completely skip the JumpThreading optimization as soon as one of the
predecessors finishes with an indirect branch instruction. (The CallBrInst has
been added recently for asm-goto support and I don't know if it has the same
issue but I'd expect so.)
Obviously this will prevent optimizations that beforehand had been possible and
might have been correct.
This fix will break the test callbr-edge-split.ll which has been added
recently. I am not sure if this failure is caused by a missed optimization.

If you agree on the issue and agree with the fix, I can contribute it.
Otherwise I'd be interested in details how this issue could be fixed in a way
that doesn't completely stop the JumpThreading optimization when indirect
branches are involved.

Thanks in advance and best regards,
Matthias

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190307/8f5e639f/attachment.html>


More information about the llvm-bugs mailing list