On 11/22/2016 08:02 PM, Martin Sebor wrote:
Calls to bounded functions like snprintf with a zero-size buffer
are special requests to compute the size of output without actually
writing any.  For example:

  int n = snprintf(0, 0, "%08x", rand ());

is a request to compute the number of bytes that the function would
format if it were passed a buffer of non-zero size.  In the example
above since the return value is known to be exactly 8, not only can
the snprintf return value be folded into a constant but the whole
call to snprintf can be eliminated.

The attached patch enables this optimization under the
-fprintf-return-value option.  The patch depends on the one for bug
78461 (posted earlier today) during the testing of which I noticed
that this optimization was missing from the gimple-ssa-sprintf pass.

Thanks
Martin

gcc-78476.diff


PR tree-optimization/78476 - snprintf(0, 0, ...) with known arguments not 
optimized away

gcc/testsuite/ChangeLog:

        PR tree-optimization/78476
        * gcc.dg/tree-ssa/builtin-sprintf-5.c: New test.

gcc/ChangeLog:

        PR tree-optimization/78476
        * gimple-ssa-sprintf.c (struct pass_sprintf_length::call_info):
        Add a member.
        (handle_gimple_call): Adjust signature.
        (try_substitute_return_value): Remove calls to bounded functions
        with zero buffer size whose result is known.
        (pass_sprintf_length::execute): Adjust call to handle_gimple_call.
OK.

I was initially a little surprised you didn't just delete the call from the IL and emit the trivial constant assignment. Then I realized you probably would need to update the vuse/vdefs that were on the original call. Using update_call_from_tree seems to take care of that for you.

I didn't see a negative test -- ie one that you shouldn't transform. Could you extract the one from c#0 in the referenced bz and add it as a negative test. You can do that as a separate patch which you should consider pre-approved.

Jeff

Reply via email to