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  <meiss...@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  <meiss...@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: meiss...@linux.ibm.com, phone: +1 (978) 899-4797
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}   } }   */

Reply via email to