[PATCH] Add support on powerpc to change CASE_VALUES_THRESHOLD

Michael Meissner meissner@linux.vnet.ibm.com
Wed Jun 29 23:10:00 GMT 2011


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.

[gcc]
2011-06-29  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.opt (-mcase-values-threshold): New switch.

	* config/rs6000/rs6000.c (TARGET_CASE_VALUES_THRESHOLD): New
	target hook for override choice of when to do jump table vs. if
	statements based on -mcase-values-threshold=<n>.

	* doc/invoke.texi (RS/6000 and PowerPC Options): Document
	-mcase-values-threshold.

[gcc/testsuite]
2011-06-29  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* 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
meissner@linux.vnet.ibm.com	fax +1 (978) 399-6899
-------------- next part --------------
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 175662)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -521,4 +521,7 @@ mxilinx-fpu
 Target Var(rs6000_xilinx_fpu) Save
 Specify Xilinx FPU.
 
-
+mcase-values-threshold=
+Target Report Var(rs6000_case_values_threshold_num) Init(4) RejectNegative Joined UInteger Save
+Specify the smallest number of different values for which it is best to use a
+jump-table instead of a tree of conditional branches (default, 4).
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 175662)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1210,6 +1210,7 @@ static void rs6000_function_specific_pri
 					    struct cl_target_option *);
 static bool rs6000_can_inline_p (tree, tree);
 static void rs6000_set_current_function (tree);
+static unsigned int rs6000_case_values_threshold (void);
 
 
 /* Default register names.  */
@@ -1617,6 +1618,9 @@ static const struct attribute_spec rs600
 #undef TARGET_LEGITIMATE_CONSTANT_P
 #define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p
 
+#undef TARGET_CASE_VALUES_THRESHOLD
+#define TARGET_CASE_VALUES_THRESHOLD rs6000_case_values_threshold
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -26834,6 +26838,18 @@ rs6000_libcall_value (enum machine_mode 
   return gen_rtx_REG (mode, regno);
 }
 
+/* If the machine does not have a case insn that compares the bounds,
+   this means extra overhead for dispatch tables, which raises the
+   threshold for using them.  */
+
+static unsigned int
+rs6000_case_values_threshold (void)
+{
+  if (rs6000_case_values_threshold_num)
+    return rs6000_case_values_threshold_num;
+
+  return default_case_values_threshold ();
+}
 
 /* Given FROM and TO register numbers, say whether this elimination is allowed.
    Frame pointer elimination is automatically handled.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 175662)
+++ gcc/doc/invoke.texi	(working copy)
@@ -807,7 +807,7 @@ See RS/6000 and PowerPC Options.
 -msdata=@var{opt}  -mvxworks  -G @var{num}  -pthread @gol
 -mrecip -mrecip=@var{opt} -mno-recip -mrecip-precision @gol
 -mno-recip-precision @gol
--mveclibabi=@var{type} -mfriz -mno-friz}
+-mveclibabi=@var{type} -mfriz -mno-friz -mcase-values-threshold=@var{n}}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -16320,6 +16320,11 @@ Generate (do not generate) the @code{fri
 rounding a floating point value to 64-bit integer and back to floating
 point.  The @code{friz} instruction does not return the same value if
 the floating point number is too large to fit in an integer.
+
+@item -mcase-values-threshold=@var{n}
+Specify the smallest number of different values for which it is best to
+use a jump-table instead of a tree of conditional branches.  The
+default for @option{-mcase-values-threshold} is 4.
 @end table
 
 @node RX Options
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 -mcase-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 -mcase-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;
+}


More information about the Gcc-patches mailing list