On Thu, Jun 30, 2011 at 12:31:44PM +0200, Richard Guenther wrote:
> On Thu, Jun 30, 2011 at 12:34 AM, Michael Meissner
> <[email protected]> wrote:
> > On the powerpc, switch statements can be expensive, and we would like to be
> > able to tune the threshold of when the compiler generates if statements
> > vs. using a table jump operation (and different processors within the
> > powerpc
> > have different limits). This patch adds a powerpc tuning option to control
> > this.
> >
> > I've done bootstraps and make checks with no regressions. Is this ok to
> > apply
> > to the trunk? At this time, I am not changing the default value (4). With
> > the
> > option, I've seen a few spec 2006 benchmarks run faster, and a few run
> > slower.
>
> Hmm. This hook looks like it could be turned into a --param. In fact
> it doesn't get whatever context information, so I wonder if any target
> does something fancy.
I've done it also as a --param. I tend to think it is better as a param, and
then other people can tune their code. One slight problem is the default for
CASE_VALUES_THRESHOLD depends on whether you have a named casesi pattern that
is active (HAVE_casesi ? 4 : 5). Either we need two separate parameters, or we
have just one parameter, and if that is 0, fall back to the 4 or 5 value.
This patch swtiches to use --param to set the value. Is it acceptable to check
in? I've done a bootstrap and I'm about to do a make check.
[gcc]
2011-06-30 Michael Meissner <[email protected]>
* params.def (PARAM_CASE_VALUES_THRESHOLD): New parameter to
override CASE_VALUES_THRESHOLD.
* stmt.c (toplevel): Include params.h.
(case_values_threshold): Use the --param case-values-threshold
value if non-zero, otherwise use machine dependent value.
(expand_case): Use case_values_threshold.
* Makefile.in (stmt.o): Add $(PARAMS_H) dependency.
* doc/invoke.texi (--param case-values-threshold): Document.
[gcc/testsuite]
2011-06-30 Michael Meissner <[email protected]>
* gcc.target/powerpc/ppc-switch-1.c: New test for
-mcase-values-threshold.
* gcc.target/powerpc/ppc-switch-2.c: Ditto.
--
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
[email protected] fax +1 (978) 399-6899
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 175662)
+++ gcc/doc/invoke.texi (working copy)
@@ -9026,6 +9026,11 @@ The maximum number of conditional stores
if either vectorization (@option{-ftree-vectorize}) or if-conversion
(@option{-ftree-loop-if-convert}) is disabled. The default is 2.
+@item case-values-threshold
+The smallest number of different values for which it is best to use a
+jump-table instead of a tree of conditional branches. If the value is
+0, use the default for the machine. The default is 0.
+
@end table
@end table
Index: gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/ppc-switch-1.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-options "-O2 --param case-values-threshold=2" } */
+/* { dg-final { scan-assembler "mtctr" } } */
+/* { dg-final { scan-assembler "bctr" } } */
+
+/* Force using a dispatch table even though by default we would generate
+ ifs. */
+
+extern long call (long);
+
+long
+test_switch (long a, long b)
+{
+ long c;
+
+ switch (a)
+ {
+ case 0: c = -b; break;
+ case 1: c = ~b; break;
+ case 2: c = b+1; break;
+ default: c = b & 9; break;
+ }
+
+ return call (c) + 1;
+}
Index: gcc/testsuite/gcc.target/powerpc/ppc-switch-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/ppc-switch-2.c (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/ppc-switch-2.c (revision 0)
@@ -0,0 +1,32 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-options "-O2 --param case-values-threshold=20" } */
+/* { dg-final { scan-assembler-not "mtctr" } } */
+/* { dg-final { scan-assembler-not "bctr" } } */
+
+/* Force using if tests, instead of a dispatch table. */
+
+extern long call (long);
+
+long
+test_switch (long a, long b)
+{
+ long c;
+
+ switch (a)
+ {
+ case 0: c = -b; break;
+ case 1: c = ~b; break;
+ case 2: c = b+1; break;
+ case 3: c = b-2; break;
+ case 4: c = b*3; break;
+ case 5: c = b/4; break;
+ case 6: c = b<<5; break;
+ case 7: c = b>>6; break;
+ case 8: c = b|7; break;
+ case 9: c = b^8; break;
+ default: c = b&9; break;
+ }
+
+ return call (c) + 1;
+}
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in (revision 175662)
+++ gcc/Makefile.in (working copy)
@@ -2946,7 +2946,7 @@ stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H)
$(LIBFUNCS_H) $(EXCEPT_H) $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
output.h $(GGC_H) $(TM_P_H) langhooks.h $(PREDICT_H) $(OPTABS_H) \
$(TARGET_H) $(GIMPLE_H) $(MACHMODE_H) $(REGS_H) alloc-pool.h \
- $(PRETTY_PRINT_H) $(BITMAP_H)
+ $(PRETTY_PRINT_H) $(BITMAP_H) $(PARAMS_H)
except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(EXCEPT_H) $(FUNCTION_H) $(EXPR_H) $(LIBFUNCS_H) \
langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
Index: gcc/stmt.c
===================================================================
--- gcc/stmt.c (revision 175662)
+++ gcc/stmt.c (working copy)
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.
#include "alloc-pool.h"
#include "pretty-print.h"
#include "bitmap.h"
+#include "params.h"
/* Functions and data structures for expanding case statements. */
@@ -2270,6 +2271,20 @@ expand_switch_using_bit_tests_p (tree in
|| (uniq == 3 && count >= 6)));
}
+/* Return the smallest number of different values for which it is best to use a
+ jump-table instead of a tree of conditional branches. */
+
+static unsigned int
+case_values_threshold (void)
+{
+ unsigned int threshold = PARAM_VALUE (PARAM_CASE_VALUES_THRESHOLD);
+
+ if (threshold == 0)
+ threshold = targetm.case_values_threshold ();
+
+ return threshold;
+}
+
/* Terminate a case (Pascal/Ada) or switch (C) statement
in which ORIG_INDEX is the expression to be tested.
If ORIG_TYPE is not NULL, it is the original ORIG_INDEX
@@ -2424,7 +2439,7 @@ expand_case (gimple stmt)
If the switch-index is a constant, do it this way
because we can optimize it. */
- else if (count < targetm.case_values_threshold ()
+ else if (count < case_values_threshold ()
|| compare_tree_int (range,
(optimize_insn_for_size_p () ? 3 : 10) *
count) > 0
/* RANGE may be signed, and really large ranges will show up
Index: gcc/params.def
===================================================================
--- gcc/params.def (revision 175662)
+++ gcc/params.def (working copy)
@@ -892,6 +892,16 @@ DEFPARAM (PARAM_MAX_STORES_TO_SINK,
"Maximum number of conditional store pairs that can be sunk",
2, 0, 0)
+/* Override CASE_VALUES_THRESHOLD of when to switch from doing switch
+ statements via if statements to using a table jump operation. If the value
+ is 0, the default CASE_VALUES_THRESHOLD will be used. */
+DEFPARAM (PARAM_CASE_VALUES_THRESHOLD,
+ "case-values-threshold",
+ "The smallest number of different values for which it is best to "
+ "use a jump-table instead of a tree of conditional branches, "
+ "if 0, use the default for the machine",
+ 0, 0, 0)
+
/*
Local variables: