public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] [PATCH][GCC] arm: Enable no-writeback vldr.16/vstr.16.
@ 2020-07-27 14:08 Joe Ramsay
  2020-07-28  9:16 ` Kyrylo Tkachov
  0 siblings, 1 reply; 4+ messages in thread
From: Joe Ramsay @ 2020-07-27 14:08 UTC (permalink / raw)
  To: Jakub Jelinek via Gcc-patches

Hi,

There was previously no way to specify that a register operand cannot
have any writeback modifiers, and as a result the argument to vldr.16
and vstr.16 could be erroneously output with post-increment. This
change adds an operand specifier which forbids all writeback, and
selects it in the relevant case for vldr.16 and vstr.16

Bootstrapped on arm-linux, gcc and CMSIS-DSP testsuites are clean.
Is this patch OK for trunk? If yes, please commit on my behalf as I don't
have commit rights.

Thanks,
Joe

gcc/ChangeLog:

2020-05-20  Joe Ramsay  <joe.ramsay@arm.com>

        * config/arm/arm-protos.h (arm_coproc_mem_operand_no_writeback): Declare prototype.
        (arm_mve_mode_and_operands_type_check): Declare prototype.
        * config/arm/arm.c (arm_coproc_mem_operand): Refactor to use _arm_coproc_mem_operand.
        (arm_coproc_mem_operand_wb): New function to cover full, limited and no writeback.
        (arm_coproc_mem_operand_no_writeback): New constraint for memory operand with no writeback.
        (arm_print_operand): Implement 'j' specifier for memory operand that does not support
        writeback.
        (arm_mve_mode_and_operands_type_check): New constraint check for MVE memory operands.
        * config/arm/constraints.md: Add Uj constraint for VFP vldr.16 and vstr.16.
        * config/arm/vfp.md (*mov_load_vfp_hf16): New pattern for vldr.16.
        (*mov_store_vfp_hf16): New pattern for vstr.16.
        (*mov<mode>_vfp_<mode>16): Remove MVE moves.

gcc/testsuite/ChangeLog:

2020-05-20  Joe Ramsay  <joe.ramsay@arm.com>

        * gcc.target/arm/mve/intrinsics/mve-vldstr16-no-writeback.c: New test.

---
 gcc/config/arm/arm-protos.h                        |   3 +
 gcc/config/arm/arm.c                               | 100 ++++++++++++++++++---
 gcc/config/arm/constraints.md                      |   7 ++
 gcc/config/arm/vfp.md                              |  28 ++++--
 .../arm/mve/intrinsics/mve-vldstr16-no-writeback.c |  17 ++++
 5 files changed, 135 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/mve/intrinsics/mve-vldstr16-no-writeback.c

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 33d162c..e811da4 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -115,8 +115,11 @@ extern enum reg_class coproc_secondary_reload_class (machine_mode, rtx,
 extern bool arm_tls_referenced_p (rtx);
 
 extern int arm_coproc_mem_operand (rtx, bool);
+extern int arm_coproc_mem_operand_no_writeback (rtx);
+extern int arm_coproc_mem_operand_wb (rtx, int);
 extern int neon_vector_mem_operand (rtx, int, bool);
 extern int mve_vector_mem_operand (machine_mode, rtx, bool);
+bool arm_mve_mode_and_operands_type_check (machine_mode, rtx, rtx);
 extern int neon_struct_mem_operand (rtx);
 
 extern rtx *neon_vcmla_lane_prepare_operands (rtx *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6b7ca82..ed080d2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13217,13 +13217,14 @@ neon_element_bits (machine_mode mode)
 /* Predicates for `match_operand' and `match_operator'.  */
 
 /* Return TRUE if OP is a valid coprocessor memory address pattern.
-   WB is true if full writeback address modes are allowed and is false
+   WB level is 2 if full writeback address modes are allowed, 1
    if limited writeback address modes (POST_INC and PRE_DEC) are
-   allowed.  */
+   allowed and 0 if no writeback at all is supported.  */
 
 int
