https://gcc.gnu.org/g:0a91f1db49791101e9ecd13dbd4820240e737e02

commit 0a91f1db49791101e9ecd13dbd4820240e737e02
Author: Michael Meissner <[email protected]>
Date:   Sat Oct 17 01:37:38 2026 -0400

    Add bfloat16 define_peephole2.
    
    2026-10-17  Michael Meissner  <[email protected]>
    
            * config/rs6000/float16.md (bfloat16 define_peephole2): Add a 
peephole2
            to try to catch some cases where bfloat16 uses vector V4SFmode
            arithmetic for some things and then converts the value to scalar 
SFmode
            for other calculations.
            * config/rs6000/rs6000.opt (-mfloat16-peephole2): New debug switch.

Diff:
---
 gcc/config/rs6000/float16.md | 138 +++++++++++++++++++++++++++++++++++++++++++
 gcc/config/rs6000/rs6000.opt |   4 ++
 2 files changed, 142 insertions(+)

diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md
index d3a31791f9bc..fd9039b465db 100644
--- a/gcc/config/rs6000/float16.md
+++ b/gcc/config/rs6000/float16.md
@@ -1524,3 +1524,141 @@
                              operands[3], FP16_NFMS);
   DONE;
 })
+
+
+;; Peephole2 to try and catch some conversions from V4SFmode to SFmode,
+;; do an operation in SFmode and convert it V4SFmode.
+;;
+;; During testing, it was discovered that sometimes we optimized some
+;; calculations to use the vector format, while others forced the
+;; calculation to use scalar values.
+
+(define_peephole2
+  [(match_scratch:V4SF 0 "wa") ;; tmp
+
+   ;; Convert a vector V4SFmode operation back to scalar SFmode.
+   (set (match_operand:SF 1 "vsx_register_operand")
+       (unspec:SF [(match_operand:V4SF 2 "vsx_register_operand")]
+                  UNSPEC_VSX_CVSPDP))
+
+   ;; Do an operation in scalar SFmode.
+   (set (match_operand:SF 3 "vsx_register_operand")
+       (match_operator:SF 4 "fp16_binary_operator"
+                          [(match_operand:SF 5 "vsx_register_operand")
+                           (match_operand:SF 6 "vsx_register_operand")]))
+
+   ;; Convert the scalar result back to vector.
+   (set (match_operand:V4SF 7 "vsx_register_operand")
+       (unspec:V4SF [(match_dup 3)]
+                    UNSPEC_VSX_CVSPDP))
+
+   ;; Make sure the temporary register are live through this point.
+   (match_dup 0)
+   (match_dup 5)
+   (match_dup 6)
+
+   ;; Convert the result to BFmode.
+   (set (match_operand:BF 8 "vsx_register_operand")
+        (unspec:BF [(match_dup 7)] UNSPEC_XVCVSPBF16_BF))]
+
+  "TARGET_FLOAT16_PEEPHOLE2 && TARGET_BFLOAT16_HW
+   && (rtx_equal_p (operands[1], operands[5])
+       || rtx_equal_p (operands[1], operands[6]))
+   && (peep2_reg_dead_p (2, operands[1])
+       || reg_or_subregno (operands[1]) == reg_or_subregno (operands[3]))
+   && (peep2_reg_dead_p (3, operands[3])
+       || reg_or_subregno (operands[3]) == reg_or_subregno (operands[7]))
+   && (peep2_reg_dead_p (4, operands[7])
+       || reg_or_subregno (operands[7]) == reg_or_subregno (operands[8]))"
+
+  ;; Convert the other scalar argument to vector form.
+  [(match_dup 9)
+
+   ;; Do the operation in vector mode.
+   (set (match_dup 7)
+       (match_dup 10))
+
+   ;; Convert the result to BFmode.
+   (set (match_dup 8)
+       (unspec:BF[(match_dup 7)] UNSPEC_XVCVSPBF16_BF))]
+
+{
+  rtx tmp = operands[0];       // temporary
+  rtx scalar = operands[1];    // conversion from V4SF output
+  rtx vin = operands[2];       // V4SF before conversion to scalar
+  rtx sop = operands[4];       // SF binary operation 
+  rtx sarg1 = operands[5];     // SF binary arg1
+  rtx sarg2 = operands[6];     // SF binary arg2
+  rtx varg1, varg2;            // vector inputs
+
+  unsigned int scalar_reg = reg_or_subregno (scalar);
+  unsigned int sarg1_reg = reg_or_subregno (sarg1);
+  unsigned int sarg2_reg = reg_or_subregno (sarg2);
+
+#ifdef TARGET_DEBUG_EXTRA1
+  if (TARGET_DEBUG_EXTRA1)
+    {
+      fprintf (stderr, "\n========== Bfloat16 peephole2 input insns\n\n");
+      debug_rtx (gen_rtx_CLOBBER (VOIDmode, tmp));
+      debug_rtx (gen_vsx_xscvspdp_scalar2 (scalar, vin));
+      debug_rtx (gen_rtx_SET (operands[3], operands[4]));
+      debug_rtx (gen_vsx_xscvdpsp_scalar (operands[7], operands[3]));
+      debug_rtx (gen_xvcvspbf16_bf (operands[8], operands[7]));
+    }
+#endif
+
+  /*
+   * Create the vector operation.  We convert the scalar argument that
+   * was not the result of a vector to scalar operation to being a
+   * vector value.
+   */
+
+  /*
+   * Both scalar registers are the same.  The move is a NOP and it
+   * will be deleted.
+   */
+
+  if (scalar_reg == sarg1_reg && scalar_reg == sarg2_reg)
+    {
+      varg1 = vin;
+      varg2 = vin;
+      operands[9] = gen_rtx_SET (vin, vin);
+    }
+
+  /* The converted scalar reg is arg1, convert arg2 to vector.  */
+  else if (scalar_reg == sarg1_reg)
+    {
+      varg1 = vin;
+      varg2 = tmp;
+      operands[9] = gen_vsx_xscvdpsp (tmp,
+                                     gen_rtx_REG (DFmode, sarg2_reg));
+    }
+
+  /* The converted scalar reg is arg2, convert arg1 to vector.  */
+  else if (scalar_reg == sarg2_reg)
+    {
+      varg1 = tmp;
+      varg2 = vin;
+      operands[9] = gen_vsx_xscvdpsp (tmp,
+                                     gen_rtx_REG (DFmode, sarg1_reg));
+    }
+
+  else
+    gcc_unreachable ();
+
+  /* Create the vector binary operation operations instead of using scalar.  */
+  operands[10] = gen_rtx_fmt_ee (GET_CODE (sop), V4SFmode, varg1, varg2);
+
+#ifdef TARGET_DEBUG_EXTRA1
+  if (TARGET_DEBUG_EXTRA1)
+    {
+      fprintf (stderr, "\n========== Bfloat16 peephole2 output insns\n\n");
+      debug_rtx (operands[9]);
+      debug_rtx (gen_rtx_SET (operands[7], operands[10]));
+      debug_rtx (gen_xvcvspbf16_bf (operands[8], operands[7]));
+      fprintf (stderr, "\n========== Bfloat16 peephole2 done\n\n");
+    }
+#endif
+})
+
+
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index 973051afc350..893c8a3dfcf2 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -650,6 +650,10 @@ mfloat16-gpr-convert
 Target Undocumented Var(TARGET_FLOAT16_GPR_CONVERT) Init(1) Save
 Pass/return (do not pass/return) 16-it float conversions in GPR registers.
 
+mfloat16-peephole2
+Target Undocumented Var(TARGET_FLOAT16_PEEPHOLE2) Init(1) Save
+Enable/disble peephole2 processing.
+
 ; Documented parameters
 
 -param=rs6000-vect-unroll-limit=

Reply via email to