public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Check calls before loop unrolling
@ 2020-08-20  4:34 guojiufu
  2020-08-24  9:16 ` Richard Biener
  2020-09-01  3:33 ` Jiufu Guo
  0 siblings, 2 replies; 17+ messages in thread
From: guojiufu @ 2020-08-20  4:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: guojiufu, wschmidt, segher, dje.gcc

Hi,

When unroll loops, if there are calls inside the loop, those calls
may raise negative impacts for unrolling.  This patch adds a param
param_max_unrolled_calls, and checks if the number of calls inside
the loop bigger than this param, loop is prevent from unrolling.

This patch is checking the _average_ number of calls which is the
summary of call numbers multiply the possibility of the call maybe
executed.  The _average_ number could be a fraction, to keep the
precision, the param is the threshold number multiply 10000.

Bootstrap and regtest pass on powerpc64le.  Is this ok for trunk?

gcc/ChangeLog
2020-08-19  Jiufu Guo   <guojiufu@cn.ibm.com>

	* params.opt (param_max_unrolled_average_calls_x10000): New param.
	* cfgloop.h (average_num_loop_calls): New declare.
	* cfgloopanal.c (average_num_loop_calls): New function.
	* loop-unroll.c (decide_unroll_constant_iteration,
	decide_unroll_runtime_iterations,
	decide_unroll_stupid): Check average_num_loop_calls and
	param_max_unrolled_average_calls_x10000.
---
 gcc/cfgloop.h     |  2 ++
 gcc/cfgloopanal.c | 25 +++++++++++++++++++++++++
 gcc/loop-unroll.c | 10 ++++++++++
 gcc/params.opt    |  4 ++++
 4 files changed, 41 insertions(+)

diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 18b404e292f..dab933da150 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_CFGLOOP_H
 
 #include "cfgloopmanip.h"
+#include "sreal.h"
 
 /* Structure to hold decision about unrolling/peeling.  */
 enum lpt_dec
@@ -387,6 +388,7 @@ extern vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
 extern edge single_exit (const class loop *);
 extern edge single_likely_exit (class loop *loop, vec<edge>);
 extern unsigned num_loop_branches (const class loop *);
+extern sreal average_num_loop_calls (const class loop *);
 
 extern edge loop_preheader_edge (const class loop *);
 extern edge loop_latch_edge (const class loop *);
diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c
index 0b33e8272a7..a314db4e0c0 100644
--- a/gcc/cfgloopanal.c
+++ b/gcc/cfgloopanal.c
@@ -233,6 +233,31 @@ average_num_loop_insns (const class loop *loop)
   return ret;
 }
 
+/* Count the number of call insns in LOOP.  */
+sreal
+average_num_loop_calls (const class loop *loop)
+{
+  basic_block *bbs;
+  rtx_insn *insn;
+  unsigned int i, bncalls;
+  sreal ncalls = 0;
+
+  bbs = get_loop_body (loop);
+  for (i = 0; i < loop->num_nodes; i++)
+    {
+      bncalls = 0;
+      FOR_BB_INSNS (bbs[i], insn)
+	if (CALL_P (insn))
+	  bncalls++;
+
+      ncalls += (sreal) bncalls
+	* bbs[i]->count.to_sreal_scale (loop->header->count);
+    }
+  free (bbs);
+
+  return ncalls;
+}
+
 /* Returns expected number of iterations of LOOP, according to
    measured or guessed profile.
 
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 693c7768868..56b8fb37d2a 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -370,6 +370,10 @@ decide_unroll_constant_iterations (class loop *loop, int flags)
     nunroll = nunroll_by_av;
   if (nunroll > (unsigned) param_max_unroll_times)
     nunroll = param_max_unroll_times;
+  if (!loop->unroll
+      && (average_num_loop_calls (loop) * (sreal) 10000).to_int ()
+	   > (unsigned) param_max_unrolled_average_calls_x10000)
+    nunroll = 0;
 
   if (targetm.loop_unroll_adjust)
     nunroll = targetm.loop_unroll_adjust (nunroll, loop);
@@ -689,6 +693,9 @@ decide_unroll_runtime_iterations (class loop *loop, int flags)
     nunroll = nunroll_by_av;
   if (nunroll > (unsigned) param_max_unroll_times)
     nunroll = param_max_unroll_times;
+  if ((average_num_loop_calls (loop) * (sreal) 10000).to_int ()
+      > (unsigned) param_max_unrolled_average_calls_x10000)
+    nunroll = 0;
 
   if (targetm.loop_unroll_adjust)
     nunroll = targetm.loop_unroll_adjust (nunroll, loop);
@@ -1173,6 +1180,9 @@ decide_unroll_stupid (class loop *loop, int flags)
     nunroll = nunroll_by_av;
   if (nunroll > (unsigned) param_max_unroll_times)
     nunroll = param_max_unroll_times;
+  if ((average_num_loop_calls (loop) * (sreal) 10000).to_int ()
+      > (unsigned) param_max_unrolled_average_calls_x10000)
+    nunroll = 0;
 
   if (targetm.loop_unroll_adjust)
     nunroll = targetm.loop_unroll_adjust (nunroll, loop);
diff --git a/gcc/params.opt b/gcc/params.opt
index f39e5d1a012..80605861223 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -634,6 +634,10 @@ The maximum number of unrollings of a single loop.
 Common Joined UInteger Var(param_max_unrolled_insns) Init(200) Param Optimization
 The maximum number of instructions to consider to unroll in a loop.
 
+-param=max-unrolled-average-calls-x10000=
+Common Joined UInteger Var(param_max_unrolled_average_calls_x10000) Init(0) Param Optimization
+The maximum number of calls to consider to unroll in a loop on average and multiply 10000.
+
 -param=max-unswitch-insns=
 Common Joined UInteger Var(param_max_unswitch_insns) Init(50) Param Optimization
 The maximum number of insns of an unswitched loop.
-- 
2.25.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2020-11-23  8:42 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-20  4:34 [PATCH] Check calls before loop unrolling guojiufu
2020-08-24  9:16 ` Richard Biener
2020-08-24 11:16   ` Jan Hubicka
2020-08-25  2:26     ` Jiufu Guo
2020-09-16  3:27     ` Jiufu Guo
2020-09-01  3:33 ` Jiufu Guo
2020-11-19 19:13   ` Jeff Law
2020-11-19 19:42     ` Segher Boessenkool
2020-11-19 19:53       ` Jeff Law
2020-11-19 20:01         ` Segher Boessenkool
2020-11-19 22:30           ` Jeff Law
2020-11-19 23:56             ` Segher Boessenkool
2020-11-20  7:48               ` Richard Biener
2020-11-20 14:58                 ` David Edelsohn
2020-11-20 15:22               ` Jan Hubicka
2020-11-20 18:09                 ` Segher Boessenkool
2020-11-23  8:42                   ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).