]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ipa-cp: Adjust general IPA-CP cloning heuristics
authorMartin Jambor <mjambor@suse.cz>
Thu, 21 May 2026 12:05:18 +0000 (14:05 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Thu, 21 May 2026 12:06:14 +0000 (14:06 +0200)
This winter I have had a long look at the effects of different values
of parameter param_ipa_cp_eval_threshold on performance on SPEC 2017
and on how they affect code size - and how quickly we reach growth
size limit in param_ipa_cp_unit_growth - when compiling these
benchmarks bit also, cc1 in an -O3 bootstrap and clang.

After going through the numbers, it turns out that we tend to clone a
bit too much and especially that we hit the overall growth limit way
too quickly.  As a result this patch does two things.  First, it
raises the heuristics cost/benefit threshold to 1100 (from 500) which
is the value at which I started to see cloning benefits.

Second, it reverts a recent change to get_max_overall_size where the
size limit also depended on the current call-graph sweep.  We only
want the threshold to gradually come down (now to 1100), not the size
constraints also, it turned out to defeat the initial purpose.

gcc/ChangeLog:

2026-04-07  Martin Jambor  <mjambor@suse.cz>

* ipa-cp.cc (get_max_overall_size): Remove parameter CUR_SWEEP and
its use.
(decide_about_value): Adjust the call to get_max_overall_size.
(decide_whether_version_node): Likewise.
* params.opt (param_ipa_cp_eval_threshold): Initialize to 1100.

libgomp/ChangeLog:

2026-04-07  Martin Jambor  <mjambor@suse.cz>

* testsuite/libgomp.c/ipcp-cb-spec1.c: Set lower param
ipa-cp-eval-threshold.

gcc/testsuite/ChangeLog:

2026-04-07  Martin Jambor  <mjambor@suse.cz>

* gcc.dg/ipa/ipa-5.c: Adjust dump.
* gcc.dg/independent-cloneids-1.c: Set lower param
ipa-cp-eval-threshold.
* gcc.dg/vla-1.c: Likewise.
* g++.dg/ipa/devirt-2.C: Add an extra caller of the to-be-cloned
function.

gcc/ipa-cp.cc
gcc/params.opt
gcc/testsuite/g++.dg/ipa/devirt-2.C
gcc/testsuite/gcc.dg/independent-cloneids-1.c
gcc/testsuite/gcc.dg/ipa/ipa-5.c
gcc/testsuite/gcc.dg/vla-1.c
libgomp/testsuite/libgomp.c/ipcp-cb-spec1.c

index c1b1f6201fd3db7fd10832d84ea466e7c464bff4..ce77acf8e0da51e560d4a8d76afabd93e9ab595a 100644 (file)
@@ -3620,25 +3620,21 @@ perform_estimation_of_a_value (cgraph_node *node,
   val->local_size_cost = size;
 }
 
-/* Get the overall limit of growth based on parameters extracted from growth,
-   and CUR_SWEEP, which is the number of the current sweep of IPA-CP over the
-   call-graph in the decision stage.  It does not really make sense to mix
-   functions with different overall growth limits or even number of sweeps but
-   it is possible and if it happens, we do not want to select one limit at
-   random, so get the limits from NODE.  */
+/* Get the overall limit of growth based on parameters extracted from NODE.  It
+   does not really make sense to mix functions with different overall growth
+   limits or even number of sweeps but it is possible and if it happens, we do
+   not want to select one limit at random, so get the limits from NODE.  */
 
 static long
-get_max_overall_size (cgraph_node *node, int cur_sweep)
+get_max_overall_size (cgraph_node *node)
 {
   long max_new_size = orig_overall_size;
   long large_unit = opt_for_fn (node->decl, param_ipa_cp_large_unit_insns);
   if (max_new_size < large_unit)
     max_new_size = large_unit;
-  int num_sweeps = opt_for_fn (node->decl, param_ipa_cp_sweeps);
-  gcc_assert (cur_sweep <= num_sweeps);
   int unit_growth = opt_for_fn (node->decl, param_ipa_cp_unit_growth);
-  max_new_size += ((max_new_size * unit_growth * cur_sweep)
-                  / num_sweeps) / 100 + 1;
+  max_new_size += max_new_size * unit_growth / 100 + 1;
+
   return max_new_size;
 }
 
@@ -5958,8 +5954,7 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
       perhaps_add_new_callers (node, val);
       return false;
     }
-  else if (val->local_size_cost + overall_size
-          > get_max_overall_size (node, cur_sweep))
+  else if (val->local_size_cost + overall_size > get_max_overall_size (node))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "   Ignoring candidate value because "
@@ -6337,7 +6332,7 @@ decide_whether_version_node (struct cgraph_node *node, int cur_sweep)
                                           stats.called_without_ipa_profile,
                                           cur_sweep))
        {
-         if (size + overall_size <= get_max_overall_size (node, cur_sweep))
+         if (size + overall_size <= get_max_overall_size (node))
            {
              if (!dbg_cnt (ipa_cp_values))
                return ret;
index 9eeb1f3fa64e80a2e4ef89583966497b5f602da8..90f9943c8cb4aeeb8c110ee436c329d8c0a255da 100644 (file)
@@ -250,7 +250,7 @@ Common Joined UInteger Var(param_integer_share_limit) Init(251) IntegerRange(2,
 The upper bound for sharing integer constants.
 
 -param=ipa-cp-eval-threshold=
-Common Joined UInteger Var(param_ipa_cp_eval_threshold) Init(500) Param Optimization
+Common Joined UInteger Var(param_ipa_cp_eval_threshold) Init(1100) Param Optimization
 Threshold ipa-cp opportunity evaluation that is still considered beneficial to clone.
 
 -param=ipa-cp-loop-hint-bonus=
index 3fffe278ecea9bdf5bde271a74ad2b9c3624a73e..6a81140e03d9255ee534d7c7fabcf0e3bda1c7a9 100644 (file)
@@ -48,6 +48,16 @@ int __attribute__ ((noinline,noclone,noipa)) get_input(void)
   return 1;
 }
 
+int extra (int init)
+{
+  class B b;
+  int i;
+  for (i = init; i < get_input(); i++)
+    if (b.middleman (get_input ()) != 3)
+      abort ();
+  return 0;
+}
+
 int main (int argc, char *argv[])
 {
   class B b;
index efbc1c51da0bd2683f49e328bb1351f25981e9d0..c6e9581cbce426c9bcf73a7962851467f053ff6c 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-rtl-final"  } */
+/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-rtl-final --param ipa-cp-eval-threshold=500"  } */
 /* { dg-skip-if "Odd label definition syntax" { mmix-*-* } } */
 
 extern int printf (const char *, ...);
index e4f77a967682c44cb26902cbeff520df3997e220..a6678b12c7c1fe53c7d103e90e8f77706d5ba9eb 100644 (file)
@@ -27,6 +27,6 @@ int main ()
   return 0;
 }
 
-/* { dg-final { scan-ipa-dump-times "Creating a specialized node" 3 "cp"  } } */
+/* { dg-final { scan-ipa-dump-times "Creating a specialized node" 2 "cp"  } } */
 /* { dg-final { scan-ipa-dump "replacing param .1 c with const 3" "cp"  } } */
 /* { dg-final { scan-ipa-dump "replacing param .0 a with const 7" "cp"  } } */
index 2ab2b7a48acf61c5b015c8214bfb04ed775e244c..52a1d9772d9f741c2d86c98f5ca08b3889e36c4f 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-g -O3 -fdump-tree-optimized -fvar-tracking-assignments -fno-selective-scheduling -fno-selective-scheduling2 -fno-ipa-vrp" } */
+/* { dg-options "-g -O3 -fdump-tree-optimized -fvar-tracking-assignments -fno-selective-scheduling -fno-selective-scheduling2 -fno-ipa-vrp --param ipa-cp-eval-threshold=1" } */
 
 int __attribute__((noinline))
 f1 (int i)
index ff82f4c2f29d9507613326c30e79b6780c14769f..a2ab03f692a45f9a2cbb46838a5f113d6dadd0a1 100644 (file)
@@ -1,7 +1,7 @@
 /* Test that GOMP_task is special cased when cpyfn is NULL.  */
 
 /* { dg-do run } */
-/* { dg-options "-O3 -fopenmp -std=gnu99 -fdump-ipa-cp-details" } */
+/* { dg-options "-O3 -fopenmp -std=gnu99 -fdump-ipa-cp-details --param ipa-cp-eval-threshold=1" } */
 /* { dg-require-effective-target fopenmp } */
 
 void test(int c) {