[PATCH][instcombine] Remove preservesCFG from instcombine
Hal Finkel
hfinkel at anl.gov
Tue Nov 4 08:36:49 PST 2014
----- Original Message -----
> From: "Nick Lewycky" <nicholas at mxc.ca>
> To: "Mark Heffernan" <meheff at google.com>
> Cc: llvm-commits at cs.uiuc.edu
> Sent: Tuesday, November 4, 2014 2:28:20 AM
> Subject: Re: [PATCH][instcombine] Remove preservesCFG from instcombine
>
> Mark Heffernan wrote:
> > Hi Andrew,
> >
> > (Let me know if someone else is more appropriate to review this).
> > This
> > patch removes setPreservesCFG() from the instcombine pass.
>
> NAK. Please don't commit this.
Already happened (r221223) [but, via the wonders of version control...]
>
> The reason
> > is that InstCombine can modify terminator instructions (branches)
> > specifically the predicate.
>
> This is the thing where it removes an '%newcond = xor %cond, true'
> and
> switches 'br %newcond, label %A, label %B' with 'br %cond, label %B,
> label %A'?
>
> If it's actually causing you problems, please just move that
> transform
> to simplifycfg instead of removing preserves-cfg from instcombine.
It seems like the problem is more general than that:
>> The reason is that InstCombine can modify terminator instructions (branches) specifically the predicate. Instcombine clears out dead blocks and replaces all the dead instruction uses with undef:
>>
>> http://llvm.org/docs/doxygen/html/InstructionCombining_8cpp_source.html#l02792
>>
>> These new undefs can be predicates of branches, and from the comment of setPreservesCFG():
So perhaps any optimization that produces an undef, where that undef could possibly propagate to a branch condition, could under iteration cause this problem. And the code above there says:
// Do a quick scan over the function. If we find any blocks that are
// unreachable, remove any instructions inside of them. This prevents
// the instcombine code from having to deal with some bad special cases.
So this may actually be trickier to solve otherwise than it at-first appears.
-Hal
>
> Nick
>
> Instcombine clears out dead blocks and
> > replaces all the dead instruction uses with undef:
> >
> > http://llvm.org/docs/doxygen/html/InstructionCombining_8cpp_source.html#l02792
> >
> > These new undefs can be predicates of branches, and from the
> > comment
> > of setPreservesCFG():
> >
> > // setPreservesCFG - This function should be called to by the pass,
> > iff
> > they do
> > // not:
> > //
> > // 1. Add or remove basic blocks from the function
> > // 2. Modify terminator instructions in any way.
> >
> > Clearly instcombine is modifying terminator instructions so should
> > not
> > be calling setPreservesCFG(). The specific issue I ran into was a
> > dead
> > loop not being deleted because of stale analysis data. Repro:
> >
> > void foo(int *a, int start_x, int end_x, int start_y, int end_y,
> > int k) {
> > for (int y = start_y; y < end_y; y++) {
> > for (int x = start_x; x < end_x; x++) {
> > for (int i = 0; i < 1000; i++) {
> > a[x + y + k*i] = 0;
> > }
> > }
> > }
> > }
> >
> > # Dead loop left after loop deletion:
> > clang -S -emit-llvm foo.c -o - | opt -O1 -loop-rotate
> > -loop-unswitch
> > -instcombine -loop-deletion -S > bad.ll
> >
> > # Dead loop removed by splitting out loop-deletion into separate
> > opt
> > invocation:
> > clang -S -emit-llvm foo.c -o - | opt -O1 -loop-rotate
> > -loop-unswitch
> > -instcombine | opt -loop-deletion -S > good.ll
> >
> > This patch fixes this discrepancy.
> >
> > Mark
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
--
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory
More information about the llvm-commits
mailing list