gimple-ssa-sprintf.c (try_substitute_return_value): Remove info.nowrite calls with no lhs that can't throw.
* gimple-ssa-sprintf.c (try_substitute_return_value): Remove info.nowrite calls with no lhs that can't throw. Return bool whether gsi_remove has been called or not. (pass_sprintf_length::handle_gimple_call): Return bool whether try_substitute_return_value called gsi_remove. Formatting fix. (pass_sprintf_length::execute): Don't use gsi_remove if handle_gimple_call returned true. * gcc.dg/tree-ssa/builtin-snprintf-1.c: New test. From-SVN: r244384
This commit is contained in:
parent
b34f29a19d
commit
3eefa646f4
@ -1,5 +1,13 @@
|
||||
2017-01-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gimple-ssa-sprintf.c (try_substitute_return_value): Remove
|
||||
info.nowrite calls with no lhs that can't throw. Return bool
|
||||
whether gsi_remove has been called or not.
|
||||
(pass_sprintf_length::handle_gimple_call): Return bool whether
|
||||
try_substitute_return_value called gsi_remove. Formatting fix.
|
||||
(pass_sprintf_length::execute): Don't use gsi_remove if
|
||||
handle_gimple_call returned true.
|
||||
|
||||
PR bootstrap/79069
|
||||
* cfgrtl.c (rtl_tidy_fallthru_edge): For any_uncondjump_p that can't
|
||||
be removed due to side-effects, don't remove following barrier nor
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
fold_return_value = param;
|
||||
}
|
||||
|
||||
void handle_gimple_call (gimple_stmt_iterator*);
|
||||
bool handle_gimple_call (gimple_stmt_iterator *);
|
||||
|
||||
struct call_info;
|
||||
bool compute_format_length (call_info &, format_result *);
|
||||
@ -2738,9 +2738,11 @@ get_destination_size (tree dest)
|
||||
described by INFO, substitute the result for the return value of
|
||||
the call. The result is suitable if the number of bytes it represents
|
||||
is known and exact. A result that isn't suitable for substitution may
|
||||
have its range set to the range of return values, if that is known. */
|
||||
have its range set to the range of return values, if that is known.
|
||||
Return true if the call is removed and gsi_next should not be performed
|
||||
in the caller. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
try_substitute_return_value (gimple_stmt_iterator *gsi,
|
||||
const pass_sprintf_length::call_info &info,
|
||||
const format_result &res)
|
||||
@ -2800,6 +2802,24 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
|
||||
res.constant ? "constant" : "variable");
|
||||
}
|
||||
}
|
||||
else if (lhs == NULL_TREE
|
||||
&& info.nowrite
|
||||
&& !stmt_ends_bb_p (info.callstmt))
|
||||
{
|
||||
/* Remove the call to the bounded function with a zero size
|
||||
(e.g., snprintf(0, 0, "%i", 123)) if there is no lhs. */
|
||||
unlink_stmt_vdef (info.callstmt);
|
||||
gsi_remove (gsi, true);
|
||||
if (dump_file)
|
||||
{
|
||||
location_t callloc = gimple_location (info.callstmt);
|
||||
fprintf (dump_file, "On line %i removing ",
|
||||
LOCATION_LINE (callloc));
|
||||
print_generic_expr (dump_file, info.func, dump_flags);
|
||||
fprintf (dump_file, " call.\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned HOST_WIDE_INT maxbytes;
|
||||
@ -2855,19 +2875,22 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
|
||||
inbounds, (unsigned long)res.number_chars - 1, ign);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Determine if a GIMPLE CALL is to one of the sprintf-like built-in
|
||||
functions and if so, handle it. */
|
||||
functions and if so, handle it. Return true if the call is removed
|
||||
and gsi_next should not be performed in the caller. */
|
||||
|
||||
void
|
||||
bool
|
||||
pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
{
|
||||
call_info info = call_info ();
|
||||
|
||||
info.callstmt = gsi_stmt (*gsi);
|
||||
if (!gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL))
|
||||
return;
|
||||
return false;
|
||||
|
||||
info.func = gimple_call_fndecl (info.callstmt);
|
||||
info.fncode = DECL_FUNCTION_CODE (info.func);
|
||||
@ -2958,7 +2981,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The first argument is a pointer to the destination. */
|
||||
@ -3022,11 +3045,9 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
}
|
||||
|
||||
if (idx_objsize != HOST_WIDE_INT_M1U)
|
||||
{
|
||||
if (tree size = gimple_call_arg (info.callstmt, idx_objsize))
|
||||
if (tree_fits_uhwi_p (size))
|
||||
objsize = tree_to_uhwi (size);
|
||||
}
|
||||
if (tree size = gimple_call_arg (info.callstmt, idx_objsize))
|
||||
if (tree_fits_uhwi_p (size))
|
||||
objsize = tree_to_uhwi (size);
|
||||
|
||||
if (info.bounded && !dstsize)
|
||||
{
|
||||
@ -3051,7 +3072,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
location_t loc = gimple_location (info.callstmt);
|
||||
warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
|
||||
info.warnopt (), "null destination pointer");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the object size to the smaller of the two arguments
|
||||
@ -3080,12 +3101,12 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
location_t loc = gimple_location (info.callstmt);
|
||||
warning_at (EXPR_LOC_OR_LOC (info.format, loc),
|
||||
info.warnopt (), "null format string");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
info.fmtstr = get_format_string (info.format, &info.fmtloc);
|
||||
if (!info.fmtstr)
|
||||
return;
|
||||
return false;
|
||||
|
||||
/* The result is the number of bytes output by the formatted function,
|
||||
including the terminating NUL. */
|
||||
@ -3101,7 +3122,8 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
|
||||
&& optimize > 0
|
||||
&& flag_printf_return_value
|
||||
&& (!flag_rounding_math || !res.floating))
|
||||
try_substitute_return_value (gsi, info, res);
|
||||
return try_substitute_return_value (gsi, info, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Execute the pass for function FUN. */
|
||||
@ -3112,14 +3134,17 @@ pass_sprintf_length::execute (function *fun)
|
||||
basic_block bb;
|
||||
FOR_EACH_BB_FN (bb, fun)
|
||||
{
|
||||
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
|
||||
gsi_next (&si))
|
||||
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); )
|
||||
{
|
||||
/* Iterate over statements, looking for function calls. */
|
||||
gimple *stmt = gsi_stmt (si);
|
||||
|
||||
if (is_gimple_call (stmt))
|
||||
handle_gimple_call (&si);
|
||||
if (is_gimple_call (stmt) && handle_gimple_call (&si))
|
||||
/* If handle_gimple_call returns true, the iterator is
|
||||
already pointing to the next statement. */
|
||||
continue;
|
||||
|
||||
gsi_next (&si);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2017-01-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.dg/tree-ssa/builtin-snprintf-1.c: New test.
|
||||
|
||||
2017-01-12 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR testsuite/79051
|
||||
|
16
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-1.c
Normal file
16
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-1.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fprintf-return-value -fdump-tree-optimized" } */
|
||||
/* { dg-final { scan-tree-dump-not "__builtin_snprintf" "optimized"} } */
|
||||
|
||||
int
|
||||
foo (void)
|
||||
{
|
||||
int a = __builtin_snprintf (0, 0, "%s", "abcdefgh");
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
__builtin_snprintf (0, 0, "%s", "abcdefgh");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user