IPA ICF: target and optimization flags comparison.
authorMartin Liska <mliska@suse.cz>
Fri, 9 Jan 2015 10:33:00 +0000 (11:33 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Fri, 9 Jan 2015 10:33:00 +0000 (10:33 +0000)
* cgraphunit.c (cgraph_node::create_wrapper): Fix level of indentation.
* ipa-icf.c (sem_function::equals_private): Add support for target and
(sem_item_optimizer::merge_classes): Remove redundant function
optimization flags comparison.
* tree.h (target_opts_for_fn): New function.
* gcc.dg/ipa/ipa-icf-32.c: New test.

From-SVN: r219377

gcc/ChangeLog
gcc/cgraphunit.c
gcc/ipa-icf.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ipa/ipa-icf-32.c [new file with mode: 0644]
gcc/tree.h

index d3d121ddff49bd64f373f4179b46932702feb6c9..eb69b39cf36624be7414b62f27594b252ee8ba37 100644 (file)
@@ -1,3 +1,11 @@
+2015-01-09  Martin Liska  <mliska@suse.cz>
+
+       * cgraphunit.c (cgraph_node::create_wrapper): Fix level of indentation.
+       * ipa-icf.c (sem_function::equals_private): Add support for target and
+       (sem_item_optimizer::merge_classes): Remove redundant function
+       optimization flags comparison.
+       * tree.h (target_opts_for_fn): New function.
+
 2015-01-09  Tom de Vries  <tom@codesourcery.com>
 
        * omp-low.c (expand_omp_for_static_chunk): Fix assert.
index c8c8562dc2c9c46c1287f54860796d34e6376893..81246e28fc8537baa16a70b7599f1d13b31d9766 100644 (file)
@@ -2385,40 +2385,40 @@ cgraphunit_c_finalize (void)
 void
 cgraph_node::create_wrapper (cgraph_node *target)
 {
-    /* Preserve DECL_RESULT so we get right by reference flag.  */
-    tree decl_result = DECL_RESULT (decl);
+  /* Preserve DECL_RESULT so we get right by reference flag.  */
+  tree decl_result = DECL_RESULT (decl);
 
-    /* Remove the function's body but keep arguments to be reused
-       for thunk.  */
-    release_body (true);
-    reset ();
+  /* Remove the function's body but keep arguments to be reused
+     for thunk.  */
+  release_body (true);
+  reset ();
 
-    DECL_RESULT (decl) = decl_result;
-    DECL_INITIAL (decl) = NULL;
-    allocate_struct_function (decl, false);
-    set_cfun (NULL);
+  DECL_RESULT (decl) = decl_result;
+  DECL_INITIAL (decl) = NULL;
+  allocate_struct_function (decl, false);
+  set_cfun (NULL);
 
-    /* Turn alias into thunk and expand it into GIMPLE representation.  */
-    definition = true;
-    thunk.thunk_p = true;
-    thunk.this_adjusting = false;
+  /* Turn alias into thunk and expand it into GIMPLE representation.  */
+  definition = true;
+  thunk.thunk_p = true;
+  thunk.this_adjusting = false;
 
-    cgraph_edge *e = create_edge (target, NULL, 0, CGRAPH_FREQ_BASE);
+  cgraph_edge *e = create_edge (target, NULL, 0, CGRAPH_FREQ_BASE);
 
-    tree arguments = DECL_ARGUMENTS (decl);
+  tree arguments = DECL_ARGUMENTS (decl);
 
-    while (arguments)
-      {
-       TREE_ADDRESSABLE (arguments) = false;
-       arguments = TREE_CHAIN (arguments);
-      }
+  while (arguments)
+    {
+      TREE_ADDRESSABLE (arguments) = false;
+      arguments = TREE_CHAIN (arguments);
+    }
 
-    expand_thunk (false, true);
-    e->call_stmt_cannot_inline_p = true;
+  expand_thunk (false, true);
+  e->call_stmt_cannot_inline_p = true;
 
-    /* Inline summary set-up.  */
-    analyze ();
-    inline_analyze_function (this);
+  /* Inline summary set-up.  */
+  analyze ();
+  inline_analyze_function (this);
 }
 
 #include "gt-cgraphunit.h"
index c7ba75adc47e872d360fe58fdadd73be7c51f210..28158b35312029009e79ad151833bc9ed8c25620 100644 (file)
@@ -427,6 +427,49 @@ sem_function::equals_private (sem_item *item,
   if (!equals_wpa (item, ignored_nodes))
     return false;
 
+  /* Checking function TARGET and OPTIMIZATION flags.  */
+  cl_target_option *tar1 = target_opts_for_fn (decl);
+  cl_target_option *tar2 = target_opts_for_fn (m_compared_func->decl);
+
+  if (tar1 != NULL || tar2 != NULL)
+    {
+      if (!cl_target_option_eq (tar1, tar2))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Source target flags\n");
+             cl_target_option_print (dump_file, 2, tar1);
+             fprintf (dump_file, "Target target flags\n");
+             cl_target_option_print (dump_file, 2, tar2);
+           }
+
+         return return_false_with_msg ("Target flags are different");
+       }
+    }
+  else if (tar1 != NULL || tar2 != NULL)
+    return return_false_with_msg ("Target flags are different");
+
+  cl_optimization *opt1 = opts_for_fn (decl);
+  cl_optimization *opt2 = opts_for_fn (m_compared_func->decl);
+
+  if (opt1 != NULL && opt2 != NULL)
+    {
+      if (memcmp (opt1, opt2, sizeof(cl_optimization)))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Source optimization flags\n");
+             cl_optimization_print (dump_file, 2, opt1);
+             fprintf (dump_file, "Target optimization flags\n");
+             cl_optimization_print (dump_file, 2, opt2);
+           }
+
+         return return_false_with_msg ("optimization flags are different");
+       }
+    }
+  else if (opt1 != NULL || opt2 != NULL)
+    return return_false_with_msg ("optimization flags are different");
+
   /* Checking function arguments.  */
   tree decl1 = DECL_ATTRIBUTES (decl);
   tree decl2 = DECL_ATTRIBUTES (m_compared_func->decl);