-arm_coproc_mem_operand (rtx op, bool wb)
+arm_coproc_mem_operand_wb (rtx op, int wb_level)
 {
+  gcc_assert (wb_level == 0 || wb_level == 1 || wb_level == 2);
   rtx ind;
 
   /* Reject eliminable registers.  */
@@ -13256,16 +13257,18 @@ arm_coproc_mem_operand (rtx op, bool wb)
 
   /* Autoincremment addressing modes.  POST_INC and PRE_DEC are
      acceptable in any case (subject to verification by
-     arm_address_register_rtx_p).  We need WB to be true to accept
+     arm_address_register_rtx_p).  We need full writeback to accept
+     PRE_INC and POST_DEC, and at least restricted writeback for
      PRE_INC and POST_DEC.  */
-  if (GET_CODE (ind) == POST_INC
-      || GET_CODE (ind) == PRE_DEC
-      || (wb
-	  && (GET_CODE (ind) == PRE_INC
-	      || GET_CODE (ind) == POST_DEC)))
+  if (wb_level > 0
+      && (GET_CODE (ind) == POST_INC
+	  || GET_CODE (ind) == PRE_DEC
+	  || (wb_level > 1
+	      && (GET_CODE (ind) == PRE_INC
+		  || GET_CODE (ind) == POST_DEC))))
     return arm_address_register_rtx_p (XEXP (ind, 0), 0);
 
-  if (wb
+  if (wb_level > 1
       && (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY)
       && arm_address_register_rtx_p (XEXP (ind, 0), 0)
       && GET_CODE (XEXP (ind, 1)) == PLUS
@@ -13287,6 +13290,25 @@ arm_coproc_mem_operand (rtx op, bool wb)
   return FALSE;
 }
 
+/* Return TRUE if OP is a valid coprocessor memory address pattern.
+   WB is true if full writeback address modes are allowed and is false
+   if limited writeback address modes (POST_INC and PRE_DEC) are
+   allowed.  */
+
+int arm_coproc_mem_operand (rtx op, bool wb)
+{
+  return arm_coproc_mem_operand_wb (op, wb ? 2 : 1);
+}
+
+/* Return TRUE if OP is a valid coprocessor memory address pattern in a
+   context in which no writeback address modes are allowed.  */
+
+int
+arm_coproc_mem_operand_no_writeback (rtx op)
+{
+  return arm_coproc_mem_operand_wb (op, 0);
+}
+
 /* This function returns TRUE on matching mode and op.
 1. For given modes, check for [Rn], return TRUE for Rn <= LO_REGS.
 2. For other modes, check for [Rn], return TRUE for Rn < R15 (expect R13).  */
@@ -23549,8 +23571,8 @@ arm_print_condition (FILE *stream)
 
 /* Globally reserved letters: acln
    Puncutation letters currently used: @_|?().!#
-   Lower case letters currently used: bcdefhimpqtvwxyz
-   Upper case letters currently used: ABCDFGHJKLMNOPQRSTU
+   Lower case letters currently used: bcdefhijmpqtvwxyz
+   Upper case letters currently used: ABCDEFGHIJKLMNOPQRSTU
    Letters previously used, but now deprecated/obsolete: sVWXYZ.
 
    Note that the global reservation for 'c' is only for CONSTANT_ADDRESS_P.
@@ -24163,6 +24185,41 @@ arm_print_operand (FILE *stream, rtx x, int code)
       }
       return;
 
+    /* To print memory operand in the case that the instruction does
+       not support writeback.  i.e. the output will look like either of
+       the following:
+       1. [Rn]
+       2. [Rn, #+/-<imm>] */
+    case 'j':
+      {
+	gcc_assert (MEM_P (x));
+	rtx addr = XEXP (x, 0);
+
+	switch (GET_CODE (addr))
+	  {
+	  case REG:
+	    asm_fprintf (stream, "[%r]", REGNO (addr));
+	    return;
+
+	  case PLUS:
+	    {
+	      rtx base = XEXP (addr, 0);
+	      rtx index = XEXP (addr, 1);
+
+	      if (!REG_P (base) || !CONST_INT_P (index))
+		gcc_unreachable ();
+
+	      HOST_WIDE_INT offset = INTVAL (index);
+	      asm_fprintf (stream, "[%r, #%wd]", REGNO (base), offset);
+	      return;
+	    }
+
+	  default:
+	    gcc_unreachable ();
+	  }
+	return;
+      }
+
     case 'C':
       {
 	rtx addr;
@@ -33496,4 +33553,23 @@ arm_mode_base_reg_class (machine_mode mode)
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
+bool
+arm_mve_mode_and_operands_type_check (machine_mode mode, rtx op0, rtx op1)
+{
+  if (!(TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT))
+    {
+       return true;
+    }
+  else if (mode == E_BFmode)
+    {
+      return false;
+    }
+  else if ((s_register_operand (op0, mode) && MEM_P (op1))
+	   || (s_register_operand (op1, mode) && MEM_P (op0)))
+    {
+      return false;
+    }
+  return true;
+}
+
 #include "gt-arm.h"
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 011badc..ff229aa 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -452,6 +452,13 @@
  (and (match_code "mem")
       (match_test "TARGET_32BIT && arm_coproc_mem_operand (op, FALSE)")))
 
+(define_memory_constraint "Uj"
+ "@internal
+  In ARM/Thumb-2 state an VFP load/store address which does not support
+  writeback at all (eg vldr.16)."
+ (and (match_code "mem")
+      (match_test "TARGET_32BIT && arm_coproc_mem_operand_no_writeback (op)")))
+
 (define_memory_constraint "Uy"
  "@internal
   In ARM/Thumb-2 state a valid iWMMX load/store address."
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 3470679..13174bb 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -387,6 +387,22 @@
    (set_attr "arch"           "t2,any,any,any,a,t2,any,any,any,any,any,any")]
 )
 
+(define_insn "*mov_load_vfp_hf16"
+  [(set (match_operand:HF 0 "s_register_operand" "=t")
+	(match_operand:HF 1 "memory_operand" "Uj"))]
+  "TARGET_HAVE_MVE_FLOAT"
+  "vldr.16\\t%0, %j1"
+  [(set_attr "length" "4")]
+)
+
+(define_insn "*mov_store_vfp_hf16"
+  [(set (match_operand:HF 0 "memory_operand" "=Uj")
+	(match_operand:HF 1 "s_register_operand"   "t"))]
+  "TARGET_HAVE_MVE_FLOAT"
+  "vstr.16\\t%1, %j0"
+  [(set_attr "length" "4")]
+)
+
 ;; HFmode and BFmode moves
 
 (define_insn "*mov<mode>_vfp_<mode>16"
@@ -396,6 +412,8 @@
 			  "  m,r,t,r,r,t,Dv,Um,t, F"))]
   "TARGET_32BIT
    && TARGET_VFP_FP16INST
