When enabling XTheadMemIdx, we enable the pre- and post-modify
addressing modes in the RISC-V backend.
Unfortunately, the auto_inc_dec pass will then attempt to utilize
this feature regardless of the mode class (i.e. scalar or vector).
The assumption seems to be, that an enabled addressing mode for
scalar instructions will also be available for vector instructions.

In case of XTheadMemIdx and RVV, this is ovbiously not the case.
Still, auto_inc_dec (-O3) performs optimizations like the following:

(insn 23 20 27 3 (set (mem:V4QI (reg:DI 136 [ ivtmp.13 ]) [0 MEM <vector(4) 
char> [(char *)_39]+0 S4 A32])
        (reg:V4QI 168)) "gcc/testsuite/gcc.target/riscv/pr116033.c":12:27 3183 
{*movv4qi}
     (nil))
(insn 40 39 41 3 (set (reg:DI 136 [ ivtmp.13 ])
        (plus:DI (reg:DI 136 [ ivtmp.13 ])
            (const_int 20 [0x14]))) 5 {adddi3}
     (nil))
====>
(insn 23 20 27 3 (set (mem:V4QI (post_modify:DI (reg:DI 136 [ ivtmp.13 ])
                (plus:DI (reg:DI 136 [ ivtmp.13 ])
                    (const_int 20 [0x14]))) [0 MEM <vector(4) char> [(char 
*)_39]+0 S4 A32])
        (reg:V4QI 168)) "gcc/testsuite/gcc.target/riscv/pr116033.c":12:27 3183 
{*movv4qi}
     (expr_list:REG_INC (reg:DI 136 [ ivtmp.13 ])
        (nil)))

The resulting memory-store with post-modify addressing cannot be
lowered to an existing instruction (see PR116033).
At a lower optimization level (-O2) this is currently fine,
but we can't rely on that.

One solution would be to introduce a target hook to check if a certain
type can be used for pre-/post-modify optimizations.
However, it will be hard to justify such a hook, if only a single
RISC-V vendor extension requires that.
Therefore, this patch takes a more drastic approach and disables
pre-/post-modify addressing if TARGET_VECTOR is set.
This results in not emitting pre-/post-modify instructions from
XTheadMemIdx if RVV is enabled.

Note, that this is not an issue with XTheadVector, because
we currently don't have auto-vectorization for that extension.
To ensure this won't changed without being noticed, an additional
test is added.

        PR target/116033

gcc/ChangeLog:

        * config/riscv/riscv.h (HAVE_POST_MODIFY_DISP): Disable for RVV.
        (HAVE_PRE_MODIFY_DISP): Likewise.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/pr116033-1.c: New test.
        * gcc.target/riscv/pr116033-2.c: New test.
        * gcc.target/riscv/pr116033-3.c: New test.

Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu>
---
 gcc/config/riscv/riscv.h                    |  6 ++--
 gcc/testsuite/gcc.target/riscv/pr116033-1.c | 40 +++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/pr116033-2.c | 40 +++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/pr116033-3.c | 38 ++++++++++++++++++++
 4 files changed, 122 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr116033-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr116033-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr116033-3.c

diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 6f040011864..e5760294506 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1254,8 +1254,10 @@ extern void riscv_remove_unneeded_save_restore_calls 
(void);
    e.g. RVVMF64BI vs RVVMF1BI on zvl512b, which is [1, 1] vs [64, 64].  */
 #define MAX_POLY_VARIANT 64
 
-#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
-#define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
+#define HAVE_POST_MODIFY_DISP \
+  (TARGET_XTHEADMEMIDX && (!TARGET_VECTOR || TARGET_XTHEADVECTOR))
+#define HAVE_PRE_MODIFY_DISP \
+  (TARGET_XTHEADMEMIDX && (!TARGET_VECTOR || TARGET_XTHEADVECTOR))
 
 /* Check TLS Descriptors mechanism is selected.  */
 #define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
