From 68f800b3093c6a5bf9fff86ec362af766ad5288b Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 6 Jan 2017 16:01:23 +0100
Subject: [PATCH] Ignore Debug options for ICF equality.
gcc/testsuite/ChangeLog:
2017-01-09 Martin Liska <mliska@suse.cz>
* gcc.dg/ipa/ipa-icf-38.c: New test.
* gcc.dg/ipa/ipa-icf-39.c: New test.
gcc/ChangeLog:
2017-01-09 Martin Liska <mliska@suse.cz>
* common.opt: Add Debug attribute for debug
optimization flags.
* ipa-icf.c (sem_function::get_hash): Ignore CL_DEBUG options.
(sem_item::ignore_attr_p): New function.
(sem_item::compare_attributes): Use the function.
(sem_function::equals_wpa): Fix typo.
* ipa-icf.h (ignore_attr_p): Declare new function.
* ipa-inline.c (can_inline_edge_p): Remove comparison
of optimization flags.
* opt-functions.awk (switch_opts_type_flags): New function.
* optc-save-gen.awk: Add new assert.
(cl_optimization_hash): Add new argument.
(cl_optimization_eq): New function.
* opth-gen.awk: Update declaration.
* opts.h (CL_DEBUG): Define new macro.
---
gcc/common.opt | 8 ++--
gcc/ipa-icf.c | 25 +++++++----
gcc/ipa-icf.h | 3 ++
gcc/ipa-inline.c | 7 ----
gcc/opt-functions.awk | 12 +++++-
gcc/optc-save-gen.awk | 79 ++++++++++++++++++++---------------
gcc/opth-gen.awk | 16 +++----
gcc/opts.h | 1 +
gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c | 23 ++++++++++
gcc/testsuite/gcc.dg/ipa/ipa-icf-39.c | 13 ++++++
10 files changed, 123 insertions(+), 64 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c
create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-icf-39.c
@@ -2644,7 +2644,7 @@ Common Undocumented Var(flag_use_linker_plugin)
; will be set according to optimize, debug_info_level and debug_hooks
; in process_options ().
fvar-tracking
-Common Report Var(flag_var_tracking) Init(2) Optimization
+Common Report Var(flag_var_tracking) Init(2) Optimization Debug
Perform variable tracking.
; Positive if we should track variables at assignments, negative if
@@ -2652,13 +2652,13 @@ Perform variable tracking.
; annotations. When flag_var_tracking_assignments ==
; AUTODETECT_VALUE it will be set according to flag_var_tracking.
fvar-tracking-assignments
-Common Report Var(flag_var_tracking_assignments) Init(2) Optimization
+Common Report Var(flag_var_tracking_assignments) Init(2) Optimization Debug
Perform variable tracking by annotating assignments.
; Nonzero if we should toggle flag_var_tracking_assignments after
; processing options and computing its default. */
fvar-tracking-assignments-toggle
-Common Report Var(flag_var_tracking_assignments_toggle) Optimization
+Common Report Var(flag_var_tracking_assignments_toggle) Optimization Debug
Toggle -fvar-tracking-assignments.
; Positive if we should track uninitialized variables, negative if
@@ -2666,7 +2666,7 @@ Toggle -fvar-tracking-assignments.
; annotations. When flag_var_tracking_uninit == AUTODETECT_VALUE it
; will be set according to flag_var_tracking.
fvar-tracking-uninit
-Common Report Var(flag_var_tracking_uninit) Optimization
+Common Report Var(flag_var_tracking_uninit) Optimization Debug
Perform variable tracking and also tag variables that are uninitialized.
ftree-vectorize
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-icf.h"
#include "stor-layout.h"
#include "dbgcnt.h"
+#include "opts.h"
using namespace ipa_icf_gimple;
@@ -289,10 +290,7 @@ sem_function::get_hash (void)
hstate.add_wide_int
(cl_target_option_hash
(TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (decl))));
- if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
- hstate.add_wide_int
- (cl_optimization_hash
- (TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
+ hstate.add_wide_int (cl_optimization_hash (opts_for_fn (decl), CL_DEBUG));
hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));
@@ -302,6 +300,17 @@ sem_function::get_hash (void)
return m_hash;
}
+bool
+sem_item::ignore_attr_p (const attribute_spec *as)
+{
+ /* Do not allow optimization or (and) target options. */
+ if (strcmp (as->name, "optimize") == 0
+ || strcmp (as->name, "target") == 0)
+ return true;
+
+ return false;
+}
+
/* Return ture if A1 and A2 represent equivalent function attribute lists.
Based on comp_type_attributes. */
@@ -324,7 +333,7 @@ sem_item::compare_attributes (const_tree a1, const_tree a2)
For example returns_nonnull affects only references, while
optimize attribute can be ignored because it is already lowered
into flags representation and compared separately. */
- if (!as)
+ if (!as || ignore_attr_p (as))
continue;
attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
@@ -338,7 +347,7 @@ sem_item::compare_attributes (const_tree a1, const_tree a2)
const struct attribute_spec *as;
as = lookup_attribute_spec (get_attribute_name (a));
- if (!as)
+ if (!as || ignore_attr_p (as))
continue;
if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
@@ -652,13 +661,13 @@ sem_function::equals_wpa (sem_item *item,
cl_target_option_print_diff (dump_file, 2, tar1, tar2);
}
- return return_false_with_msg ("Target flags are different");
+ return return_false_with_msg ("target flags are different");
}
cl_optimization *opt1 = opts_for_fn (decl);
cl_optimization *opt2 = opts_for_fn (item->decl);
- if (opt1 != opt2 && memcmp (opt1, opt2, sizeof(cl_optimization)))
+ if (opt1 != opt2 && !cl_optimization_eq (opt1, opt2, CL_DEBUG))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -253,6 +253,9 @@ protected:
symtab_node *n2,
bool address);
+ /* Return true when attribute specification AC should be ignored. */
+ static bool ignore_attr_p (const attribute_spec *as);
+
/* Compare two attribute lists. */
static bool compare_attributes (const_tree list1, const_tree list2);
@@ -448,13 +448,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
/* gcc.dg/pr43564.c. Apply user-forced inline even at -O0. */
else if (always_inline)
;
- /* When user added an attribute to the callee honor it. */
- else if (lookup_attribute ("optimize", DECL_ATTRIBUTES (callee->decl))
- && opts_for_fn (caller->decl) != opts_for_fn (callee->decl))
- {
- e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
- inlinable = false;
- }
/* If explicit optimize attribute are not used, the mismatch is caused
by different command line options used to build different units.
Do not care about COMDAT functions - those are intended to be
@@ -105,7 +105,17 @@ function switch_flags (flags)
test_flag("Undocumented", flags, " | CL_UNDOCUMENTED") \
test_flag("NoDWARFRecord", flags, " | CL_NO_DWARF_RECORD") \
test_flag("Warning", flags, " | CL_WARNING") \
- test_flag("Optimization", flags, " | CL_OPTIMIZATION")
+ test_flag("Optimization", flags, " | CL_OPTIMIZATION") \
+ test_flag("Debug", flags, " | CL_DEBUG")
+ sub( "^0 \\| ", "", result )
+ return result
+}
+
+function switch_opts_type_flags (flags)
+{
+ result = "0"
+ result = result \
+ test_flag("Debug", flags, " | CL_DEBUG")
sub( "^0 \\| ", "", result )
return result
}
@@ -127,7 +127,7 @@ for (i = 0; i < n_opts; i++) {
var_opt_range[name] = "-128, 127"
}
else
- var_opt_other[n_opt_other++] = name;
+ n_opt_other++;
}
}
@@ -137,10 +137,8 @@ for (i = 0; i < n_opt_char; i++) {
print " gcc_assert (IN_RANGE (opts->x_" name ", " var_opt_range[name] "));";
}
-print "";
-for (i = 0; i < n_opt_other; i++) {
- print " ptr->x_" var_opt_other[i] " = opts->x_" var_opt_other[i] ";";
-}
+if (n_opt_other > 0)
+ print "#error Unsupported type of optimization node";
for (i = 0; i < n_opt_int; i++) {
print " ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
@@ -166,10 +164,6 @@ print "void";
print "cl_optimization_restore (struct gcc_options *opts, struct cl_optimization *ptr)";
print "{";
-for (i = 0; i < n_opt_other; i++) {
- print " opts->x_" var_opt_other[i] " = ptr->x_" var_opt_other[i] ";";
-}
-
for (i = 0; i < n_opt_int; i++) {
print " opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
}
@@ -198,15 +192,6 @@ print " struct cl_optimization *ptr)";
print "{";
print " fputs (\"\\n\", file);";
-for (i = 0; i < n_opt_other; i++) {
- print " if (ptr->x_" var_opt_other[i] ")";
- print " fprintf (file, \"%*s%s (%#lx)\\n\",";
- print " indent_to, \"\",";
- print " \"" var_opt_other[i] "\",";
- print " (unsigned long)ptr->x_" var_opt_other[i] ");";
- print "";
-}
-
for (i = 0; i < n_opt_int; i++) {
print " if (ptr->x_" var_opt_int[i] ")";
print " fprintf (file, \"%*s%s (%#x)\\n\",";
@@ -254,16 +239,6 @@ print " struct cl_optimization *ptr2)";
print "{";
print " fputs (\"\\n\", file);";
-for (i = 0; i < n_opt_other; i++) {
- print " if (ptr1->x_" var_opt_other[i] " != ptr2->x_" var_opt_other[i] ")";
- print " fprintf (file, \"%*s%s (%#lx/%#lx)\\n\",";
- print " indent_to, \"\",";
- print " \"" var_opt_other[i] "\",";
- print " (unsigned long)ptr1->x_" var_opt_other[i] ",";
- print " (unsigned long)ptr2->x_" var_opt_other[i] ");";
- print "";
-}
-
for (i = 0; i < n_opt_int; i++) {
print " if (ptr1->x_" var_opt_int[i] " != ptr2->x_" var_opt_int[i] ")";
print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
@@ -306,7 +281,6 @@ for (i = 0; i < n_opt_char; i++) {
print "}";
-
print "";
print "/* Save selected option variables into a structure. */"
print "void";
@@ -738,10 +712,13 @@ print "}";
n_opt_val = 3;
var_opt_val[0] = "x_optimize"
var_opt_val_type[0] = "char "
+var_opt_type_flags[0] = "0"
var_opt_val[1] = "x_optimize_size"
-var_opt_val[2] = "x_optimize_debug"
var_opt_val_type[1] = "char "
+var_opt_type_flags[1] = "0"
+var_opt_val[2] = "x_optimize_debug"
var_opt_val_type[2] = "char "
+var_opt_type_flags[2] = 0""
for (i = 0; i < n_opts; i++) {
if (flag_set_p("Optimization", flags[i])) {
name = var_name(flags[i])
@@ -755,18 +732,29 @@ for (i = 0; i < n_opts; i++) {
otype = var_type_struct(flags[i])
var_opt_val_type[n_opt_val] = otype;
- var_opt_val[n_opt_val++] = "x_" name;
+ var_opt_val[n_opt_val] = "x_" name;
+ var_opt_type_flags[n_opt_val++] = switch_opts_type_flags(flags[i])
}
}
+
+print "";
+print "/* Hash optimization options, ignore flags having a flag in IGNORED flags. */";
print "";
-print "/* Hash optimization options */";
print "hashval_t";
-print "cl_optimization_hash (struct cl_optimization const *ptr ATTRIBUTE_UNUSED)";
+print "cl_optimization_hash (struct cl_optimization const *ptr ATTRIBUTE_UNUSED,";
+print " unsigned int ignored_flags ATTRIBUTE_UNUSED)";
print "{";
print " inchash::hash hstate;";
for (i = 0; i < n_opt_val; i++) {
name = var_opt_val[i]
- print " hstate.add_wide_int (ptr->" name");";
+ f = var_opt_type_flags[i];
+ padding = "";
+ if (f != "0") {
+ print " if (!(ignored_flags & (" f ")))"
+ padding = " "
+ }
+
+ print padding " hstate.add_wide_int (ptr->" name");";
}
print " return hstate.end ();";
print "}";
@@ -794,4 +782,27 @@ for (i = 0; i < n_opt_val; i++) {
print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_value (bp, 64);";
}
print "}";
+
+print "";
+print "/* Compare two target options */";
+print "bool";
+print "cl_optimization_eq (struct cl_optimization const *ptr1 ATTRIBUTE_UNUSED,";
+print " struct cl_optimization const *ptr2 ATTRIBUTE_UNUSED,";
+print " unsigned int ignored_flags ATTRIBUTE_UNUSED)";
+print "{";
+
+for (i = 0; i < n_opt_val; i++) {
+ name = var_opt_val[i]
+ f = var_opt_type_flags[i];
+ printf " if (ptr1->" name" != ptr2->" name;
+ if (f != "0")
+ print "\n && !(ignored_flags & (" f ")))";
+ else
+ print(")")
+ print " return false;";
+}
+
+print " return true;";
+print "}";
+
}
@@ -136,7 +136,6 @@ n_opt_char = 3;
n_opt_short = 0;
n_opt_int = 0;
n_opt_enum = 0;
-n_opt_other = 0;
var_opt_char[0] = "unsigned char x_optimize";
var_opt_char[1] = "unsigned char x_optimize_size";
var_opt_char[2] = "unsigned char x_optimize_debug";
@@ -164,15 +163,9 @@ for (i = 0; i < n_opts; i++) {
else if (otype ~ ("^enum +[_" alnum "]+ *$"))
var_opt_enum[n_opt_enum++] = otype "x_" name;
- else
- var_opt_other[n_opt_other++] = otype "x_" name;
}
}
-for (i = 0; i < n_opt_other; i++) {
- print " " var_opt_other[i] ";";
-}
-
for (i = 0; i < n_opt_int; i++) {
print " " var_opt_int[i] ";";
}
@@ -306,7 +299,10 @@ print "/* Hash option variables from a structure. */";
print "extern hashval_t cl_target_option_hash (const struct cl_target_option *);";
print "";
print "/* Hash optimization from a structure. */";
-print "extern hashval_t cl_optimization_hash (const struct cl_optimization *);";
+print "extern hashval_t cl_optimization_hash (const struct cl_optimization *, unsigned int ignored_flags = 0);";
+print "";
+print "/* Compare two optimization option variables from a structure. */";
+print "extern bool cl_optimization_eq (const struct cl_optimization *, const struct cl_optimization *, unsigned int ignored_flags = 0);";
print "";
print "/* Generator files may not have access to location_t, and don't need these. */"
print "#if defined(UNKNOWN_LOCATION)"
@@ -332,7 +328,7 @@ for (i = 0; i < n_langs; i++) {
print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
print " struct cpp_options * cpp_opts);"
print "void init_global_opts_from_cpp(struct gcc_options * opts, "
-print " const struct cpp_options * cpp_opts);"
+print " const struct cpp_options * cpp_opts);"
print "#endif";
print "#endif";
print "";
@@ -436,7 +432,7 @@ print "#define CL_LANG_ALL ((1U << " n_langs ") - 1)"
print ""
print "enum opt_code"
print "{"
-
+
for (i = 0; i < n_opts; i++)
back_chain[i] = "N_OPTS";
@@ -145,6 +145,7 @@ extern const unsigned int cl_lang_count;
#define CL_UNDOCUMENTED (1U << 24) /* Do not output with --help. */
#define CL_NO_DWARF_RECORD (1U << 25) /* Do not add to producer string. */
#define CL_PCH_IGNORE (1U << 26) /* Do compare state for pch. */
+#define CL_DEBUG (1U << 27) /* Drives debug info generation. */
/* Flags for an enumerated option argument. */
#define CL_ENUM_CANONICAL (1 << 0) /* Canonical for this value. */
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-ipa-icf" } */
+
+int
+__attribute__((optimize(("split-loops"))))
+foo(void) { return 0; }
+
+int
+__attribute__((optimize(("split-loops"))))
+bar (void) { return 0; }
+
+
+int
+__attribute__ ((hot))
+foo2(void) { return 0; }
+
+int
+__attribute__ ((hot))
+bar2(void) { return 0; }
+
+/* { dg-final { scan-ipa-dump "Equal symbols: 2" "icf" } } */
+/* { dg-final { scan-ipa-dump "Semantic equality hit:foo->bar" "icf" } } */
+/* { dg-final { scan-ipa-dump "Semantic equality hit:foo2->bar2" "icf" } } */
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-ipa-icf" } */
+
+int
+__attribute__((hot, no_reorder))
+foo(void) { return 0; }
+
+int
+__attribute__((no_reorder, hot))
+bar (void) { return 0; }
+
+/* { dg-final { scan-ipa-dump "Equal symbols: 1" "icf" } } */
+/* { dg-final { scan-ipa-dump "Semantic equality hit:foo->bar" "icf" } } */
--
2.11.0