As I discussed in my 2018 Cauldron talk, the PowerPC GCC compiler supported a
subset of the original design for fusion in the power9 hardware using peepholes
to fuse together ADDIS instructions and floating point load/store operations.

However, while fusion was part of the original power9 design, by the time the
machine came out, the fusion support was no longer part of the architecture.

This patch removes all of the so-called power9 fusion support for the GCC
compiler.  It leaves -mpower9-fusion as a deprecated switch in case somebody
used it (the switch was never documented).  If you do -mcpu=power9, it will
turn off the power8 fusion support.  If you do -mcpu=power8 and -mtune=power9,
it will also turn off the power8 fusion support.

I have done a bootstrap on a power9 system and there were no regressions in the
tests, other than the two tests for power9 fusion that are now deleted as part
of this patch.  I have also done runs of the Spec 2006 benchmark on the same
machine with and without the patches.  The CactusADM benchmark gets a slight
bump (1.6%) if it doesn't do the power9 fusion.

Can I check these changes into the GCC 9 trunk?

[gcc]
2018-11-02  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/constraints.md (wF constraint): Only document the
        wF constraint for power8 fusion.  Remove documentation for power9
        fusion.
        * config/rs6000/predicates.md (p9_fusion_reg_operand): Delete, the
        predicate only used for power9 fusion support.
        (fusion_gpr_addis): Drop support to allow fusing offsets where the
        top 11 bits weren't all 0 or all 1's.
        (fusion_gpr_mem_load): Add comment about not allowing SFmode or
        DFmode in power8 fusion.
        (fusion_addis_mem_combo_load): Drop power9 fusion support.  Only
        support power8 fusion.  Add comment about not allowing SFmode or
        DFmode in power8 fusion.
        (fusion_offsettable_mem_operand): Delete, the predicate only used
        for power9 fusion support.
        * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_NO_FUSION): New
        option masks that is all of the ISA 2.07 bits except for fusion.
        (ISA_2_7_MASKS_SERVER): Add fusion bits back in.
        (ISA_3_0_MASKS_SERVER): Delete power9 fusion.  Use ISA 2.07 bits
        without enabling power8 fusion.
        (POWERPC_MASKS): Delete power9 fusion option mask.
        * config/rs6000/rs6000-protos.h (emit_fusion_load_store): Delete
        function declarations used for power9 fusion.
        (fusion_p9_p): Likewise.
        (expand_fusion_p9_load): Likewise.
        (expand_fusion_p9_store): Likewise.
        (emit_fusion_p9_load): Likewise.
        (emit_fusion_p9_store): Likewise.
        * config/rs6000/rs6000.c (rs6000_debug_reg_global): Delete power9
        fusion debug print.
        (rs6000_option_override_internal): Delete power9 fusion option
        support.  If we do -mcpu=power8 -mtune=power9, turn off power8
        fusion.
        (rs6000_opt_masks): Delete power9 fusion option.
        (emit_fusion_load): Rename function from emit_fusion_load_store.
        Make the function static.  Delete support for fusing stores, since
        we are deleting power9 fusion.
        (fusion_p9_p): Delete power9 fusion support functions.
        (expand_fusion_p9_load): Likewise.
        (expand_fusion_p9_store): Likewise.
        (emit_fusion_p9_load): Likewise.
        (emit_fusion_p9_store): Likewise.
        * config/rs6000/rs6000.h: Delete comment about power9 fusion.
        * config/rs6000/rs6000.md (UNSPEC_FUSION_P9): Delete, no longer
        used since power9 fusion support has been deleted.
        (GPR_FUSION iterator): Likewise.
        (FPR_FUSION iterator): Likewise.
        (power9 fusion peephole2's): Likewise.
        (fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load): Likewise.
        (fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store): Likewise.
        (fusion_vsx_<P:mode>_<FPR_FUSION:mode>_load): Likewise.
        (fusion_vsx_<P:mode>_<FPR_FUSION:mode>_store): Likewise.
        (fusion_p9_<mode>_constant): Likewise.
        * config/rs6000/rs6000.opt (-mpower9-fusion): Mark as deprecated.
        * doc/md.texi (PowerPC constraints): Update wF documentation.

[gcc/testsuite]
2018-11-02  Michael Meissner  <meiss...@linux.ibm.com>

        * gcc.target/powerpc/fusion3.c: Delete power9 fusion.
        * gcc.target/powerpc/fusion4.c: Likewise.


-- 
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/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md 
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/rs6000.md (.../gcc/config/rs6000) (working copy)
@@ -136,7 +136,6 @@ (define_c_enum "unspec"
    UNSPEC_LSQ
    UNSPEC_FUSION_GPR
    UNSPEC_STACK_CHECK
-   UNSPEC_FUSION_P9
    UNSPEC_ADD_ROUND_TO_ODD
    UNSPEC_SUB_ROUND_TO_ODD
    UNSPEC_MUL_ROUND_TO_ODD
@@ -349,19 +348,6 @@ (define_mode_iterator HSI [HI SI])
 ; SImode or DImode, even if DImode doesn't fit in GPRs.
 (define_mode_iterator SDI [SI DI])
 
-; Types that can be fused with an ADDIS instruction to load or store a GPR
-; register that has reg+offset addressing.
-(define_mode_iterator GPR_FUSION [QI
-                                 HI
-                                 SI
-                                 (DI   "TARGET_POWERPC64")
-                                 SF
-                                 (DF   "TARGET_POWERPC64")])
-
-; Types that can be fused with an ADDIS instruction to load or store a FPR
-; register that has reg+offset addressing.
-(define_mode_iterator FPR_FUSION [DI SF DF])
-
 ; The size of a pointer.  Also, the size of the value that a record-condition
 ; (one with a '.') will compare; and the size used for arithmetic carries.
 (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
@@ -13712,134 +13698,6 @@ (define_insn "*fusion_gpr_load_<mode>"
    (set_attr "length" "8")])
 
 
-;; ISA 3.0 (power9) fusion support
-;; Merge addis with floating load/store to FPRs (or GPRs).
-(define_peephole2
-  [(set (match_operand:P 0 "base_reg_operand")
-       (match_operand:P 1 "fusion_gpr_addis"))
-   (set (match_operand:SFDF 2 "p9_fusion_reg_operand")
-       (match_operand:SFDF 3 "fusion_offsettable_mem_operand"))]
-  "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
-   && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])"
-  [(const_int 0)]
-{
-  expand_fusion_p9_load (operands);
-  DONE;
-})
-
-(define_peephole2
-  [(set (match_operand:P 0 "base_reg_operand")
-       (match_operand:P 1 "fusion_gpr_addis"))
-   (set (match_operand:SFDF 2 "offsettable_mem_operand")
-       (match_operand:SFDF 3 "p9_fusion_reg_operand"))]
-  "TARGET_P9_FUSION && peep2_reg_dead_p (2, operands[0])
-   && fusion_p9_p (operands[0], operands[1], operands[2], operands[3])
-   && !rtx_equal_p (operands[0], operands[3])"
-  [(const_int 0)]
-{
-  expand_fusion_p9_store (operands);
-  DONE;
-})
-
-(define_peephole2
-  [(set (match_operand:SDI 0 "int_reg_operand")
-       (match_operand:SDI 1 "upper16_cint_operand"))
-   (set (match_dup 0)
-       (ior:SDI (match_dup 0)
-                (match_operand:SDI 2 "u_short_cint_operand")))]
-  "TARGET_P9_FUSION"
-  [(set (match_dup 0)
-       (unspec:SDI [(match_dup 1)
-                    (match_dup 2)] UNSPEC_FUSION_P9))])
-
-(define_peephole2
-  [(set (match_operand:SDI 0 "int_reg_operand")
-       (match_operand:SDI 1 "upper16_cint_operand"))
-   (set (match_operand:SDI 2 "int_reg_operand")
-       (ior:SDI (match_dup 0)
-                (match_operand:SDI 3 "u_short_cint_operand")))]
-  "TARGET_P9_FUSION
-   && !rtx_equal_p (operands[0], operands[2])
-   && peep2_reg_dead_p (2, operands[0])"
-  [(set (match_dup 2)
-       (unspec:SDI [(match_dup 1)
-                    (match_dup 3)] UNSPEC_FUSION_P9))])
-
-;; Fusion insns, created by the define_peephole2 above (and eventually by
-;; reload).  Because we want to eventually have secondary_reload generate
-;; these, they have to have a single alternative that gives the register
-;; classes.  This means we need to have separate gpr/fpr/altivec versions.
-(define_insn "*fusion_gpr_<P:mode>_<GPR_FUSION:mode>_load"
-  [(set (match_operand:GPR_FUSION 0 "int_reg_operand" "=r")
-       (unspec:GPR_FUSION
-        [(match_operand:GPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
-        UNSPEC_FUSION_P9))
-   (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
-  "TARGET_P9_FUSION"
-{
-  /* This insn is a secondary reload insn, which cannot have alternatives.
-     If we are not loading up register 0, use the power8 fusion instead.  */
-  if (base_reg_operand (operands[0], <GPR_FUSION:MODE>mode))
-    return emit_fusion_gpr_load (operands[0], operands[1]);
-
-  return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
-}
-  [(set_attr "type" "load")
-   (set_attr "length" "8")])
-
-(define_insn "*fusion_gpr_<P:mode>_<GPR_FUSION:mode>_store"
-  [(set (match_operand:GPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
-       (unspec:GPR_FUSION
-        [(match_operand:GPR_FUSION 1 "int_reg_operand" "r")]
-        UNSPEC_FUSION_P9))
-   (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
-  "TARGET_P9_FUSION"
-{
-  return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
-}
-  [(set_attr "type" "store")
-   (set_attr "length" "8")])
-
-(define_insn "*fusion_vsx_<P:mode>_<FPR_FUSION:mode>_load"
-  [(set (match_operand:FPR_FUSION 0 "vsx_register_operand" "=dwb")
-       (unspec:FPR_FUSION
-        [(match_operand:FPR_FUSION 1 "fusion_addis_mem_combo_load" "wF")]
-        UNSPEC_FUSION_P9))
-   (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
-  "TARGET_P9_FUSION"
-{
-  return emit_fusion_p9_load (operands[0], operands[1], operands[2]);
-}
-  [(set_attr "type" "fpload")
-   (set_attr "length" "8")])
-
-(define_insn "*fusion_vsx_<P:mode>_<FPR_FUSION:mode>_store"
-  [(set (match_operand:FPR_FUSION 0 "fusion_addis_mem_combo_store" "=wF")
-       (unspec:FPR_FUSION
-        [(match_operand:FPR_FUSION 1 "vsx_register_operand" "dwb")]
-        UNSPEC_FUSION_P9))
-   (clobber (match_operand:P 2 "base_reg_operand" "=b"))]
-  "TARGET_P9_FUSION"
-{
-  return emit_fusion_p9_store (operands[0], operands[1], operands[2]);
-}
-  [(set_attr "type" "fpstore")
-   (set_attr "length" "8")])
-
-(define_insn "*fusion_p9_<mode>_constant"
-  [(set (match_operand:SDI 0 "int_reg_operand" "=r")
-       (unspec:SDI [(match_operand:SDI 1 "upper16_cint_operand" "L")
-                    (match_operand:SDI 2 "u_short_cint_operand" "K")]
-                   UNSPEC_FUSION_P9))] 
-  "TARGET_P9_FUSION"
-{
-  emit_fusion_addis (operands[0], operands[1]);
-  return "ori %0,%0,%2";
-}
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-
 ;; Optimize cases where we want to do a D-form load (register+offset) on
 ;; ISA 2.06/2.07 to an Altivec register, and the register allocator
 ;; has generated:
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/rs6000.c  (.../gcc/config/rs6000) (working copy)
@@ -2787,7 +2787,7 @@ rs6000_debug_reg_global (void)
     {
       char options[80];
 
-      strcpy (options, (TARGET_P9_FUSION) ? "power9" : "power8");
+      strcpy (options, "power8");
       if (TARGET_P8_FUSION_SIGN)
        strcat (options, ", sign");
 
@@ -4163,10 +4163,17 @@ rs6000_option_override_internal (bool gl
     rs6000_isa_flags |= OPTION_MASK_SAVE_TOC_INDIRECT;
 
   /* Enable power8 fusion if we are tuning for power8, even if we aren't
-     generating power8 instructions.  */
+     generating power8 instructions.  The power9 cpu does not set the power8
+     fusion option mask, so if you tune for power9 it will not add fusion
+     support.  */
   if (!(rs6000_isa_flags_explicit & OPTION_MASK_P8_FUSION))
-    rs6000_isa_flags |= (processor_target_table[tune_index].target_enable
-                        & OPTION_MASK_P8_FUSION);
+    {
+      if (processor_target_table[tune_index].target_enable
+         & OPTION_MASK_P8_FUSION)
+       rs6000_isa_flags |= OPTION_MASK_P8_FUSION;
+      else
+       rs6000_isa_flags &= ~OPTION_MASK_P8_FUSION;
+    }
 
   /* Setting additional fusion flags turns on base fusion.  */
   if (!TARGET_P8_FUSION && TARGET_P8_FUSION_SIGN)
@@ -4183,28 +4190,6 @@ rs6000_option_override_internal (bool gl
        rs6000_isa_flags |= OPTION_MASK_P8_FUSION;
     }
 
-  /* Power9 fusion is a superset over power8 fusion.  */
-  if (TARGET_P9_FUSION && !TARGET_P8_FUSION)
-    {
-      if (rs6000_isa_flags_explicit & OPTION_MASK_P8_FUSION)
-       {
-         /* We prefer to not mention undocumented options in
-            error messages.  However, if users have managed to select
-            power9-fusion without selecting power8-fusion, they
-            already know about undocumented flags.  */
-         error ("%qs requires %qs", "-mpower9-fusion", "-mpower8-fusion");
-         rs6000_isa_flags &= ~OPTION_MASK_P9_FUSION;
-       }
-      else
-       rs6000_isa_flags |= OPTION_MASK_P8_FUSION;
-    }
-
-  /* Enable power9 fusion if we are tuning for power9, even if we aren't
-     generating power9 instructions.  */
-  if (!(rs6000_isa_flags_explicit & OPTION_MASK_P9_FUSION))
-    rs6000_isa_flags |= (processor_target_table[tune_index].target_enable
-                        & OPTION_MASK_P9_FUSION);
-
   /* Power8 does not fuse sign extended loads with the addis.  If we are
      optimizing at high levels for speed, convert a sign extended load into a
      zero extending load, and an explicit sign extension.  */
@@ -36010,7 +35995,6 @@ static struct rs6000_opt_mask const rs60
   { "power8-fusion",           OPTION_MASK_P8_FUSION,          false, true  },
   { "power8-fusion-sign",      OPTION_MASK_P8_FUSION_SIGN,     false, true  },
   { "power8-vector",           OPTION_MASK_P8_VECTOR,          false, true  },
-  { "power9-fusion",           OPTION_MASK_P9_FUSION,          false, true  },
   { "power9-minmax",           OPTION_MASK_P9_MINMAX,          false, true  },
   { "power9-misc",             OPTION_MASK_P9_MISC,            false, true  },
   { "power9-vector",           OPTION_MASK_P9_VECTOR,          false, true  },
@@ -38116,14 +38100,13 @@ emit_fusion_addis (rtx target, rtx addis
 /* Emit a D-form load or store instruction that is the second instruction
    of a fusion sequence.  */
 
-void
-emit_fusion_load_store (rtx load_store_reg, rtx addis_reg, rtx offset,
-                       const char *insn_str)
+static void
+emit_fusion_load (rtx load_reg, rtx addis_reg, rtx offset, const char 
*insn_str)
 {
   rtx fuse_ops[10];
   char insn_template[80];
 
-  fuse_ops[0] = load_store_reg;
+  fuse_ops[0] = load_reg;
   fuse_ops[1] = addis_reg;
 
   if (CONST_INT_P (offset) && satisfies_constraint_I (offset))
@@ -38261,367 +38244,12 @@ emit_fusion_gpr_load (rtx target, rtx me
   emit_fusion_addis (target, addis_value);
 
   /* Emit the D-form load instruction.  */
-  emit_fusion_load_store (target, target, load_offset, load_str);
+  emit_fusion_load (target, target, load_offset, load_str);
 
   return "";
 }
 
 
-/* Return true if the peephole2 can combine a load/store involving a
-   combination of an addis instruction and the memory operation.  This was
-   added to the ISA 3.0 (power9) hardware.  */
-
-bool
-fusion_p9_p (rtx addis_reg,            /* register set via addis.  */
-            rtx addis_value,           /* addis value.  */
-            rtx dest,                  /* destination (memory or register). */
-            rtx src)                   /* source (register or memory).  */
-{
-  rtx addr, mem, offset;
-  machine_mode mode = GET_MODE (src);
-
-  /* Validate arguments.  */
-  if (!base_reg_operand (addis_reg, GET_MODE (addis_reg)))
-    return false;
-
-  if (!fusion_gpr_addis (addis_value, GET_MODE (addis_value)))
-    return false;
-
-  /* Ignore extend operations that are part of the load.  */
-  if (GET_CODE (src) == FLOAT_EXTEND || GET_CODE (src) == ZERO_EXTEND)
-    src = XEXP (src, 0);
-
-  /* Test for memory<-register or register<-memory.  */
-  if (fpr_reg_operand (src, mode) || int_reg_operand (src, mode))
-    {
-      if (!MEM_P (dest))
-       return false;
-
-      mem = dest;
-    }
-
-  else if (MEM_P (src))
-    {
-      if (!fpr_reg_operand (dest, mode) && !int_reg_operand (dest, mode))
-       return false;
-
-      mem = src;
-    }
-
-  else
-    return false;
-
-  addr = XEXP (mem, 0);                        /* either PLUS or LO_SUM.  */
-  if (GET_CODE (addr) == PLUS)
-    {
-      if (!rtx_equal_p (addis_reg, XEXP (addr, 0)))
-       return false;
-
-      return satisfies_constraint_I (XEXP (addr, 1));
-    }
-
-  else if (GET_CODE (addr) == LO_SUM)
-    {
-      if (!rtx_equal_p (addis_reg, XEXP (addr, 0)))
-       return false;
-
-      offset = XEXP (addr, 1);
-      if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64))
-       return small_toc_ref (offset, GET_MODE (offset));
-
-      else if (TARGET_ELF && !TARGET_POWERPC64)
-       return CONSTANT_P (offset);
-    }
-
-  return false;
-}
-
-/* During the peephole2 pass, adjust and expand the insns for an extended 
fusion
-   load sequence.
-
-   The operands are:
-       operands[0]     register set with addis
-       operands[1]     value set via addis
-       operands[2]     target register being loaded
-       operands[3]     D-form memory reference using operands[0].
-
-  This is similar to the fusion introduced with power8, except it scales to
-  both loads/stores and does not require the result register to be the same as
-  the base register.  At the moment, we only do this if register set with addis
-  is dead.  */
-
-void
-expand_fusion_p9_load (rtx *operands)
-{
-  rtx tmp_reg = operands[0];
-  rtx addis_value = operands[1];
-  rtx target = operands[2];
-  rtx orig_mem = operands[3];
-  rtx  new_addr, new_mem, orig_addr, offset, set, clobber, insn;
-  enum rtx_code plus_or_lo_sum;
-  machine_mode target_mode = GET_MODE (target);
-  machine_mode extend_mode = target_mode;
-  machine_mode ptr_mode = Pmode;
-  enum rtx_code extend = UNKNOWN;
-
-  if (GET_CODE (orig_mem) == FLOAT_EXTEND || GET_CODE (orig_mem) == 
ZERO_EXTEND)
-    {
-      extend = GET_CODE (orig_mem);
-      orig_mem = XEXP (orig_mem, 0);
-      target_mode = GET_MODE (orig_mem);
-    }
-
-  gcc_assert (MEM_P (orig_mem));
-
-  orig_addr = XEXP (orig_mem, 0);
-  plus_or_lo_sum = GET_CODE (orig_addr);
-  gcc_assert (plus_or_lo_sum == PLUS || plus_or_lo_sum == LO_SUM);
-
-  offset = XEXP (orig_addr, 1);
-  new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_value, offset);
-  new_mem = replace_equiv_address_nv (orig_mem, new_addr, false);
-
-  if (extend != UNKNOWN)
-    new_mem = gen_rtx_fmt_e (extend, extend_mode, new_mem);
-
-  new_mem = gen_rtx_UNSPEC (extend_mode, gen_rtvec (1, new_mem),
-                           UNSPEC_FUSION_P9);
-
-  set = gen_rtx_SET (target, new_mem);
-  clobber = gen_rtx_CLOBBER (VOIDmode, tmp_reg);
-  insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber));
-  emit_insn (insn);
-
-  return;
-}
-
-/* During the peephole2 pass, adjust and expand the insns for an extended 
fusion
-   store sequence.
-
-   The operands are:
-       operands[0]     register set with addis
-       operands[1]     value set via addis
-       operands[2]     target D-form memory being stored to
-       operands[3]     register being stored
-
-  This is similar to the fusion introduced with power8, except it scales to
-  both loads/stores and does not require the result register to be the same as
-  the base register.  At the moment, we only do this if register set with addis
-  is dead.  */
-
-void
-expand_fusion_p9_store (rtx *operands)
-{
-  rtx tmp_reg = operands[0];
-  rtx addis_value = operands[1];
-  rtx orig_mem = operands[2];
-  rtx src = operands[3];
-  rtx  new_addr, new_mem, orig_addr, offset, set, clobber, insn, new_src;
-  enum rtx_code plus_or_lo_sum;
-  machine_mode target_mode = GET_MODE (orig_mem);
-  machine_mode ptr_mode = Pmode;
-
-  gcc_assert (MEM_P (orig_mem));
-
-  orig_addr = XEXP (orig_mem, 0);
-  plus_or_lo_sum = GET_CODE (orig_addr);
-  gcc_assert (plus_or_lo_sum == PLUS || plus_or_lo_sum == LO_SUM);
-
-  offset = XEXP (orig_addr, 1);
-  new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_value, offset);
-  new_mem = replace_equiv_address_nv (orig_mem, new_addr, false);
-
-  new_src = gen_rtx_UNSPEC (target_mode, gen_rtvec (1, src),
-                           UNSPEC_FUSION_P9);
-
-  set = gen_rtx_SET (new_mem, new_src);
-  clobber = gen_rtx_CLOBBER (VOIDmode, tmp_reg);
-  insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber));
-  emit_insn (insn);
-
-  return;
-}
-
-/* Return a string to fuse an addis instruction with a load using extended
-   fusion.  The address that is used is the logical address that was formed
-   during peephole2: (lo_sum (high) (low-part))
-
-   The code is complicated, so we call output_asm_insn directly, and just
-   return "".  */
-
-const char *
-emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
-{
-  machine_mode mode = GET_MODE (reg);
-  rtx hi;
-  rtx lo;
-  rtx addr;
-  const char *load_string;
-  int r;
-
-  if (GET_CODE (mem) == FLOAT_EXTEND || GET_CODE (mem) == ZERO_EXTEND)
-    {
-      mem = XEXP (mem, 0);
-      mode = GET_MODE (mem);
-    }
-
-  if (GET_CODE (reg) == SUBREG)
-    {
-      gcc_assert (SUBREG_BYTE (reg) == 0);
-      reg = SUBREG_REG (reg);
-    }
-
-  if (!REG_P (reg))
-    fatal_insn ("emit_fusion_p9_load, bad reg #1", reg);
-
-  r = REGNO (reg);
-  if (FP_REGNO_P (r))
-    {
-      if (mode == SFmode)
-       load_string = "lfs";
-      else if (mode == DFmode || mode == DImode)
-       load_string = "lfd";
-      else
-       gcc_unreachable ();
-    }
-  else if (ALTIVEC_REGNO_P (r) && TARGET_P9_VECTOR)
-    {
-      if (mode == SFmode)
-       load_string = "lxssp";
-      else if (mode == DFmode || mode == DImode)
-       load_string = "lxsd";
-      else
-       gcc_unreachable ();
-    }
-  else if (INT_REGNO_P (r))
-    {
-      switch (mode)
-       {
-       case E_QImode:
-         load_string = "lbz";
-         break;
-       case E_HImode:
-         load_string = "lhz";
-         break;
-       case E_SImode:
-       case E_SFmode:
-         load_string = "lwz";
-         break;
-       case E_DImode:
-       case E_DFmode:
-         if (!TARGET_POWERPC64)
-           gcc_unreachable ();
-         load_string = "ld";
-         break;
-       default:
-         gcc_unreachable ();
-       }
-    }
-  else
-    fatal_insn ("emit_fusion_p9_load, bad reg #2", reg);
-
-  if (!MEM_P (mem))
-    fatal_insn ("emit_fusion_p9_load not MEM", mem);
-
-  addr = XEXP (mem, 0);
-  fusion_split_address (addr, &hi, &lo);
-
-  /* Emit the addis instruction.  */
-  emit_fusion_addis (tmp_reg, hi);
-
-  /* Emit the D-form load instruction.  */
-  emit_fusion_load_store (reg, tmp_reg, lo, load_string);
-
-  return "";
-}
-
-/* Return a string to fuse an addis instruction with a store using extended
-   fusion.  The address that is used is the logical address that was formed
-   during peephole2: (lo_sum (high) (low-part))
-
-   The code is complicated, so we call output_asm_insn directly, and just
-   return "".  */
-
-const char *
-emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
-{
-  machine_mode mode = GET_MODE (reg);
-  rtx hi;
-  rtx lo;
-  rtx addr;
-  const char *store_string;
-  int r;
-
-  if (GET_CODE (reg) == SUBREG)
-    {
-      gcc_assert (SUBREG_BYTE (reg) == 0);
-      reg = SUBREG_REG (reg);
-    }
-
-  if (!REG_P (reg))
-    fatal_insn ("emit_fusion_p9_store, bad reg #1", reg);
-
-  r = REGNO (reg);
-  if (FP_REGNO_P (r))
-    {
-      if (mode == SFmode)
-       store_string = "stfs";
-      else if (mode == DFmode)
-       store_string = "stfd";
-      else
-       gcc_unreachable ();
-    }
-  else if (ALTIVEC_REGNO_P (r) && TARGET_P9_VECTOR)
-    {
-      if (mode == SFmode)
-       store_string = "stxssp";
-      else if (mode == DFmode || mode == DImode)
-       store_string = "stxsd";
-      else
-       gcc_unreachable ();
-    }
-  else if (INT_REGNO_P (r))
-    {
-      switch (mode)
-       {
-       case E_QImode:
-         store_string = "stb";
-         break;
-       case E_HImode:
-         store_string = "sth";
-         break;
-       case E_SImode:
-       case E_SFmode:
-         store_string = "stw";
-         break;
-       case E_DImode:
-       case E_DFmode:
-         if (!TARGET_POWERPC64)
-           gcc_unreachable ();
-         store_string = "std";
-         break;
-       default:
-         gcc_unreachable ();
-       }
-    }
-  else
-    fatal_insn ("emit_fusion_p9_store, bad reg #2", reg);
-
-  if (!MEM_P (mem))
-    fatal_insn ("emit_fusion_p9_store not MEM", mem);
-
-  addr = XEXP (mem, 0);
-  fusion_split_address (addr, &hi, &lo);
-
-  /* Emit the addis instruction.  */
-  emit_fusion_addis (tmp_reg, hi);
-
-  /* Emit the D-form load instruction.  */
-  emit_fusion_load_store (reg, tmp_reg, lo, store_string);
-
-  return "";
-}
-
 #ifdef RS6000_GLIBC_ATOMIC_FENV
 /* Function declarations for rs6000_atomic_assign_expand_fenv.  */
 static tree atomic_hold_decl, atomic_clear_decl, atomic_update_decl;
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt        
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/rs6000.opt        (.../gcc/config/rs6000) (working copy)
@@ -499,8 +499,7 @@ Target Undocumented Var(rs6000_optimize_
 Analyze and remove doubleword swaps from VSX computations.
 
 mpower9-fusion
-Target Undocumented Report Mask(P9_FUSION) Var(rs6000_isa_flags)
-Fuse certain operations together for better performance on power9.
+Target Undocumented Mask(P9_FUSION) Var(rs6000_isa_flags) Deprecated
 
 mpower9-misc
 Target Undocumented Report Mask(P9_MISC) Var(rs6000_isa_flags)
Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md    
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/constraints.md    (.../gcc/config/rs6000) (working copy)
@@ -154,7 +154,7 @@ (define_constraint "wE"
 
 ;; Extended fusion store
 (define_memory_constraint "wF"
-  "Memory operand suitable for power9 fusion load/stores"
+  "Memory operand suitable for power8 GPR load fusion"
   (match_operand 0 "fusion_addis_mem_combo_load"))
 
 (define_register_constraint "wH" "rs6000_constraints[RS6000_CONSTRAINT_wH]"
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md     
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/predicates.md     (.../gcc/config/rs6000) (working copy)
@@ -406,48 +406,6 @@ (define_predicate "fpr_reg_operand"
   return FP_REGNO_P (r);
 })
 
-;; Return true if this is a register that can has D-form addressing (GPR,
-;; traditional FPR registers, and Altivec registers for scalars).  Unlike
-;; power8 fusion, this fusion does not depend on putting the ADDIS instruction
-;; into the GPR register being loaded.
-(define_predicate "p9_fusion_reg_operand"
-  (match_code "reg,subreg")
-{
-  HOST_WIDE_INT r;
-  bool gpr_p = (mode == QImode || mode == HImode || mode == SImode
-               || mode == SFmode
-               || (TARGET_POWERPC64 && (mode == DImode || mode == DFmode)));
-  bool fpr_p = (TARGET_P9_FUSION
-               && (mode == DFmode || mode == SFmode
-                   || (TARGET_POWERPC64 && mode == DImode)));
-  bool vmx_p = (TARGET_P9_FUSION && TARGET_P9_VECTOR
-               && (mode == DFmode || mode == SFmode));
-
-  if (!TARGET_P8_FUSION)
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  if (!REG_P (op))
-    return 0;
-
-  r = REGNO (op);
-  if (r >= FIRST_PSEUDO_REGISTER)
-    return (gpr_p || fpr_p || vmx_p);
-
-  if (INT_REGNO_P (r))
-    return gpr_p;
-
-  if (FP_REGNO_P (r))
-    return fpr_p;
-
-  if (ALTIVEC_REGNO_P (r))
-    return vmx_p;
-
-  return 0;
-})
-
 ;; Return 1 if op is a HTM specific SPR register.
 (define_predicate "htm_spr_reg_operand"
   (match_operand 0 "register_operand")
@@ -1692,11 +1650,7 @@ (define_predicate "fusion_gpr_addis"
     return 0;
 
   /* Power8 currently will only do the fusion if the top 11 bits of the addis
-     value are all 1's or 0's.  Ignore this restriction if we are testing
-     advanced fusion.  */
-  if (TARGET_P9_FUSION)
-    return 1;
-
+     value are all 1's or 0's.  */
   return (IN_RANGE (value >> 16, -32, 31));
 })
 
@@ -1730,6 +1684,8 @@ (define_predicate "fusion_gpr_mem_load"
        return 0;
       break;
 
+    /* Do not allow SF/DFmode in GPR fusion.  While the loads do occur, they
+       are not common.  */  
     default:
       return 0;
     }
@@ -1762,14 +1718,13 @@ (define_predicate "fusion_gpr_mem_load"
 ;; Match a GPR load (lbz, lhz, lwz, ld) that uses a combined address in the
 ;; memory field with both the addis and the memory offset.  Sign extension
 ;; is not handled here, since lha and lwa are not fused.
-;; With P9 fusion, also match a fpr/vector load and float_extend
 (define_predicate "fusion_addis_mem_combo_load"
   (match_code "mem,zero_extend,float_extend")
 {
   rtx addr, base, offset;
 
-  /* Handle zero/float extend.  */
-  if (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == FLOAT_EXTEND)
+  /* Handle zero extend.  */
+  if (GET_CODE (op) == ZERO_EXTEND)
     {
       op = XEXP (op, 0);
       mode = GET_MODE (op);
@@ -1792,80 +1747,8 @@ (define_predicate "fusion_addis_mem_comb
        return 0;
       break;
 
-    /* ISA 2.08/power8 only had fusion of GPR loads.  */
-    case E_SFmode:
-      if (!TARGET_P9_FUSION)
-       return 0;
-      break;
-
-    /* ISA 2.08/power8 only had fusion of GPR loads.  Do not allow 64-bit
-       DFmode in 32-bit if -msoft-float since it splits into two separate
-       instructions.  */
-    case E_DFmode:
-      if ((!TARGET_POWERPC64 && !TARGET_HARD_FLOAT) || !TARGET_P9_FUSION)
-       return 0;
-      break;
-
-    default:
-      return 0;
-    }
-
-  addr = XEXP (op, 0);
-  if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM)
-    return 0;
-
-  base = XEXP (addr, 0);
-  if (!fusion_gpr_addis (base, GET_MODE (base)))
-    return 0;
-
-  offset = XEXP (addr, 1);
-  if (GET_CODE (addr) == PLUS)
-    return satisfies_constraint_I (offset);
-
-  else if (GET_CODE (addr) == LO_SUM)
-    {
-      if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64))
-       return small_toc_ref (offset, GET_MODE (offset));
-
-      else if (TARGET_ELF && !TARGET_POWERPC64)
-       return CONSTANT_P (offset);
-    }
-
-  return 0;
-})
-
-;; Like fusion_addis_mem_combo_load, but for stores
-(define_predicate "fusion_addis_mem_combo_store"
-  (match_code "mem")
-{
-  rtx addr, base, offset;
-
-  if (!MEM_P (op) || !TARGET_P9_FUSION)
-    return 0;
-
-  switch (mode)
-    {
-    case E_QImode:
-    case E_HImode:
-    case E_SImode:
-    case E_SFmode:
-      break;
-
-    /* Do not fuse 64-bit DImode in 32-bit since it splits into two
-       separate instructions.  */
-    case E_DImode:
-      if (!TARGET_POWERPC64)
-       return 0;
-      break;
-
-    /* Do not allow 64-bit DFmode in 32-bit if -msoft-float since it splits
-       into two separate instructions.  Do allow fusion if we have hardware
-       floating point.  */
-    case E_DFmode:
-      if (!TARGET_POWERPC64 && !TARGET_HARD_FLOAT)
-       return 0;
-      break;
-
+    /* Do not allow SF/DFmode in GPR fusion.  While the loads do occur, they
+       are not common.  */  
     default:
       return 0;
     }
@@ -1893,20 +1776,3 @@ (define_predicate "fusion_addis_mem_comb
 
   return 0;
 })
-
-;; Return true if the operand is a float_extend or zero extend of an
-;; offsettable memory operand suitable for use in fusion
-(define_predicate "fusion_offsettable_mem_operand"
-  (match_code "mem,zero_extend,float_extend")
-{
-  if (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == FLOAT_EXTEND)
-    {
-      op = XEXP (op, 0);
-      mode = GET_MODE (op);
-    }
-
-  if (!memory_operand (op, mode))
-    return 0;
-
-  return offsettable_nonstrict_memref_p (op);
-})
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def   
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/rs6000-cpus.def   (.../gcc/config/rs6000) (working copy)
@@ -44,9 +44,10 @@
                                 | OPTION_MASK_ALTIVEC                  \
                                 | OPTION_MASK_VSX)
 
-/* For now, don't provide an embedded version of ISA 2.07.  */
-#define ISA_2_7_MASKS_SERVER   (ISA_2_6_MASKS_SERVER                   \
-                                | OPTION_MASK_P8_FUSION                \
+/* For now, don't provide an embedded version of ISA 2.07.  Power9 does not
+   support power8 fusion.  Provide a version of the masks with fusion set and
+   one without.  */
+#define ISA_2_7_MASKS_NO_FUSION        (ISA_2_6_MASKS_SERVER                   
\
                                 | OPTION_MASK_P8_VECTOR                \
                                 | OPTION_MASK_CRYPTO                   \
                                 | OPTION_MASK_DIRECT_MOVE              \
@@ -55,12 +56,15 @@
                                 | OPTION_MASK_QUAD_MEMORY              \
                                 | OPTION_MASK_QUAD_MEMORY_ATOMIC)
 
+#define ISA_2_7_MASKS_SERVER   (ISA_2_7_MASKS_NO_FUSION                \
+                                | OPTION_MASK_P8_FUSION)
+
 /* Add ISEL back into ISA 3.0, since it is supposed to be a win.  Do not add
-   FLOAT128_HW here until we are ready to make -mfloat128 on by default.  */
-#define ISA_3_0_MASKS_SERVER   (ISA_2_7_MASKS_SERVER                   \
+   FLOAT128_HW here until we are ready to make -mfloat128 on by default.
+   Power9 did not support power8 fusion, so disable it by default.  */
+#define ISA_3_0_MASKS_SERVER   (ISA_2_7_MASKS_NO_FUSION                \
                                 | OPTION_MASK_ISEL                     \
                                 | OPTION_MASK_MODULO                   \
-                                | OPTION_MASK_P9_FUSION                \
                                 | OPTION_MASK_P9_MINMAX                \
                                 | OPTION_MASK_P9_MISC                  \
                                 | OPTION_MASK_P9_VECTOR)
@@ -121,7 +125,6 @@
                                 | OPTION_MASK_NO_UPDATE                \
                                 | OPTION_MASK_P8_FUSION                \
                                 | OPTION_MASK_P8_VECTOR                \
-                                | OPTION_MASK_P9_FUSION                \
                                 | OPTION_MASK_P9_MINMAX                \
                                 | OPTION_MASK_P9_MISC                  \
                                 | OPTION_MASK_P9_VECTOR                \
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h   
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)    
(revision 265537)
+++ gcc/config/rs6000/rs6000-protos.h   (.../gcc/config/rs6000) (working copy)
@@ -90,13 +90,7 @@ extern bool quad_load_store_p (rtx, rtx)
 extern bool fusion_gpr_load_p (rtx, rtx, rtx, rtx);
 extern void expand_fusion_gpr_load (rtx *);
 extern void emit_fusion_addis (rtx, rtx);
-extern void emit_fusion_load_store (rtx, rtx, rtx, const char *);
 extern const char *emit_fusion_gpr_load (rtx, rtx);
-extern bool fusion_p9_p (rtx, rtx, rtx, rtx);
-extern void expand_fusion_p9_load (rtx *);
-extern void expand_fusion_p9_store (rtx *);
-extern const char *emit_fusion_p9_load (rtx, rtx, rtx);
-extern const char *emit_fusion_p9_store (rtx, rtx, rtx);
 extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx,
                                                            enum reg_class);
 extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class,
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi     
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/doc)      (revision 
265537)
+++ gcc/doc/md.texi     (.../gcc/doc)   (working copy)
@@ -3213,7 +3213,7 @@ Int constant that is the element number
 Vector constant that can be loaded with the XXSPLTIB instruction.
 
 @item wF
-Memory operand suitable for power9 fusion load/stores.
+Memory operand suitable for power8 GPR load fusion
 
 @item wG
 Memory operand suitable for TOC fusion memory references.
Index: gcc/testsuite/gcc.target/powerpc/fusion4.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/fusion4.c  
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)
     (revision 265537)