+   && arm_mve_mode_and_operands_type_check (<MODE>mode, operands[0],
+					    operands[1])
    && (s_register_operand (operands[0], <MODE>mode)
        || s_register_operand (operands[1], <MODE>mode))"
  {
@@ -414,15 +432,9 @@
     case 6: /* S register from immediate.  */
       return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\";
     case 7: /* S register from memory.  */
-      if (TARGET_HAVE_MVE)
-	return \"vldr.16\\t%0, %A1\";
-      else
-	return \"vld1.16\\t{%z0}, %A1\";
+      return \"vld1.16\\t{%z0}, %A1\";
     case 8: /* Memory from S register.  */
-      if (TARGET_HAVE_MVE)
-	return \"vstr.16\\t%1, %A0\";
-      else
-	return \"vst1.16\\t{%z1}, %A0\";
+      return \"vst1.16\\t{%z1}, %A0\";
     case 9: /* ARM register from constant.  */
       {
 	long bits;
diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve-vldstr16-no-writeback.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve-vldstr16-no-writeback.c
new file mode 100644
index 0000000..0a69ace
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve-vldstr16-no-writeback.c
@@ -0,0 +1,17 @@
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+/* { dg-additional-options "-O2" } */
+
+void
+fn1 (__fp16 *pSrc)
+{
+  __fp16 high;
+  __fp16 *pDst = 0;
+  unsigned i;
+  for (i = 0;; i++)
+    if (pSrc[i])
+      pDst[i] = high;
+}
+
+/* { dg-final { scan-assembler {vldr\.16\ts[0-9]+, \[r[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {vstr\.16\ts[0-9]+, \[r[0-9]+\]\n} } } */
-- 
2.7.4



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-07-28 10:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-27 14:08 [PATCH] [PATCH][GCC] arm: Enable no-writeback vldr.16/vstr.16 Joe Ramsay
2020-07-28  9:16 ` Kyrylo Tkachov
2020-07-28 10:23   ` Joe Ramsay
2020-07-28 10:53     ` Kyrylo Tkachov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).