@@ -2302,7 +2345,6 @@ sem_item_optimizer::merge_classes (unsigned int prev_class_count)
        for (unsigned int j = 1; j < c->members.length (); j++)
          {
            sem_item *alias = c->members[j];
-           source->equals (alias, m_symtab_node_map);
 
            if (dump_file)
              {
index bc1c52cd2d680345813926a2e80a6479a64fb72c..b1aff26b889cedd91ddfef084371ca4d5abc7a13 100644 (file)
@@ -1,3 +1,7 @@
+2015-01-09  Martin Liska  <mliska@suse.cz>
+
+       * gcc.dg/ipa/ipa-icf-32.c: New test.
+
 2015-01-08  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * c-c++-common/tsan/tsan_barrier.h: New.
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-32.c b/gcc/testsuite/gcc.dg/ipa/ipa-icf-32.c
new file mode 100644 (file)
index 0000000..22544a7
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O0 -fipa-icf -fdump-ipa-icf-details" } */
+
+int
+__attribute__((optimize("O0"), noinline, noclone))
+foo(int a)
+{
+  return a * a;
+}
+
+__attribute__ ((noinline, noclone))
+int bar(int b)
+{
+  return b * b;
+}
+
+int main()
+{
+  return foo (0) + bar (0);
+}
+
+/* { dg-final { scan-ipa-dump "optimization flags are different" "icf"  } } */
+/* { dg-final { scan-ipa-dump "Equal symbols: 0" "icf"  } } */
+/* { dg-final { cleanup-ipa-dump "icf" } } */
index 3e74c7e4bcf001e9da12b9b1ef80106c95365093..e9af9bf239165358286c8ad80bc31ecae3d80fe4 100644 (file)
@@ -4671,6 +4671,16 @@ opts_for_fn (const_tree fndecl)
   return TREE_OPTIMIZATION (fn_opts);
 }
 
+/* Return pointer to target flags of FNDECL.  */
+static inline cl_target_option *
+target_opts_for_fn (const_tree fndecl)
+{
+  tree fn_opts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+  if (fn_opts == NULL_TREE)
+    fn_opts = target_option_default_node;
+  return TREE_TARGET_OPTION (fn_opts);
+}
+
 /* opt flag for function FNDECL, e.g. opts_for_fn (fndecl, optimize) is
    the optimization level of function fndecl.  */
 #define opt_for_fn(fndecl, opt) (opts_for_fn (fndecl)->x_##opt)