[llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner.

Eli Friedman eli.friedman at gmail.com
Wed Aug 10 13:59:51 PDT 2011


On Wed, Aug 10, 2011 at 6:07 AM, Pranav Bhandarkar
<pranavb at codeaurora.org> wrote:
> Hi,
>
> Subsequent to a discussion on the 'nsw' flag on llvm dev
> (http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-June/040856.html), I have
> written a small function that allows the instruction combiner to preserve
> the 'nsw' flag under certain conditions. Preserving this flag allows
> optimization passes down the pipeline to be more aggressive.
>
> For instance, consider this synthetic test case.
> int foo (int x)
> {     int j = x + 2;
>      int y = j + 3;
>
>      if (j < y) return 1;
>      else return 0;
> }
> This can be reduced to always return 1. However LLVM does not do this
> transformation. Consider the following piece of code
>
> 1 %add = add nsw i32 %tmp, 2
> 2 %add3 = add nsw i32 %add, 3
> 3 %cmp = icmp slt i32 %add, %add3
> 4 br i1 %cmp, label %if.then, label %if.else
>
> Here add = tmp + 2 and add3 is effectively tmp + 5 and the comparison "slt
> %add, %add3" is always true. However, the instruction combiner combines
> instructions 1 and 2 to produce
>
> 2 %add3 = add i32 %tmp, 5
>
> Note the 'nsw' flag is dropped because the combiner does not reason about
> the applicability of the 'nsw' flag in the new combined instruction. If now
> the simplifycfg pass is run it does not simplify the comparison because one
> of its operands has the 'nsw' flag while the other does not. The attached
> patch checks the resulting constant in the new instruction for overflow. If
> not, it keeps the flag. This allows the "simplifycfg" pass to simplify the
> comparison and reduces the above function to return 1.
>
> I have three attachments - The patch, a testcase that should be added to
> test/Transforms/InstCombine and my regression report. This patch was
> successfully regression tested on x86_64.

A couple notes on the patch:

1. When submitting a patch, please include the test in the patch itself.
2. Using APInt::sadd_ov and APInt::ssub_ov might simplify the logic here a bit.

-Eli




More information about the llvm-commits mailing list