[v2] , Improve PowerPC switch behavior on medium code model system

Message ID 20180829230352.GA20250@ibm-toto.the-meissners.org
State New
Headers show
Series
  • [v2] , Improve PowerPC switch behavior on medium code model system
Related show

Commit Message

Michael Meissner Aug. 29, 2018, 11:03 p.m.
This patch is a respin of the original patch.

I moved the support for the LWAX instruction in a separate patch, and it has
already been committed.

I added a test case for the switch code on PowerPC LE medium code.

I made the labelref insn not have a generator because there was no caller for
it (the labelref insn is created by the fwprop pass).

I did a bootstrap test on a little endian power8 system and there were no
regressions.  Can I commit this patch?  Assuming I put it into the tree, should
I back port it to GCC 8 and possibly GCC 7.

[gcc]
2018-08-29  Michael Meissner  <meissner@linux.ibm.com>

	* config/rs6000/predicates.md (label_ref_operand): New predicate
	to recognize LABEL_REF.
	* config/rs6000/rs6000.c (rs6000_output_addr_const_extra): Allow
	LABEL_REF's inside of UNSPEC_TOCREL's.
	* config/rs6000/rs6000.md (labelref): New insn to optimize loading
	a label address into registers on a medium code system.

[gcc/testsuite]
2018-08-29  Michael Meissner  <meissner@linux.ibm.com>

	* gcc.target/powerpc/switch-01.c: New test to verify that we use
	TOC commands to load the label address.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

Patch

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 263965)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -1662,6 +1662,10 @@  (define_predicate "small_toc_ref"
   return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
 })
 
+;; Match a LABEL_REF operand
+(define_predicate "label_ref_operand"
+  (match_code "label_ref"))
+
 ;; Match the first insn (addis) in fusing the combination of addis and loads to
 ;; GPR registers on power8.
 (define_predicate "fusion_gpr_addis"
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 263965)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -20994,7 +20994,8 @@  rs6000_output_addr_const_extra (FILE *fi
     switch (XINT (x, 1))
       {
       case UNSPEC_TOCREL:
-	gcc_checking_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF
+	gcc_checking_assert ((GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF
+			      || GET_CODE (XVECEXP (x, 0, 0)) == LABEL_REF)
 			     && REG_P (XVECEXP (x, 0, 1))
 			     && REGNO (XVECEXP (x, 0, 1)) == TOC_REGISTER);
 	output_addr_const (file, XVECEXP (x, 0, 0));
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 263965)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -10219,6 +10219,21 @@  (define_insn_and_split "*tocref<mode>"
   [(set (match_dup 0) (high:P (match_dup 1)))
    (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])
 
+;; This pattern exists to allow fwprop to convert the load of the LABEL_REF
+;; address for switches into using ADDIS/ADDI if we can use the TOC
+;; to get the address.
+(define_insn_and_split "*labelref"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
+	(match_operand:DI 1 "label_ref_operand"))]
+  "TARGET_POWERPC64 && TARGET_ELF && TARGET_CMODEL == CMODEL_MEDIUM"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+	(match_dup 2))]
+{
+  operands[2] = create_TOC_reference (operands[1], NULL_RTX);
+})
+
 ;; Elf specific ways of loading addresses for non-PIC code.
 ;; The output of this could be r0, but we make a very strong
 ;; preference for a base register because it will usually
Index: gcc/testsuite/gcc.target/powerpc/switch-01.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/switch-01.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/switch-01.c	(working copy)
@@ -0,0 +1,29 @@ 
+/* { dg-do compile { target { powerpc64le*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcmodel=medium -mcpu=power8" } */
+
+/* Test that we don't load the label address when creating a switch table on
+   PowerPC LE systems using the medium code model.  */
+
+unsigned long test (unsigned long a, unsigned long b, unsigned long c)
+{
+  switch (a)
+  {
+    default: return a+b;
+    case 10: return a-b;
+    case 11: return a*b;
+    case 12: return a/b;
+    case 13: return a<<b;
+    case 14: return a>>b;
+    case 15: return a | b;
+    case 16: return a & b;
+    case 17: return a ^ b;
+    case 18: return a & ~b;
+    case 19: return a | ~b;
+    case 20: return a ^ ~b;
+  }
+}
+
+/* { dg-final { scan-assembler-not {\mld\M}              } } */
+/* { dg-final { scan-assembler     {\maddis .*@toc@ha\M} } } */
+/* { dg-final { scan-assembler     {\maddi .*@toc@l\M}   } }   */