aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2010-04-08 15:07:57 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2010-04-08 15:07:57 +0000
commit40ac4f73faa256e049279c1611d47a685ff7f370 (patch)
tree0ebeefa37492fc33063a9f55bc090391a092d0fd
parent07c60ef701e0fe0c65f0186bd521ee83b6c24c3c (diff)
downloadgcc-40ac4f73faa256e049279c1611d47a685ff7f370.zip
gcc-40ac4f73faa256e049279c1611d47a685ff7f370.tar.gz
gcc-40ac4f73faa256e049279c1611d47a685ff7f370.tar.bz2
Implement target hook for loop unrolling
2010-04-08 Christian Borntraeger <borntraeger@de.ibm.com> Wolfgang Gellerich <gellerich@de.ibm.com> Implement target hook for loop unrolling * target.h (loop_unroll_adjust): Add a new target hook function. * target-def.h (TARGET_LOOP_UNROLL_ADJUST): Likewise. * doc/tm.texi (TARGET_LOOP_UNROLL_ADJUST): Document it. * config/s390/s390.c (TARGET_LOOP_UNROLL_ADJUST): Define it. (s390_loop_unroll_adjust): Implement the new target hook for s390. * loop-unroll.c (decide_unroll_runtime_iterations): Call loop unroll target hook (decide_unroll_stupid): Likewise. Co-Authored-By: Wolfgang Gellerich <gellerich@de.ibm.com> From-SVN: r158132
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/s390/s390.c60
-rw-r--r--gcc/doc/tm.texi9
-rw-r--r--gcc/loop-unroll.c7
-rw-r--r--gcc/target-def.h2
-rw-r--r--gcc/target.h6
6 files changed, 96 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d9eb6d..ecf1f26 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2010-04-08 Christian Borntraeger <borntraeger@de.ibm.com>
+ Wolfgang Gellerich <gellerich@de.ibm.com>
+
+ Implement target hook for loop unrolling
+ * target.h (loop_unroll_adjust): Add a new target hook function.
+ * target-def.h (TARGET_LOOP_UNROLL_ADJUST): Likewise.
+ * doc/tm.texi (TARGET_LOOP_UNROLL_ADJUST): Document it.
+ * config/s390/s390.c (TARGET_LOOP_UNROLL_ADJUST): Define it.
+ (s390_loop_unroll_adjust): Implement the new target hook for s390.
+ * loop-unroll.c (decide_unroll_runtime_iterations): Call loop unroll target hook
+ (decide_unroll_stupid): Likewise.
+
2010-04-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR target/43643
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index e6cc4ba..fea70fb 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "df.h"
#include "params.h"
+#include "cfgloop.h"
/* Define the specific costs for a given cpu. */
@@ -10245,6 +10246,62 @@ s390_sched_init (FILE *file ATTRIBUTE_UNUSED,
last_scheduled_insn = NULL_RTX;
}
+/* This function checks the whole of insn X for memory references. The
+ function always returns zero because the framework it is called
+ from would stop recursively analyzing the insn upon a return value
+ other than zero. The real result of this function is updating
+ counter variable MEM_COUNT. */
+static int
+check_dpu (rtx *x, unsigned *mem_count)
+{
+ if (*x != NULL_RTX && MEM_P (*x))
+ (*mem_count)++;
+ return 0;
+}
+
+/* This target hook implementation for TARGET_LOOP_UNROLL_ADJUST calculates
+ a new number struct loop *loop should be unrolled if tuned for the z10
+ cpu. The loop is analyzed for memory accesses by calling check_dpu for
+ each rtx of the loop. Depending on the loop_depth and the amount of
+ memory accesses a new number <=nunroll is returned to improve the
+ behaviour of the hardware prefetch unit. */
+static unsigned
+s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
+{
+ basic_block *bbs;
+ rtx insn;
+ unsigned i;
+ unsigned mem_count = 0;
+
+ /* Only z10 needs special handling. */
+ if (s390_tune != PROCESSOR_2097_Z10)
+ return nunroll;
+
+ /* Count the number of memory references within the loop body. */
+ bbs = get_loop_body (loop);
+ for (i = 0; i < loop->num_nodes; i++)
+ {
+ for (insn = BB_HEAD (bbs[i]); insn != BB_END (bbs[i]); insn = NEXT_INSN (insn))
+ if (INSN_P (insn) && INSN_CODE (insn) != -1)
+ for_each_rtx (&insn, (rtx_function) check_dpu, &mem_count);
+ }
+ free (bbs);
+
+ /* Prevent division by zero, and we do not need to adjust nunroll in this case. */
+ if (mem_count == 0)
+ return nunroll;
+
+ switch (loop_depth(loop))
+ {
+ case 1:
+ return MIN (nunroll, 28 / mem_count);
+ case 2:
+ return MIN (nunroll, 22 / mem_count);
+ default:
+ return MIN (nunroll, 16 / mem_count);
+ }
+}
+
/* Initialize GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -10373,6 +10430,9 @@ s390_sched_init (FILE *file ATTRIBUTE_UNUSED,
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE s390_can_eliminate
+#undef TARGET_LOOP_UNROLL_ADJUST
+#define TARGET_LOOP_UNROLL_ADJUST s390_loop_unroll_adjust
+
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
#define TARGET_ASM_TRAMPOLINE_TEMPLATE s390_asm_trampoline_template
#undef TARGET_TRAMPOLINE_INIT
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 012edd7..222117d 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10881,6 +10881,15 @@ This target hook is required only when the target has several different
modes and they have different conditional execution capability, such as ARM.
@end deftypefn
+@deftypefn {Target Hook} unsigned TARGET_LOOP_UNROLL_ADJUST (unsigned @var{nunroll}, struct loop *@var{loop})
+This target hook returns a new value for the number of times @var{loop}
+should be unrolled. The parameter @var{nunroll} is the number of times
+the loop is to be unrolled. The parameter @var{loop} is a pointer to
+the loop, which is going to be checked for unrolling. This target hook
+is required only when the target has special constraints like maximum
+number of memory accesses.
+@end deftypefn
+
@defmac POWI_MAX_MULTS
If defined, this macro is interpreted as a signed integer C expression
that specifies the maximum number of floating point multiplications
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 231d12d..8ea449d 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "hashtab.h"
#include "recog.h"
+#include "target.h"
/* This pass performs loop unrolling and peeling. We only perform these
optimizations on innermost loops (with single exception) because
@@ -826,6 +827,9 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES))
nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES);
+ if (targetm.loop_unroll_adjust)
+ nunroll = targetm.loop_unroll_adjust (nunroll, loop);
+
/* Skip big loops. */
if (nunroll <= 1)
{
@@ -1366,6 +1370,9 @@ decide_unroll_stupid (struct loop *loop, int flags)
if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES))
nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES);
+ if (targetm.loop_unroll_adjust)
+ nunroll = targetm.loop_unroll_adjust (nunroll, loop);
+
/* Skip big loops. */
if (nunroll <= 1)
{
diff --git a/gcc/target-def.h b/gcc/target-def.h
index a3c0b2c..d056665 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -545,6 +545,7 @@
default_branch_target_register_class
#define TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED hook_bool_bool_false
#define TARGET_HAVE_CONDITIONAL_EXECUTION default_have_conditional_execution
+#define TARGET_LOOP_UNROLL_ADJUST NULL
#define TARGET_CANNOT_FORCE_CONST_MEM hook_bool_rtx_false
#define TARGET_CANNOT_COPY_INSN_P NULL
#define TARGET_COMMUTATIVE_P hook_bool_const_rtx_commutative_p
@@ -947,6 +948,7 @@
TARGET_BRANCH_TARGET_REGISTER_CLASS, \
TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED, \
TARGET_HAVE_CONDITIONAL_EXECUTION, \
+ TARGET_LOOP_UNROLL_ADJUST, \
TARGET_CANNOT_FORCE_CONST_MEM, \
TARGET_CANNOT_COPY_INSN_P, \
TARGET_COMMUTATIVE_P, \
diff --git a/gcc/target.h b/gcc/target.h
index 41ae3e3..e4e82a3 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -97,6 +97,9 @@ struct _dep;
/* This is defined in ddg.h . */
struct ddg;
+/* This is defined in cfgloop.h . */
+struct loop;
+
/* Assembler instructions for creating various kinds of integer object. */
struct asm_int_op
@@ -637,6 +640,9 @@ struct gcc_target
/* Return true if the target supports conditional execution. */
bool (* have_conditional_execution) (void);
+ /* Return a new value for loop unroll size. */
+ unsigned (* loop_unroll_adjust) (unsigned nunroll, struct loop *loop);
+
/* True if the constant X cannot be placed in the constant pool. */
bool (* cannot_force_const_mem) (rtx);