+++ gcc/testsuite/gcc.target/powerpc/fusion4.c  
(.../gcc/testsuite/gcc.target/powerpc)  (working copy)
@@ -1,12 +0,0 @@
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { 
"-mcpu=power7" } } */
-/* { dg-options "-mcpu=power7 -mtune=power9 -O3 -msoft-float -dp" } */
-
-#define LARGE 0x12345
-
-float fusion_float_read (float *p){ return p[LARGE]; }
-
-void fusion_float_write (float *p, float f){ p[LARGE] = f; }
-
-/* { dg-final { scan-assembler {fusion_gpr_[sd]i_sf_store}  } } */
Index: gcc/testsuite/gcc.target/powerpc/fusion3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/fusion3.c  
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)
     (revision 265537)
+++ gcc/testsuite/gcc.target/powerpc/fusion3.c  
(.../gcc/testsuite/gcc.target/powerpc)  (working copy)
@@ -1,18 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { 
"-mcpu=power7" } } */
-/* { dg-options "-mcpu=power7 -mtune=power9 -O3 -dp" } */
-
-#define LARGE 0x12345
-
-int fusion_float_read (float *p){ return p[LARGE]; }
-int fusion_double_read (double *p){ return p[LARGE]; }
-
-void fusion_float_write (float *p, float f){ p[LARGE] = f; }
-void fusion_double_write (double *p, double d){ p[LARGE] = d; }
-
-/* { dg-final { scan-assembler {fusion_vsx_[sd]i_sf_load}  } } */
-/* { dg-final { scan-assembler {fusion_vsx_[sd]i_df_load}  } } */
-/* { dg-final { scan-assembler {fusion_vsx_[sd]i_sf_store}  } } */
-/* { dg-final { scan-assembler {fusion_vsx_[sd]i_df_store}  } } */

Reply via email to