diff --git a/gcc/testsuite/gcc.target/riscv/pr116033-1.c 
b/gcc/testsuite/gcc.target/riscv/pr116033-1.c
new file mode 100644
index 00000000000..8dcbe6cc2b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr116033-1.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O2" "-Og" "-Os" "-Oz" } } */
+/* { dg-options "-march=rv64gv_xtheadmemidx" { target { rv64 } } } */
+/* { dg-options "-march=rv32gv_xtheadmemidx" { target { rv32 } } } */
+
+char arr_3[20][20];
+void init()
+{
+  for (int i_0 = 0; i_0 < 20; ++i_0)
+    for (int i_1 = 0; i_0 < 20; ++i_0)
+      for (int i_1 = 0; i_1 < 20; ++i_0)
+        for (int i_1 = 0; i_1 < 20; ++i_1)
+          arr_3[i_0][i_1] = i_1;
+}
+
+long
+lr_reg_imm_upd_char_1 (long *rs1, long rs2)
+{
+  /* Register+register addressing still works.  */
+  *rs1 = *rs1 + (rs2 << 1);
+  return *(char*)(*rs1);
+}
+
+void
+char_pre_dec_load_1 (char *p)
+{
+  /* Missed optimization for V+XTheadMemIdx.  */
+  extern void fchar1(char*, long);
+  p = p - 1;
+  char x = *p;
+  fchar1 (p, x);
+}
+
+/* { dg-final { scan-assembler "vse8.v\tv\[0-9\]+,\[0-9\]+\\(\[a-x0-9\]+\\)" } 
} */
+/* { dg-final { scan-assembler-not 
"vse8.v\t\[a-x0-9\]+,\\(\[a-x0-9\]+\\),\[0-9\]+,\[0-9\]+" } } */
+
+/* { dg-final { scan-assembler "th.lrbu\t" } } */
+
+/* Missed optimization for V+XTheadMemIdx.  */
+/* { dg-final { scan-assembler "th.lbuib\t" { xfail "*-*-*" } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr116033-2.c 
b/gcc/testsuite/gcc.target/riscv/pr116033-2.c
new file mode 100644
index 00000000000..92e69c17e65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr116033-2.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-Og" "-Os" "-Oz" } } */
+/* { dg-options "-march=rv64gv_xtheadmemidx" { target { rv64 } } } */
+/* { dg-options "-march=rv32gv_xtheadmemidx" { target { rv32 } } } */
+
+char arr_3[20][20];
+void init()
+{
+  for (int i_0 = 0; i_0 < 20; ++i_0)
+    for (int i_1 = 0; i_0 < 20; ++i_0)
+      for (int i_1 = 0; i_1 < 20; ++i_0)
+        for (int i_1 = 0; i_1 < 20; ++i_1)
+          arr_3[i_0][i_1] = i_1;
+}
+
+long
+lr_reg_imm_upd_char_1 (long *rs1, long rs2)
+{
+  *rs1 = *rs1 + (rs2 << 1);
+  return *(char*)(*rs1);
+}
+
+void
+char_pre_dec_load_1 (char *p)
+{
+  /* Missed optimization for V+XTheadMemIdx.  */
+  extern void fchar1(char*, long);
+  p = p - 1;
+  char x = *p;
+  fchar1 (p, x);
+}
+
+/* No auto-vectorization for XTheadVector.  */
+/* { dg-final { scan-assembler 
"th.srb\t\[a-x0-9\]+,\[a-x0-9\]+,\[a-x0-9\]+,\[0-9\]+" } } */
+/* { dg-final { scan-assembler-not "vse8.v" } } */
+
+/* { dg-final { scan-assembler "th.lrbu\t" } } */
+
+/* Missed optimization for V+XTheadMemIdx.  */
+/* { dg-final { scan-assembler "th.lbuib\t" { xfail "*-*-*" } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr116033-3.c 
b/gcc/testsuite/gcc.target/riscv/pr116033-3.c
new file mode 100644
index 00000000000..cc89a6a0da5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr116033-3.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" "-Os" "-Oz" } } */
+/* { dg-options "-march=rv64g_xtheadvector_xtheadmemidx" { target { rv64 } } } 
*/
+/* { dg-options "-march=rv32g_xtheadvector_xtheadmemidx" { target { rv32 } } } 
*/
+
+char arr_3[20][20];
+void init()
+{
+  for (int i_0 = 0; i_0 < 20; ++i_0)
+    for (int i_1 = 0; i_0 < 20; ++i_0)
+      for (int i_1 = 0; i_1 < 20; ++i_0)
+        for (int i_1 = 0; i_1 < 20; ++i_1)
+          arr_3[i_0][i_1] = i_1;
+}
+
+long
+lr_reg_imm_upd_char_1 (long *rs1, long rs2)
+{
+  *rs1 = *rs1 + (rs2 << 1);
+  return *(char*)(*rs1);
+}
+
+void
+char_pre_dec_load_1 (char *p)
+{
+  extern void fchar1(char*, long);
+  p = p - 1;
+  char x = *p;
+  fchar1 (p, x);
+}
+
+/* No auto-vectorization for XTheadVector.  */
+/* { dg-final { scan-assembler 
"th.srb\t\[a-x0-9\]+,\[a-x0-9\]+,\[a-x0-9\]+,\[0-9\]+" } } */
+/* { dg-final { scan-assembler-not "vse8.v" } } */
+
+/* { dg-final { scan-assembler "th.lrbu\t" } } */
+
+/* { dg-final { scan-assembler "th.lbuib\t" } } */
-- 
2.45.2

Reply via email to