This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][4.5] Fix PR47278
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jan Hubicka <jh at suse dot de>
- Date: Wed, 2 Mar 2011 17:04:39 +0100 (CET)
- Subject: [PATCH][4.5] Fix PR47278
This fixes PR47278 by backporting some of the cgraph changes from trunk.
In particular this replaces DECL_REPLACEABLE_P with a stripped down
(non-LTO aware) version of the trunk replacement.
Bootstrap and regtest running on x86_64-unknown-linux-gnu (a 4.3 version
bootstrapped and tested ok).
Looks ok?
Thanks,
Richard.
2011-03-02 Richard Guenther <rguenther@suse.de>
PR tree-optimization/47278
* tree.h (DECL_REPLACEABLE_P): Remove.
(decl_replaceable_p): Declare.
(decl_binds_to_current_def_p): Likewise.
* varasm.c (decl_replaceable_p): New function.
(decl_binds_to_current_def_p): Likewise.
* cgraph.c (cgraph_function_body_availability): Use decl_replaceable_p.
* tree-inline.c (inlinable_function_p): Likewise.
cp/
* decl.c (finish_function): Use decl_replaceable_p.
testsuite/
* gcc.dg/torture/pr47278-1.c: New testcase.
* gcc.dg/torture/pr47278-2.c: Likewise.
Index: gcc/testsuite/gcc.dg/torture/pr47278-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr47278-1.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr47278-1.c (revision 0)
***************
*** 0 ****
--- 1,4 ----
+ /* { dg-do run } */
+ /* { dg-additional-sources "pr47278-2.c" } */
+
+ int foo (void) { return 1; }
Index: gcc/testsuite/gcc.dg/torture/pr47278-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr47278-2.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr47278-2.c (revision 0)
***************
*** 0 ****
--- 1,13 ----
+ extern void abort (void);
+
+ int __attribute__((weak,visibility("hidden"))) foo (void)
+ {
+ return 0;
+ }
+
+ int main()
+ {
+ if (foo() != 1)
+ abort ();
+ return 0;
+ }
Index: gcc/cgraph.c
===================================================================
*** gcc/cgraph.c (revision 170616)
--- gcc/cgraph.c (working copy)
*************** cgraph_function_body_availability (struc
*** 2093,2099 ****
AVAIL_AVAILABLE here? That would be good reason to preserve this
bit. */
! else if (DECL_REPLACEABLE_P (node->decl) && !DECL_EXTERNAL (node->decl))
avail = AVAIL_OVERWRITABLE;
else avail = AVAIL_AVAILABLE;
--- 2093,2099 ----
AVAIL_AVAILABLE here? That would be good reason to preserve this
bit. */
! else if (decl_replaceable_p (node->decl) && !DECL_EXTERNAL (node->decl))
avail = AVAIL_OVERWRITABLE;
else avail = AVAIL_AVAILABLE;
Index: gcc/tree.h
===================================================================
*** gcc/tree.h (revision 170616)
--- gcc/tree.h (working copy)
*************** struct GTY(()) tree_parm_decl {
*** 2913,2938 ****
#define DECL_COMDAT_GROUP(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_group)
- /* A replaceable function is one which may be replaced at link-time
- with an entirely different definition, provided that the
- replacement has the same type. For example, functions declared
- with __attribute__((weak)) on most systems are replaceable.
-
- COMDAT functions are not replaceable, since all definitions of the
- function must be equivalent. It is important that COMDAT functions
- not be treated as replaceable so that use of C++ template
- instantiations is not penalized.
-
- For example, DECL_REPLACEABLE is used to determine whether or not a
- function (including a template instantiation) which is not
- explicitly declared "inline" can be inlined. If the function is
- DECL_REPLACEABLE then it is not safe to do the inlining, since the
- implementation chosen at link-time may be different. However, a
- function that is not DECL_REPLACEABLE can be inlined, since all
- versions of the function will be functionally identical. */
- #define DECL_REPLACEABLE_P(NODE) \
- (!DECL_COMDAT (NODE) && !targetm.binds_local_p (NODE))
-
/* The name of the object as the assembler will see it (but before any
translations made by ASM_OUTPUT_LABELREF). Often this is the same
as DECL_NAME. It is an IDENTIFIER_NODE. */
--- 2913,2918 ----
*************** extern void finish_aliases_1 (void);
*** 5145,5150 ****
--- 5125,5132 ----
extern void finish_aliases_2 (void);
extern tree emutls_decl (tree);
extern void remove_unreachable_alias_pairs (void);
+ extern bool decl_replaceable_p (tree);
+ extern bool decl_binds_to_current_def_p (tree);
/* In stmt.c */
extern void expand_computed_goto (tree);
Index: gcc/cp/decl.c
===================================================================
*** gcc/cp/decl.c (revision 170616)
--- gcc/cp/decl.c (working copy)
*************** finish_function (int flags)
*** 12502,12508 ****
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
! && !DECL_REPLACEABLE_P (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
--- 12502,12508 ----
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
! && !decl_replaceable_p (fndecl))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
Index: gcc/varasm.c
===================================================================
*** gcc/varasm.c (revision 170616)
--- gcc/varasm.c (working copy)
*************** default_binds_local_p_1 (const_tree exp,
*** 6691,6696 ****
--- 6691,6741 ----
return local_p;
}
+ /* Return true when references to DECL must bind to current definition in
+ final executable.
+
+ The condition is usually equivalent to whether the function binds to the
+ current module (shared library or executable), that is to binds_local_p.
+ We use this fact to avoid need for another target hook and implement
+ the logic using binds_local_p and just special cases where
+ decl_binds_to_current_def_p is stronger than binds local_p. In particular
+ the weak definitions (that can be overwritten at linktime by other
+ definition from different object file) and when resolution info is available
+ we simply use the knowledge passed to us by linker plugin. */
+ bool
+ decl_binds_to_current_def_p (tree decl)
+ {
+ gcc_assert (DECL_P (decl));
+ if (!TREE_PUBLIC (decl))
+ return true;
+ if (!targetm.binds_local_p (decl))
+ return false;
+ /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
+ binds localy but still can be overwritten).
+ This rely on fact that binds_local_p behave as decl_replaceable_p
+ for all other declaration types. */
+ return !DECL_WEAK (decl);
+ }
+
+ /* A replaceable function or variable is one which may be replaced
+ at link-time with an entirely different definition, provided that the
+ replacement has the same type. For example, functions declared
+ with __attribute__((weak)) on most systems are replaceable.
+
+ COMDAT functions are not replaceable, since all definitions of the
+ function must be equivalent. It is important that COMDAT functions
+ not be treated as replaceable so that use of C++ template
+ instantiations is not penalized. */
+
+ bool
+ decl_replaceable_p (tree decl)
+ {
+ gcc_assert (DECL_P (decl));
+ if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl))
+ return false;
+ return !decl_binds_to_current_def_p (decl);
+ }
+
/* Default function to output code that will globalize a label. A
target must define GLOBAL_ASM_OP or provide its own function to
globalize a label. */
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c (revision 170616)
--- gcc/tree-inline.c (working copy)
*************** tree_inlinable_function_p (tree fn)
*** 3067,3073 ****
/* Don't auto-inline anything that might not be bound within
this unit of translation. */
else if (!DECL_DECLARED_INLINE_P (fn)
! && DECL_REPLACEABLE_P (fn))
inlinable = false;
else if (!function_attribute_inlinable_p (fn))
--- 3067,3073 ----
/* Don't auto-inline anything that might not be bound within
this unit of translation. */
else if (!DECL_DECLARED_INLINE_P (fn)
! && decl_replaceable_p (fn))
inlinable = false;
else if (!function_attribute_inlinable_p (fn))