Commit 3eefa646 by Jakub Jelinek Committed by Jakub Jelinek

gimple-ssa-sprintf.c (try_substitute_return_value): Remove info.nowrite calls…

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
parent b34f29a1
2017-01-12 Jakub Jelinek <jakub@redhat.com> 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 PR bootstrap/79069
* cfgrtl.c (rtl_tidy_fallthru_edge): For any_uncondjump_p that can't * 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 be removed due to side-effects, don't remove following barrier nor
......
...@@ -128,7 +128,7 @@ public: ...@@ -128,7 +128,7 @@ public:
fold_return_value = param; fold_return_value = param;
} }
void handle_gimple_call (gimple_stmt_iterator*); bool handle_gimple_call (gimple_stmt_iterator *);
struct call_info; struct call_info;
bool compute_format_length (call_info &, format_result *); bool compute_format_length (call_info &, format_result *);
...@@ -2738,9 +2738,11 @@ get_destination_size (tree dest) ...@@ -2738,9 +2738,11 @@ get_destination_size (tree dest)
described by INFO, substitute the result for the return value of described by INFO, substitute the result for the return value of
the call. The result is suitable if the number of bytes it represents 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 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, try_substitute_return_value (gimple_stmt_iterator *gsi,
const pass_sprintf_length::call_info &info, const pass_sprintf_length::call_info &info,
const format_result &res) const format_result &res)
...@@ -2800,6 +2802,24 @@ try_substitute_return_value (gimple_stmt_iterator *gsi, ...@@ -2800,6 +2802,24 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
res.constant ? "constant" : "variable"); 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 else
{ {
unsigned HOST_WIDE_INT maxbytes; unsigned HOST_WIDE_INT maxbytes;
...@@ -2855,19 +2875,22 @@ try_substitute_return_value (gimple_stmt_iterator *gsi, ...@@ -2855,19 +2875,22 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
inbounds, (unsigned long)res.number_chars - 1, ign); inbounds, (unsigned long)res.number_chars - 1, ign);
} }
} }
return false;
} }
/* Determine if a GIMPLE CALL is to one of the sprintf-like built-in /* 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) pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
{ {
call_info info = call_info (); call_info info = call_info ();
info.callstmt = gsi_stmt (*gsi); info.callstmt = gsi_stmt (*gsi);
if (!gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL)) if (!gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL))
return; return false;
info.func = gimple_call_fndecl (info.callstmt); info.func = gimple_call_fndecl (info.callstmt);
info.fncode = DECL_FUNCTION_CODE (info.func); info.fncode = DECL_FUNCTION_CODE (info.func);
...@@ -2958,7 +2981,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) ...@@ -2958,7 +2981,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
break; break;
default: default:
return; return false;
} }
/* The first argument is a pointer to the destination. */ /* The first argument is a pointer to the destination. */
...@@ -3022,11 +3045,9 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) ...@@ -3022,11 +3045,9 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
} }
if (idx_objsize != HOST_WIDE_INT_M1U) if (idx_objsize != HOST_WIDE_INT_M1U)
{ if (tree size = gimple_call_arg (info.callstmt, idx_objsize))
if (tree size = gimple_call_arg (info.callstmt, idx_objsize)) if (tree_fits_uhwi_p (size))
if (tree_fits_uhwi_p (size)) objsize = tree_to_uhwi (size);
objsize = tree_to_uhwi (size);
}
if (info.bounded && !dstsize) if (info.bounded && !dstsize)
{ {
...@@ -3051,7 +3072,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) ...@@ -3051,7 +3072,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (info.callstmt); location_t loc = gimple_location (info.callstmt);
warning_at (EXPR_LOC_OR_LOC (dstptr, loc), warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
info.warnopt (), "null destination pointer"); info.warnopt (), "null destination pointer");
return; return false;
} }
/* Set the object size to the smaller of the two arguments /* 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) ...@@ -3080,12 +3101,12 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (info.callstmt); location_t loc = gimple_location (info.callstmt);
warning_at (EXPR_LOC_OR_LOC (info.format, loc), warning_at (EXPR_LOC_OR_LOC (info.format, loc),
info.warnopt (), "null format string"); info.warnopt (), "null format string");
return; return false;
} }
info.fmtstr = get_format_string (info.format, &info.fmtloc); info.fmtstr = get_format_string (info.format, &info.fmtloc);
if (!info.fmtstr) if (!info.fmtstr)
return; return false;
/* The result is the number of bytes output by the formatted function, /* The result is the number of bytes output by the formatted function,
including the terminating NUL. */ including the terminating NUL. */
...@@ -3101,7 +3122,8 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) ...@@ -3101,7 +3122,8 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
&& optimize > 0 && optimize > 0
&& flag_printf_return_value && flag_printf_return_value
&& (!flag_rounding_math || !res.floating)) && (!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. */ /* Execute the pass for function FUN. */
...@@ -3112,14 +3134,17 @@ pass_sprintf_length::execute (function *fun) ...@@ -3112,14 +3134,17 @@ pass_sprintf_length::execute (function *fun)
basic_block bb; basic_block bb;
FOR_EACH_BB_FN (bb, fun) FOR_EACH_BB_FN (bb, fun)
{ {
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); )
gsi_next (&si))
{ {
/* Iterate over statements, looking for function calls. */ /* Iterate over statements, looking for function calls. */
gimple *stmt = gsi_stmt (si); gimple *stmt = gsi_stmt (si);
if (is_gimple_call (stmt)) if (is_gimple_call (stmt) && handle_gimple_call (&si))
handle_gimple_call (&si); /* If handle_gimple_call returns true, the iterator is
already pointing to the next statement. */
continue;
gsi_next (&si);
} }
} }
......
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> 2017-01-12 Martin Sebor <msebor@redhat.com>
PR testsuite/79051 PR testsuite/79051
......
/* { 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");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment