Commit 0fab169b by Prathamesh Kulkarni Committed by Prathamesh Kulkarni

Extend ipa-pure-const pass to propagate malloc attribute.

2017-10-27  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

	* cgraph.h (set_malloc_flag): Declare.
	* cgraph.c (set_malloc_flag_1): New function.
	(set_malloc_flag): Likewise.
	* ipa-fnsummary.h (ipa_call_summary): Add new field is_return_callee.
	* ipa-fnsummary.c (ipa_call_summary::reset): Set is_return_callee to
	false.
	(read_ipa_call_summary): Add support for reading is_return_callee.
	(write_ipa_call_summary): Stream is_return_callee.
	* ipa-inline.c (ipa_inline): Remove call to ipa_free_fn_summary.
	* ipa-pure-const.c: Add headers ssa.h, alloc-pool.h, symbol-summary.h,
	ipa-prop.h, ipa-fnsummary.h.
	(pure_const_names): Change to static.
	(malloc_state_e): Define.
	(malloc_state_names): Define.
	(funct_state_d): Add field malloc_state.
	(varying_state): Set malloc_state to STATE_MALLOC_BOTTOM.
	(check_retval_uses): New function.
	(malloc_candidate_p): Likewise.
	(analyze_function): Add support for malloc attribute.
	(pure_const_write_summary): Stream malloc_state.
	(pure_const_read_summary): Add support for reading malloc_state.
	(dump_malloc_lattice): New function.
	(propagate_malloc): New function.
	(warn_function_malloc): New function.
	(ipa_pure_const::execute): Call propagate_malloc and
	ipa_free_fn_summary.
	(pass_local_pure_const::execute): Add support for malloc attribute.
	* ssa-iterators.h (RETURN_FROM_IMM_USE_STMT): New macro.
	* doc/invoke.texi: Document Wsuggest-attribute=malloc.

testsuite/
	* gcc.dg/ipa/propmalloc-1.c: New test-case.
	* gcc.dg/ipa/propmalloc-2.c: Likewise.
	* gcc.dg/ipa/propmalloc-3.c: Likewise.

From-SVN: r254140
parent e89b556b
2017-10-27 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
* cgraph.h (set_malloc_flag): Declare.
* cgraph.c (set_malloc_flag_1): New function.
(set_malloc_flag): Likewise.
* ipa-fnsummary.h (ipa_call_summary): Add new field is_return_callee.
* ipa-fnsummary.c (ipa_call_summary::reset): Set is_return_callee to
false.
(read_ipa_call_summary): Add support for reading is_return_callee.
(write_ipa_call_summary): Stream is_return_callee.
* ipa-inline.c (ipa_inline): Remove call to ipa_free_fn_summary.
* ipa-pure-const.c: Add headers ssa.h, alloc-pool.h, symbol-summary.h,
ipa-prop.h, ipa-fnsummary.h.
(pure_const_names): Change to static.
(malloc_state_e): Define.
(malloc_state_names): Define.
(funct_state_d): Add field malloc_state.
(varying_state): Set malloc_state to STATE_MALLOC_BOTTOM.
(check_retval_uses): New function.
(malloc_candidate_p): Likewise.
(analyze_function): Add support for malloc attribute.
(pure_const_write_summary): Stream malloc_state.
(pure_const_read_summary): Add support for reading malloc_state.
(dump_malloc_lattice): New function.
(propagate_malloc): New function.
(warn_function_malloc): New function.
(ipa_pure_const::execute): Call propagate_malloc and
ipa_free_fn_summary.
(pass_local_pure_const::execute): Add support for malloc attribute.
* ssa-iterators.h (RETURN_FROM_IMM_USE_STMT): New macro.
* doc/invoke.texi: Document Wsuggest-attribute=malloc.
2017-10-27 Martin Liska <mliska@suse.cz>
PR gcov-profile/82457
......@@ -2530,6 +2530,53 @@ cgraph_node::set_nothrow_flag (bool nothrow)
return changed;
}
/* Worker to set malloc flag. */
static void
set_malloc_flag_1 (cgraph_node *node, bool malloc_p, bool *changed)
{
if (malloc_p && !DECL_IS_MALLOC (node->decl))
{
DECL_IS_MALLOC (node->decl) = true;
*changed = true;
}
ipa_ref *ref;
FOR_EACH_ALIAS (node, ref)
{
cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
if (!malloc_p || alias->get_availability () > AVAIL_INTERPOSABLE)
set_malloc_flag_1 (alias, malloc_p, changed);
}
for (cgraph_edge *e = node->callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p
&& (!malloc_p || e->caller->get_availability () > AVAIL_INTERPOSABLE))
set_malloc_flag_1 (e->caller, malloc_p, changed);
}
/* Set DECL_IS_MALLOC on NODE's decl and on NODE's aliases if any. */
bool
cgraph_node::set_malloc_flag (bool malloc_p)
{
bool changed = false;
if (!malloc_p || get_availability () > AVAIL_INTERPOSABLE)
set_malloc_flag_1 (this, malloc_p, &changed);
else
{
ipa_ref *ref;
FOR_EACH_ALIAS (this, ref)
{
cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
if (!malloc_p || alias->get_availability () > AVAIL_INTERPOSABLE)
set_malloc_flag_1 (alias, malloc_p, &changed);
}
}
return changed;
}
/* Worker to set_const_flag. */
static void
......
......@@ -1151,6 +1151,10 @@ public:
if any to NOTHROW. */
bool set_nothrow_flag (bool nothrow);
/* SET DECL_IS_MALLOC on cgraph_node's decl and on aliases of the node
if any. */
bool set_malloc_flag (bool malloc_p);
/* If SET_CONST is true, mark function, aliases and thunks to be ECF_CONST.
If SET_CONST if false, clear the flag.
......
......@@ -741,6 +741,10 @@ Wsuggest-attribute=noreturn
Common Var(warn_suggest_attribute_noreturn) Warning
Warn about functions which might be candidates for __attribute__((noreturn)).
Wsuggest-attribute=malloc
Common Var(warn_suggest_attribute_malloc) Warning
Warn about functions which might be candidates for __attribute__((malloc)).
Wsuggest-final-types
Common Var(warn_suggest_final_types) Warning
Warn about C++ polymorphic types where adding final keyword would improve code quality.
......
......@@ -315,7 +315,7 @@ Objective-C and Objective-C++ Dialects}.
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wstringop-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}malloc@r{]} @gol
-Wsuggest-final-types @gol -Wsuggest-final-methods -Wsuggest-override @gol
-Wmissing-format-attribute -Wsubobject-linkage @gol
-Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum @gol
......@@ -5204,7 +5204,7 @@ whether to issue a warning. Similarly to @option{-Wstringop-overflow=3} this
setting of the option may result in warnings for benign code.
@end table
@item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{]}
@item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]}
@opindex Wsuggest-attribute=
@opindex Wno-suggest-attribute=
Warn for cases where adding an attribute may be beneficial. The
......@@ -5214,21 +5214,25 @@ attributes currently supported are listed below.
@item -Wsuggest-attribute=pure
@itemx -Wsuggest-attribute=const
@itemx -Wsuggest-attribute=noreturn
@itemx -Wsuggest-attribute=malloc
@opindex Wsuggest-attribute=pure
@opindex Wno-suggest-attribute=pure
@opindex Wsuggest-attribute=const
@opindex Wno-suggest-attribute=const
@opindex Wsuggest-attribute=noreturn
@opindex Wno-suggest-attribute=noreturn
@opindex Wsuggest-attribute=malloc
@opindex Wno-suggest-attribute=malloc
Warn about functions that might be candidates for attributes
@code{pure}, @code{const} or @code{noreturn}. The compiler only warns for
functions visible in other compilation units or (in the case of @code{pure} and
@code{const}) if it cannot prove that the function returns normally. A function
returns normally if it doesn't contain an infinite loop or return abnormally
by throwing, calling @code{abort} or trapping. This analysis requires option
@option{-fipa-pure-const}, which is enabled by default at @option{-O} and
higher. Higher optimization levels improve the accuracy of the analysis.
@code{pure}, @code{const} or @code{noreturn} or @code{malloc}. The compiler
only warns for functions visible in other compilation units or (in the case of
@code{pure} and @code{const}) if it cannot prove that the function returns
normally. A function returns normally if it doesn't contain an infinite loop or
return abnormally by throwing, calling @code{abort} or trapping. This analysis
requires option @option{-fipa-pure-const}, which is enabled by default at
@option{-O} and higher. Higher optimization levels improve the accuracy
of the analysis.
@item -Wsuggest-attribute=format
@itemx -Wmissing-format-attribute
......@@ -542,6 +542,7 @@ void
ipa_call_summary::reset ()
{
call_stmt_size = call_stmt_time = 0;
is_return_callee_uncaptured = false;
if (predicate)
edge_predicate_pool.remove (predicate);
predicate = NULL;
......@@ -3204,6 +3205,10 @@ read_ipa_call_summary (struct lto_input_block *ib, struct cgraph_edge *e)
es->call_stmt_size = streamer_read_uhwi (ib);
es->call_stmt_time = streamer_read_uhwi (ib);
es->loop_depth = streamer_read_uhwi (ib);
bitpack_d bp = streamer_read_bitpack (ib);
es->is_return_callee_uncaptured = bp_unpack_value (&bp, 1);
p.stream_in (ib);
edge_set_predicate (e, &p);
length = streamer_read_uhwi (ib);
......@@ -3360,6 +3365,11 @@ write_ipa_call_summary (struct output_block *ob, struct cgraph_edge *e)
streamer_write_uhwi (ob, es->call_stmt_size);
streamer_write_uhwi (ob, es->call_stmt_time);
streamer_write_uhwi (ob, es->loop_depth);
bitpack_d bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, es->is_return_callee_uncaptured, 1);
streamer_write_bitpack (&bp);
if (es->predicate)
es->predicate->stream_out (ob);
else
......
......@@ -197,7 +197,9 @@ struct ipa_call_summary
int call_stmt_time;
/* Depth of loop nest, 0 means no nesting. */
unsigned int loop_depth;
/* Indicates whether the caller returns the value of it's callee. */
bool is_return_callee_uncaptured;
/* Keep all field empty so summary dumping works during its computation.
This is useful for debugging. */
ipa_call_summary ()
......
......@@ -2526,9 +2526,6 @@ ipa_inline (void)
if (dump_file)
ipa_dump_fn_summaries (dump_file);
/* In WPA we use inline summaries for partitioning process. */
if (!flag_wpa)
ipa_free_fn_summary ();
return remove_functions ? TODO_remove_functions : 0;
}
......
......@@ -93,6 +93,12 @@ struct imm_use_iterator
break; \
}
/* Similarly for return. */
#define RETURN_FROM_IMM_USE_STMT(ITER, VAL) \
{ \
end_imm_use_stmt_traverse (&(ITER)); \
return (VAL); \
}
/* Use this iterator in combination with FOR_EACH_IMM_USE_STMT to
get access to each occurrence of ssavar on the stmt returned by
......
2017-10-27 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
* gcc.dg/ipa/propmalloc-1.c: New test-case.
* gcc.dg/ipa/propmalloc-2.c: Likewise.
* gcc.dg/ipa/propmalloc-3.c: Likewise.
2017-10-27 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/71385
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
__attribute__((noinline, no_icf, used))
static void *f(__SIZE_TYPE__ n)
{
void *p = __builtin_malloc (n);
if (p == 0)
__builtin_abort ();
return p;
}
__attribute__((noinline, no_icf, used))
static void *bar(__SIZE_TYPE__ n)
{
void *p = f (n);
return p;
}
/* { dg-final { scan-ipa-dump "Function f found to be malloc" "pure-const" } } */
/* { dg-final { scan-ipa-dump "Function bar found to be malloc" "pure-const" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
__attribute__((noinline, used, no_icf))
static void *foo (__SIZE_TYPE__ n)
{
return __builtin_malloc (n * 10);
}
__attribute__((noinline, used, no_icf))
static void *bar(__SIZE_TYPE__ n, int cond)
{
void *p;
if (cond)
p = foo (n);
else
p = __builtin_malloc (n);
return p;
}
/* { dg-final { scan-ipa-dump "Function foo found to be malloc" "pure-const" } } */
/* { dg-final { scan-ipa-dump "Function bar found to be malloc" "pure-const" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-pure-const-details" } */
static void *foo(__SIZE_TYPE__, int) __attribute__((noinline, no_icf, used));
__attribute__((noinline, used, no_icf))
static void *bar(__SIZE_TYPE__ n, int m)
{
return foo (n, m);
}
static void *foo(__SIZE_TYPE__ n, int m)
{
void *p;
if (m > 0)
p = bar (n, --m);
else
p = __builtin_malloc (n);
return p;
}
/* { dg-final { scan-ipa-dump "Function foo found to be malloc" "pure-const" } } */
/* { dg-final { scan-ipa-dump "Function bar found to be malloc" "pure-const" } } */
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