public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3 00/11] RISC-V: Add XThead* extension support
@ 2023-02-24  5:51 Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 01/11] riscv: Add basic XThead* vendor " Christoph Muellner
                   ` (11 more replies)
  0 siblings, 12 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This series introduces support for the T-Head specific RISC-V ISA extensions
which are available e.g. on the T-Head XuanTie C906.

The ISA spec can be found here:
  https://github.com/T-head-Semi/thead-extension-spec

This series adds support for the following XThead* extensions:
* XTheadBa
* XTheadBb
* XTheadBs
* XTheadCmo
* XTheadCondMov
* XTheadFMemIdx
* XTheadFmv
* XTheadInt
* XTheadMac
* XTheadMemIdx
* XTheadMemPair
* XTheadSync

All extensions are properly integrated and the included tests
demonstrate the improvements of the generated code.

The series also introduces support for "-mcpu=thead-c906", which also
enables all available XThead* ISA extensions of the T-Head C906.

All patches have been tested and don't introduce regressions for RV32 or RV64.
The patches have also been tested with SPEC CPU2017 on QEMU and real HW
(D1 board).

Support patches for these extensions for Binutils, QEMU, and LLVM have
already been merged in the corresponding upstream projects.

Changes in v3:
- Bugfix in XTheadBa
- Rewrite of XTheadMemPair
- Inclusion of XTheadMemIdx and XTheadFMemIdx

Christoph Müllner (9):
  riscv: Add basic XThead* vendor extension support
  riscv: riscv-cores.def: Add T-Head XuanTie C906
  riscv: thead: Add support for the XTheadBa ISA extension
  riscv: thead: Add support for the XTheadBs ISA extension
  riscv: thead: Add support for the XTheadBb ISA extension
  riscv: thead: Add support for the XTheadCondMov ISA extensions
  riscv: thead: Add support for the XTheadMac ISA extension
  riscv: thead: Add support for the XTheadFmv ISA extension
  riscv: thead: Add support for the XTheadMemPair ISA extension

moiz.hussain (2):
  riscv: thead: Add support for the XTheadMemIdx ISA extension
  riscv: thead: Add support for the XTheadFMemIdx ISA extension

 gcc/common/config/riscv/riscv-common.cc       |   26 +
 gcc/config/riscv/bitmanip.md                  |   52 +-
 gcc/config/riscv/constraints.md               |   43 +
 gcc/config/riscv/iterators.md                 |    4 +
 gcc/config/riscv/peephole.md                  |   56 +
 gcc/config/riscv/riscv-cores.def              |    4 +
 gcc/config/riscv/riscv-opts.h                 |   29 +
 gcc/config/riscv/riscv-protos.h               |   28 +-
 gcc/config/riscv/riscv.cc                     | 1090 +++++++++++++++--
 gcc/config/riscv/riscv.h                      |    8 +-
 gcc/config/riscv/riscv.md                     |  169 ++-
 gcc/config/riscv/riscv.opt                    |    3 +
 gcc/config/riscv/thead.md                     |  351 ++++++
 .../gcc.target/riscv/mcpu-thead-c906.c        |   28 +
 .../gcc.target/riscv/xtheadba-addsl.c         |   55 +
 gcc/testsuite/gcc.target/riscv/xtheadba.c     |   14 +
 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c |   20 +
 .../gcc.target/riscv/xtheadbb-extu-2.c        |   22 +
 .../gcc.target/riscv/xtheadbb-extu.c          |   22 +
 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c |   18 +
 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c |   45 +
 .../gcc.target/riscv/xtheadbb-srri.c          |   21 +
 gcc/testsuite/gcc.target/riscv/xtheadbb.c     |   14 +
 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c |   13 +
 gcc/testsuite/gcc.target/riscv/xtheadbs.c     |   14 +
 gcc/testsuite/gcc.target/riscv/xtheadcmo.c    |   14 +
 .../riscv/xtheadcondmov-mveqz-imm-eqz.c       |   38 +
 .../riscv/xtheadcondmov-mveqz-imm-not.c       |   38 +
 .../riscv/xtheadcondmov-mveqz-reg-eqz.c       |   38 +
 .../riscv/xtheadcondmov-mveqz-reg-not.c       |   38 +
 .../riscv/xtheadcondmov-mvnez-imm-cond.c      |   38 +
 .../riscv/xtheadcondmov-mvnez-imm-nez.c       |   38 +
 .../riscv/xtheadcondmov-mvnez-reg-cond.c      |   38 +
 .../riscv/xtheadcondmov-mvnez-reg-nez.c       |   38 +
 .../gcc.target/riscv/xtheadcondmov.c          |   14 +
 .../riscv/xtheadfmemidx-fldr-fstr.c           |   58 +
 .../gcc.target/riscv/xtheadfmemidx.c          |   14 +
 .../gcc.target/riscv/xtheadfmv-fmv.c          |   24 +
 gcc/testsuite/gcc.target/riscv/xtheadfmv.c    |   14 +
 gcc/testsuite/gcc.target/riscv/xtheadint.c    |   14 +
 .../gcc.target/riscv/xtheadmac-mula-muls.c    |   43 +
 gcc/testsuite/gcc.target/riscv/xtheadmac.c    |   14 +
 .../gcc.target/riscv/xtheadmemidx-ldi-sdi.c   |   72 ++
 .../riscv/xtheadmemidx-ldr-str-32.c           |   23 +
 .../riscv/xtheadmemidx-ldr-str-64.c           |   53 +
 .../gcc.target/riscv/xtheadmemidx-macros.h    |  110 ++
 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c |   14 +
 .../gcc.target/riscv/xtheadmempair-1.c        |   98 ++
 .../gcc.target/riscv/xtheadmempair-2.c        |   84 ++
 .../gcc.target/riscv/xtheadmempair-3.c        |   29 +
 .../gcc.target/riscv/xtheadmempair.c          |   13 +
 gcc/testsuite/gcc.target/riscv/xtheadsync.c   |   14 +
 52 files changed, 3048 insertions(+), 124 deletions(-)
 create mode 100644 gcc/config/riscv/thead.md
 create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcmo.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadint.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadsync.c

-- 
2.39.2


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

* [PATCH v3 01/11] riscv: Add basic XThead* vendor extension support
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 02/11] riscv: riscv-cores.def: Add T-Head XuanTie C906 Christoph Muellner
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch add basic support for the following XThead* ISA extensions:

* XTheadBa
* XTheadBb
* XTheadBs
* XTheadCmo
* XTheadCondMov
* XTheadFMemIdx
* XTheadFmv
* XTheadInt
* XTheadMac
* XTheadMemIdx
* XTheadMemPair
* XTheadSync

The extensions are just recognized by the compiler and feature test
macros are generated (which this patch also brings tests for).

gcc/ChangeLog:

	* common/config/riscv/riscv-common.cc: Add xthead* extensions.
	* config/riscv/riscv-opts.h (MASK_XTHEADBA): New.
	(MASK_XTHEADBB): New.
	(MASK_XTHEADBS): New.
	(MASK_XTHEADCMO): New.
	(MASK_XTHEADCONDMOV): New.
	(MASK_XTHEADFMEMIDX): New.
	(MASK_XTHEADFMV): New.
	(MASK_XTHEADINT): New.
	(MASK_XTHEADMAC): New.
	(MASK_XTHEADMEMIDX): New.
	(MASK_XTHEADMEMPAIR): New.
	(MASK_XTHEADSYNC): New.
	(TARGET_XTHEADBA): New.
	(TARGET_XTHEADBB): New.
	(TARGET_XTHEADBS): New.
	(TARGET_XTHEADCMO): New.
	(TARGET_XTHEADCONDMOV): New.
	(TARGET_XTHEADFMEMIDX): New.
	(TARGET_XTHEADFMV): New.
	(TARGET_XTHEADINT): New.
	(TARGET_XTHEADMAC): New.
	(TARGET_XTHEADMEMIDX): New.
	(TARGET_XTHEADMEMPAIR): new.
	(TARGET_XTHEADSYNC): New.
	* config/riscv/riscv.opt: Add riscv_xthead_subext.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadba.c: New test.
	* gcc.target/riscv/xtheadbb.c: New test.
	* gcc.target/riscv/xtheadbs.c: New test.
	* gcc.target/riscv/xtheadcmo.c: New test.
	* gcc.target/riscv/xtheadcondmov.c: New test.
	* gcc.target/riscv/xtheadfmemidx.c: New test.
	* gcc.target/riscv/xtheadfmv.c: New test.
	* gcc.target/riscv/xtheadint.c: New test.
	* gcc.target/riscv/xtheadmac.c: New test.
	* gcc.target/riscv/xtheadmemidx.c: New test.
	* gcc.target/riscv/xtheadmempair.c: New test.
	* gcc.target/riscv/xtheadsync.c: New test.

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/common/config/riscv/riscv-common.cc       | 26 +++++++++++++++++++
 gcc/config/riscv/riscv-opts.h                 | 26 +++++++++++++++++++
 gcc/config/riscv/riscv.opt                    |  3 +++
 gcc/testsuite/gcc.target/riscv/xtheadba.c     | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadbb.c     | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadbs.c     | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadcmo.c    | 14 ++++++++++
 .../gcc.target/riscv/xtheadcondmov.c          | 14 ++++++++++
 .../gcc.target/riscv/xtheadfmemidx.c          | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadfmv.c    | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadint.c    | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadmac.c    | 14 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c | 14 ++++++++++
 .../gcc.target/riscv/xtheadmempair.c          | 13 ++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadsync.c   | 14 ++++++++++
 15 files changed, 222 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcmo.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadint.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadsync.c

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index ebc1ed7d7e4..ef221be1eb1 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -222,6 +222,19 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"svinval", ISA_SPEC_CLASS_NONE, 1, 0},
   {"svnapot", ISA_SPEC_CLASS_NONE, 1, 0},
 
+  {"xtheadba", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadbb", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadbs", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadcmo", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadcondmov", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadfmemidx", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadfmv", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadint", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadmac", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadmemidx", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadmempair", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xtheadsync", ISA_SPEC_CLASS_NONE, 1, 0},
+
   /* Terminate the list.  */
   {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
 };
@@ -1248,6 +1261,19 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"svinval", &gcc_options::x_riscv_sv_subext, MASK_SVINVAL},
   {"svnapot", &gcc_options::x_riscv_sv_subext, MASK_SVNAPOT},
 
+  {"xtheadba",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBA},
+  {"xtheadbb",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBB},
+  {"xtheadbs",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBS},
+  {"xtheadcmo",     &gcc_options::x_riscv_xthead_subext, MASK_XTHEADCMO},
+  {"xtheadcondmov", &gcc_options::x_riscv_xthead_subext, MASK_XTHEADCONDMOV},
+  {"xtheadfmemidx", &gcc_options::x_riscv_xthead_subext, MASK_XTHEADFMEMIDX},
+  {"xtheadfmv",     &gcc_options::x_riscv_xthead_subext, MASK_XTHEADFMV},
+  {"xtheadint",     &gcc_options::x_riscv_xthead_subext, MASK_XTHEADINT},
+  {"xtheadmac",     &gcc_options::x_riscv_xthead_subext, MASK_XTHEADMAC},
+  {"xtheadmemidx",  &gcc_options::x_riscv_xthead_subext, MASK_XTHEADMEMIDX},
+  {"xtheadmempair", &gcc_options::x_riscv_xthead_subext, MASK_XTHEADMEMPAIR},
+  {"xtheadsync",    &gcc_options::x_riscv_xthead_subext, MASK_XTHEADSYNC},
+
   {NULL, NULL, 0}
 };
 
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index ff398c0a2ae..cf0cd669be4 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -189,4 +189,30 @@ enum stack_protector_guard {
    ? 0 \
    : 32 << (__builtin_popcount (riscv_zvl_flags) - 1))
 
+#define MASK_XTHEADBA      (1 << 0)
+#define MASK_XTHEADBB      (1 << 1)
+#define MASK_XTHEADBS      (1 << 2)
+#define MASK_XTHEADCMO     (1 << 3)
+#define MASK_XTHEADCONDMOV (1 << 4)
+#define MASK_XTHEADFMEMIDX (1 << 5)
+#define MASK_XTHEADFMV     (1 << 6)
+#define MASK_XTHEADINT     (1 << 7)
+#define MASK_XTHEADMAC     (1 << 8)
+#define MASK_XTHEADMEMIDX  (1 << 9)
+#define MASK_XTHEADMEMPAIR (1 << 10)
+#define MASK_XTHEADSYNC    (1 << 11)
+
+#define TARGET_XTHEADBA      ((riscv_xthead_subext & MASK_XTHEADBA) != 0)
+#define TARGET_XTHEADBB      ((riscv_xthead_subext & MASK_XTHEADBB) != 0)
+#define TARGET_XTHEADBS      ((riscv_xthead_subext & MASK_XTHEADBS) != 0)
+#define TARGET_XTHEADCMO     ((riscv_xthead_subext & MASK_XTHEADCMO) != 0)
+#define TARGET_XTHEADCONDMOV ((riscv_xthead_subext & MASK_XTHEADCONDMOV) != 0)
+#define TARGET_XTHEADFMEMIDX ((riscv_xthead_subext & MASK_XTHEADFMEMIDX) != 0)
+#define TARGET_XTHEADFMV     ((riscv_xthead_subext & MASK_XTHEADFMV) != 0)
+#define TARGET_XTHEADINT     ((riscv_xthead_subext & MASK_XTHEADINT) != 0)
+#define TARGET_XTHEADMAC     ((riscv_xthead_subext & MASK_XTHEADMAC) != 0)
+#define TARGET_XTHEADMEMIDX  ((riscv_xthead_subext & MASK_XTHEADMEMIDX) != 0)
+#define TARGET_XTHEADMEMPAIR ((riscv_xthead_subext & MASK_XTHEADMEMPAIR) != 0)
+#define TARGET_XTHEADSYNC    ((riscv_xthead_subext & MASK_XTHEADSYNC) != 0)
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 95535235354..ff1dd4ddd4f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -235,6 +235,9 @@ int riscv_zm_subext
 TargetVariable
 int riscv_sv_subext
 
+TargetVariable
+int riscv_xthead_subext
+
 Enum
 Name(isa_spec_class) Type(enum riscv_isa_spec_class)
 Supported ISA specs (for use with the -misa-spec= option):
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba.c b/gcc/testsuite/gcc.target/riscv/xtheadba.c
new file mode 100644
index 00000000000..14cdb1ffe2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadba.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadba
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb.c b/gcc/testsuite/gcc.target/riscv/xtheadbb.c
new file mode 100644
index 00000000000..66988abf221
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadbb
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbs.c b/gcc/testsuite/gcc.target/riscv/xtheadbs.c
new file mode 100644
index 00000000000..808d7378a7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbs.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbs" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbs" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadbs
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcmo.c b/gcc/testsuite/gcc.target/riscv/xtheadcmo.c
new file mode 100644
index 00000000000..eab8fef421c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcmo.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcmo" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcmo" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadcmo
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
new file mode 100644
index 00000000000..a239c3f9f46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadcondmov
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
new file mode 100644
index 00000000000..e450c5e5c5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadfmemidx" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadfmemidx" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadfmemidx
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmv.c b/gcc/testsuite/gcc.target/riscv/xtheadfmv.c
new file mode 100644
index 00000000000..e97e8f461f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmv.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadfmv" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadfmv" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadfmv
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadint.c b/gcc/testsuite/gcc.target/riscv/xtheadint.c
new file mode 100644
index 00000000000..ee6989a380e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadint.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadint" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadint" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadint
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmac.c b/gcc/testsuite/gcc.target/riscv/xtheadmac.c
new file mode 100644
index 00000000000..7c635407b31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmac.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadmac" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadmac" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadmac
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmemidx.c b/gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
new file mode 100644
index 00000000000..076eab00f54
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadmemidx" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadmemidx" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadmemidx
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmempair.c b/gcc/testsuite/gcc.target/riscv/xtheadmempair.c
new file mode 100644
index 00000000000..5135d2175dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmempair.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadmempair" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadmempair" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadmempair
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadsync.c b/gcc/testsuite/gcc.target/riscv/xtheadsync.c
new file mode 100644
index 00000000000..835d60c96e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadsync.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadsync" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadsync" { target { rv64 } } } */
+
+#ifndef __riscv_xtheadsync
+#error Feature macro not defined
+#endif
+
+int
+foo (int a)
+{
+  return a;
+}
+
-- 
2.39.2


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

* [PATCH v3 02/11] riscv: riscv-cores.def: Add T-Head XuanTie C906
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 01/11] riscv: Add basic XThead* vendor " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension Christoph Muellner
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This adds T-Head's XuanTie C906 to the list of known cores as "thead-c906".
The C906 is shipped for quite some time (it is the core of the Allwinner D1).
Note, that the tuning struct for the C906 is already part of GCC (it is
also name "thead-c906").

gcc/ChangeLog:

	* config/riscv/riscv-cores.def (RISCV_CORE): Add "thead-c906".

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/mcpu-thead-c906.c: New test.

Changes for v2:
- Enable all supported vendor extensions

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/riscv-cores.def              |  4 +++
 .../gcc.target/riscv/mcpu-thead-c906.c        | 28 +++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c

diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index 2a834cae21d..7d87ab7ce28 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -73,4 +73,8 @@ RISCV_CORE("sifive-s76",      "rv64imafdc", "sifive-7-series")
 RISCV_CORE("sifive-u54",      "rv64imafdc", "sifive-5-series")
 RISCV_CORE("sifive-u74",      "rv64imafdc", "sifive-7-series")
 
+RISCV_CORE("thead-c906",      "rv64imafdc_xtheadba_xtheadbb_xtheadbs_xtheadcmo_"
+			      "xtheadcondmov_xtheadfmemidx_xtheadmac_"
+			      "xtheadmemidx_xtheadmempair_xtheadsync",
+			      "thead-c906")
 #undef RISCV_CORE
diff --git a/gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c b/gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c
new file mode 100644
index 00000000000..a71b43a6167
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-skip-if "-march given" { *-*-* } { "-march=*" } } */
+/* { dg-options "-mcpu=thead-c906" { target { rv64 } } } */
+/* T-Head XuanTie C906 => rv64imafdc */
+
+#if !((__riscv_xlen == 64)		\
+      && !defined(__riscv_32e)		\
+      && defined(__riscv_mul)		\
+      && defined(__riscv_atomic)	\
+      && (__riscv_flen == 64)		\
+      && defined(__riscv_compressed)	\
+      && defined(__riscv_xtheadba)	\
+      && defined(__riscv_xtheadbb)	\
+      && defined(__riscv_xtheadbs)	\
+      && defined(__riscv_xtheadcmo)	\
+      && defined(__riscv_xtheadcondmov)	\
+      && defined(__riscv_xtheadfmemidx)	\
+      && defined(__riscv_xtheadmac)	\
+      && defined(__riscv_xtheadmemidx)	\
+      && defined(__riscv_xtheadmempair)	\
+      && defined(__riscv_xtheadsync))
+#error "unexpected arch"
+#endif
+
+int main()
+{
+  return 0;
+}
-- 
2.39.2


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

* [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 01/11] riscv: Add basic XThead* vendor " Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 02/11] riscv: riscv-cores.def: Add T-Head XuanTie C906 Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  6:52   ` Andrew Pinski
  2023-02-24  5:51 ` [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs " Christoph Muellner
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch adds support for the XTheadBa ISA extension.
The new INSN pattern is defined in a new file to separate
this vendor extension from the standard extensions.

gcc/ChangeLog:

	* config/riscv/riscv.md: Include thead.md
	* config/riscv/thead.md: New file.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadba-addsl.c: New test.

Changes in v3:
- Fix operand order for th.addsl.

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/riscv.md                     |  1 +
 gcc/config/riscv/thead.md                     | 31 +++++++++++
 .../gcc.target/riscv/xtheadba-addsl.c         | 55 +++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 gcc/config/riscv/thead.md
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 05924e9bbf1..d6c2265e9d4 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3093,4 +3093,5 @@ (define_insn "riscv_prefetchi_<mode>"
 (include "pic.md")
 (include "generic.md")
 (include "sifive-7.md")
+(include "thead.md")
 (include "vector.md")
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
new file mode 100644
index 00000000000..158e9124c3a
--- /dev/null
+++ b/gcc/config/riscv/thead.md
@@ -0,0 +1,31 @@
+;; Machine description for T-Head vendor extensions
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; XTheadBa
+
+(define_insn "*th_addsl"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
+			  (match_operand:QI 2 "immediate_operand" "I"))
+		(match_operand:X 3 "register_operand" "r")))]
+  "TARGET_XTHEADBA
+   && (INTVAL (operands[2]) >= 0) && (INTVAL (operands[2]) <= 3)"
+  "th.addsl\t%0,%3,%1,%2"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<X:MODE>")])
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
new file mode 100644
index 00000000000..5004735a246
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+long
+test_1 (long a, long b)
+{
+  /* th.addsl aX, aX, 1  */
+  return a + (b << 1);
+}
+
+int
+foos (short *x, int n)
+{
+  /* th.addsl aX, aX, 1  */
+  return x[n];
+}
+
+long
+test_2 (long a, long b)
+{
+  /* th.addsl aX, aX, 2  */
+  return a + (b << 2);
+}
+
+int
+fooi (int *x, int n)
+{
+  /* th.addsl aX, aX, 2  */
+  return x[n];
+}
+
+long
+test_3 (long a, long b)
+{
+  /* th.addsl aX, aX, 3  */
+  return a + (b << 3);
+}
+
+long
+fool (long *x, int n)
+{
+  /* th.addsl aX, aX, 2 (rv32)  */
+  /* th.addsl aX, aX, 3 (rv64)  */
+  return x[n];
+}
+
+/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,1" 2 } } */
+
+/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 2 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 2 { target { rv64 } } } } */
-- 
2.39.2


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

* [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (2 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  7:36   ` Kito Cheng
  2023-02-25 23:42   ` Hans-Peter Nilsson
  2023-02-24  5:51 ` [PATCH v3 05/11] riscv: thead: Add support for the XTheadBb " Christoph Muellner
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch adds support for the XTheadBs ISA extension.
The new INSN pattern is defined in a new file to separate
this vendor extension from the standard extensions.
The cost model adjustment reuses the xbs:bext cost.

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_rtx_costs): Add xthead:tst cost.
	* config/riscv/thead.md (*th_tst): New INSN.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadbs-tst.c: New test.

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/riscv.cc                     |  4 ++--
 gcc/config/riscv/thead.md                     | 11 +++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c | 13 +++++++++++++
 3 files changed, 26 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f11b7949a49..e35bc0a745b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2400,8 +2400,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
 	  return true;
 	}
-      /* bext pattern for zbs.  */
-      if (TARGET_ZBS && outer_code == SET
+      /* bit extraction pattern (zbs:bext, xtheadbs:tst).  */
+      if ((TARGET_ZBS || TARGET_XTHEADBS) && outer_code == SET
 	  && GET_CODE (XEXP (x, 1)) == CONST_INT
 	  && INTVAL (XEXP (x, 1)) == 1)
 	{
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index 158e9124c3a..2c684885850 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -29,3 +29,14 @@ (define_insn "*th_addsl"
   "th.addsl\t%0,%3,%1,%2"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<X:MODE>")])
+
+;; XTheadBs
+
+(define_insn "*th_tst"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(zero_extract:X (match_operand:X 1 "register_operand" "r")
+			(const_int 1)
+			(match_operand 2 "immediate_operand" "i")))]
+  "TARGET_XTHEADBS"
+  "th.tst\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c b/gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c
new file mode 100644
index 00000000000..674cec09128
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbs" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbs" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+long
+foo1 (long i)
+{
+  return 1L & (i >> 20);
+}
+
+/* { dg-final { scan-assembler-times "th.tst\t" 1 } } */
+/* { dg-final { scan-assembler-not "andi" } } */
-- 
2.39.2


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

* [PATCH v3 05/11] riscv: thead: Add support for the XTheadBb ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (3 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 06/11] riscv: thead: Add support for the XTheadCondMov ISA extensions Christoph Muellner
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch adds support for the XTheadBb ISA extension.
Thus, there is a functional overlap of the new instructions with
existing Bitmanip instruction, which allows a good amount of code
sharing. However, the vendor extensions are cleanly separated from
the standard extensions (e.g. by using INSN expand pattern that
will re-emit RTL that matches the patterns of either Bitmanip or
XThead INSNs).

gcc/ChangeLog:

	* config/riscv/bitmanip.md (clzdi2): New expand.
	(clzsi2): New expand.
	(ctz<mode>2): New expand.
	(popcount<mode>2): New expand.
	(<bitmanip_optab>si2): Rename INSN.
	(*<bitmanip_optab>si2): Hide INSN name.
	(<bitmanip_optab>di2): Rename INSN.
	(*<bitmanip_optab>di2): Hide INSN name.
	(rotrsi3): Remove INSN.
	(rotr<mode>3): Add expand.
	(*rotrsi3): New INSN.
	(rotrdi3): Rename INSN.
	(*rotrdi3): Hide INSN name.
	(rotrsi3_sext): Rename INSN.
	(*rotrsi3_sext): Hide INSN name.
	(bswap<mode>2): Remove INSN.
	(bswapdi2): Add expand.
	(bswapsi2): Add expand.
	(*bswap<mode>2): Hide INSN name.
	* config/riscv/riscv.cc (riscv_rtx_costs): Add costs for sign
	extraction.
	* config/riscv/riscv.md (extv<mode>): New expand.
	(extzv<mode>): New expand.
	* config/riscv/thead.md (*th_srrisi3): New INSN.
	(*th_srridi3): New INSN.
	(*th_ext<mode>): New INSN.
	(*th_extu<mode>): New INSN.
	(*th_clz<mode>2): New INSN.
	(*th_revsi2): New INSN.
	(*th_revdi2): New INSN.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadbb-ext.c: New test.
	* gcc.target/riscv/xtheadbb-extu-2.c: New test.
	* gcc.target/riscv/xtheadbb-extu.c: New test.
	* gcc.target/riscv/xtheadbb-ff1.c: New test.
	* gcc.target/riscv/xtheadbb-rev.c: New test.
	* gcc.target/riscv/xtheadbb-srri.c: New test.

Changes for v2:
- Merge all XTheadB* support patches
- Remove useless operand sanity checks for extv<mode> and extzv<mode>
- Prefer c.andi over th.extu if possible
- Add ff1 tests for clz/ctz
- Fix ext/extu test cases
- Enable tests for RV32

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/bitmanip.md                  | 52 +++++++++++++--
 gcc/config/riscv/riscv.cc                     |  9 +++
 gcc/config/riscv/riscv.md                     | 20 ++++++
 gcc/config/riscv/thead.md                     | 66 +++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c | 20 ++++++
 .../gcc.target/riscv/xtheadbb-extu-2.c        | 22 +++++++
 .../gcc.target/riscv/xtheadbb-extu.c          | 22 +++++++
 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c | 18 +++++
 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c | 45 +++++++++++++
 .../gcc.target/riscv/xtheadbb-srri.c          | 21 ++++++
 10 files changed, 289 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 14d18edbe62..ca0c98ee686 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -185,6 +185,26 @@ (define_insn "*slliuw"
 
 ;; ZBB extension.
 
+(define_expand "clzdi2"
+  [(set (match_operand:DI 0 "register_operand")
+	(clz:DI (match_operand:DI 1 "register_operand")))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB)")
+
+(define_expand "clzsi2"
+  [(set (match_operand:SI 0 "register_operand")
+	(clz:SI (match_operand:SI 1 "register_operand")))]
+  "TARGET_ZBB || (!TARGET_64BIT && TARGET_XTHEADBB)")
+
+(define_expand "ctz<mode>2"
+  [(set (match_operand:GPR 0 "register_operand")
+	(ctz:GPR (match_operand:GPR 1 "register_operand")))]
+  "TARGET_ZBB")
+
+(define_expand "popcount<mode>2"
+  [(set (match_operand:GPR 0 "register_operand")
+	(popcount:GPR (match_operand:GPR 1 "register_operand")))]
+  "TARGET_ZBB")
+
 (define_insn "*<optab>_not<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
         (bitmanip_bitwise:X (not:X (match_operand:X 1 "register_operand" "r"))
@@ -216,7 +236,7 @@ (define_insn "*xor_not<mode>"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<X:MODE>")])
 
-(define_insn "<bitmanip_optab>si2"
+(define_insn "*<bitmanip_optab>si2"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))]
   "TARGET_ZBB"
@@ -233,7 +253,7 @@ (define_insn "*<bitmanip_optab>disi2"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "SI")])
 
-(define_insn "<bitmanip_optab>di2"
+(define_insn "*<bitmanip_optab>di2"
   [(set (match_operand:DI 0 "register_operand" "=r")
         (clz_ctz_pcnt:DI (match_operand:DI 1 "register_operand" "r")))]
   "TARGET_64BIT && TARGET_ZBB"
@@ -273,7 +293,17 @@ (define_insn "*zero_extendhi<GPR:mode>2_zbb"
   [(set_attr "type" "bitmanip,load")
    (set_attr "mode" "HI")])
 
-(define_insn "rotrsi3"
+(define_expand "rotr<mode>3"
+  [(set (match_operand:GPR 0 "register_operand")
+	(rotatert:GPR (match_operand:GPR 1 "register_operand")
+		     (match_operand:QI 2 "arith_operand")))]
+  "TARGET_ZBB || TARGET_XTHEADBB"
+{
+  if (TARGET_XTHEADBB && !immediate_operand (operands[2], VOIDmode))
+    FAIL;
+})
+
+(define_insn "*rotrsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(rotatert:SI (match_operand:SI 1 "register_operand" "r")
 		     (match_operand:QI 2 "arith_operand" "rI")))]
@@ -281,7 +311,7 @@ (define_insn "rotrsi3"
   "ror%i2%~\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "rotrdi3"
+(define_insn "*rotrdi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(rotatert:DI (match_operand:DI 1 "register_operand" "r")
 		     (match_operand:QI 2 "arith_operand" "rI")))]
@@ -289,7 +319,7 @@ (define_insn "rotrdi3"
   "ror%i2\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
-(define_insn "rotrsi3_sext"
+(define_insn "*rotrsi3_sext"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(sign_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "r")
 				     (match_operand:QI 2 "register_operand" "r"))))]
@@ -329,7 +359,17 @@ (define_insn "orcb<mode>2"
   "TARGET_ZBB"
   "orc.b\t%0,%1")
 
-(define_insn "bswap<mode>2"
+(define_expand "bswapdi2"
+  [(set (match_operand:DI 0 "register_operand")
+	(bswap:DI (match_operand:DI 1 "register_operand")))]
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB)")
+
+(define_expand "bswapsi2"
+  [(set (match_operand:SI 0 "register_operand")
+	(bswap:SI (match_operand:SI 1 "register_operand")))]
+  "(!TARGET_64BIT && TARGET_ZBB) || TARGET_XTHEADBB")
+
+(define_insn "*bswap<mode>2"
   [(set (match_operand:X 0 "register_operand" "=r")
         (bswap:X (match_operand:X 1 "register_operand" "r")))]
   "TARGET_ZBB"
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index e35bc0a745b..7613bae8024 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2408,6 +2408,15 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
 	  return true;
 	}
+      gcc_fallthrough ();
+    case SIGN_EXTRACT:
+      if (TARGET_XTHEADBB && outer_code == SET
+	  && CONST_INT_P (XEXP (x, 1))
+	  && CONST_INT_P (XEXP (x, 2)))
+	{
+	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+	  return true;
+	}
       return false;
 
     case ASHIFT:
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index d6c2265e9d4..fc8ce9f5226 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3087,6 +3087,26 @@ (define_insn "riscv_prefetchi_<mode>"
   "prefetch.i\t%a0"
 )
 
+(define_expand "extv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
+			 (match_operand 2 "const_int_operand")
+			 (match_operand 3 "const_int_operand")))]
+  "TARGET_XTHEADBB"
+)
+
+(define_expand "extzv<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
+			 (match_operand 2 "const_int_operand")
+			 (match_operand 3 "const_int_operand")))]
+  "TARGET_XTHEADBB"
+{
+  if (TARGET_XTHEADBB
+      && (INTVAL (operands[2]) < 8) && (INTVAL (operands[3]) == 0))
+    FAIL;
+})
+
 (include "bitmanip.md")
 (include "sync.md")
 (include "peephole.md")
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index 2c684885850..79cdcbb553f 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -30,6 +30,72 @@ (define_insn "*th_addsl"
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<X:MODE>")])
 
+;; XTheadBb
+
+(define_insn "*th_srrisi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(rotatert:SI (match_operand:SI 1 "register_operand" "r")
+		     (match_operand:QI 2 "immediate_operand" "I")))]
+  "TARGET_XTHEADBB"
+  { return TARGET_64BIT ? "th.srriw\t%0,%1,%2" : "th.srri\t%0,%1,%2"; }
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*th_srridi3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(rotatert:DI (match_operand:DI 1 "register_operand" "r")
+		     (match_operand:QI 2 "immediate_operand" "I")))]
+  "TARGET_XTHEADBB && TARGET_64BIT"
+  "th.srri\t%0,%1,%2"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*th_ext<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
+			(match_operand 2 "const_int_operand")
+			(match_operand 3 "const_int_operand")))]
+  "TARGET_XTHEADBB"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
+  return "th.ext\t%0,%1,%2,%3";
+}
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*th_extu<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
+			(match_operand 2 "const_int_operand")
+			(match_operand 3 "const_int_operand")))]
+  "TARGET_XTHEADBB"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
+  return "th.extu\t%0,%1,%2,%3";
+}
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*th_clz<mode>2"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(clz:X (match_operand:X 1 "register_operand" "r")))]
+  "TARGET_XTHEADBB"
+  "th.ff1\t%0,%1"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<X:MODE>")])
+
+(define_insn "*th_revsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(bswap:SI (match_operand:SI 1 "register_operand" "r")))]
+  "TARGET_XTHEADBB"
+  { return TARGET_64BIT ? "th.revw\t%0,%1" : "th.rev\t%0,%1"; }
+  [(set_attr "type" "bitmanip")])
+
+(define_insn "*th_revdi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(bswap:DI (match_operand:DI 1 "register_operand" "r")))]
+  "TARGET_XTHEADBB && TARGET_64BIT"
+  "th.rev\t%0,%1"
+  [(set_attr "type" "bitmanip")])
+
 ;; XTheadBs
 
 (define_insn "*th_tst"
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
new file mode 100644
index 00000000000..60fb7d44e39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+struct bar
+{
+  long a:9;
+  long b:26;
+  long c:22;
+};
+
+long
+foo (struct bar *s)
+{
+  return s->b;
+}
+
+/* { dg-final { scan-assembler "th.ext\t" } } */
+/* { dg-final { scan-assembler-not "andi" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
new file mode 100644
index 00000000000..029be93f401
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+struct bar
+{
+  unsigned long a:6;
+  unsigned long b:26;
+  unsigned long c:22;
+};
+
+/* We prefer andi over th.extu because it can be compressed.  */
+
+unsigned long
+foo (struct bar *s)
+{
+  return s->a;
+}
+
+/* { dg-final { scan-assembler-not "th.extu\t" } } */
+/* { dg-final { scan-assembler "andi\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
new file mode 100644
index 00000000000..e0492f1f5ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+struct bar
+{
+  unsigned long a:5;
+  unsigned long b:26;
+  unsigned long c:22;
+};
+
+unsigned long
+foo (struct bar *s)
+{
+  return s->b;
+}
+
+/* { dg-final { scan-assembler "th.extu\t" } } */
+/* { dg-final { scan-assembler-not "andi" } } */
+/* { dg-final { scan-assembler-not "slli" } } */
+/* { dg-final { scan-assembler-not "srli" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
new file mode 100644
index 00000000000..72038c4e281
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+foo (unsigned long a)
+{
+  return __builtin_clzl (a);
+}
+
+int
+bar (unsigned long a)
+{
+  return __builtin_ctzl (a);
+}
+
+/* { dg-final { scan-assembler-times "th.ff1\t" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
new file mode 100644
index 00000000000..411d52007d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */
+
+unsigned int
+foo32 (unsigned int x)
+{
+  return (((x << 24) & 0xff000000)
+	  | ((x << 8) & 0xff0000)
+	  | ((x >> 8) & 0xff00)
+	  | ((x >> 24) & 0xff));
+}
+
+unsigned int
+foo32_1 (unsigned int x)
+{
+  return __builtin_bswap32 (x);
+}
+
+#if __riscv_xlen == 64
+unsigned long
+foo64 (unsigned long x)
+{
+  return (((x << 56) & 0xff00000000000000ull)
+	  | ((x << 40) & 0xff000000000000ull)
+	  | ((x << 24) & 0xff0000000000ull)
+	  | ((x << 8) & 0xff00000000ull)
+	  | ((x >> 8) & 0xff000000)
+	  | ((x >> 24) & 0xff0000)
+	  | ((x >> 40) & 0xff00)
+	  | ((x >> 56) & 0xff));
+}
+
+unsigned long
+foo64_1 (unsigned long x)
+{
+  return __builtin_bswap64 (x);
+}
+#endif
+
+/* { dg-final { scan-assembler-times "th.rev\t" 2 { target { rv32 } } } } */
+
+/* { dg-final { scan-assembler-times "th.revw\t" 2 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.rev\t" 2 { target { rv64 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c b/gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
new file mode 100644
index 00000000000..033a500dfe9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadbb" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadbb" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+unsigned long
+foo1 (unsigned long rs1)
+{
+    long shamt = __riscv_xlen - 11;
+    return (rs1 << shamt)
+	   | (rs1 >> ((__riscv_xlen - shamt) & (__riscv_xlen - 1)));
+}
+unsigned long
+foo2 (unsigned long rs1)
+{
+    unsigned long shamt = __riscv_xlen - 11;
+    return (rs1 >> shamt)
+	   | (rs1 << ((__riscv_xlen - shamt) & (__riscv_xlen - 1)));
+}
+
+/* { dg-final { scan-assembler-times "th.srri" 2 } } */
-- 
2.39.2


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

* [PATCH v3 06/11] riscv: thead: Add support for the XTheadCondMov ISA extensions
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (4 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 05/11] riscv: thead: Add support for the XTheadBb " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 07/11] riscv: thead: Add support for the XTheadMac ISA extension Christoph Muellner
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

This patch adds support for XTheadCondMov ISA extension.
The extension brings a one-sided conditional move (no else-assignment).
Given that GCC has a great if-conversion pass, we don't need to do much,
besides properly expanding mov<mode>cc accordingly and adjust the cost
model.

gcc/ChangeLog:

	* config/riscv/iterators.md (TARGET_64BIT): Add GPR2 iterator.
	* config/riscv/riscv-protos.h (riscv_expand_conditional_move):
	Add prototype.
	* config/riscv/riscv.cc (riscv_rtx_costs): Add costs for
	XTheadCondMov.
	(riscv_expand_conditional_move): New function.
	(riscv_expand_conditional_move_onesided): New function.
	* config/riscv/riscv.md: Add support for XTheadCondMov.
	* config/riscv/thead.md (*th_cond_mov<GPR:mode><GPR2:mode>): Add
	support for XTheadCondMov.
	(*th_cond_gpr_mov<GPR:mode><GPR2:mode>): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c: New test.
	* gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c: New test.
	* gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c: New test.
	* gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c: New test.
	* gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c: New test.
	* gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c: New test.
	* gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c: New test.
	* gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c: New test.

Changes for v2:
- Properly gate expansion constraints to avoid failing INSN lookup
- Restrict subreg comparisons

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/iterators.md                 |   4 +
 gcc/config/riscv/riscv-protos.h               |   2 +-
 gcc/config/riscv/riscv.cc                     | 100 +++++++++++++++---
 gcc/config/riscv/riscv.md                     |  17 ++-
 gcc/config/riscv/thead.md                     |  37 +++++++
 .../riscv/xtheadcondmov-mveqz-imm-eqz.c       |  38 +++++++
 .../riscv/xtheadcondmov-mveqz-imm-not.c       |  38 +++++++
 .../riscv/xtheadcondmov-mveqz-reg-eqz.c       |  38 +++++++
 .../riscv/xtheadcondmov-mveqz-reg-not.c       |  38 +++++++
 .../riscv/xtheadcondmov-mvnez-imm-cond.c      |  38 +++++++
 .../riscv/xtheadcondmov-mvnez-imm-nez.c       |  38 +++++++
 .../riscv/xtheadcondmov-mvnez-reg-cond.c      |  38 +++++++
 .../riscv/xtheadcondmov-mvnez-reg-nez.c       |  38 +++++++
 13 files changed, 440 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c

diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 5b70ab20758..9b767038452 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -26,6 +26,10 @@
 ;; from the same template.
 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
 
+;; A copy of GPR that can be used when a pattern has two independent
+;; modes.
+(define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")])
+
 ;; This mode iterator allows :P to be used for patterns that operate on
 ;; pointer-sized quantities.  Exactly one of the two alternatives will match.
 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 37c634eca1d..5cf4fafd662 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -58,8 +58,8 @@ extern const char *riscv_output_return ();
 extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
-extern void riscv_expand_conditional_move (rtx, rtx, rtx, rtx_code, rtx, rtx);
 #endif
+extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx);
 extern rtx riscv_legitimize_call_address (rtx);
 extern void riscv_set_return_address (rtx, rtx);
 extern bool riscv_expand_block_move (rtx, rtx, rtx);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7613bae8024..a60ab2c7fad 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2300,8 +2300,8 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
       return false;
 
     case IF_THEN_ELSE:
-      if (TARGET_SFB_ALU
-	  && register_operand (XEXP (x, 1), mode)
+      if ((TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+	  && reg_or_0_operand (XEXP (x, 1), mode)
 	  && sfb_alu_operand (XEXP (x, 2), mode)
 	  && comparison_operator (XEXP (x, 0), VOIDmode))
 	{
@@ -3098,13 +3098,30 @@ riscv_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
     }
 }
 
-/* Convert a comparison into something that can be used in a branch.  On
-   entry, *OP0 and *OP1 are the values being compared and *CODE is the code
-   used to compare them.  Update them to describe the final comparison.  */
+/* Convert a comparison into something that can be used in a branch or
+   conditional move.  On entry, *OP0 and *OP1 are the values being
+   compared and *CODE is the code used to compare them.
+
+   Update *CODE, *OP0 and *OP1 so that they describe the final comparison.
+   If NEED_EQ_NE_P, then only EQ or NE comparisons against zero are
+   emitted.  */
 
 static void
-riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1)
+riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1,
+			bool need_eq_ne_p = false)
 {
+  if (need_eq_ne_p)
+    {
+      rtx cmp_op0 = *op0;
+      rtx cmp_op1 = *op1;
+      if (*code == EQ || *code == NE)
+	{
+	  *op0 = riscv_zero_if_equal (cmp_op0, cmp_op1);
+	  *op1 = const0_rtx;
+	  return;
+	}
+    }
+
   if (splittable_const_int_operand (*op1, VOIDmode))
     {
       HOST_WIDE_INT rhs = INTVAL (*op1);
@@ -3290,16 +3307,71 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1)
   emit_jump_insn (gen_condjump (condition, label));
 }
 
-/* If (CODE OP0 OP1) holds, move CONS to DEST; else move ALT to DEST.  */
+/* Helper to emit two one-sided conditional moves for the movecc.  */
 
-void
-riscv_expand_conditional_move (rtx dest, rtx cons, rtx alt, rtx_code code,
-			       rtx op0, rtx op1)
+static void
+riscv_expand_conditional_move_onesided (rtx dest, rtx cons, rtx alt,
+					rtx_code code, rtx op0, rtx op1)
 {
-  riscv_emit_int_compare (&code, &op0, &op1);
-  rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
-  emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond,
-						      cons, alt)));
+  machine_mode mode = GET_MODE (dest);
+
+  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+  gcc_assert (reg_or_0_operand (cons, mode));
+  gcc_assert (reg_or_0_operand (alt, mode));
+
+  riscv_emit_int_compare (&code, &op0, &op1, true);
+  rtx cond = gen_rtx_fmt_ee (code, mode, op0, op1);
+
+  rtx tmp1 = gen_reg_rtx (mode);
+  rtx tmp2 = gen_reg_rtx (mode);
+
+  emit_insn (gen_rtx_SET (tmp1, gen_rtx_IF_THEN_ELSE (mode, cond,
+						      cons, const0_rtx)));
+
+  /* We need to expand a sequence for both blocks and we do that such,
+     that the second conditional move will use the inverted condition.
+     We use temporaries that are or'd to the dest register.  */
+  cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, mode, op0, op1);
+  emit_insn (gen_rtx_SET (tmp2, gen_rtx_IF_THEN_ELSE (mode, cond,
+						      alt, const0_rtx)));
+
+  emit_insn (gen_rtx_SET (dest, gen_rtx_IOR (mode, tmp1, tmp2)));
+ }
+
+/* Emit a cond move: If OP holds, move CONS to DEST; else move ALT to DEST.
+   Return 0 if expansion failed.  */
+
+bool
+riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
+{
+  machine_mode mode = GET_MODE (dest);
+  rtx_code code = GET_CODE (op);
+  rtx op0 = XEXP (op, 0);
+  rtx op1 = XEXP (op, 1);
+
+  if (TARGET_XTHEADCONDMOV
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && reg_or_0_operand (cons, mode)
+      && reg_or_0_operand (alt, mode)
+      && GET_MODE (op) == mode
+      && GET_MODE (op0) == mode
+      && GET_MODE (op1) == mode
+      && (code == EQ || code == NE))
+    {
+      riscv_expand_conditional_move_onesided (dest, cons, alt, code, op0, op1);
+      return true;
+    }
+  else if (TARGET_SFB_ALU
+	   && mode == word_mode)
+    {
+      riscv_emit_int_compare (&code, &op0, &op1);
+      rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+      emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
+							  cond, cons, alt)));
+      return true;
+    }
+
+  return false;
 }
 
 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  Every parameter gets at
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index fc8ce9f5226..5562e5621fa 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -242,6 +242,7 @@ (define_attr "enabled" "no,yes"
 ;; bitmanip	bit manipulation instructions
 ;; rotate   rotation instructions
 ;; atomic   atomic instructions
+;; condmove	conditional moves
 ;; Classification of RVV instructions which will be added to each RVV .md pattern and used by scheduler.
 ;; rdvlenb     vector byte length vlenb csrr read
 ;; rdvl        vector length vl csrr read
@@ -335,7 +336,7 @@ (define_attr "type"
   "unknown,branch,jump,call,load,fpload,store,fpstore,
    mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
    fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
-   atomic,rdvlenb,rdvl,vsetvl,vlde,vste,vldm,vstm,vlds,vsts,
+   atomic,condmove,rdvlenb,rdvl,vsetvl,vlde,vste,vldm,vstm,vlds,vsts,
    vldux,vldox,vstux,vstox,vldff,vldr,vstr,
    vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
    vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,
@@ -2308,17 +2309,15 @@ (define_insn "*branch<mode>"
 (define_expand "mov<mode>cc"
   [(set (match_operand:GPR 0 "register_operand")
 	(if_then_else:GPR (match_operand 1 "comparison_operator")
-			  (match_operand:GPR 2 "register_operand")
+			  (match_operand:GPR 2 "reg_or_0_operand")
 			  (match_operand:GPR 3 "sfb_alu_operand")))]
-  "TARGET_SFB_ALU"
+  "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV"
 {
-  rtx cmp = operands[1];
-  /* We only handle word mode integer compares for now.  */
-  if (GET_MODE (XEXP (cmp, 0)) != word_mode)
+  if (riscv_expand_conditional_move (operands[0], operands[1],
+				     operands[2], operands[3]))
+    DONE;
+  else
     FAIL;
-  riscv_expand_conditional_move (operands[0], operands[2], operands[3],
-				 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
-  DONE;
 })
 
 (define_insn "*mov<GPR:mode><X:mode>cc"
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index 79cdcbb553f..ae5a65e9a7e 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -106,3 +106,40 @@ (define_insn "*th_tst"
   "TARGET_XTHEADBS"
   "th.tst\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
+
+;; XTheadCondMov
+
+(define_insn "*th_cond_mov<GPR:mode><GPR2:mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r,r")
+	(if_then_else:GPR
+	 (match_operator 4 "equality_operator"
+		[(match_operand:GPR2 1 "register_operand" "r,r")
+		 (const_int 0)])
+	 (match_operand:GPR 2 "reg_or_0_operand" "rJ,0")
+	 (match_operand:GPR 3 "reg_or_0_operand" "0,rJ")))]
+  "TARGET_XTHEADCONDMOV"
+{
+  if (which_alternative == 0)
+    return "th.mv%C4z\t%0,%z2,%1";
+
+  /* Invert the condition and take else-block.  */
+  rtx_code code = GET_CODE (operands[4]);
+  code = (code == EQ) ? NE : EQ;
+  operands[4] = gen_rtx_fmt_ee (code, VOIDmode, const0_rtx, const0_rtx);
+  return "th.mv%C4z\t%0,%z3,%1";
+}
+  [(set_attr "type" "condmove")
+   (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*th_cond_gpr_mov<GPR:mode><GPR2:mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r,r")
+	(if_then_else:GPR
+	 (match_operand:GPR2 1 "register_operand" "r,r")
+	 (match_operand:GPR 2 "reg_or_0_operand" "rJ,0")
+	 (match_operand:GPR 3 "reg_or_0_operand" "0,rJ")))]
+  "TARGET_XTHEADCONDMOV"
+  "@
+   th.mvnez\t%0,%z2,%1
+   th.mveqz\t%0,%z3,%1"
+  [(set_attr "type" "condmove")
+   (set_attr "mode" "<GPR:MODE>")])
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
new file mode 100644
index 00000000000..913ae43f21b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond)
+{
+  if (cond == 0)
+    return 1025;
+  return x;
+}
+
+long
+not_long_int (long x, int cond)
+{
+  if (cond == 0)
+    return 1025l;
+  return x;
+}
+
+int
+not_int_long (int x, long cond)
+{
+  if (cond == 0)
+    return 1025;
+  return x;
+}
+
+long
+not_long_long (long x, int cond)
+{
+  if (cond == 0)
+    return 1025l;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mveqz" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
new file mode 100644
index 00000000000..1bc8b838233
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond)
+{
+  if (!cond)
+    return 1025;
+  return x;
+}
+
+long
+not_long_int (long x, int cond)
+{
+  if (!cond)
+    return 1025l;
+  return x;
+}
+
+int
+not_int_long (int x, long cond)
+{
+  if (!cond)
+    return 1025;
+  return x;
+}
+
+long
+not_long_long (long x, int cond)
+{
+  if (!cond)
+    return 1025l;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mveqz" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
new file mode 100644
index 00000000000..8ef5869a89b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond, int v)
+{
+  if (cond == 0)
+    return v;
+  return x;
+}
+
+long
+not_long_int (long x, int cond, long v)
+{
+  if (cond == 0)
+    return v;
+  return x;
+}
+
+int
+not_int_long (int x, long cond, int v)
+{
+  if (cond == 0)
+    return v;
+  return x;
+}
+
+long
+not_long_long (long x, int cond, long v)
+{
+  if (cond == 0)
+    return v;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mveqz" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
new file mode 100644
index 00000000000..f9568bee27f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond, int v)
+{
+  if (!cond)
+    return v;
+  return x;
+}
+
+long
+not_long_int (long x, int cond, long v)
+{
+  if (!cond)
+    return v;
+  return x;
+}
+
+int
+not_int_long (int x, long cond, int v)
+{
+  if (!cond)
+    return v;
+  return x;
+}
+
+long
+not_long_long (long x, int cond, long v)
+{
+  if (!cond)
+    return v;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mveqz" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
new file mode 100644
index 00000000000..8feddbeb79d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond)
+{
+  if (cond)
+    return 1025;
+  return x;
+}
+
+long
+not_long_int (long x, int cond)
+{
+  if (cond)
+    return 1025l;
+  return x;
+}
+
+int
+not_int_long (int x, long cond)
+{
+  if (cond)
+    return 1025;
+  return x;
+}
+
+long
+not_long_long (long x, int cond)
+{
+  if (cond)
+    return 1025l;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mvnez" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
new file mode 100644
index 00000000000..7c08e20c25d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond)
+{
+  if (cond != 0)
+    return 1025;
+  return x;
+}
+
+long
+not_long_int (long x, int cond)
+{
+  if (cond != 0)
+    return 1025l;
+  return x;
+}
+
+int
+not_int_long (int x, long cond)
+{
+  if (cond != 0)
+    return 1025;
+  return x;
+}
+
+long
+not_long_long (long x, int cond)
+{
+  if (cond != 0)
+    return 1025l;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mvnez" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
new file mode 100644
index 00000000000..c1619509af9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond, int v)
+{
+  if (cond)
+    return v;
+  return x;
+}
+
+long
+not_long_int (long x, int cond, long v)
+{
+  if (cond)
+    return v;
+  return x;
+}
+
+int
+not_int_long (int x, long cond, int v)
+{
+  if (cond)
+    return v;
+  return x;
+}
+
+long
+not_long_long (long x, int cond, long v)
+{
+  if (cond)
+    return v;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mvnez" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c
new file mode 100644
index 00000000000..ff95a57927a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadcondmov" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadcondmov" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" } } */
+
+int
+not_int_int (int x, int cond, int v)
+{
+  if (cond != 0)
+    return v;
+  return x;
+}
+
+long
+not_long_int (long x, int cond, long v)
+{
+  if (cond != 0)
+    return v;
+  return x;
+}
+
+int
+not_int_long (int x, long cond, int v)
+{
+  if (cond != 0)
+    return v;
+  return x;
+}
+
+long
+not_long_long (long x, int cond, long v)
+{
+  if (cond != 0)
+    return v;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times "th.mvnez" 4 } } */
-- 
2.39.2


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

* [PATCH v3 07/11] riscv: thead: Add support for the XTheadMac ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (5 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 06/11] riscv: thead: Add support for the XTheadCondMov ISA extensions Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 08/11] riscv: thead: Add support for the XTheadFmv " Christoph Muellner
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

The XTheadMac ISA extension provides multiply-accumulate/subtract
instructions:
* mula/mulaw/mulah
* muls/mulsw/mulsh

To benefit from middle-end passes, we expand the following named
patterns in riscv.md (as they are not T-Head-specific):
* maddhisi4
* msubhisi4

gcc/ChangeLog:

	* config/riscv/riscv.md (maddhisi4): New expand.
	(msubhisi4): New expand.
	* config/riscv/thead.md (*th_mula<mode>): New pattern.
	(*th_mulawsi): New pattern.
	(*th_mulawsi2): New pattern.
	(*th_maddhisi4): New pattern.
	(*th_sextw_maddhisi4): New pattern.
	(*th_muls<mode>): New pattern.
	(*th_mulswsi): New pattern.
	(*th_mulswsi2): New pattern.
	(*th_msubhisi4): New pattern.
	(*th_sextw_msubhisi4): New pattern.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/thead-mula-muls.c: New test.

Co-Developed-by: Xianmiao Qu <cooper.qu@linux.alibaba.com>
Signed-off-by: Xianmiao Qu <cooper.qu@linux.alibaba.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>

Changed in v2:
- Add missing prefix in on INSN
---
 gcc/config/riscv/riscv.md                     |  18 +++
 gcc/config/riscv/thead.md                     | 121 ++++++++++++++++++
 .../gcc.target/riscv/xtheadmac-mula-muls.c    |  43 +++++++
 3 files changed, 182 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 5562e5621fa..112c93f733e 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3106,6 +3106,24 @@ (define_expand "extzv<mode>"
     FAIL;
 })
 
+(define_expand "maddhisi4"
+  [(set (match_operand:SI 0 "register_operand")
+	(plus:SI
+	  (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
+		   (sign_extend:SI (match_operand:HI 2 "register_operand")))
+	  (match_operand:SI 3 "register_operand")))]
+  "TARGET_XTHEADMAC"
+)
+
+(define_expand "msubhisi4"
+  [(set (match_operand:SI 0 "register_operand")
+	(minus:SI
+	  (match_operand:SI 3 "register_operand")
+	  (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
+		   (sign_extend:SI (match_operand:HI 2 "register_operand")))))]
+  "TARGET_XTHEADMAC"
+)
+
 (include "bitmanip.md")
 (include "sync.md")
 (include "peephole.md")
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index ae5a65e9a7e..f616035e5a5 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -143,3 +143,124 @@ (define_insn "*th_cond_gpr_mov<GPR:mode><GPR2:mode>"
    th.mveqz\t%0,%z3,%1"
   [(set_attr "type" "condmove")
    (set_attr "mode" "<GPR:MODE>")])
+
+;; XTheadMac
+
+(define_insn "*th_mula<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	      (plus:X (mult:X (match_operand:X 1 "register_operand" "r")
+			      (match_operand:X 2 "register_operand" "r"))
+		      (match_operand:X 3 "register_operand" "0")))]
+  "TARGET_XTHEADMAC"
+  "th.mula\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "<MODE>")]
+)
+
+(define_insn "*th_mulawsi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(sign_extend:DI
+	  (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+			    (match_operand:SI 2 "register_operand" "r"))
+		   (match_operand:SI 3 "register_operand" "0"))))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulaw\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_mulawsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	      (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+				(match_operand:SI 2 "register_operand" "r"))
+		       (match_operand:SI 3 "register_operand" "0")))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulaw\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_maddhisi4"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	  (plus:SI
+	    (mult:SI
+	      (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
+	      (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
+	    (match_operand:SI 3 "register_operand" " 0")))]
+  "TARGET_XTHEADMAC"
+  "th.mulah\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_sextw_maddhisi4"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(sign_extend:DI
+	  (plus:SI
+	    (mult:SI
+	      (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
+	      (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
+	    (match_operand:SI 3 "register_operand" " 0"))))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulah\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_muls<mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+	      (minus:X (match_operand:X 3 "register_operand" "0")
+		       (mult:X (match_operand:X 1 "register_operand" "r")
+			       (match_operand:X 2 "register_operand" "r"))))]
+  "TARGET_XTHEADMAC"
+  "th.muls\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "<MODE>")]
+)
+
+(define_insn "*th_mulswsi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(sign_extend:DI
+	  (minus:SI (match_operand:SI 3 "register_operand" "0")
+		    (mult:SI (match_operand:SI 1 "register_operand" "r")
+			     (match_operand:SI 2 "register_operand" "r")))))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulsw\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_mulswsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(minus:SI (match_operand:SI 3 "register_operand" "0")
+		  (mult:SI (match_operand:SI 1 "register_operand" "r")
+			   (match_operand:SI 2 "register_operand" "r"))))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulsw\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_msubhisi4"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(minus:SI (match_operand:SI 3 "register_operand" " 0")
+	  (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
+	    (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))))]
+  "TARGET_XTHEADMAC"
+  "th.mulsh\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
+
+(define_insn "*th_sextw_msubhisi4"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(sign_extend:DI
+	  (minus:SI (match_operand:SI 3 "register_operand" " 0")
+	    (mult:SI
+	      (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
+	      (sign_extend:SI (match_operand:HI 2 "register_operand" " r"))))))]
+  "TARGET_XTHEADMAC && TARGET_64BIT"
+  "th.mulsh\\t%0,%1,%2"
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")]
+)
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c b/gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
new file mode 100644
index 00000000000..751a4be5091
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xtheadmac" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xtheadmac" { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */
+
+long f_mula(long a, long b, long c)
+{
+  return a + b * c;
+}
+
+long f_muls(long a, long b, long c)
+{
+  return a - b * c;
+}
+
+#if __riscv_xlen == 64
+int f_mulaw(int a, int b, int c)
+{
+  return a + b * c;
+}
+
+int f_mulsw(int a, int b, int c)
+{
+  return a - b * c;
+}
+#endif
+
+long f_mulah(int a, unsigned short b, unsigned short c)
+{
+  return a + (int)(short)b * (int)(short)c;
+}
+
+long f_mulsh(int a, unsigned short b, unsigned short c)
+{
+  return a - (int)(short)b * (int)(short)c;
+}
+
+/* { dg-final { scan-assembler-times "th.mula\t" 1 } } */
+/* { dg-final { scan-assembler-times "th.muls\t" 1 } } */
+/* { dg-final { scan-assembler-times "th.mulaw\t" 1 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.mulsw\t" 1 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.mulah\t" 1 } } */
+/* { dg-final { scan-assembler-times "th.mulsh\t" 1 } } */
-- 
2.39.2


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

* [PATCH v3 08/11] riscv: thead: Add support for the XTheadFmv ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (6 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 07/11] riscv: thead: Add support for the XTheadMac ISA extension Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  5:51 ` [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair " Christoph Muellner
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

The XTheadFmv ISA extension provides instructions to move
data between 32-bit GP registers and 64-bit FP registers.

gcc/ChangeLog:

	* config/riscv/constraints.md (TARGET_XTHEADFMV ? FP_REGS : NO_REGS)
	New constraint "th_f_fmv".
	(TARGET_XTHEADFMV ? GR_REGS : NO_REGS): New constraint
	"th_r_fmv".
	* config/riscv/riscv.cc (riscv_split_doubleword_move):
	Add split code for XTheadFmv.
	(riscv_secondary_memory_needed): XTheadFmv does not need
	secondary memory.
	* config/riscv/riscv.md: Add new UNSPEC_XTHEADFMV and
	UNSPEC_XTHEADFMV_HW. Add support for XTheadFmv to
	movdf_hardfloat_rv32.
	* config/riscv/thead.md (th_fmv_hw_w_x): New INSN.
	(th_fmv_x_w): New INSN.
	(th_fmv_x_hw): New INSN.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadfmv-fmv.c: New test.

Co-Developed-by: Xianmiao Qu <cooper.qu@linux.alibaba.com>
Signed-off-by: Xianmiao Qu <cooper.qu@linux.alibaba.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/constraints.md               |  8 +++++
 gcc/config/riscv/riscv.cc                     | 25 ++++++++++++--
 gcc/config/riscv/riscv.md                     | 11 +++++--
 gcc/config/riscv/thead.md                     | 33 +++++++++++++++++++
 .../gcc.target/riscv/xtheadfmv-fmv.c          | 24 ++++++++++++++
 5 files changed, 95 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index a051d466ae2..e49019d8fa9 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -166,3 +166,11 @@ (define_memory_constraint "Wdm"
   "Vector duplicate memory operand"
   (and (match_code "mem")
        (match_code "reg" "0")))
+
+;; Vendor ISA extension constraints.
+
+(define_register_constraint "th_f_fmv" "TARGET_XTHEADFMV ? FP_REGS : NO_REGS"
+  "A floating-point register for XTheadFmv.")
+
+(define_register_constraint "th_r_fmv" "TARGET_XTHEADFMV ? GR_REGS : NO_REGS"
+  "An integer register for XTheadFmv.")
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a60ab2c7fad..48f2cb399ae 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2754,11 +2754,29 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
 void
 riscv_split_doubleword_move (rtx dest, rtx src)
 {
-  rtx low_dest;
+  /* XTheadFmv has instructions for accessing the upper bits of a double.  */
+  if (!TARGET_64BIT && TARGET_XTHEADFMV)
+    {
+      if (FP_REG_RTX_P (dest))
+	{
+	  rtx low_src = riscv_subword (src, false);
+	  rtx high_src = riscv_subword (src, true);
+	  emit_insn (gen_th_fmv_hw_w_x (dest, high_src, low_src));
+	  return;
+	}
+      if (FP_REG_RTX_P (src))
+	{
+	  rtx low_dest = riscv_subword (dest, false);
+	  rtx high_dest = riscv_subword (dest, true);
+	  emit_insn (gen_th_fmv_x_w (low_dest, src));
+	  emit_insn (gen_th_fmv_x_hw (high_dest, src));
+	  return;
+	}
+    }
 
    /* The operation can be split into two normal moves.  Decide in
       which order to do them.  */
-   low_dest = riscv_subword (dest, false);
+   rtx low_dest = riscv_subword (dest, false);
    if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src))
      {
        riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true));
@@ -5802,7 +5820,8 @@ riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1,
 {
   return (!riscv_v_ext_vector_mode_p (mode)
 	  && GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
-	  && (class1 == FP_REGS) != (class2 == FP_REGS));
+	  && (class1 == FP_REGS) != (class2 == FP_REGS)
+	  && !TARGET_XTHEADFMV);
 }
 
 /* Implement TARGET_REGISTER_MOVE_COST.  */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 112c93f733e..61f175bb62b 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -100,6 +100,10 @@ (define_c_enum "unspecv" [
 
   ;; Zihintpause unspec
   UNSPECV_PAUSE
+
+  ;; XTheadFmv unspec
+  UNSPEC_XTHEADFMV
+  UNSPEC_XTHEADFMV_HW
 ])
 
 (define_constants
@@ -1856,16 +1860,17 @@ (define_expand "movdf"
     DONE;
 })
 
+
 ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
 (define_insn "*movdf_hardfloat_rv32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,  *r,*r,*m")
-	(match_operand:DF 1 "move_operand"         " f,G,m,f,G,*r*G,*m,*r"))]
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*th_f_fmv,*th_r_fmv,  *r,*r,*m")
+	(match_operand:DF 1 "move_operand"         " f,G,m,f,G,*th_r_fmv,*th_f_fmv,*r*G,*m,*r"))]
   "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
    && (register_operand (operands[0], DFmode)
        || reg_or_0_operand (operands[1], DFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
+  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "DF")])
 
 (define_insn "*movdf_hardfloat_rv64"
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index f616035e5a5..6ec3613071f 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -144,6 +144,39 @@ (define_insn "*th_cond_gpr_mov<GPR:mode><GPR2:mode>"
   [(set_attr "type" "condmove")
    (set_attr "mode" "<GPR:MODE>")])
 
+;; XTheadFmv
+
+;; In RV32, we lack fmv.x.d and fmv.d.x, but XTheadFmv has instructions
+;; that cover this case.
+
+(define_insn "th_fmv_hw_w_x"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+	(unspec:DF [(match_operand:SI 1 "register_operand" "r")
+                (match_operand:SI 2 "register_operand" "r")]
+     UNSPEC_XTHEADFMV))]
+  "!TARGET_64BIT && TARGET_XTHEADFMV"
+  "fmv.w.x\t%0,%2\n\tth.fmv.hw.x\t%0,%1"
+  [(set_attr "move_type" "move")
+   (set_attr "mode" "DF")])
+
+(define_insn "th_fmv_x_w"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:DF 1 "register_operand" "f")]
+     UNSPEC_XTHEADFMV))]
+  "!TARGET_64BIT && TARGET_XTHEADFMV"
+  "fmv.x.w\t%0,%1"
+  [(set_attr "move_type" "move")
+   (set_attr "mode" "DF")])
+
+(define_insn "th_fmv_x_hw"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:DF 1 "register_operand" "f")]
+     UNSPEC_XTHEADFMV_HW))]
+  "!TARGET_64BIT && TARGET_XTHEADFMV"
+  "th.fmv.x.hw\t%0,%1"
+  [(set_attr "move_type" "move")
+   (set_attr "mode" "DF")])
+
 ;; XTheadMac
 
 (define_insn "*th_mula<mode>"
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c b/gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
new file mode 100644
index 00000000000..10d035e9e1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { rv32 } } } */
+/* { dg-options "-march=rv32gc_xtheadfmv" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+double
+ll2d (long long ll)
+{
+  return *(double*)&ll;
+}
+
+long long
+d2ll (double d)
+{
+  return *(long long*)&d;
+}
+
+/* { dg-final { scan-assembler "fmv.w.x" } } */
+/* { dg-final { scan-assembler "th.fmv.hw.x" } } */
+/* { dg-final { scan-assembler "fmv.x.w" } } */
+/* { dg-final { scan-assembler "th.fmv.x.hw" } } */
+/* { dg-final { scan-assembler-not "sw" } } */
+/* { dg-final { scan-assembler-not "fld" } } */
+/* { dg-final { scan-assembler-not "fsd" } } */
+/* { dg-final { scan-assembler-not "lw" } } */
-- 
2.39.2


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

* [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (7 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 08/11] riscv: thead: Add support for the XTheadFmv " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  9:00   ` Kito Cheng
  2023-02-24 15:48   ` Kito Cheng
  2023-02-24  5:51 ` [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx " Christoph Muellner
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: Christoph Müllner

From: Christoph Müllner <christoph.muellner@vrull.eu>

The XTheadMemPair ISA extension allows to pair two loads or stores:
* th.ldd (2x LD)
* th.lwd (2x LW)
* th.lwud (2x LWU)
* th.sdd (2x SD)
* th.swd (2x SW)

The displacement of these instructions is quite limited:
* Displacement := imm2 << shamt
* imm2 is a 2-bit unsigned value {0..3}
* shamt is 4 for th.ldd/th.sdd and 3 otherwise
But even with this small displacement we can identify many candidates.

The merge of the two loads/stores is realized in form of peephole2
passes that support instruction reordering.
The CFA expansion (save/restore registers on/from stack) is not
processed by the peephole2 pass and, therefore, needs special-treatment.
Many ideas of this patch are inspired by similar/equal approaches
in other backends.

gcc/ChangeLog:

	* config/riscv/peephole.md: New peephole passes for
	XTheadMemPair.
	* config/riscv/riscv-protos.h (thead_mempair_operands_p):
	New prototype.
	(thead_mempair_order_operands): Likewise.
	(thead_mempair_output_move): Likewise.
	* config/riscv/riscv.cc (extract_base_offset_in_addr):
	New function.
	(riscv_split_plus): New function.
	(thead_mempair_output_move): New function.
	(thead_mempair_check_consecutive_mems): New function.
	(thead_mempair_operand_p): New function.
	(thead_mempair_load_overlap_p): New function.
	(thead_mempair_operands_p): New function.
	(thead_mempair_order_operands): New function.
	(riscv_save_reg): Moved code.
	(th_mempair_save_reg): New function.
	(riscv_restore_reg): Moved code.
	(th_mempair_restore_reg): New function.
	(riscv_for_each_saved_reg): Add code to handle mempair
	instructions.
	* config/riscv/thead.md (*th_mempair_load_<GPR:mode>2):
	New pattern.
	(*th_mempair_store_<GPR:mode>2): Likewise.
	(*th_mempair_load_extendsidi2): Likewise.
	(*th_mempair_load_zero_extendsidi2): Likewise.

gcc/testsuite/ChangeLog:

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

Changes in v3:
- Don't emit instructions during peephole2, but emit parallel INSNs
- Add proper checks for the INSN patterns to avoid ICEs or illegal
  instructions reported by the assembler
- Don't insert any `add` instructions
- Rework the constraint handling
- Simplify the output function
- Restructure and simplify CFA processing
- Add debug notes to CFA instructions
- Emit parallel INSNs in the CFA code (same as peephole2)
- Drop tests that target reordering
- Drop tests that are irrelevant (e.g. unrolled loops)
- Add tests for all possible displacements and all instructions
- Add tests for CFA

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/peephole.md                  |  56 +++
 gcc/config/riscv/riscv-protos.h               |   6 +
 gcc/config/riscv/riscv.cc                     | 450 ++++++++++++++++--
 gcc/config/riscv/thead.md                     |  52 ++
 .../gcc.target/riscv/xtheadmempair-1.c        |  98 ++++
 .../gcc.target/riscv/xtheadmempair-2.c        |  84 ++++
 .../gcc.target/riscv/xtheadmempair-3.c        |  29 ++
 7 files changed, 746 insertions(+), 29 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c

diff --git a/gcc/config/riscv/peephole.md b/gcc/config/riscv/peephole.md
index 0ef0c04410b..ea696f3116c 100644
--- a/gcc/config/riscv/peephole.md
+++ b/gcc/config/riscv/peephole.md
@@ -38,3 +38,59 @@ (define_peephole2
 {
   operands[5] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[5]));
 })
+
+;; XTheadMemPair: merge two SI or DI loads
+(define_peephole2
+  [(set (match_operand:GPR 0 "register_operand" "")
+	(match_operand:GPR 1 "memory_operand" ""))
+   (set (match_operand:GPR 2 "register_operand" "")
+	(match_operand:GPR 3 "memory_operand" ""))]
+  "TARGET_XTHEADMEMPAIR
+  && thead_mempair_operands_p (operands, true, <GPR:MODE>mode)"
+  [(parallel [(set (match_dup 0) (match_dup 1))
+	          (set (match_dup 2) (match_dup 3))])]
+{
+  thead_mempair_order_operands (operands, true, <GPR:MODE>mode);
+})
+
+;; XTheadMemPair: merge two SI or DI stores
+(define_peephole2
+  [(set (match_operand:GPR 0 "memory_operand" "")
+	(match_operand:GPR 1 "register_operand" ""))
+   (set (match_operand:GPR 2 "memory_operand" "")
+	(match_operand:GPR 3 "register_operand" ""))]
+  "TARGET_XTHEADMEMPAIR
+  && thead_mempair_operands_p (operands, false, <GPR:MODE>mode)"
+  [(parallel [(set (match_dup 0) (match_dup 1))
+              (set (match_dup 2) (match_dup 3))])]
+{
+  thead_mempair_order_operands (operands, false, <GPR:MODE>mode);
+})
+
+;; XTheadMemPair: merge two SI loads with sign-extension
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+	(sign_extend:DI (match_operand:SI 1 "memory_operand" "")))
+   (set (match_operand:DI 2 "register_operand" "")
+	(sign_extend:DI (match_operand:SI 3 "memory_operand" "")))]
+  "TARGET_XTHEADMEMPAIR && TARGET_64BIT
+  && thead_mempair_operands_p (operands, true, SImode)"
+  [(parallel [(set (match_dup 0) (sign_extend:DI (match_dup 1)))
+              (set (match_dup 2) (sign_extend:DI (match_dup 3)))])]
+{
+  thead_mempair_order_operands (operands, true, SImode);
+})
+
+;; XTheadMemPair: merge two SI loads with zero-extension
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+	(zero_extend:DI (match_operand:SI 1 "memory_operand" "")))
+   (set (match_operand:DI 2 "register_operand" "")
+	(zero_extend:DI (match_operand:SI 3 "memory_operand" "")))]
+  "TARGET_XTHEADMEMPAIR && TARGET_64BIT
+  && thead_mempair_operands_p (operands, true, SImode)"
+  [(parallel [(set (match_dup 0) (zero_extend:DI (match_dup 1)))
+              (set (match_dup 2) (zero_extend:DI (match_dup 3)))])]
+{
+  thead_mempair_order_operands (operands, true, SImode);
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 5cf4fafd662..1b7ba02726d 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -54,7 +54,13 @@ extern bool riscv_split_64bit_move_p (rtx, rtx);
 extern void riscv_split_doubleword_move (rtx, rtx);
 extern const char *riscv_output_move (rtx, rtx);
 extern const char *riscv_output_return ();
+
+extern bool thead_mempair_operands_p (rtx[4], bool, machine_mode);
+extern void thead_mempair_order_operands (rtx[4], bool, machine_mode);
+
 #ifdef RTX_CODE
+extern const char *thead_mempair_output_move (rtx[4], bool, machine_mode, RTX_CODE);
+
 extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 48f2cb399ae..33854393bd2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2943,6 +2943,332 @@ riscv_output_move (rtx dest, rtx src)
   gcc_unreachable ();
 }
 
+/* If MEM is in the form of "base+offset", extract the two parts
+   of address and set to BASE and OFFSET, otherwise return false
+   after clearing BASE and OFFSET.  */
+
+static bool
+extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset)
+{
+  rtx addr;
+
+  gcc_assert (MEM_P (mem));
+
+  addr = XEXP (mem, 0);
+
+  if (REG_P (addr))
+    {
+      *base = addr;
+      *offset = const0_rtx;
+      return true;
+    }
+
+  if (GET_CODE (addr) == PLUS
+      && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1)))
+    {
+      *base = XEXP (addr, 0);
+      *offset = XEXP (addr, 1);
+      return true;
+    }
+
+  *base = NULL_RTX;
+  *offset = NULL_RTX;
+
+  return false;
+}
+
+/* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR
+   and *OFFSET_PTR.  Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise.  */
+
+static void
+riscv_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr)
+{
+  if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
+    {
+      *base_ptr = XEXP (x, 0);
+      *offset_ptr = INTVAL (XEXP (x, 1));
+    }
+  else
+    {
+      *base_ptr = x;
+      *offset_ptr = 0;
+    }
+}
+
+/* Output a mempair instruction with the provided OPERANDS.
+   LOAD_P is true if a we have a pair of loads (stores otherwise).
+   MODE is the access mode (DI or SI).
+   CODE is the extension code (UNKNOWN, SIGN_EXTEND or ZERO_EXTEND).
+   This instruction does not handle invalid inputs gracefully,
+   but is full of assertions to ensure that only valid instructions
+   are emitted.  */
+
+const char *
+thead_mempair_output_move (rtx operands[4], bool load_p,
+			   machine_mode mode, RTX_CODE code)
+{
+  rtx reg1, reg2, mem1, mem2, base1, base2;
+  HOST_WIDE_INT offset1, offset2;
+  rtx output_operands[5];
+  const char* format;
+
+  gcc_assert (mode == SImode || mode == DImode);
+
+  /* Paired 64-bit access instructions have a fixed shift amount of 4.
+     Paired 32-bit access instructions have a fixed shift amount of 3.  */
+  unsigned shamt = (mode == DImode) ? 4 : 3;
+
+  if (load_p)
+    {
+	reg1 = copy_rtx (operands[0]);
+	reg2 = copy_rtx (operands[2]);
+	mem1 = copy_rtx (operands[1]);
+	mem2 = copy_rtx (operands[3]);
+
+	if (mode == SImode)
+	  if (code == ZERO_EXTEND)
+	    format = "th.lwud\t%0, %1, (%2), %3, %4";
+	  else //SIGN_EXTEND or UNKNOWN
+	    format = "th.lwd\t%0, %1, (%2), %3, %4";
+	else
+	  format = "th.ldd\t%0, %1, (%2), %3, %4";
+    }
+  else
+    {
+	reg1 = copy_rtx (operands[1]);
+	reg2 = copy_rtx (operands[3]);
+	mem1 = copy_rtx (operands[0]);
+	mem2 = copy_rtx (operands[2]);
+
+	if (mode == SImode)
+	  format = "th.swd\t%z0, %z1, (%2), %3, %4";
+	else
+	  format = "th.sdd\t%z0, %z1, (%2), %3, %4";
+    }
+
+  riscv_split_plus (XEXP (mem1, 0), &base1, &offset1);
+  riscv_split_plus (XEXP (mem2, 0), &base2, &offset2);
+  gcc_assert (rtx_equal_p (base1, base2));
+  auto size1 = MEM_SIZE (mem1);
+  auto size2 = MEM_SIZE (mem2);
+  gcc_assert (known_eq (size1, size2));
+  gcc_assert (known_eq (offset1 + size1, offset2));
+
+  HOST_WIDE_INT imm2 = offset1 >> shamt;
+
+  /* Make sure all mempair instruction constraints are met.  */
+  gcc_assert (imm2 >= 0 && imm2 < 4);
+  gcc_assert ((imm2 << shamt) == offset1);
+  gcc_assert (REG_P (reg1));
+  gcc_assert (REG_P (reg2));
+  gcc_assert (REG_P (base1));
+  if (load_p)
+    {
+      gcc_assert (REGNO (reg1) != REGNO (reg2));
+      gcc_assert (REGNO (reg1) != REGNO (base1));
+      gcc_assert (REGNO (reg2) != REGNO (base1));
+    }
+
+  /* Output the mempair instruction.  */
+  output_operands[0] = copy_rtx (reg1);
+  output_operands[1] = copy_rtx (reg2);
+  output_operands[2] = copy_rtx (base1);
+  output_operands[3] = gen_rtx_CONST_INT (mode, imm2);
+  output_operands[4] = gen_rtx_CONST_INT (mode, shamt);
+  output_asm_insn (format, output_operands);
+
+  return "";
+}
+
+/* Analyse if a pair of loads/stores MEM1 and MEM2 with given MODE
+   are consecutive so they can be merged into a mempair instruction.
+   RESERVED will be set to true, if a reversal of the accesses is
+   required (false otherwise). Returns true if the accesses can be
+   merged (even if reversing is necessary) and false if not.  */
+
+static bool
+thead_mempair_check_consecutive_mems (machine_mode mode, rtx *mem1, rtx *mem2,
+				      bool *reversed)
+{
+  rtx base1, base2, offset1, offset2;
+  extract_base_offset_in_addr (*mem1, &base1, &offset1);
+  extract_base_offset_in_addr (*mem2, &base2, &offset2);
+
+  /* Make sure both mems are in base+offset form.  */
+  if (!base1 || !base2)
+    return false;
+
+  /* If both mems use the same base register, just check the offsets.  */
+  if (rtx_equal_p (base1, base2))
+    {
+      auto size = GET_MODE_SIZE (mode);
+
+      if (known_eq (UINTVAL (offset1) + size, UINTVAL (offset2)))
+	{
+	  *reversed = false;
+	  return true;
+	}
+
+      if (known_eq (UINTVAL (offset2) + size, UINTVAL (offset1)))
+	{
+	  *reversed = true;
+	  return true;
+	}
+
+      return false;
+    }
+
+  return false;
+}
+
+/* Check if the given MEM can be used to define the address of a mempair
+   instruction.  */
+
+static bool
+thead_mempair_operand_p (rtx mem, machine_mode mode)
+{
+  if (!MEM_SIZE_KNOWN_P (mem))
+    return false;
+
+  /* Only DI or SI mempair instructions exist.  */
+  auto mem_sz = MEM_SIZE (mem);
+  auto mode_sz = GET_MODE_SIZE (mode);
+  if (!known_eq (mem_sz, mode_sz))
+    return false;
+
+  /* Paired 64-bit access instructions have a fixed shift amount of 4.
+     Paired 32-bit access instructions have a fixed shift amount of 3.  */
+  machine_mode mem_mode = GET_MODE (mem);
+  unsigned shamt = (mem_mode == DImode) ? 4 : 3;
+
+  rtx base;
+  HOST_WIDE_INT offset;
+  riscv_split_plus (XEXP (mem, 0), &base, &offset);
+  HOST_WIDE_INT imm2 = offset >> shamt;
+
+  if (imm2 < 0 || imm2 >= 4)
+    return false;
+
+  if ((imm2 << shamt) != offset)
+    return false;
+
+  return true;
+}
+
+static bool
+thead_mempair_load_overlap_p (rtx reg1, rtx reg2, rtx mem)
+{
+  if (REGNO (reg1) == REGNO (reg2))
+    return true;
+
+  if (reg_overlap_mentioned_p (reg1, mem))
+    return true;
+
+  rtx base;
+  HOST_WIDE_INT offset;
+  riscv_split_plus (XEXP (mem, 0), &base, &offset);
+
+  if (!REG_P (base))
+    return true;
+
+  if (REG_P (base))
+    {
+      if (REGNO (base) == REGNO (reg1)
+	  || REGNO (base) == REGNO (reg2))
+	return true;
+    }
+
+  return false;
+}
+
+/* Given OPERANDS of consecutive load/store, check if we can merge
+   them into load-pair or store-pair instructions.
+   LOAD is true if they are load instructions.
+   MODE is the mode of memory operation.  */
+
+bool
+thead_mempair_operands_p (rtx operands[4], bool load_p,
+			  machine_mode mode)
+{
+  rtx mem_1, mem_2, reg_1, reg_2;
+
+  if (load_p)
+    {
+      reg_1 = operands[0];
+      mem_1 = operands[1];
+      reg_2 = operands[2];
+      mem_2 = operands[3];
+      if (!REG_P (reg_1) || !REG_P (reg_2))
+	return false;
+      if (thead_mempair_load_overlap_p (reg_1, reg_2, mem_1))
+	return false;
+      if (thead_mempair_load_overlap_p (reg_1, reg_2, mem_2))
+	return false;
+    }
+  else
+    {
+      mem_1 = operands[0];
+      reg_1 = operands[1];
+      mem_2 = operands[2];
+      reg_2 = operands[3];
+    }
+
+  /* Check if the registers are GP registers.  */
+  if (!REG_P (reg_1) || !GP_REG_P (REGNO (reg_1))
+      || !REG_P (reg_2) || !GP_REG_P (REGNO (reg_2)))
+    return false;
+
+  /* The mems cannot be volatile.  */
+  if (!MEM_P (mem_1) || !MEM_P (mem_2))
+    return false;
+  if (MEM_VOLATILE_P (mem_1) || MEM_VOLATILE_P (mem_2))
+    return false;
+
+  /* If we have slow unaligned access, we only accept aligned memory.  */
+  if (riscv_slow_unaligned_access_p
+      && known_lt (MEM_ALIGN (mem_1), GET_MODE_SIZE (mode) * BITS_PER_UNIT))
+    return false;
+
+  /* Check if the addresses are in the form of [base+offset].  */
+  bool reversed = false;
+  if (!thead_mempair_check_consecutive_mems (mode, &mem_1, &mem_2, &reversed))
+    return false;
+
+  /* The first memory accesses must be a mempair operand.  */
+  if ((!reversed && !thead_mempair_operand_p (mem_1, mode))
+      || (reversed && !thead_mempair_operand_p (mem_2, mode)))
+    return false;
+
+  /* The operands must be of the same size.  */
+  gcc_assert (known_eq (GET_MODE_SIZE (GET_MODE (mem_1)),
+			GET_MODE_SIZE (GET_MODE (mem_2))));
+
+  return true;
+}
+
+/* Given OPERANDS of consecutive load/store that can be merged,
+   swap them if they are not in ascending order.
+   Return true if swap was performed.  */
+void
+thead_mempair_order_operands (rtx operands[4], bool load_p, machine_mode mode)
+{
+  int mem_op = load_p ? 1 : 0;
+  bool reversed = false;
+  if (!thead_mempair_check_consecutive_mems (mode,
+					     operands + mem_op,
+					     operands + mem_op + 2,
+					     &reversed))
+    gcc_unreachable ();
+
+  if (reversed)
+    {
+      /* Irrespective of whether this is a load or a store,
+	 we do the same swap.  */
+      std::swap (operands[0], operands[2]);
+      std::swap (operands[1], operands[3]);
+    }
+}
+
 const char *
 riscv_output_return ()
 {
@@ -4963,6 +5289,61 @@ riscv_set_return_address (rtx address, rtx scratch)
   riscv_emit_move (gen_frame_mem (GET_MODE (address), slot_address), address);
 }
 
+/* Save register REG to MEM.  Make the instruction frame-related.  */
+
+static void
+riscv_save_reg (rtx reg, rtx mem)
+{
+  riscv_emit_move (mem, reg);
+  riscv_set_frame_expr (riscv_frame_set (mem, reg));
+}
+
+/* Save register 2x REG to MEM.  Make the instruction frame-related.  */
+
+static void
+th_mempair_save_reg (rtx operands[4])
+{
+  rtx set1 = gen_rtx_SET (operands[0], operands[1]);
+  rtx set2 = gen_rtx_SET (operands[2], operands[3]);
+  rtx insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set1, set2)));
+  RTX_FRAME_RELATED_P (insn) = 1;
+  add_reg_note (insn, REG_CFA_OFFSET, copy_rtx (set1));
+  add_reg_note (insn, REG_CFA_OFFSET, copy_rtx (set2));
+}
+
+/* Restore register REG from MEM.  */
+
+static void
+riscv_restore_reg (rtx reg, rtx mem)
+{
+  rtx insn = riscv_emit_move (reg, mem);
+  rtx dwarf = NULL_RTX;
+  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
+
+  if (epilogue_cfa_sp_offset && REGNO (reg) == HARD_FRAME_POINTER_REGNUM)
+    {
+      rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+					 GEN_INT (epilogue_cfa_sp_offset));
+      dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
+    }
+
+  REG_NOTES (insn) = dwarf;
+  RTX_FRAME_RELATED_P (insn) = 1;
+}
+
+/* Restore register 2x REG from MEM.  Make the instruction frame-related.  */
+
+static void
+th_mempair_restore_reg (rtx operands[4])
+{
+  rtx set1 = gen_rtx_SET (operands[0], operands[1]);
+  rtx set2 = gen_rtx_SET (operands[2], operands[3]);
+  rtx insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set1, set2)));
+  RTX_FRAME_RELATED_P (insn) = 1;
+  add_reg_note (insn, REG_CFA_RESTORE, operands[0]);
+  add_reg_note (insn, REG_CFA_RESTORE, operands[2]);
+}
+
 /* A function to save or store a register.  The first argument is the
    register and the second is the stack slot.  */
 typedef void (*riscv_save_restore_fn) (rtx, rtx);
@@ -5057,6 +5438,46 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
 	  && riscv_is_eh_return_data_register (regno))
 	continue;
 
+      if (TARGET_XTHEADMEMPAIR)
+	{
+	  /* Get the next reg/offset pair.  */
+	  HOST_WIDE_INT offset2 = offset;
+	  unsigned int regno2 = riscv_next_saved_reg (regno, limit, &offset2);
+
+	  /* Prepare the operands for a mempair instruction.  */
+	  bool load_p = (fn == riscv_restore_reg);
+	  int reg_op = load_p ? 0 : 1;
+	  int mem_op = load_p ? 1 : 0;
+	  rtx operands[4];
+	  operands[reg_op] = gen_rtx_REG (word_mode, regno);
+	  rtx mem1 = plus_constant (word_mode, stack_pointer_rtx, offset);
+	  mem1 = gen_frame_mem (word_mode, mem1);
+	  operands[mem_op] = mem1;
+	  operands[2 + reg_op] = gen_rtx_REG (word_mode, regno2);
+	  rtx mem2 = plus_constant (word_mode, stack_pointer_rtx, offset2);
+	  mem2 = gen_frame_mem (word_mode, mem2);
+	  operands[2 + mem_op] = mem2;
+
+	  /* Validate everything before emitting a mempair instruction.  */
+	  if (regno2 != INVALID_REGNUM
+	      && !cfun->machine->reg_is_wrapped_separately[regno2]
+	      && !(epilogue && !maybe_eh_return
+		   && riscv_is_eh_return_data_register (regno2))
+	      && thead_mempair_operands_p (operands, load_p, word_mode))
+	    {
+	      thead_mempair_order_operands (operands, load_p, word_mode);
+
+	      if (load_p)
+		th_mempair_restore_reg (operands);
+	      else
+		th_mempair_save_reg (operands);
+
+	      offset = offset2;
+	      regno = regno2;
+	      continue;
+	    }
+	}
+
       riscv_save_restore_reg (word_mode, regno, offset, fn);
     }
 
@@ -5075,35 +5496,6 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
       }
 }
 
-/* Save register REG to MEM.  Make the instruction frame-related.  */
-
-static void
-riscv_save_reg (rtx reg, rtx mem)
-{
-  riscv_emit_move (mem, reg);
-  riscv_set_frame_expr (riscv_frame_set (mem, reg));
-}
-
-/* Restore register REG from MEM.  */
-
-static void
-riscv_restore_reg (rtx reg, rtx mem)
-{
-  rtx insn = riscv_emit_move (reg, mem);
-  rtx dwarf = NULL_RTX;
-  dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
-
-  if (epilogue_cfa_sp_offset && REGNO (reg) == HARD_FRAME_POINTER_REGNUM)
-    {
-      rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-					 GEN_INT (epilogue_cfa_sp_offset));
-      dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
-    }
-
-  REG_NOTES (insn) = dwarf;
-  RTX_FRAME_RELATED_P (insn) = 1;
-}
-
 /* For stack frames that can't be allocated with a single ADDI instruction,
    compute the best value to initially allocate.  It must at a minimum
    allocate enough space to spill the callee-saved registers.  If TARGET_RVC,
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index 6ec3613071f..cbfe51cbd85 100644
--- a/gcc/config/riscv/thead.md
+++ b/gcc/config/riscv/thead.md
@@ -297,3 +297,55 @@ (define_insn "*th_sextw_msubhisi4"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")]
 )
+
+;; XTheadMemPair
+
+;; MEMPAIR load 64/32 bit
+(define_insn "*th_mempair_load_<GPR:mode>2"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(match_operand:GPR 1 "memory_operand" "m"))
+   (set (match_operand:GPR 2 "register_operand" "=r")
+	(match_operand:GPR 3 "memory_operand" "m"))]
+  "TARGET_XTHEADMEMPAIR && reload_completed
+   && thead_mempair_operands_p (operands, true, <GPR:MODE>mode)"
+  { return thead_mempair_output_move (operands, true, <GPR:MODE>mode, UNKNOWN); }
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; MEMPAIR store 64/32 bit
+(define_insn "*th_mempair_store_<GPR:mode>2"
+  [(set (match_operand:GPR 0 "memory_operand" "=m")
+	(match_operand:GPR 1 "register_operand" "r"))
+   (set (match_operand:GPR 2 "memory_operand" "=m")
+	(match_operand:GPR 3 "register_operand" "r"))]
+  "TARGET_XTHEADMEMPAIR && reload_completed
+   && thead_mempair_operands_p (operands, false, <GPR:MODE>mode)"
+  { return thead_mempair_output_move (operands, false, <GPR:MODE>mode, UNKNOWN); }
+  [(set_attr "move_type" "store")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; MEMPAIR load DI extended signed SI
+(define_insn "*th_mempair_load_extendsidi2"
+  [(set (match_operand 0 "register_operand" "=r")
+	(sign_extend:DI (match_operand 1 "memory_operand" "m")))
+   (set (match_operand 2 "register_operand" "=r")
+	(sign_extend:DI (match_operand 3 "memory_operand" "m")))]
+  "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
+   && thead_mempair_operands_p (operands, true, SImode)"
+  { return thead_mempair_output_move (operands, true, SImode, SIGN_EXTEND); }
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "DI")
+   (set_attr "length" "8")])
+
+;; MEMPAIR load DI extended unsigned SI
+(define_insn "*th_mempair_load_zero_extendsidi2"
+  [(set (match_operand 0 "register_operand" "=r")
+	(zero_extend:DI (match_operand 1 "memory_operand" "m")))
+   (set (match_operand 2 "register_operand" "=r")
+	(zero_extend:DI (match_operand 3 "memory_operand" "m")))]
+  "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
+   && thead_mempair_operands_p (operands, true, SImode)"
+  { return thead_mempair_output_move (operands, true, SImode, ZERO_EXTEND); }
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "DI")
+   (set_attr "length" "8")])
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c b/gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
new file mode 100644
index 00000000000..c324555fd35
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
@@ -0,0 +1,98 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os" "-flto" } } */
+/* { dg-options "-march=rv64gc_xtheadmempair -mtune=thead-c906" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmempair -mtune=thead-c906" { target { rv32 } } } */
+
+#include <inttypes.h>
+
+#if __riscv_xlen == 32
+typedef uint32_t xlen_t;
+#else
+typedef uint64_t xlen_t;
+#endif
+
+void foof (xlen_t*, xlen_t, xlen_t);
+void foor (xlen_t*, xlen_t, xlen_t);
+void foowu (uint32_t*, uint64_t, uint64_t);
+void foows (int32_t*, int64_t, int64_t);
+
+#define LxD_TEST(f, T, i1, i2)		\
+void					\
+f ## i1 ## i2(T *arr)			\
+{					\
+  foo ## f(arr, arr[i1], arr[i2]);	\
+}
+
+// works
+LxD_TEST(f, xlen_t, 0, 1)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(f, xlen_t, 1, 2)
+// works
+LxD_TEST(f, xlen_t, 2, 3)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(f, xlen_t, 3, 4)
+// works
+LxD_TEST(f, xlen_t, 4, 5)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(f, xlen_t, 5, 6)
+// works
+LxD_TEST(f, xlen_t, 6, 7)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(f, xlen_t, 7, 8)
+// does not work (out of range)
+LxD_TEST(f, xlen_t, 8, 9)
+
+// works with reordering
+LxD_TEST(r, xlen_t, 1, 0)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(r, xlen_t, 2, 1)
+// works with reordering
+LxD_TEST(r, xlen_t, 3, 2)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(r, xlen_t, 4, 3)
+// works with reordering
+LxD_TEST(r, xlen_t, 5, 4)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(r, xlen_t, 6, 5)
+// works with reordering
+LxD_TEST(r, xlen_t, 7, 6)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(r, xlen_t, 8, 7)
+// does not work (out of range)
+LxD_TEST(r, xlen_t, 9, 8)
+
+#if __riscv_xlen != 32
+// works
+LxD_TEST(wu, uint32_t, 0, 1)
+LxD_TEST(ws, int32_t, 0, 1)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(wu, uint32_t, 1, 2)
+LxD_TEST(ws, int32_t, 1, 2)
+// works
+LxD_TEST(wu, uint32_t, 2, 3)
+LxD_TEST(ws, int32_t, 2, 3)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(wu, uint32_t, 3, 4)
+LxD_TEST(ws, int32_t, 3, 4)
+// works
+LxD_TEST(wu, uint32_t, 4, 5)
+LxD_TEST(ws, int32_t, 4, 5)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(wu, uint32_t, 5, 6)
+LxD_TEST(ws, int32_t, 5, 6)
+// works
+LxD_TEST(wu, uint32_t, 6, 7)
+LxD_TEST(ws, int32_t, 6, 7)
+// does not work (can't merge with unaligned offset)
+LxD_TEST(wu, uint32_t, 7, 8)
+LxD_TEST(ws, int32_t, 7, 8)
+// does not work (out of range)
+LxD_TEST(wu, uint32_t, 8, 9)
+LxD_TEST(ws, int32_t, 8, 9)
+#endif
+
+/* { dg-final { scan-assembler-times "th.ldd\t" 8 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.luwd\t" 4 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.lwd\t" 4 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "th.lwd\t" 8 { target { rv32 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c b/gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
new file mode 100644
index 00000000000..ed639709196
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os" "-flto" } } */
+/* { dg-options "-march=rv64gc_xtheadmempair -mtune=thead-c906" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmempair -mtune=thead-c906" { target { rv32 } } } */
+
+#include <inttypes.h>
+
+#if __riscv_xlen == 32
+typedef uint32_t xlen_t;
+#else
+typedef uint64_t xlen_t;
+#endif
+
+#define SxD_TEST(f, T, i1, i2)		\
+void					\
+f ## i1 ## i2(T *arr, T x, T y)		\
+{					\
+  arr[i1] = x;				\
+  arr[i2] = y;				\
+}
+
+// works
+SxD_TEST(f, xlen_t, 0, 1)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(f, xlen_t, 1, 2)
+// works
+SxD_TEST(f, xlen_t, 2, 3)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(f, xlen_t, 3, 4)
+// works
+SxD_TEST(f, xlen_t, 4, 5)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(f, xlen_t, 5, 6)
+// works
+SxD_TEST(f, xlen_t, 6, 7)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(f, xlen_t, 7, 8)
+// does not work (out of range)
+SxD_TEST(f, xlen_t, 8, 9)
+
+// works with reordering
+SxD_TEST(r, xlen_t, 1, 0)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(r, xlen_t, 2, 1)
+// works with reordering
+SxD_TEST(r, xlen_t, 3, 2)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(r, xlen_t, 4, 3)
+// works with reordering
+SxD_TEST(r, xlen_t, 5, 4)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(r, xlen_t, 6, 5)
+// works with reordering
+SxD_TEST(r, xlen_t, 7, 6)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(r, xlen_t, 8, 7)
+// does not work (out of range)
+SxD_TEST(r, xlen_t, 9, 8)
+
+#if __riscv_xlen != 32
+// works
+SxD_TEST(w, uint32_t, 0, 1)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(w, uint32_t, 1, 2)
+// works
+SxD_TEST(w, uint32_t, 2, 3)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(w, uint32_t, 3, 4)
+// works
+SxD_TEST(w, uint32_t, 4, 5)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(w, uint32_t, 5, 6)
+// works
+SxD_TEST(w, uint32_t, 6, 7)
+// does not work (can't merge with unaligned offset)
+SxD_TEST(w, uint32_t, 7, 8)
+// does not work (out of range)
+SxD_TEST(w, uint32_t, 8, 9)
+#endif
+
+/* { dg-final { scan-assembler-times "th.sdd\t" 8 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.swd\t" 4 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "th.swd\t" 8 { target { rv32 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c b/gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c
new file mode 100644
index 00000000000..5dec702819a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os" "-flto" } } */
+/* { dg-options "-march=rv64gc_xtheadmempair -mtune=thead-c906" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmempair -mtune=thead-c906" { target { rv32 } } } */
+
+#include <inttypes.h>
+
+#if __riscv_xlen == 32
+typedef uint32_t xlen_t;
+#else
+typedef uint64_t xlen_t;
+#endif
+
+void foo (xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t);
+void bar (xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t, xlen_t);
+
+void baz (xlen_t a, xlen_t b, xlen_t c, xlen_t d, xlen_t e, xlen_t f, xlen_t g, xlen_t h)
+{
+  foo (a, b, c, d, e, f, g, h);
+  /* RV64: We don't use 0(sp), therefore we can only get 3 mempairs.  */
+  /* RV32: We don't use 0(sp)-8(sp), therefore we can only get 2 mempairs.  */
+  bar (a, b, c, d, e, f, g, h);
+}
+
+/* { dg-final { scan-assembler-times "th.ldd\t" 3 { target { rv64 } } } } */
+/* { dg-final { scan-assembler-times "th.sdd\t" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "th.lwd\t" 2 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "th.swd\t" 2 { target { rv32 } } } } */
-- 
2.39.2


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

* [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (8 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  9:46   ` Kito Cheng
  2023-02-24  5:51 ` [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx " Christoph Muellner
  2023-02-24  8:08 ` [PATCH v3 00/11] RISC-V: Add XThead* extension support Kito Cheng
  11 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: moiz.hussain, Christoph Müllner

From: "moiz.hussain" <muhammad.hussain@vrull.eu>

The XTheadMemIdx ISA extension provides a additional addressing
modes to load and store instructions:
* increment after
* increment before
* register indexed

gcc/ChangeLog:

	* config/riscv/constraints.md (Qmb): New constraint.
	(Qma): Likewise.
	(Qmr): Likewise.
	(Qmu): Likewise.
	* config/riscv/riscv-opts.h (HAVE_POST_MODIFY_DISP): New macro.
	(HAVE_PRE_MODIFY_DISP): Likewise.
	* config/riscv/riscv-protos.h (riscv_classify_address_index):
	New prototype.
	(riscv_classify_address_modify): Likewise.
	(riscv_output_move_index): Likewise.
	(riscv_output_move_modify): Likewise.
	(riscv_legitimize_address_index_p): Likewise.
	(riscv_legitimize_address_modify_p): Likewise.
	* config/riscv/riscv.cc (enum riscv_address_type): Add
	new addressing modes.
	(struct riscv_address_info): New field 'shift'.
	(riscv_classify_address): Add support for XTheadMemIdx.
	(riscv_classify_address_index): New function.
	(riscv_classify_address_modify): New function.
	(AM_IMM): New helper macro.
	(AM_OFFSET): New helper macro.
	(riscv_legitimize_address_modify_p): New function.
	(riscv_output_move_modify): New function.
	(riscv_legitimize_address_index_p): New function.
	(riscv_output_move_index): New function.
	(riscv_legitimize_address): Add support for XTheadMemIdx.
	(riscv_rtx_costs): Adjust for XTheadMemIdx.
	(riscv_output_move): Generalize to support XTheadMemIdx.
	(riscv_print_operand_address): Add support for XTheadMemIdx.
	* config/riscv/riscv.h (INDEX_REG_CLASS): Adjust for
	XTheadMemIdx.
	(REGNO_OK_FOR_INDEX_P): Adjust for XTheadMemIdx.
	* config/riscv/riscv.md (*zero_extendhi<GPR:mode>2): Adjust
	pattern for XTheadMemIdx.
	(*zero_extendhi<GPR:mode>2_internal): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadmemidx-ldi-sdi.c: New test.
	* gcc.target/riscv/xtheadmemidx-ldr-str-32.c: New test.
	* gcc.target/riscv/xtheadmemidx-ldr-str-64.c: New test.
	* gcc.target/riscv/xtheadmemidx-macros.h: New test.

Signed-off-by: M. Moiz Hussain <muhammad.hussain@vrull.eu>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/constraints.md               |  28 ++
 gcc/config/riscv/riscv-opts.h                 |   3 +
 gcc/config/riscv/riscv-protos.h               |  18 +
 gcc/config/riscv/riscv.cc                     | 438 ++++++++++++++++--
 gcc/config/riscv/riscv.h                      |   8 +-
 gcc/config/riscv/riscv.md                     |  78 +++-
 .../gcc.target/riscv/xtheadmemidx-ldi-sdi.c   |  72 +++
 .../riscv/xtheadmemidx-ldr-str-32.c           |  23 +
 .../riscv/xtheadmemidx-ldr-str-64.c           |  53 +++
 .../gcc.target/riscv/xtheadmemidx-macros.h    | 110 +++++
 10 files changed, 772 insertions(+), 59 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index e49019d8fa9..a007cf0b4f5 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -174,3 +174,31 @@ (define_register_constraint "th_f_fmv" "TARGET_XTHEADFMV ? FP_REGS : NO_REGS"
 
 (define_register_constraint "th_r_fmv" "TARGET_XTHEADFMV ? GR_REGS : NO_REGS"
   "An integer register for XTheadFmv.")
+
+(define_memory_constraint "Qmb"
+  "@internal
+   An address valid for LDIB/LDIA and STIB/STIA instructions."
+  (and (match_code "mem")
+       (match_test "riscv_legitimize_address_modify_p (
+		    XEXP (op, 0), GET_MODE (op), false)")))
+
+(define_memory_constraint "Qma"
+  "@internal
+   An address valid for LDIA and STIA instructions."
+  (and (match_code "mem")
+       (match_test "riscv_legitimize_address_modify_p (
+		    XEXP (op, 0), GET_MODE (op), true)")))
+
+(define_memory_constraint "Qmr"
+  "@internal
+   An address valid for LDR and STR instructions."
+  (and (match_code "mem")
+       (match_test "riscv_legitimize_address_index_p (
+		    XEXP (op, 0), GET_MODE (op), false)")))
+
+(define_memory_constraint "Qmu"
+  "@internal
+   An address valid for LDUR and STUR instructions."
+  (and (match_code "mem")
+       (match_test "riscv_legitimize_address_index_p (
+		    XEXP (op, 0), GET_MODE (op), true)")))
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index cf0cd669be4..5cd3f7673f0 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -215,4 +215,7 @@ enum stack_protector_guard {
 #define TARGET_XTHEADMEMPAIR ((riscv_xthead_subext & MASK_XTHEADMEMPAIR) != 0)
 #define TARGET_XTHEADSYNC    ((riscv_xthead_subext & MASK_XTHEADSYNC) != 0)
 
+#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
+#define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 1b7ba02726d..019a0e08285 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -65,6 +65,24 @@ extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
 extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
 #endif
+
+extern bool
+riscv_classify_address_index (struct riscv_address_info *info, rtx x,
+			      machine_mode mode, bool strict_p);
+extern bool
+riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
+			       machine_mode mode, bool strict_p);
+
+extern const char *
+riscv_output_move_index (rtx x, machine_mode mode, bool ldr);
+extern const char *
+riscv_output_move_modify (rtx x, machine_mode mode, bool ldi);
+
+extern bool
+riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex);
+extern bool
+riscv_legitimize_address_modify_p (rtx x, machine_mode mode, bool post);
+
 extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx);
 extern rtx riscv_legitimize_call_address (rtx);
 extern void riscv_set_return_address (rtx, rtx);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 33854393bd2..2980dbd69f9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -83,6 +83,19 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Classifies an address.
 
+   ADDRESS_REG_REG
+       A base register indexed by (optionally scaled) register.
+
+   ADDRESS_REG_UREG
+       A base register indexed by (optionally scaled) zero-extended register.
+
+   ADDRESS_REG_WB
+       A base register indexed by immediate offset with writeback.
+
+   ADDRESS_REG
+       A natural register + offset address.  The register satisfies
+       riscv_valid_base_register_p and the offset is a const_arith_operand.
+
    ADDRESS_REG
        A natural register + offset address.  The register satisfies
        riscv_valid_base_register_p and the offset is a const_arith_operand.
@@ -97,6 +110,9 @@ along with GCC; see the file COPYING3.  If not see
    ADDRESS_SYMBOLIC:
        A constant symbolic address.  */
 enum riscv_address_type {
+  ADDRESS_REG_REG,
+  ADDRESS_REG_UREG,
+  ADDRESS_REG_WB,
   ADDRESS_REG,
   ADDRESS_LO_SUM,
   ADDRESS_CONST_INT,
@@ -201,6 +217,7 @@ struct riscv_address_info {
   rtx reg;
   rtx offset;
   enum riscv_symbol_type symbol_type;
+  int shift;
 };
 
 /* One stage in a constant building sequence.  These sequences have
@@ -1025,12 +1042,31 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
       if (riscv_v_ext_vector_mode_p (mode))
 	return false;
 
+      if (riscv_valid_base_register_p (XEXP (x, 0), mode, strict_p)
+	  && riscv_classify_address_index (info, XEXP (x, 1), mode, strict_p))
+	{
+	  info->reg = XEXP (x, 0);
+	  return true;
+	}
+      else if (riscv_valid_base_register_p (XEXP (x, 1), mode, strict_p)
+		&& riscv_classify_address_index (info, XEXP (x, 0),
+						 mode, strict_p))
+	{
+	  info->reg = XEXP (x, 1);
+	  return true;
+	}
+
       info->type = ADDRESS_REG;
       info->reg = XEXP (x, 0);
       info->offset = XEXP (x, 1);
       return (riscv_valid_base_register_p (info->reg, mode, strict_p)
 	      && riscv_valid_offset_p (info->offset, mode));
 
+    case POST_MODIFY:
+    case PRE_MODIFY:
+
+      return riscv_classify_address_modify (info, x, mode, strict_p);
+
     case LO_SUM:
       /* RVV load/store disallow LO_SUM.  */
       if (riscv_v_ext_vector_mode_p (mode))
@@ -1269,6 +1305,263 @@ riscv_emit_move (rtx dest, rtx src)
 	  : emit_move_insn_1 (dest, src));
 }
 
+/* Return true if address offset is a valid index.  If it is, fill in INFO
+   appropriately.  STRICT_P is true if REG_OK_STRICT is in effect.  */
+
+bool
+riscv_classify_address_index (struct riscv_address_info *info, rtx x,
+      machine_mode mode, bool strict_p)
+{
+  enum riscv_address_type type = ADDRESS_REG_REG;;
+  rtx index;
+  int shift = 0;
+
+  if (!TARGET_XTHEADMEMIDX)
+    return false;
+
+  if (!TARGET_64BIT && mode == DImode)
+    return false;
+
+  if (SCALAR_FLOAT_MODE_P (mode))
+    {
+      if (!TARGET_HARD_FLOAT)
+	return false;
+      if (GET_MODE_SIZE (mode).to_constant () == 2)
+	return false;
+    }
+
+  /* (reg:P) */
+  if ((REG_P (x) || GET_CODE (x) == SUBREG)
+      && GET_MODE (x) == Pmode)
+    {
+      index = x;
+      shift = 0;
+    }
+  /* (zero_extend:DI (reg:SI)) */
+  else if (GET_CODE (x) == ZERO_EXTEND
+	   && GET_MODE (x) == DImode
+	   && GET_MODE (XEXP (x, 0)) == SImode)
+    {
+      type = ADDRESS_REG_UREG;
+      index = XEXP (x, 0);
+      shift = 0;
+    }
+  /* (mult:DI (zero_extend:DI (reg:SI)) (const_int scale)) */
+  else if (GET_CODE (x) == MULT
+	   && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+	   && GET_MODE (XEXP (x, 0)) == DImode
+	   && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode
+	   && CONST_INT_P (XEXP (x, 1)))
+    {
+      type = ADDRESS_REG_UREG;
+      index = XEXP (XEXP (x, 0), 0);
+      shift = exact_log2 (INTVAL (XEXP (x, 1)));
+    }
+  /* (ashift:DI (zero_extend:DI (reg:SI)) (const_int shift)) */
+  else if (GET_CODE (x) == ASHIFT
+	   && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+	   && GET_MODE (XEXP (x, 0)) == DImode
+	   && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode
+	   && CONST_INT_P (XEXP (x, 1)))
+    {
+      type = ADDRESS_REG_UREG;
+      index = XEXP (XEXP (x, 0), 0);
+      shift = INTVAL (XEXP (x, 1));
+    }
+  /* (mult:P (reg:P) (const_int scale)) */
+  else if (GET_CODE (x) == MULT
+	   && GET_MODE (x) == Pmode
+	   && GET_MODE (XEXP (x, 0)) == Pmode
+	   && CONST_INT_P (XEXP (x, 1)))
+    {
+      index = XEXP (x, 0);
+      shift = exact_log2 (INTVAL (XEXP (x, 1)));
+    }
+  /* (ashift:P (reg:P) (const_int shift)) */
+  else if (GET_CODE (x) == ASHIFT
+	   && GET_MODE (x) == Pmode
+	   && GET_MODE (XEXP (x, 0)) == Pmode
+	   && CONST_INT_P (XEXP (x, 1)))
+    {
+      index = XEXP (x, 0);
+      shift = INTVAL (XEXP (x, 1));
+    }
+  else
+    return false;
+
+  if (shift != 0 && !IN_RANGE (shift, 1, 3))
+    return false;
+
+  if (!strict_p
+      && GET_CODE (index) == SUBREG
+      && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
+    index = SUBREG_REG (index);
+
+  if (riscv_valid_base_register_p (index, mode, strict_p))
+    {
+      info->type = type;
+      info->offset = index;
+      info->shift = shift;
+      return true;
+    }
+  return false;
+}
+
+/* Return true if address is a valid modify.  If it is, fill in INFO
+   appropriately.  STRICT_P is true if REG_OK_STRICT is in effect.  */
+
+bool
+riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
+      machine_mode mode, bool strict_p)
+{
+
+#define AM_IMM(BIT) (1LL << (5 + (BIT)))
+#define AM_OFFSET(VALUE, SHIFT) (\
+  ((unsigned HOST_WIDE_INT) (VALUE) + AM_IMM (SHIFT)/2 < AM_IMM (SHIFT)) \
+  && !((unsigned HOST_WIDE_INT) (VALUE) & ((1 << (SHIFT)) - 1)) \
+  ? (SHIFT) + 1 \
+  : 0)
+
+  if (!TARGET_XTHEADMEMIDX)
+    return false;
+
+  if (!(INTEGRAL_MODE_P (mode) && GET_MODE_SIZE (mode).to_constant () <= 8))
+    return false;
+
+  if (!TARGET_64BIT && mode == DImode)
+    return false;
+
+  if (GET_CODE (x) != POST_MODIFY
+      && GET_CODE (x) != PRE_MODIFY)
+    return false;
+
+  info->type = ADDRESS_REG_WB;
+  info->reg = XEXP (x, 0);
+
+  if (GET_CODE (XEXP (x, 1)) == PLUS
+      && CONST_INT_P (XEXP (XEXP (x, 1), 1))
+      && rtx_equal_p (XEXP (XEXP (x, 1), 0), info->reg)
+      && riscv_valid_base_register_p (info->reg, mode, strict_p))
+    {
+      info->offset = XEXP (XEXP (x, 1), 1);
+      int shift = AM_OFFSET (INTVAL (info->offset), 0);
+      if (!shift)
+	shift = AM_OFFSET (INTVAL (info->offset), 1);
+      if (!shift)
+	shift = AM_OFFSET (INTVAL (info->offset), 2);
+      if (!shift)
+	shift = AM_OFFSET (INTVAL (info->offset), 3);
+      if (shift)
+	{
+	  info->shift = shift - 1;
+	  return true;
+	}
+    }
+  return false;
+}
+
+/* Return TRUE if X is a legitimate address modify.  */
+
+bool
+riscv_legitimize_address_modify_p (rtx x, machine_mode mode, bool post)
+{
+  struct riscv_address_info addr;
+  return riscv_classify_address_modify (&addr, x, mode, false)
+	 && (!post || GET_CODE (x) == POST_MODIFY);
+}
+
+/* Return the LDIB/LDIA and STIB/STIA instructions.  Assume
+   that X is MEM operand.  */
+
+const char *
+riscv_output_move_modify (rtx x, machine_mode mode, bool ldi)
+{
+  static char buf[128] = {0};
+
+  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
+  if (!IN_RANGE (index, 0, 3))
+    return NULL;
+
+  if (!riscv_legitimize_address_modify_p (x, mode, false))
+    return NULL;
+
+  bool post = riscv_legitimize_address_modify_p (x, mode, true);
+
+  const char *const insn[][4] = {
+    {
+      "th.sbi%s\t%%z1,%%0",
+      "th.shi%s\t%%z1,%%0",
+      "th.swi%s\t%%z1,%%0",
+      "th.sdi%s\t%%z1,%%0"
+    },
+    {
+      "th.lbui%s\t%%0,%%1",
+      "th.lhui%s\t%%0,%%1",
+      "th.lwi%s\t%%0,%%1",
+      "th.ldi%s\t%%0,%%1"
+    }
+  };
+
+  snprintf (buf, sizeof (buf), insn[ldi][index], post ? "a" : "b");
+  return buf;
+}
+
+bool
+riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex)
+{
+  struct riscv_address_info addr;
+  rtx op0, op1;
+
+  if (GET_CODE (x) != PLUS)
+    return false;
+
+  op0 = XEXP (x, 0);
+  op1 = XEXP (x, 1);
+
+  return ((riscv_valid_base_register_p (op0, mode, false)
+	   && riscv_classify_address_index (&addr, op1, mode, false))
+	  || (riscv_valid_base_register_p (op1, mode, false)
+	      && riscv_classify_address_index (&addr, op0, mode, false)))
+	 && (!uindex || addr.type == ADDRESS_REG_UREG);
+}
+
+/* Return the LDR or STR instructions.  Assume
+   that X is MEM operand.  */
+
+const char *
+riscv_output_move_index (rtx x, machine_mode mode, bool ldr)
+{
+  static char buf[128] = {0};
+
+  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
+  if (!IN_RANGE (index, 0, 3))
+    return NULL;
+
+  if (!riscv_legitimize_address_index_p (x, mode, false))
+    return NULL;
+
+  bool uindex = riscv_legitimize_address_index_p (x, mode, true);
+
+  const char *const insn[][4] = {
+    {
+      "th.s%srb\t%%z1,%%0",
+      "th.s%srh\t%%z1,%%0",
+      "th.s%srw\t%%z1,%%0",
+      "th.s%srd\t%%z1,%%0"
+    },
+    {
+      "th.l%srbu\t%%0,%%1",
+      "th.l%srhu\t%%0,%%1",
+      "th.l%srw\t%%0,%%1",
+      "th.l%srd\t%%0,%%1"
+    }
+  };
+
+  snprintf (buf, sizeof (buf), insn[ldr][index], uindex ? "u" : "");
+
+  return buf;
+}
+
 /* Emit an instruction of the form (set TARGET SRC).  */
 
 static rtx
@@ -1631,6 +1924,42 @@ riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   if (riscv_split_symbol (NULL, x, mode, &addr, FALSE))
     return riscv_force_address (addr, mode);
 
+  /* Optimize BASE + OFFSET into BASE + INDEX.  */
+  if (TARGET_XTHEADMEMIDX
+      && GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))
+      && INTVAL (XEXP (x, 1)) != 0
+      && GET_CODE (XEXP (x, 0)) == PLUS)
+    {
+      rtx base = XEXP (x, 0);
+      rtx offset_rtx = XEXP (x, 1);
+
+      rtx op0 = XEXP (base, 0);
+      rtx op1 = XEXP (base, 1);
+      /* Force any scaling into a temp for CSE.  */
+      op0 = force_reg (Pmode, op0);
+      op1 = force_reg (Pmode, op1);
+
+      /* Let the pointer register be in op0.  */
+      if (REG_POINTER (op1))
+	std::swap (op0, op1);
+
+      unsigned regno = REGNO (op0);
+
+      /* If the pointer is virtual or frame related, then we know that
+       virtual register instantiation or register elimination is going
+       to apply a second constant.  We want the two constants folded
+       together easily.  Therefore, emit as (OP0 + CONST) + OP1.  */
+      if ((regno >= FIRST_VIRTUAL_REGISTER
+	   && regno <= LAST_VIRTUAL_POINTER_REGISTER)
+	  || regno == FRAME_POINTER_REGNUM
+	  || regno == ARG_POINTER_REGNUM)
+	{
+	  base = expand_binop (Pmode, add_optab, op0, offset_rtx,
+			       NULL_RTX, true, OPTAB_DIRECT);
+	  return gen_rtx_PLUS (Pmode, base, op1);
+	}
+    }
+
   /* Handle BASE + OFFSET.  */
   if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))
       && INTVAL (XEXP (x, 1)) != 0)
@@ -2408,6 +2737,13 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
 	  return true;
 	}
+      /* bit extraction pattern (xtheadmemidx, xtheadfmemidx).  */
+      if (outer_code == SET
+	  && TARGET_XTHEADMEMIDX)
+	{
+	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+	  return true;
+	}
       gcc_fallthrough ();
     case SIGN_EXTRACT:
       if (TARGET_XTHEADBB && outer_code == SET
@@ -2826,13 +3162,23 @@ riscv_output_move (rtx dest, rtx src)
 	  }
 
       if (src_code == MEM)
-	switch (width)
-	  {
-	  case 1: return "lbu\t%0,%1";
-	  case 2: return "lhu\t%0,%1";
-	  case 4: return "lw\t%0,%1";
-	  case 8: return "ld\t%0,%1";
-	  }
+	{
+	  const char *insn = NULL;
+	  insn = riscv_output_move_index (XEXP (src, 0), GET_MODE (src), true);
+	  if (!insn)
+	    insn = riscv_output_move_modify (XEXP (src, 0),
+					     GET_MODE (src), true);
+	  if (insn)
+	    return insn;
+
+	  switch (width)
+	    {
+	    case 1: return "lbu\t%0,%1";
+	    case 2: return "lhu\t%0,%1";
+	    case 4: return "lw\t%0,%1";
+	    case 8: return "ld\t%0,%1";
+	    }
+	}
 
       if (src_code == CONST_INT)
 	{
@@ -2887,13 +3233,24 @@ riscv_output_move (rtx dest, rtx src)
 	      }
 	}
       if (dest_code == MEM)
-	switch (width)
-	  {
-	  case 1: return "sb\t%z1,%0";
-	  case 2: return "sh\t%z1,%0";
-	  case 4: return "sw\t%z1,%0";
-	  case 8: return "sd\t%z1,%0";
-	  }
+	{
+	  const char *insn = NULL;
+	  insn = riscv_output_move_index (XEXP (dest, 0),
+					  GET_MODE (dest), false);
+	  if (!insn)
+	    insn = riscv_output_move_modify (XEXP (dest, 0),
+					     GET_MODE (dest), false);
+	  if (insn)
+	    return insn;
+
+	  switch (width)
+	    {
+	    case 1: return "sb\t%z1,%0";
+	    case 2: return "sh\t%z1,%0";
+	    case 4: return "sw\t%z1,%0";
+	    case 8: return "sd\t%z1,%0";
+	    }
+	}
     }
   if (src_code == REG && FP_REG_P (REGNO (src)))
     {
@@ -2911,28 +3268,32 @@ riscv_output_move (rtx dest, rtx src)
 	  }
 
       if (dest_code == MEM)
-	switch (width)
-	  {
-	  case 2:
-	    return "fsh\t%1,%0";
-	  case 4:
-	    return "fsw\t%1,%0";
-	  case 8:
-	    return "fsd\t%1,%0";
-	  }
+	{
+	  switch (width)
+	    {
+	    case 2:
+	      return "fsh\t%1,%0";
+	    case 4:
+	      return "fsw\t%1,%0";
+	    case 8:
+	      return "fsd\t%1,%0";
+	    }
+	}
     }
   if (dest_code == REG && FP_REG_P (REGNO (dest)))
     {
       if (src_code == MEM)
-	switch (width)
-	  {
-	  case 2:
-	    return "flh\t%0,%1";
-	  case 4:
-	    return "flw\t%0,%1";
-	  case 8:
-	    return "fld\t%0,%1";
-	  }
+	{
+	  switch (width)
+	    {
+	    case 2:
+	      return "flh\t%0,%1";
+	    case 4:
+	      return "flw\t%0,%1";
+	    case 8:
+	      return "fld\t%0,%1";
+	    }
+	}
     }
   if (dest_code == REG && GP_REG_P (REGNO (dest)) && src_code == CONST_POLY_INT)
     {
@@ -4881,6 +5242,19 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
       case ADDRESS_SYMBOLIC:
 	output_addr_const (file, riscv_strip_unspec_address (x));
 	return;
+
+      case ADDRESS_REG_REG:
+      case ADDRESS_REG_UREG:
+	fprintf (file, "%s,%s,%u", reg_names[REGNO (addr.reg)],
+				   reg_names[REGNO (addr.offset)],
+				   addr.shift);
+	return;
+
+      case ADDRESS_REG_WB:
+	fprintf (file, "(%s),%ld,%u", reg_names[REGNO (addr.reg)],
+				      (long) INTVAL (addr.offset) >> addr.shift,
+				      addr.shift);
+	return;
       }
   gcc_unreachable ();
 }
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 5bc7f2f467d..199bb30162e 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -535,7 +535,8 @@ enum reg_class
    factor or added to another register (as well as added to a
    displacement).  */
 
-#define INDEX_REG_CLASS NO_REGS
+#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX) ? \
+			GR_REGS : NO_REGS)
 
 /* We generally want to put call-clobbered registers ahead of
    call-saved ones.  (IRA expects this.)  */
@@ -705,7 +706,10 @@ typedef struct {
 
 /* Addressing modes, and classification of registers for them.  */
 
-#define REGNO_OK_FOR_INDEX_P(REGNO) 0
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+  ((TARGET_XTHEADMEMIDX) ? \
+  riscv_regno_mode_ok_for_base_p (REGNO, VOIDmode, 1) : 0)
+
 #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
   riscv_regno_mode_ok_for_base_p (REGNO, MODE, 1)
 
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 61f175bb62b..df31a1fffff 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1360,12 +1360,17 @@ (define_expand "zero_extendsidi2"
   "TARGET_64BIT")
 
 (define_insn_and_split "*zero_extendsidi2_internal"
-  [(set (match_operand:DI     0 "register_operand"     "=r,r")
+  [(set (match_operand:DI     0 "register_operand"     "=r,r,r,r,r,r")
 	(zero_extend:DI
-	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
-  "TARGET_64BIT && !TARGET_ZBA"
+	    (match_operand:SI 1
+	    "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
+  "TARGET_64BIT && !(TARGET_ZBA || TARGET_ZBB)"
   "@
    #
+   th.lurwu\t%0,%1
+   th.lrwu\t%0,%1
+   th.lwuia\t%0,%1
+   th.lwuib\t%0,%1
    lwu\t%0,%1"
   "&& reload_completed
    && REG_P (operands[1])
@@ -1375,7 +1380,7 @@ (define_insn_and_split "*zero_extendsidi2_internal"
    (set (match_dup 0)
 	(lshiftrt:DI (match_dup 0) (const_int 32)))]
   { operands[1] = gen_lowpart (DImode, operands[1]); }
-  [(set_attr "move_type" "shift_shift,load")
+  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
    (set_attr "mode" "DI")])
 
 (define_expand "zero_extendhi<GPR:mode>2"
@@ -1384,13 +1389,18 @@ (define_expand "zero_extendhi<GPR:mode>2"
 	    (match_operand:HI 1 "nonimmediate_operand")))]
   "")
 
-(define_insn_and_split "*zero_extendhi<GPR:mode>2"
-  [(set (match_operand:GPR    0 "register_operand"     "=r,r")
+(define_insn_and_split "*zero_extendhi<GPR:mode>2_internal"
+  [(set (match_operand:GPR    0 "register_operand"     "=r,r,r,r,r,r")
 	(zero_extend:GPR
-	    (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
-  "!TARGET_ZBB"
+	    (match_operand:HI 1
+	    "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
+  "!(TARGET_ZBA || TARGET_ZBB)"
   "@
    #
+   th.lurhu\t%0,%1
+   th.lrhu\t%0,%1
+   th.lhuia\t%0,%1
+   th.lhuib\t%0,%1
    lhu\t%0,%1"
   "&& reload_completed
    && REG_P (operands[1])
@@ -1401,20 +1411,25 @@ (define_insn_and_split "*zero_extendhi<GPR:mode>2"
 	(lshiftrt:GPR (match_dup 0) (match_dup 2)))]
   {
     operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
-    operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
+    operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode) - 16);
   }
-  [(set_attr "move_type" "shift_shift,load")
+  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
    (set_attr "mode" "<GPR:MODE>")])
 
 (define_insn "zero_extendqi<SUPERQI:mode>2"
-  [(set (match_operand:SUPERQI 0 "register_operand"    "=r,r")
+  [(set (match_operand:SUPERQI 0 "register_operand"    "=r,r,r,r,r,r")
 	(zero_extend:SUPERQI
-	    (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
+	    (match_operand:QI 1
+	    "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
   ""
   "@
    andi\t%0,%1,0xff
+   th.lurbu\t%0,%1
+   th.lrbu\t%0,%1
+   th.lbuia\t%0,%1
+   th.lbuib\t%0,%1
    lbu\t%0,%1"
-  [(set_attr "move_type" "andi,load")
+  [(set_attr "move_type" "andi,load,load,load,load,load")
    (set_attr "mode" "<SUPERQI:MODE>")])
 
 ;;
@@ -1425,14 +1440,19 @@ (define_insn "zero_extendqi<SUPERQI:mode>2"
 ;;  ....................
 
 (define_insn "extendsidi2"
-  [(set (match_operand:DI     0 "register_operand"     "=r,r")
+  [(set (match_operand:DI     0 "register_operand"     "=r,r,r,r,r,r")
 	(sign_extend:DI
-	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+	    (match_operand:SI 1
+	    "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
   "TARGET_64BIT"
   "@
    sext.w\t%0,%1
+   th.lurw\t%0,%1
+   th.lrw\t%0,%1
+   th.lwia\t%0,%1
+   th.lwib\t%0,%1
    lw\t%0,%1"
-  [(set_attr "move_type" "move,load")
+  [(set_attr "move_type" "move,load,load,load,load,load")
    (set_attr "mode" "DI")])
 
 (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
@@ -1441,12 +1461,17 @@ (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
   "")
 
 (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
-  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
+  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r,r,r,r,r")
 	(sign_extend:SUPERQI
-	    (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+	    (match_operand:SHORT 1
+	    "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
   "!TARGET_ZBB"
   "@
    #
+   th.lur<SHORT:size>\t%0,%1
+   th.lr<SHORT:size>\t%0,%1
+   th.l<SHORT:size>ia\t%0,%1
+   th.l<SHORT:size>ib\t%0,%1
    l<SHORT:size>\t%0,%1"
   "&& reload_completed
    && REG_P (operands[1])
@@ -1459,7 +1484,7 @@ (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
   operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
 			 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
 }
-  [(set_attr "move_type" "shift_shift,load")
+  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
    (set_attr "mode" "SI")])
 
 (define_insn "extendhfsf2"
@@ -1507,7 +1532,8 @@ (define_insn "*movhf_hardfloat"
    && (register_operand (operands[0], HFmode)
        || reg_or_0_operand (operands[1], HFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+  [(set_attr "move_type"
+	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "HF")])
 
 (define_insn "*movhf_softfloat"
@@ -1836,7 +1862,8 @@ (define_insn "*movsf_hardfloat"
    && (register_operand (operands[0], SFmode)
        || reg_or_0_operand (operands[1], SFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+  [(set_attr "move_type"
+	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "SF")])
 
 (define_insn "*movsf_softfloat"
@@ -1860,7 +1887,6 @@ (define_expand "movdf"
     DONE;
 })
 
-
 ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
 (define_insn "*movdf_hardfloat_rv32"
@@ -1870,7 +1896,8 @@ (define_insn "*movdf_hardfloat_rv32"
    && (register_operand (operands[0], DFmode)
        || reg_or_0_operand (operands[1], DFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+  [(set_attr "move_type"
+	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "DF")])
 
 (define_insn "*movdf_hardfloat_rv64"
@@ -1880,7 +1907,8 @@ (define_insn "*movdf_hardfloat_rv64"
    && (register_operand (operands[0], DFmode)
        || reg_or_0_operand (operands[1], DFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+  [(set_attr "move_type"
+	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "DF")])
 
 (define_insn "*movdf_softfloat"
@@ -2187,7 +2215,7 @@ (define_split
 	(and:GPR (match_operand:GPR 1 "register_operand")
 		 (match_operand:GPR 2 "p2m1_shift_operand")))
    (clobber (match_operand:GPR 3 "register_operand"))]
-  ""
+  "!TARGET_XTHEADMEMIDX"
  [(set (match_dup 3)
        (ashift:GPR (match_dup 1) (match_dup 2)))
   (set (match_dup 0)
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
new file mode 100644
index 00000000000..8d785e62416
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os"} } */
+/* { dg-options "-march=rv64gc_xtheadmemidx --save-temps -O2" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmemidx --save-temps -O2" { target { rv32 } } } */
+
+#include "xtheadmemidx-macros.h"
+
+/* no special function attribute required */
+#define ATTR /* */
+
+POST_LOAD(s_char, ATTR)
+/* { dg-final { scan-assembler "th.lbia.*1,0" } } */
+PRE_LOAD(s_char, ATTR)
+/* { dg-final { scan-assembler "th.lbib.*1,0" } } */
+POST_LOAD(char, ATTR)
+/* { dg-final { scan-assembler "th.lbuia.*1,0" } } */
+PRE_LOAD(char, ATTR)
+/* { dg-final { scan-assembler "th.lbuib.*1,0" } } */
+POST_LOAD(short, ATTR)
+/* { dg-final { scan-assembler "th.lhia.*2,0" } } */
+PRE_LOAD(short, ATTR)
+/* { dg-final { scan-assembler "th.lhib.*2,0" } } */
+POST_LOAD(u_short, ATTR)
+/* { dg-final { scan-assembler "th.lhuia.*2,0" } } */
+PRE_LOAD(u_short, ATTR)
+/* { dg-final { scan-assembler "th.lhuib.*2,0" } } */
+
+POST_LOAD(int, ATTR)
+/* { dg-final { scan-assembler "th.lwia.*4,0" } } */
+PRE_LOAD(int, ATTR)
+/* { dg-final { scan-assembler "th.lwib.*4,0" } } */
+void int_post_load_lwuia (void* p) 
+{  
+  extern void fint2 (int*,u_ll);
+  u_int *q = (u_int*)p;
+  u_ll x = *q++;
+  fint2 (q, x);
+}
+/* { dg-final { scan-assembler "th.lwuia.*4,0" { target { rv64 } } } } */
+void int_pre_load_lwuib (void* p) 
+{  
+  extern void fint2 (int*,u_ll);
+  u_int *q = (u_int*)p;
+  u_ll x = *++q;
+  fint2 (q, x);
+}
+/* { dg-final { scan-assembler "th.lwuib.*4,0" { target { rv64 } } } } */
+
+POST_LOAD(s_ll, ATTR)
+/* { dg-final { scan-assembler "th.ldia.*8,0" { target { rv64 } } } } */
+PRE_LOAD(s_ll, ATTR)
+/* { dg-final { scan-assembler "th.ldib.*8,0" { target { rv64 } } } } */
+
+POST_STORE(char, ATTR)
+/* { dg-final { scan-assembler "th.sbia.*1,0" } } */
+PRE_STORE(char, ATTR)
+/* { dg-final { scan-assembler "th.sbib.*1,0" } } */
+POST_STORE(short, ATTR)
+/* { dg-final { scan-assembler "th.shia.*2,0" } } */
+PRE_STORE(short, ATTR)
+/* { dg-final { scan-assembler "th.shib.*2,0" } } */
+POST_STORE(int, ATTR)
+/* { dg-final { scan-assembler "th.swia.*4,0" } } */
+PRE_STORE(int, ATTR)
+/* { dg-final { scan-assembler "th.swib.*4,0" } } */
+POST_STORE(s_ll, ATTR)
+/* { dg-final { scan-assembler "th.sdia.*8,0" { target { rv64 } } } } */
+PRE_STORE(s_ll, ATTR)
+/* { dg-final { scan-assembler "th.sdib.*8,0" { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-not "\taddi" { target { rv64 } } } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
new file mode 100644
index 00000000000..6061eaf1d9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os"} } */
+/* { dg-options "-march=rv32gc_xtheadmemidx" { target { rv32 } } } */
+
+#include "xtheadmemidx-macros.h"
+
+MV_LOAD_1_AND_2(s_int, s_char)
+/* { dg-final { scan-assembler-times "th.lrb\t" 2 { target { rv32 } } } } */
+MV_LOAD_1_AND_2(s_int, u_char)
+/* { dg-final { scan-assembler-times "th.lrbu\t" 2 { target { rv32 } } } } */
+MV_LOAD_1_AND_2(s_int, s_short)
+/* { dg-final { scan-assembler-times "th.lrh\t" 2 { target { rv32 } } } } */
+MV_LOAD_1_AND_2(s_int, u_short)
+/* { dg-final { scan-assembler-times "th.lrhu\t" 2 { target { rv32 } } } } */
+MV_LOAD_1_AND_2(s_int, s_int)
+/* { dg-final { scan-assembler-times "th.lrw\t" 2 { target { rv32 } } } } */
+
+MV_STORE_1(s_int, s_int, s_char)
+/* { dg-final { scan-assembler-times "th.srb\t" 1 { target { rv32 } } } } */
+MV_STORE_1(s_int, s_int, s_short)
+/* { dg-final { scan-assembler-times "th.srh\t" 1 { target { rv32 } } } } */
+MV_STORE_1(s_int, s_int, s_int)
+/* { dg-final { scan-assembler-times "th.srw\t" 1 { target { rv32 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
new file mode 100644
index 00000000000..080d1853c83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os"} } */
+/* { dg-options "-march=rv64gc_xtheadmemidx" { target { rv64 } } } */
+
+#include "xtheadmemidx-macros.h"
+
+MV_LOAD_1_AND_2(s_ll, s_char)
+/* { dg-final { scan-assembler-times "th.lrb\t" 2 { target { rv64 } } } } */
+MV_LOAD_1_AND_2(s_ll, u_char)
+/* { dg-final { scan-assembler-times "th.lrbu\t" 2 { target { rv64 } } } } */
+MV_LOAD_1_AND_2(s_ll, s_short)
+/* { dg-final { scan-assembler-times "th.lrh\t" 2 { target { rv64 } } } } */
+MV_LOAD_1_AND_2(s_ll, u_short)
+/* { dg-final { scan-assembler-times "th.lrhu\t" 2 { target { rv64 } } } } */
+MV_LOAD_1_AND_2(s_ll, s_int)
+/* { dg-final { scan-assembler-times "th.lrw\t" 2 { target { rv64 } } } } */
+MV_LOAD_4(s_ll, s_int, u_int)
+/* { dg-final { scan-assembler-times "th.lrwu\t" 1 { target { rv64 } } } } */
+MV_LOAD_1_AND_2(s_ll, s_ll)
+/* { dg-final { scan-assembler-times "th.lrd\t" 2 { target { rv64 } } } } */
+
+MV_STORE_1(s_ll, s_ll, s_char)
+/* { dg-final { scan-assembler-times "th.srb\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, s_ll, s_short)
+/* { dg-final { scan-assembler-times "th.srh\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, s_ll, s_int)
+/* { dg-final { scan-assembler-times "th.srw\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, s_ll, s_ll)
+/* { dg-final { scan-assembler-times "th.srd\t" 1 { target { rv64 } } } } */
+
+MV_LOAD_3(s_ll, u_int, s_char)
+/* { dg-final { scan-assembler-times "th.lurb\t" 1 { target { rv64 } } } } */
+MV_LOAD_3(s_ll, u_int, u_char)
+/* { dg-final { scan-assembler-times "th.lurbu\t" 1 { target { rv64 } } } } */
+MV_LOAD_3(s_ll, u_int, s_short)
+/* { dg-final { scan-assembler-times "th.lurh\t" 1 { target { rv64 } } } } */
+MV_LOAD_3(s_ll, u_int, u_short)
+/* { dg-final { scan-assembler-times "th.lurhu\t" 1 { target { rv64 } } } } */
+MV_LOAD_3(s_ll, u_int, s_int)
+/* { dg-final { scan-assembler-times "th.lurw\t" 1 { target { rv64 } } } } */
+MV_LOAD_4(s_ll, u_int, u_int)
+/* { dg-final { scan-assembler-times "th.lurwu\t" 1 { target { rv64 } } } } */
+MV_LOAD_3(s_ll, u_int, u_ll)
+/* { dg-final { scan-assembler-times "th.lurd\t" 1 { target { rv64 } } } } */
+
+MV_STORE_1(s_ll, u_int, s_char)
+/* { dg-final { scan-assembler-times "th.surb\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, u_int, s_short)
+/* { dg-final { scan-assembler-times "th.surh\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, u_int, s_int)
+/* { dg-final { scan-assembler-times "th.surw\t" 1 { target { rv64 } } } } */
+MV_STORE_1(s_ll, u_int, s_ll)
+/* { dg-final { scan-assembler-times "th.surd\t" 1 { target { rv64 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h
new file mode 100644
index 00000000000..848e4770964
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h
@@ -0,0 +1,110 @@
+typedef unsigned char u_char;
+typedef signed char s_char;
+typedef unsigned short u_short;
+typedef signed short s_short;
+typedef unsigned int u_int;
+typedef signed int s_int;
+typedef unsigned int u_ll __attribute__((mode(DI)));
+typedef signed int s_ll __attribute__((mode(DI)));
+
+#include "stdint.h"
+
+#define PRE_STORE(T, ATTR)		\
+  ATTR T *				\
+  T ## _pre_store (T *p, T v)		\
+  {					\
+    *++p = v;				\
+    return p;				\
+  }
+
+#define POST_STORE(T, ATTR)		\
+  ATTR T *				\
+  T ## _post_store (T *p, T v)		\
+  {					\
+    *p++ = v;				\
+    return p;				\
+  }
+
+#define POST_STORE_VEC(T, VT, OP, ATTR)	\
+  ATTR T *				\
+  VT ## _post_store (T * p, VT v)	\
+  {					\
+    OP (p, v);				\
+    p += sizeof (VT) / sizeof (T);	\
+    return p;				\
+  }
+
+#define PRE_LOAD(T, ATTR)		\
+  ATTR void				\
+  T ## _pre_load (T *p)			\
+  {					\
+    ATTR extern void f ## T (T*,T);	\
+    T x = *++p;				\
+    f ## T (p, x);			\
+  }
+
+#define POST_LOAD(T, ATTR)		\
+  ATTR void				\
+  T ## _post_load (T *p)		\
+  {					\
+    ATTR extern void f ## T (T*,T);	\
+    T x = *p++;				\
+    f ## T (p, x);			\
+  }
+
+#define POST_LOAD_VEC(T, VT, OP, ATTR)	\
+  ATTR void				\
+  VT ## _post_load (T * p)		\
+  {					\
+    ATTR extern void f ## T (T*,T);	\
+    VT x = OP (p, v);			\
+    p += sizeof (VT) / sizeof (T);	\
+    f ## T (p, x);			\
+  }
+
+#define MV_LOAD_1(RS2_TYPE, RET_TYPE)	\
+  RET_TYPE   	\
+  mv_load_1_ ## RS2_TYPE ## _ ## RET_TYPE (RS2_TYPE *a, int b)  \
+  {					\
+    return a[b];  \
+  }
+
+#define MV_LOAD_2(RS2_TYPE, RET_TYPE)	\
+  RET_TYPE   	\
+  mv_load_2_ ## RS2_TYPE ## _ ## RET_TYPE (  \
+  RS2_TYPE rs1, RS2_TYPE rs2, int a)		\
+  {					\
+    return (*((RET_TYPE*)(uintptr_t)(rs1 + (rs2 << a))));  \
+  }
+
+#define MV_LOAD_3(RS2_TYPE, CONV_TYPE, RET_TYPE)	\
+  RET_TYPE   	\
+  mv_load_3_ ## RS2_TYPE ## _ ## CONV_TYPE ## _ ## RET_TYPE (  \
+  RS2_TYPE rs1, RS2_TYPE rs2, int a)		\
+  {					\
+    CONV_TYPE c = (CONV_TYPE) rs2;   \
+    return (*((RET_TYPE*)(uintptr_t)(rs1 + (c << a))));  \
+  }
+
+#define MV_LOAD_4(RS2_TYPE, CONV_TYPE, TMP_RET_TYPE)	\
+  uintptr_t   	\
+  mv_load_4_ ## RS2_TYPE ## _ ## CONV_TYPE ## _ ## TMP_RET_TYPE (  \
+  RS2_TYPE rs1, RS2_TYPE rs2, int a)		\
+  {					\
+    CONV_TYPE c = (CONV_TYPE) rs2;   \
+    return (*((TMP_RET_TYPE*)(uintptr_t)(rs1 + (c << a))));  \
+  }
+
+#define MV_STORE_1(RS2_TYPE, CONV_TYPE, STORE_TYPE)	\
+  void   	\
+  mv_store_1_ ## RS2_TYPE ## _ ## CONV_TYPE ## _ ## STORE_TYPE (  \
+  RS2_TYPE rs1, RS2_TYPE rs2, int a, int st_val)		\
+  {					\
+    CONV_TYPE c = (CONV_TYPE) rs2;   \
+    STORE_TYPE* addr = (STORE_TYPE*)(uintptr_t)(rs1 + (c << a));  \
+    *addr = st_val;  \
+  }
+
+#define MV_LOAD_1_AND_2(RS2_TYPE, RET_TYPE)	\
+  MV_LOAD_1(RS2_TYPE, RET_TYPE)  \
+  MV_LOAD_2(RS2_TYPE, RET_TYPE)
-- 
2.39.2


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

* [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx ISA extension
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (9 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx " Christoph Muellner
@ 2023-02-24  5:51 ` Christoph Muellner
  2023-02-24  7:53   ` Kito Cheng
  2023-02-24  8:08 ` [PATCH v3 00/11] RISC-V: Add XThead* extension support Kito Cheng
  11 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-02-24  5:51 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu
  Cc: moiz.hussain, Christoph Müllner

From: "moiz.hussain" <muhammad.hussain@vrull.eu>

The XTheadFMemIdx ISA extension provides register-indexed
addressing modes to floating-point load and store instructions.

gcc/ChangeLog:

	* config/riscv/constraints.md (Qmx): New constraint.
	* config/riscv/riscv-protos.h (riscv_output_move_index_float):
	New prototyp.
	* config/riscv/riscv.cc (riscv_classify_address_index): Adjust
	for XTheadFMemIdx.
	(riscv_classify_address_modify): Likewise.
	(riscv_output_move_index_float): New function.
	(riscv_rtx_costs): Adjust for XTheadFMemIdx.
	(riscv_split_64bit_move_p): Likewise.
	(riscv_output_move): Likewise.
	* config/riscv/riscv.h (INDEX_REG_CLASS): Likewise.
	(REGNO_OK_FOR_INDEX_P): Likewise.
	* config/riscv/riscv.md (*movsf_hardfloat): New pattern.
	(*movdf_hardfloat_rv32): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xtheadfmemidx-fldr-fstr.c: New test.

Signed-off-by: M. Moiz Hussain <muhammad.hussain@vrull.eu>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
 gcc/config/riscv/constraints.md               |  7 ++
 gcc/config/riscv/riscv-protos.h               |  2 +
 gcc/config/riscv/riscv.cc                     | 70 ++++++++++++++++++-
 gcc/config/riscv/riscv.h                      |  4 +-
 gcc/config/riscv/riscv.md                     | 28 ++++++++
 .../riscv/xtheadfmemidx-fldr-fstr.c           | 58 +++++++++++++++
 6 files changed, 164 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index a007cf0b4f5..711268d05f6 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -202,3 +202,10 @@ (define_memory_constraint "Qmu"
   (and (match_code "mem")
        (match_test "riscv_legitimize_address_index_p (
 		    XEXP (op, 0), GET_MODE (op), true)")))
+
+(define_memory_constraint "Qmx"
+  "@internal
+   An address valid for GPR."
+  (and (match_code "mem")
+       (match_test "!riscv_legitimize_address_index_p (
+		    XEXP (op, 0), GET_MODE (op), false)")))
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 019a0e08285..ba53bf710d7 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -77,6 +77,8 @@ extern const char *
 riscv_output_move_index (rtx x, machine_mode mode, bool ldr);
 extern const char *
 riscv_output_move_modify (rtx x, machine_mode mode, bool ldi);
+extern const char *
+riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr);
 
 extern bool
 riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 2980dbd69f9..caa30eed8d6 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1316,7 +1316,7 @@ riscv_classify_address_index (struct riscv_address_info *info, rtx x,
   rtx index;
   int shift = 0;
 
-  if (!TARGET_XTHEADMEMIDX)
+  if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
     return false;
 
   if (!TARGET_64BIT && mode == DImode)
@@ -1326,6 +1326,8 @@ riscv_classify_address_index (struct riscv_address_info *info, rtx x,
     {
       if (!TARGET_HARD_FLOAT)
 	return false;
+      if (!(TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX))
+	return false;
       if (GET_MODE_SIZE (mode).to_constant () == 2)
 	return false;
     }
@@ -1422,7 +1424,7 @@ riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
   ? (SHIFT) + 1 \
   : 0)
 
-  if (!TARGET_XTHEADMEMIDX)
+  if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
     return false;
 
   if (!(INTEGRAL_MODE_P (mode) && GET_MODE_SIZE (mode).to_constant () <= 8))
@@ -1562,6 +1564,42 @@ riscv_output_move_index (rtx x, machine_mode mode, bool ldr)
   return buf;
 }
 
+const char *
+riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr)
+{
+  static char buf[128] = {0};
+
+  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
+  if (!IN_RANGE (index, 2, 3))
+    return NULL;
+
+  if (!riscv_legitimize_address_index_p (x, mode, false))
+    return NULL;
+
+  bool uindex = riscv_legitimize_address_index_p (x, mode, true);
+
+  /* Not using index, 0, 1, as they are not implemented
+     for xtheadfmemidx yet.  */
+  const char *const insn[][4] = {
+    {
+      "th.fs%srb\t%%z1,%%0",
+      "th.fs%srh\t%%z1,%%0",
+      "th.fs%srw\t%%z1,%%0",
+      "th.fs%srd\t%%z1,%%0"
+    },
+    {
+      "th.fl%srb\t%%0,%%1",
+      "th.fl%srh\t%%0,%%1",
+      "th.fl%srw\t%%0,%%1",
+      "th.fl%srd\t%%0,%%1"
+    }
+  };
+
+  snprintf (buf, sizeof (buf), insn[ldr][index], uindex ? "u" : "");
+
+  return buf;
+}
+
 /* Emit an instruction of the form (set TARGET SRC).  */
 
 static rtx
@@ -2739,7 +2777,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	}
       /* bit extraction pattern (xtheadmemidx, xtheadfmemidx).  */
       if (outer_code == SET
-	  && TARGET_XTHEADMEMIDX)
+	  && (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
 	{
 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
 	  return true;
@@ -3071,6 +3109,20 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
   if (TARGET_64BIT)
     return false;
 
+  if (TARGET_XTHEADFMEMIDX)
+    {
+      if (MEM_P (src) && SCALAR_FLOAT_MODE_P (GET_MODE (src))
+	  && riscv_legitimize_address_index_p (XEXP (src, 0),
+					       GET_MODE (src), false)
+	  && FP_REG_RTX_P (dest))
+	return false;
+      if (MEM_P (dest) && SCALAR_FLOAT_MODE_P (GET_MODE (dest))
+	  && riscv_legitimize_address_index_p (XEXP (dest, 0),
+					       GET_MODE (dest), false)
+	  && FP_REG_RTX_P (src))
+	return false;
+    }
+
   /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case
      of zeroing an FPR with FCVT.D.W.  */
   if (TARGET_DOUBLE_FLOAT
@@ -3269,6 +3321,12 @@ riscv_output_move (rtx dest, rtx src)
 
       if (dest_code == MEM)
 	{
+	  const char *insn = NULL;
+	  insn = riscv_output_move_index_float (XEXP (dest, 0),
+						GET_MODE (dest), false);
+	  if (insn)
+	    return insn;
+
 	  switch (width)
 	    {
 	    case 2:
@@ -3284,6 +3342,12 @@ riscv_output_move (rtx dest, rtx src)
     {
       if (src_code == MEM)
 	{
+	  const char *insn = NULL;
+	  insn = riscv_output_move_index_float (XEXP (src, 0),
+						GET_MODE (src), true);
+	  if (insn)
+	    return insn;
+
 	  switch (width)
 	    {
 	    case 2:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 199bb30162e..13764d60257 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -535,7 +535,7 @@ enum reg_class
    factor or added to another register (as well as added to a
    displacement).  */
 
-#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX) ? \
+#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \
 			GR_REGS : NO_REGS)
 
 /* We generally want to put call-clobbered registers ahead of
@@ -707,7 +707,7 @@ typedef struct {
 /* Addressing modes, and classification of registers for them.  */
 
 #define REGNO_OK_FOR_INDEX_P(REGNO) \
-  ((TARGET_XTHEADMEMIDX) ? \
+  ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \
   riscv_regno_mode_ok_for_base_p (REGNO, VOIDmode, 1) : 0)
 
 #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index df31a1fffff..9d0207b8d6f 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1866,6 +1866,20 @@ (define_insn "*movsf_hardfloat"
 	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "SF")])
 
+(define_insn "*movsf_hardfloat"
+  [(set (match_operand:SF 0
+	"nonimmediate_operand" "=f,f,f,m,Qmx,*f,*r,  *r,*r,*Qmx")
+	(match_operand:SF 1
+	"move_operand" " f,G,m,f,G,*r,*f,*G*r,*Qmx,*r"))]
+  "!TARGET_64BIT
+   && TARGET_XTHEADFMEMIDX
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  { return riscv_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type"
+	      "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+   (set_attr "mode" "SF")])
+
 (define_insn "*movsf_softfloat"
   [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
 	(match_operand:SF 1 "move_operand"         " Gr,m,r"))]
@@ -1900,6 +1914,20 @@ (define_insn "*movdf_hardfloat_rv32"
 	     "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "DF")])
 
+(define_insn "*movdf_hardfloat_rv32"
+  [(set (match_operand:DF 0
+	"nonimmediate_operand" "=f,f,f,m,Qmx,  *r,*r,*Qmx")
+	(match_operand:DF 1
+	"move_operand" " f,G,m,f,G,*r*G,*Qmx,*r"))]
+  "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
+   && TARGET_XTHEADFMEMIDX
+   && (register_operand (operands[0], DFmode)
+       || reg_or_0_operand (operands[1], DFmode))"
+  { return riscv_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type"
+	     "fmove,mtc,fpload,fpstore,store,move,load,store")
+   (set_attr "mode" "DF")])
+
 (define_insn "*movdf_hardfloat_rv64"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  *r,*r,*m")
 	(match_operand:DF 1 "move_operand"         " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c
new file mode 100644
index 00000000000..006038ce3c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os"} } */
+/* { dg-options "-march=rv64gc_xtheadfmemidx --save-temps -O2" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadfmemidx --save-temps -O2" { target { rv32 } } } */
+
+float func_f(float *a, int b)
+{
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.flrw" } } */
+
+double func_d(double *a, int b)
+{
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.flrd" } } */
+
+float func_sf(float *a, int b, float c)
+{
+    a[b] = c;
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.fsrw" } } */
+
+double func_sd(double *a, int b, double c)
+{
+    a[b] = c;
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.fsrd" } } */
+
+float func_uf(float *a, unsigned int b)
+{
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.flurw" { target { rv64 } } } } */
+
+double func_ud(double *a, unsigned int b)
+{
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.flurd" { target { rv64 } } } } */
+
+float func_usf(float *a, unsigned int b, float c)
+{
+    a[b] = c;
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.fsurw" { target { rv64 } } } } */
+
+double func_usd(double *a, unsigned int b, double c)
+{
+    a[b] = c;
+    return a[b];
+}
+/* { dg-final { scan-assembler "th.fsurd" { target { rv64 } } } } */
+
+/* { dg-final { cleanup-saved-temps } } */
-- 
2.39.2


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

* Re: [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension
  2023-02-24  5:51 ` [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension Christoph Muellner
@ 2023-02-24  6:52   ` Andrew Pinski
  2023-02-24  9:54     ` Kito Cheng
  0 siblings, 1 reply; 30+ messages in thread
From: Andrew Pinski @ 2023-02-24  6:52 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Thu, Feb 23, 2023 at 9:55 PM Christoph Muellner
<christoph.muellner@vrull.eu> wrote:
>
> From: Christoph Müllner <christoph.muellner@vrull.eu>
>
> This patch adds support for the XTheadBa ISA extension.
> The new INSN pattern is defined in a new file to separate
> this vendor extension from the standard extensions.

How does this interact with doing -march=rv32gc_xtheadba_zba ?
Seems like it might be better handle that case correctly. I suspect
these all XThreadB* extensions have a similar problem too.

Thanks,
Andrew Pinski

>
> gcc/ChangeLog:
>
>         * config/riscv/riscv.md: Include thead.md
>         * config/riscv/thead.md: New file.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/xtheadba-addsl.c: New test.
>
> Changes in v3:
> - Fix operand order for th.addsl.
>
> Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> ---
>  gcc/config/riscv/riscv.md                     |  1 +
>  gcc/config/riscv/thead.md                     | 31 +++++++++++
>  .../gcc.target/riscv/xtheadba-addsl.c         | 55 +++++++++++++++++++
>  3 files changed, 87 insertions(+)
>  create mode 100644 gcc/config/riscv/thead.md
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
>
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 05924e9bbf1..d6c2265e9d4 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -3093,4 +3093,5 @@ (define_insn "riscv_prefetchi_<mode>"
>  (include "pic.md")
>  (include "generic.md")
>  (include "sifive-7.md")
> +(include "thead.md")
>  (include "vector.md")
> diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> new file mode 100644
> index 00000000000..158e9124c3a
> --- /dev/null
> +++ b/gcc/config/riscv/thead.md
> @@ -0,0 +1,31 @@
> +;; Machine description for T-Head vendor extensions
> +;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
> +
> +;; This file is part of GCC.
> +
> +;; GCC is free software; you can redistribute it and/or modify
> +;; it under the terms of the GNU General Public License as published by
> +;; the Free Software Foundation; either version 3, or (at your option)
> +;; any later version.
> +
> +;; GCC is distributed in the hope that it will be useful,
> +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +;; GNU General Public License for more details.
> +
> +;; You should have received a copy of the GNU General Public License
> +;; along with GCC; see the file COPYING3.  If not see
> +;; <http://www.gnu.org/licenses/>.
> +
> +;; XTheadBa
> +
> +(define_insn "*th_addsl"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +       (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
> +                         (match_operand:QI 2 "immediate_operand" "I"))
> +               (match_operand:X 3 "register_operand" "r")))]
> +  "TARGET_XTHEADBA
> +   && (INTVAL (operands[2]) >= 0) && (INTVAL (operands[2]) <= 3)"
> +  "th.addsl\t%0,%3,%1,%2"
> +  [(set_attr "type" "bitmanip")
> +   (set_attr "mode" "<X:MODE>")])
> diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> new file mode 100644
> index 00000000000..5004735a246
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> @@ -0,0 +1,55 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
> +/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
> +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
> +
> +long
> +test_1 (long a, long b)
> +{
> +  /* th.addsl aX, aX, 1  */
> +  return a + (b << 1);
> +}
> +
> +int
> +foos (short *x, int n)
> +{
> +  /* th.addsl aX, aX, 1  */
> +  return x[n];
> +}
> +
> +long
> +test_2 (long a, long b)
> +{
> +  /* th.addsl aX, aX, 2  */
> +  return a + (b << 2);
> +}
> +
> +int
> +fooi (int *x, int n)
> +{
> +  /* th.addsl aX, aX, 2  */
> +  return x[n];
> +}
> +
> +long
> +test_3 (long a, long b)
> +{
> +  /* th.addsl aX, aX, 3  */
> +  return a + (b << 3);
> +}
> +
> +long
> +fool (long *x, int n)
> +{
> +  /* th.addsl aX, aX, 2 (rv32)  */
> +  /* th.addsl aX, aX, 3 (rv64)  */
> +  return x[n];
> +}
> +
> +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,1" 2 } } */
> +
> +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 3 { target { rv32 } } } } */
> +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 2 { target { rv64 } } } } */
> +
> +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 1 { target { rv32 } } } } */
> +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 2 { target { rv64 } } } } */
> --
> 2.39.2
>

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-24  5:51 ` [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs " Christoph Muellner
@ 2023-02-24  7:36   ` Kito Cheng
  2023-02-24 10:21     ` Christoph Müllner
  2023-02-25 23:42   ` Hans-Peter Nilsson
  1 sibling, 1 reply; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  7:36 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Jim Wilson, Palmer Dabbelt, Andrew Waterman,
	Philipp Tomsich, Jeff Law, Cooper Qu, Lifang Xia, Yunhai Shang,
	Zhiwei Liu

> diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> index 158e9124c3a..2c684885850 100644
> --- a/gcc/config/riscv/thead.md
> +++ b/gcc/config/riscv/thead.md
> @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
>    "th.addsl\t%0,%3,%1,%2"
>    [(set_attr "type" "bitmanip")
>     (set_attr "mode" "<X:MODE>")])
> +
> +;; XTheadBs
> +
> +(define_insn "*th_tst"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +       (zero_extract:X (match_operand:X 1 "register_operand" "r")
> +                       (const_int 1)
> +                       (match_operand 2 "immediate_operand" "i")))]
> +  "TARGET_XTHEADBS"

Add range check like *bexti pattern?

TARGET_XTHEADBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)

> +  "th.tst\t%0,%1,%2"
> +  [(set_attr "type" "bitmanip")])

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

* Re: [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx ISA extension
  2023-02-24  5:51 ` [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx " Christoph Muellner
@ 2023-02-24  7:53   ` Kito Cheng
  2023-02-24  9:46     ` Kito Cheng
  0 siblings, 1 reply; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  7:53 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Jim Wilson, Palmer Dabbelt, Andrew Waterman,
	Philipp Tomsich, Jeff Law, Cooper Qu, Lifang Xia, Yunhai Shang,
	Zhiwei Liu, moiz.hussain

> +
> +(define_memory_constraint "Qmx"
> +  "@internal
> +   An address valid for GPR."
> +  (and (match_code "mem")
> +       (match_test "!riscv_legitimize_address_index_p (
> +                   XEXP (op, 0), GET_MODE (op), false)")))

Check TARGET_XTHEADFMEMIDX, and I don't quite understand why it
comes with `!` for the riscv_legitimize_address_index_p,
but saying it's an address valid for GPR?

According to the comment it sounds like (mem (reg)) but seems like not?


> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index 019a0e08285..ba53bf710d7 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -77,6 +77,8 @@ extern const char *
>  riscv_output_move_index (rtx x, machine_mode mode, bool ldr);
>  extern const char *
>  riscv_output_move_modify (rtx x, machine_mode mode, bool ldi);
> +extern const char *
> +riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr);
>
>  extern bool
>  riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex);
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 2980dbd69f9..caa30eed8d6 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1316,7 +1316,7 @@ riscv_classify_address_index (struct riscv_address_info *info, rtx x,
>    rtx index;
>    int shift = 0;
>
> -  if (!TARGET_XTHEADMEMIDX)
> +  if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
>      return false;
>
>    if (!TARGET_64BIT && mode == DImode)
> @@ -1326,6 +1326,8 @@ riscv_classify_address_index (struct riscv_address_info *info, rtx x,
>      {
>        if (!TARGET_HARD_FLOAT)
>         return false;
> +      if (!(TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX))
> +       return false;
>        if (GET_MODE_SIZE (mode).to_constant () == 2)
>         return false;
>      }
> @@ -1422,7 +1424,7 @@ riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
>    ? (SHIFT) + 1 \
>    : 0)
>
> -  if (!TARGET_XTHEADMEMIDX)
> +  if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
>      return false;
>
>    if (!(INTEGRAL_MODE_P (mode) && GET_MODE_SIZE (mode).to_constant () <= 8))
> @@ -1562,6 +1564,42 @@ riscv_output_move_index (rtx x, machine_mode mode, bool ldr)
>    return buf;
>  }
>
> +const char *
> +riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr)
> +{
> +  static char buf[128] = {0};
> +
> +  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
> +  if (!IN_RANGE (index, 2, 3))
> +    return NULL;
> +
> +  if (!riscv_legitimize_address_index_p (x, mode, false))
> +    return NULL;
> +
> +  bool uindex = riscv_legitimize_address_index_p (x, mode, true);
> +
> +  /* Not using index, 0, 1, as they are not implemented
> +     for xtheadfmemidx yet.  */
> +  const char *const insn[][4] = {
> +    {
> +      "th.fs%srb\t%%z1,%%0",
> +      "th.fs%srh\t%%z1,%%0",
> +      "th.fs%srw\t%%z1,%%0",
> +      "th.fs%srd\t%%z1,%%0"
> +    },
> +    {
> +      "th.fl%srb\t%%0,%%1",
> +      "th.fl%srh\t%%0,%%1",
> +      "th.fl%srw\t%%0,%%1",
> +      "th.fl%srd\t%%0,%%1"
> +    }
> +  };
> +
> +  snprintf (buf, sizeof (buf), insn[ldr][index], uindex ? "u" : "");
> +
> +  return buf;
> +}
> +
>  /* Emit an instruction of the form (set TARGET SRC).  */
>
>  static rtx
> @@ -2739,7 +2777,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
>         }
>        /* bit extraction pattern (xtheadmemidx, xtheadfmemidx).  */
>        if (outer_code == SET
> -         && TARGET_XTHEADMEMIDX)
> +         && (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX))
>         {
>           *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
>           return true;
> @@ -3071,6 +3109,20 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
>    if (TARGET_64BIT)
>      return false;
>
> +  if (TARGET_XTHEADFMEMIDX)
> +    {
> +      if (MEM_P (src) && SCALAR_FLOAT_MODE_P (GET_MODE (src))
> +         && riscv_legitimize_address_index_p (XEXP (src, 0),
> +                                              GET_MODE (src), false)
> +         && FP_REG_RTX_P (dest))
> +       return false;
> +      if (MEM_P (dest) && SCALAR_FLOAT_MODE_P (GET_MODE (dest))
> +         && riscv_legitimize_address_index_p (XEXP (dest, 0),
> +                                              GET_MODE (dest), false)
> +         && FP_REG_RTX_P (src))
> +       return false;
> +    }
> +
>    /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case
>       of zeroing an FPR with FCVT.D.W.  */
>    if (TARGET_DOUBLE_FLOAT
> @@ -3269,6 +3321,12 @@ riscv_output_move (rtx dest, rtx src)
>
>        if (dest_code == MEM)
>         {
> +         const char *insn = NULL;
> +         insn = riscv_output_move_index_float (XEXP (dest, 0),
> +                                               GET_MODE (dest), false);
> +         if (insn)
> +           return insn;
> +
>           switch (width)
>             {
>             case 2:
> @@ -3284,6 +3342,12 @@ riscv_output_move (rtx dest, rtx src)
>      {
>        if (src_code == MEM)
>         {
> +         const char *insn = NULL;
> +         insn = riscv_output_move_index_float (XEXP (src, 0),
> +                                               GET_MODE (src), true);
> +         if (insn)
> +           return insn;
> +
>           switch (width)
>             {
>             case 2:
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index 199bb30162e..13764d60257 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -535,7 +535,7 @@ enum reg_class
>     factor or added to another register (as well as added to a
>     displacement).  */
>
> -#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX) ? \
> +#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \
>                         GR_REGS : NO_REGS)
>
>  /* We generally want to put call-clobbered registers ahead of
> @@ -707,7 +707,7 @@ typedef struct {
>  /* Addressing modes, and classification of registers for them.  */
>
>  #define REGNO_OK_FOR_INDEX_P(REGNO) \
> -  ((TARGET_XTHEADMEMIDX) ? \
> +  ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \
>    riscv_regno_mode_ok_for_base_p (REGNO, VOIDmode, 1) : 0)
>
>  #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index df31a1fffff..9d0207b8d6f 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -1866,6 +1866,20 @@ (define_insn "*movsf_hardfloat"
>              "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
>     (set_attr "mode" "SF")])
>
> +(define_insn "*movsf_hardfloat"
> +  [(set (match_operand:SF 0
> +       "nonimmediate_operand" "=f,f,f,m,Qmx,*f,*r,  *r,*r,*Qmx")
> +       (match_operand:SF 1
> +       "move_operand" " f,G,m,f,G,*r,*f,*G*r,*Qmx,*r"))]
> +  "!TARGET_64BIT
> +   && TARGET_XTHEADFMEMIDX
> +   && (register_operand (operands[0], SFmode)
> +       || reg_or_0_operand (operands[1], SFmode))"
> +  { return riscv_output_move (operands[0], operands[1]); }
> +  [(set_attr "move_type"
> +             "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> +   (set_attr "mode" "SF")])
> +

Plz move to thead.md and named with prefix *th

>  (define_insn "*movsf_softfloat"
>    [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
>         (match_operand:SF 1 "move_operand"         " Gr,m,r"))]
> @@ -1900,6 +1914,20 @@ (define_insn "*movdf_hardfloat_rv32"
>              "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
>     (set_attr "mode" "DF")])
>
> +(define_insn "*movdf_hardfloat_rv32"
> +  [(set (match_operand:DF 0
> +       "nonimmediate_operand" "=f,f,f,m,Qmx,  *r,*r,*Qmx")
> +       (match_operand:DF 1
> +       "move_operand" " f,G,m,f,G,*r*G,*Qmx,*r"))]
> +  "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
> +   && TARGET_XTHEADFMEMIDX
> +   && (register_operand (operands[0], DFmode)
> +       || reg_or_0_operand (operands[1], DFmode))"
> +  { return riscv_output_move (operands[0], operands[1]); }
> +  [(set_attr "move_type"
> +            "fmove,mtc,fpload,fpstore,store,move,load,store")
> +   (set_attr "mode" "DF")])
> +

Ditto

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

* Re: [PATCH v3 00/11] RISC-V: Add XThead* extension support
  2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
                   ` (10 preceding siblings ...)
  2023-02-24  5:51 ` [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx " Christoph Muellner
@ 2023-02-24  8:08 ` Kito Cheng
  2023-02-24 11:27   ` Christoph Müllner
  11 siblings, 1 reply; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  8:08 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

Hi Christoph:

OK for trunk for the 1~8, feel free to commit 1~8 after you address
those minor comments, and could you also prepare release notes for
those extensions?

And 9~11 needs to take a few more rounds of review and test.




On Fri, Feb 24, 2023 at 1:52 PM Christoph Muellner
<christoph.muellner@vrull.eu> wrote:
>
> From: Christoph Müllner <christoph.muellner@vrull.eu>
>
> This series introduces support for the T-Head specific RISC-V ISA extensions
> which are available e.g. on the T-Head XuanTie C906.
>
> The ISA spec can be found here:
>   https://github.com/T-head-Semi/thead-extension-spec
>
> This series adds support for the following XThead* extensions:
> * XTheadBa
> * XTheadBb
> * XTheadBs
> * XTheadCmo
> * XTheadCondMov
> * XTheadFMemIdx
> * XTheadFmv
> * XTheadInt
> * XTheadMac
> * XTheadMemIdx
> * XTheadMemPair
> * XTheadSync
>
> All extensions are properly integrated and the included tests
> demonstrate the improvements of the generated code.
>
> The series also introduces support for "-mcpu=thead-c906", which also
> enables all available XThead* ISA extensions of the T-Head C906.
>
> All patches have been tested and don't introduce regressions for RV32 or RV64.
> The patches have also been tested with SPEC CPU2017 on QEMU and real HW
> (D1 board).
>
> Support patches for these extensions for Binutils, QEMU, and LLVM have
> already been merged in the corresponding upstream projects.
>
> Changes in v3:
> - Bugfix in XTheadBa
> - Rewrite of XTheadMemPair
> - Inclusion of XTheadMemIdx and XTheadFMemIdx
>
> Christoph Müllner (9):
>   riscv: Add basic XThead* vendor extension support
>   riscv: riscv-cores.def: Add T-Head XuanTie C906
>   riscv: thead: Add support for the XTheadBa ISA extension
>   riscv: thead: Add support for the XTheadBs ISA extension
>   riscv: thead: Add support for the XTheadBb ISA extension
>   riscv: thead: Add support for the XTheadCondMov ISA extensions
>   riscv: thead: Add support for the XTheadMac ISA extension
>   riscv: thead: Add support for the XTheadFmv ISA extension
>   riscv: thead: Add support for the XTheadMemPair ISA extension
>
> moiz.hussain (2):
>   riscv: thead: Add support for the XTheadMemIdx ISA extension
>   riscv: thead: Add support for the XTheadFMemIdx ISA extension
>
>  gcc/common/config/riscv/riscv-common.cc       |   26 +
>  gcc/config/riscv/bitmanip.md                  |   52 +-
>  gcc/config/riscv/constraints.md               |   43 +
>  gcc/config/riscv/iterators.md                 |    4 +
>  gcc/config/riscv/peephole.md                  |   56 +
>  gcc/config/riscv/riscv-cores.def              |    4 +
>  gcc/config/riscv/riscv-opts.h                 |   29 +
>  gcc/config/riscv/riscv-protos.h               |   28 +-
>  gcc/config/riscv/riscv.cc                     | 1090 +++++++++++++++--
>  gcc/config/riscv/riscv.h                      |    8 +-
>  gcc/config/riscv/riscv.md                     |  169 ++-
>  gcc/config/riscv/riscv.opt                    |    3 +
>  gcc/config/riscv/thead.md                     |  351 ++++++
>  .../gcc.target/riscv/mcpu-thead-c906.c        |   28 +
>  .../gcc.target/riscv/xtheadba-addsl.c         |   55 +
>  gcc/testsuite/gcc.target/riscv/xtheadba.c     |   14 +
>  gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c |   20 +
>  .../gcc.target/riscv/xtheadbb-extu-2.c        |   22 +
>  .../gcc.target/riscv/xtheadbb-extu.c          |   22 +
>  gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c |   18 +
>  gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c |   45 +
>  .../gcc.target/riscv/xtheadbb-srri.c          |   21 +
>  gcc/testsuite/gcc.target/riscv/xtheadbb.c     |   14 +
>  gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c |   13 +
>  gcc/testsuite/gcc.target/riscv/xtheadbs.c     |   14 +
>  gcc/testsuite/gcc.target/riscv/xtheadcmo.c    |   14 +
>  .../riscv/xtheadcondmov-mveqz-imm-eqz.c       |   38 +
>  .../riscv/xtheadcondmov-mveqz-imm-not.c       |   38 +
>  .../riscv/xtheadcondmov-mveqz-reg-eqz.c       |   38 +
>  .../riscv/xtheadcondmov-mveqz-reg-not.c       |   38 +
>  .../riscv/xtheadcondmov-mvnez-imm-cond.c      |   38 +
>  .../riscv/xtheadcondmov-mvnez-imm-nez.c       |   38 +
>  .../riscv/xtheadcondmov-mvnez-reg-cond.c      |   38 +
>  .../riscv/xtheadcondmov-mvnez-reg-nez.c       |   38 +
>  .../gcc.target/riscv/xtheadcondmov.c          |   14 +
>  .../riscv/xtheadfmemidx-fldr-fstr.c           |   58 +
>  .../gcc.target/riscv/xtheadfmemidx.c          |   14 +
>  .../gcc.target/riscv/xtheadfmv-fmv.c          |   24 +
>  gcc/testsuite/gcc.target/riscv/xtheadfmv.c    |   14 +
>  gcc/testsuite/gcc.target/riscv/xtheadint.c    |   14 +
>  .../gcc.target/riscv/xtheadmac-mula-muls.c    |   43 +
>  gcc/testsuite/gcc.target/riscv/xtheadmac.c    |   14 +
>  .../gcc.target/riscv/xtheadmemidx-ldi-sdi.c   |   72 ++
>  .../riscv/xtheadmemidx-ldr-str-32.c           |   23 +
>  .../riscv/xtheadmemidx-ldr-str-64.c           |   53 +
>  .../gcc.target/riscv/xtheadmemidx-macros.h    |  110 ++
>  gcc/testsuite/gcc.target/riscv/xtheadmemidx.c |   14 +
>  .../gcc.target/riscv/xtheadmempair-1.c        |   98 ++
>  .../gcc.target/riscv/xtheadmempair-2.c        |   84 ++
>  .../gcc.target/riscv/xtheadmempair-3.c        |   29 +
>  .../gcc.target/riscv/xtheadmempair.c          |   13 +
>  gcc/testsuite/gcc.target/riscv/xtheadsync.c   |   14 +
>  52 files changed, 3048 insertions(+), 124 deletions(-)
>  create mode 100644 gcc/config/riscv/thead.md
>  create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcmo.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadint.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadsync.c
>
> --
> 2.39.2
>

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

* Re: [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair ISA extension
  2023-02-24  5:51 ` [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair " Christoph Muellner
@ 2023-02-24  9:00   ` Kito Cheng
  2023-02-24  9:33     ` Christoph Müllner
  2023-02-24 15:48   ` Kito Cheng
  1 sibling, 1 reply; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  9:00 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

Got one fail:

FAIL: gcc.target/riscv/xtheadmempair-1.c   -O2   scan-assembler-times
th.luwd\t 4

It should scan lwud rather than luwd?

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

* Re: [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair ISA extension
  2023-02-24  9:00   ` Kito Cheng
@ 2023-02-24  9:33     ` Christoph Müllner
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-02-24  9:33 UTC (permalink / raw)
  To: Kito Cheng
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Fri, Feb 24, 2023 at 10:01 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Got one fail:
>
> FAIL: gcc.target/riscv/xtheadmempair-1.c   -O2   scan-assembler-times
> th.luwd\t 4
>
> It should scan lwud rather than luwd?

Yes, this should be th.lwud.
Must have been introduced after testing.

I also ran the whole patchset again with RV32 and RV64.
This should be the only issue of this kind in the series.
Sorry for that!

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

* Re: [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx ISA extension
  2023-02-24  5:51 ` [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx " Christoph Muellner
@ 2023-02-24  9:46   ` Kito Cheng
  0 siblings, 0 replies; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  9:46 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Jim Wilson, Palmer Dabbelt, Andrew Waterman,
	Philipp Tomsich, Jeff Law, Cooper Qu, Lifang Xia, Yunhai Shang,
	Zhiwei Liu, moiz.hussain

> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index cf0cd669be4..5cd3f7673f0 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -215,4 +215,7 @@ enum stack_protector_guard {
>  #define TARGET_XTHEADMEMPAIR ((riscv_xthead_subext & MASK_XTHEADMEMPAIR) != 0)
>  #define TARGET_XTHEADSYNC    ((riscv_xthead_subext & MASK_XTHEADSYNC) != 0)
>
> +#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
> +#define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
> +
>  #endif /* ! GCC_RISCV_OPTS_H */
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index 1b7ba02726d..019a0e08285 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -65,6 +65,24 @@ extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
>  extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
>  extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
>  #endif
> +
> +extern bool
> +riscv_classify_address_index (struct riscv_address_info *info, rtx x,
> +                             machine_mode mode, bool strict_p);
> +extern bool
> +riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
> +                              machine_mode mode, bool strict_p);
> +
> +extern const char *
> +riscv_output_move_index (rtx x, machine_mode mode, bool ldr);
> +extern const char *
> +riscv_output_move_modify (rtx x, machine_mode mode, bool ldi);
> +
> +extern bool
> +riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex);
> +extern bool
> +riscv_legitimize_address_modify_p (rtx x, machine_mode mode, bool post);
> +
>  extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx);
>  extern rtx riscv_legitimize_call_address (rtx);
>  extern void riscv_set_return_address (rtx, rtx);
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 33854393bd2..2980dbd69f9 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -83,6 +83,19 @@ along with GCC; see the file COPYING3.  If not see
>
>  /* Classifies an address.
>
> +   ADDRESS_REG_REG
> +       A base register indexed by (optionally scaled) register.
> +
> +   ADDRESS_REG_UREG
> +       A base register indexed by (optionally scaled) zero-extended register.
> +
> +   ADDRESS_REG_WB
> +       A base register indexed by immediate offset with writeback.
> +
> +   ADDRESS_REG
> +       A natural register + offset address.  The register satisfies
> +       riscv_valid_base_register_p and the offset is a const_arith_operand.
> +
>     ADDRESS_REG
>         A natural register + offset address.  The register satisfies
>         riscv_valid_base_register_p and the offset is a const_arith_operand.
> @@ -97,6 +110,9 @@ along with GCC; see the file COPYING3.  If not see
>     ADDRESS_SYMBOLIC:
>         A constant symbolic address.  */
>  enum riscv_address_type {
> +  ADDRESS_REG_REG,
> +  ADDRESS_REG_UREG,
> +  ADDRESS_REG_WB,
>    ADDRESS_REG,
>    ADDRESS_LO_SUM,
>    ADDRESS_CONST_INT,
> @@ -201,6 +217,7 @@ struct riscv_address_info {
>    rtx reg;
>    rtx offset;
>    enum riscv_symbol_type symbol_type;
> +  int shift;
>  };
>
>  /* One stage in a constant building sequence.  These sequences have
> @@ -1025,12 +1042,31 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
>        if (riscv_v_ext_vector_mode_p (mode))
>         return false;
>
> +      if (riscv_valid_base_register_p (XEXP (x, 0), mode, strict_p)
> +         && riscv_classify_address_index (info, XEXP (x, 1), mode, strict_p))
> +       {
> +         info->reg = XEXP (x, 0);
> +         return true;
> +       }
> +      else if (riscv_valid_base_register_p (XEXP (x, 1), mode, strict_p)
> +               && riscv_classify_address_index (info, XEXP (x, 0),
> +                                                mode, strict_p))
> +       {
> +         info->reg = XEXP (x, 1);
> +         return true;
> +       }
> +
>        info->type = ADDRESS_REG;
>        info->reg = XEXP (x, 0);
>        info->offset = XEXP (x, 1);
>        return (riscv_valid_base_register_p (info->reg, mode, strict_p)
>               && riscv_valid_offset_p (info->offset, mode));
>
> +    case POST_MODIFY:
> +    case PRE_MODIFY:
> +
> +      return riscv_classify_address_modify (info, x, mode, strict_p);
> +
>      case LO_SUM:
>        /* RVV load/store disallow LO_SUM.  */
>        if (riscv_v_ext_vector_mode_p (mode))
> @@ -1269,6 +1305,263 @@ riscv_emit_move (rtx dest, rtx src)
>           : emit_move_insn_1 (dest, src));
>  }
>
> +/* Return true if address offset is a valid index.  If it is, fill in INFO
> +   appropriately.  STRICT_P is true if REG_OK_STRICT is in effect.  */
> +
> +bool
> +riscv_classify_address_index (struct riscv_address_info *info, rtx x,
> +      machine_mode mode, bool strict_p)

indent

> +{
> +  enum riscv_address_type type = ADDRESS_REG_REG;;
> +  rtx index;
> +  int shift = 0;
> +
> +  if (!TARGET_XTHEADMEMIDX)
> +    return false;
> +
> +  if (!TARGET_64BIT && mode == DImode)
> +    return false;
> +
> +  if (SCALAR_FLOAT_MODE_P (mode))
> +    {
> +      if (!TARGET_HARD_FLOAT)
> +       return false;
> +      if (GET_MODE_SIZE (mode).to_constant () == 2)
> +       return false;
> +    }
> +
> +  /* (reg:P) */
> +  if ((REG_P (x) || GET_CODE (x) == SUBREG)
> +      && GET_MODE (x) == Pmode)
> +    {
> +      index = x;
> +      shift = 0;
> +    }
> +  /* (zero_extend:DI (reg:SI)) */
> +  else if (GET_CODE (x) == ZERO_EXTEND
> +          && GET_MODE (x) == DImode
> +          && GET_MODE (XEXP (x, 0)) == SImode)
> +    {
> +      type = ADDRESS_REG_UREG;
> +      index = XEXP (x, 0);
> +      shift = 0;
> +    }
> +  /* (mult:DI (zero_extend:DI (reg:SI)) (const_int scale)) */
> +  else if (GET_CODE (x) == MULT
> +          && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
> +          && GET_MODE (XEXP (x, 0)) == DImode
> +          && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode
> +          && CONST_INT_P (XEXP (x, 1)))
> +    {
> +      type = ADDRESS_REG_UREG;
> +      index = XEXP (XEXP (x, 0), 0);
> +      shift = exact_log2 (INTVAL (XEXP (x, 1)));
> +    }
> +  /* (ashift:DI (zero_extend:DI (reg:SI)) (const_int shift)) */
> +  else if (GET_CODE (x) == ASHIFT
> +          && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
> +          && GET_MODE (XEXP (x, 0)) == DImode
> +          && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode
> +          && CONST_INT_P (XEXP (x, 1)))
> +    {
> +      type = ADDRESS_REG_UREG;
> +      index = XEXP (XEXP (x, 0), 0);
> +      shift = INTVAL (XEXP (x, 1));
> +    }
> +  /* (mult:P (reg:P) (const_int scale)) */
> +  else if (GET_CODE (x) == MULT
> +          && GET_MODE (x) == Pmode
> +          && GET_MODE (XEXP (x, 0)) == Pmode
> +          && CONST_INT_P (XEXP (x, 1)))
> +    {
> +      index = XEXP (x, 0);
> +      shift = exact_log2 (INTVAL (XEXP (x, 1)));
> +    }
> +  /* (ashift:P (reg:P) (const_int shift)) */
> +  else if (GET_CODE (x) == ASHIFT
> +          && GET_MODE (x) == Pmode
> +          && GET_MODE (XEXP (x, 0)) == Pmode
> +          && CONST_INT_P (XEXP (x, 1)))
> +    {
> +      index = XEXP (x, 0);
> +      shift = INTVAL (XEXP (x, 1));
> +    }
> +  else
> +    return false;
> +
> +  if (shift != 0 && !IN_RANGE (shift, 1, 3))
> +    return false;
> +
> +  if (!strict_p
> +      && GET_CODE (index) == SUBREG
> +      && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
> +    index = SUBREG_REG (index);
> +
> +  if (riscv_valid_base_register_p (index, mode, strict_p))
> +    {
> +      info->type = type;
> +      info->offset = index;
> +      info->shift = shift;
> +      return true;
> +    }
> +  return false;
> +}
> +
> +/* Return true if address is a valid modify.  If it is, fill in INFO
> +   appropriately.  STRICT_P is true if REG_OK_STRICT is in effect.  */
> +
> +bool
> +riscv_classify_address_modify (struct riscv_address_info *info, rtx x,
> +      machine_mode mode, bool strict_p)

indent

> +{
> +
> +#define AM_IMM(BIT) (1LL << (5 + (BIT)))
> +#define AM_OFFSET(VALUE, SHIFT) (\
> +  ((unsigned HOST_WIDE_INT) (VALUE) + AM_IMM (SHIFT)/2 < AM_IMM (SHIFT)) \
> +  && !((unsigned HOST_WIDE_INT) (VALUE) & ((1 << (SHIFT)) - 1)) \
> +  ? (SHIFT) + 1 \
> +  : 0)

Plz extract AM_IMM and AM_OFFSET to function instead of marco.

> +
> +  if (!TARGET_XTHEADMEMIDX)
> +    return false;
> +
> +  if (!(INTEGRAL_MODE_P (mode) && GET_MODE_SIZE (mode).to_constant () <= 8))
> +    return false;
> +
> +  if (!TARGET_64BIT && mode == DImode)
> +    return false;
> +
> +  if (GET_CODE (x) != POST_MODIFY
> +      && GET_CODE (x) != PRE_MODIFY)
> +    return false;
> +
> +  info->type = ADDRESS_REG_WB;
> +  info->reg = XEXP (x, 0);
> +
> +  if (GET_CODE (XEXP (x, 1)) == PLUS
> +      && CONST_INT_P (XEXP (XEXP (x, 1), 1))
> +      && rtx_equal_p (XEXP (XEXP (x, 1), 0), info->reg)
> +      && riscv_valid_base_register_p (info->reg, mode, strict_p))
> +    {
> +      info->offset = XEXP (XEXP (x, 1), 1);
> +      int shift = AM_OFFSET (INTVAL (info->offset), 0);
> +      if (!shift)
> +       shift = AM_OFFSET (INTVAL (info->offset), 1);
> +      if (!shift)
> +       shift = AM_OFFSET (INTVAL (info->offset), 2);
> +      if (!shift)
> +       shift = AM_OFFSET (INTVAL (info->offset), 3);
> +      if (shift)
> +       {
> +         info->shift = shift - 1;
> +         return true;
> +       }
> +    }
> +  return false;
> +}
> +
> +/* Return TRUE if X is a legitimate address modify.  */
> +
> +bool
> +riscv_legitimize_address_modify_p (rtx x, machine_mode mode, bool post)
> +{
> +  struct riscv_address_info addr;
> +  return riscv_classify_address_modify (&addr, x, mode, false)
> +        && (!post || GET_CODE (x) == POST_MODIFY);
> +}
> +
> +/* Return the LDIB/LDIA and STIB/STIA instructions.  Assume
> +   that X is MEM operand.  */
> +
> +const char *
> +riscv_output_move_modify (rtx x, machine_mode mode, bool ldi)

Rename this function with prefix thead_ and create thead.cc and move
to that file.

> +{
> +  static char buf[128] = {0};
> +
> +  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
> +  if (!IN_RANGE (index, 0, 3))
> +    return NULL;
> +
> +  if (!riscv_legitimize_address_modify_p (x, mode, false))
> +    return NULL;
> +
> +  bool post = riscv_legitimize_address_modify_p (x, mode, true);
> +
> +  const char *const insn[][4] = {
> +    {
> +      "th.sbi%s\t%%z1,%%0",
> +      "th.shi%s\t%%z1,%%0",
> +      "th.swi%s\t%%z1,%%0",
> +      "th.sdi%s\t%%z1,%%0"
> +    },
> +    {
> +      "th.lbui%s\t%%0,%%1",
> +      "th.lhui%s\t%%0,%%1",
> +      "th.lwi%s\t%%0,%%1",
> +      "th.ldi%s\t%%0,%%1"
> +    }
> +  };
> +
> +  snprintf (buf, sizeof (buf), insn[ldi][index], post ? "a" : "b");
> +  return buf;
> +}
> +
> +bool
> +riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex)
> +{
> +  struct riscv_address_info addr;
> +  rtx op0, op1;
> +
> +  if (GET_CODE (x) != PLUS)
> +    return false;
> +
> +  op0 = XEXP (x, 0);
> +  op1 = XEXP (x, 1);
> +
> +  return ((riscv_valid_base_register_p (op0, mode, false)
> +          && riscv_classify_address_index (&addr, op1, mode, false))
> +         || (riscv_valid_base_register_p (op1, mode, false)
> +             && riscv_classify_address_index (&addr, op0, mode, false)))
> +        && (!uindex || addr.type == ADDRESS_REG_UREG);
> +}
> +
> +/* Return the LDR or STR instructions.  Assume
> +   that X is MEM operand.  */
> +
> +const char *
> +riscv_output_move_index (rtx x, machine_mode mode, bool ldr)

Rename this function with prefix thead_ and create thead.cc and move
to that file.

> +{
> +  static char buf[128] = {0};
> +
> +  int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ());
> +  if (!IN_RANGE (index, 0, 3))
> +    return NULL;
> +
> +  if (!riscv_legitimize_address_index_p (x, mode, false))
> +    return NULL;
> +
> +  bool uindex = riscv_legitimize_address_index_p (x, mode, true);
> +
> +  const char *const insn[][4] = {
> +    {
> +      "th.s%srb\t%%z1,%%0",
> +      "th.s%srh\t%%z1,%%0",
> +      "th.s%srw\t%%z1,%%0",
> +      "th.s%srd\t%%z1,%%0"
> +    },
> +    {
> +      "th.l%srbu\t%%0,%%1",
> +      "th.l%srhu\t%%0,%%1",
> +      "th.l%srw\t%%0,%%1",
> +      "th.l%srd\t%%0,%%1"
> +    }
> +  };
> +
> +  snprintf (buf, sizeof (buf), insn[ldr][index], uindex ? "u" : "");
> +
> +  return buf;
> +}
> +
>  /* Emit an instruction of the form (set TARGET SRC).  */
>
>  static rtx
> @@ -1631,6 +1924,42 @@ riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
>    if (riscv_split_symbol (NULL, x, mode, &addr, FALSE))
>      return riscv_force_address (addr, mode);
>
> +  /* Optimize BASE + OFFSET into BASE + INDEX.  */
> +  if (TARGET_XTHEADMEMIDX
> +      && GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))
> +      && INTVAL (XEXP (x, 1)) != 0
> +      && GET_CODE (XEXP (x, 0)) == PLUS)
> +    {
> +      rtx base = XEXP (x, 0);
> +      rtx offset_rtx = XEXP (x, 1);
> +
> +      rtx op0 = XEXP (base, 0);
> +      rtx op1 = XEXP (base, 1);
> +      /* Force any scaling into a temp for CSE.  */
> +      op0 = force_reg (Pmode, op0);
> +      op1 = force_reg (Pmode, op1);
> +
> +      /* Let the pointer register be in op0.  */
> +      if (REG_POINTER (op1))
> +       std::swap (op0, op1);
> +
> +      unsigned regno = REGNO (op0);
> +
> +      /* If the pointer is virtual or frame related, then we know that
> +       virtual register instantiation or register elimination is going
> +       to apply a second constant.  We want the two constants folded
> +       together easily.  Therefore, emit as (OP0 + CONST) + OP1.  */
> +      if ((regno >= FIRST_VIRTUAL_REGISTER
> +          && regno <= LAST_VIRTUAL_POINTER_REGISTER)
> +         || regno == FRAME_POINTER_REGNUM
> +         || regno == ARG_POINTER_REGNUM)
> +       {
> +         base = expand_binop (Pmode, add_optab, op0, offset_rtx,
> +                              NULL_RTX, true, OPTAB_DIRECT);
> +         return gen_rtx_PLUS (Pmode, base, op1);
> +       }
> +    }
> +
>    /* Handle BASE + OFFSET.  */
>    if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))
>        && INTVAL (XEXP (x, 1)) != 0)
> @@ -2408,6 +2737,13 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
>           *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
>           return true;
>         }
> +      /* bit extraction pattern (xtheadmemidx, xtheadfmemidx).  */
> +      if (outer_code == SET
> +         && TARGET_XTHEADMEMIDX)
> +       {
> +         *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
> +         return true;
> +       }
>        gcc_fallthrough ();
>      case SIGN_EXTRACT:
>        if (TARGET_XTHEADBB && outer_code == SET
> @@ -2826,13 +3162,23 @@ riscv_output_move (rtx dest, rtx src)
>           }
>
>        if (src_code == MEM)
> -       switch (width)
> -         {
> -         case 1: return "lbu\t%0,%1";
> -         case 2: return "lhu\t%0,%1";
> -         case 4: return "lw\t%0,%1";
> -         case 8: return "ld\t%0,%1";
> -         }
> +       {
> +         const char *insn = NULL;
> +         insn = riscv_output_move_index (XEXP (src, 0), GET_MODE (src), true);
> +         if (!insn)
> +           insn = riscv_output_move_modify (XEXP (src, 0),
> +                                            GET_MODE (src), true);
> +         if (insn)
> +           return insn;

Could you introduce thead_riscv_output_move (at thead.cc) and then
invoke that at begin of this function?

e.g.

const char *
riscv_output_move (rtx dest, rtx src)
{
  if (insn = thead_riscv_output_move (dest, src))
    return insn;


> +
> +         switch (width)
> +           {
> +           case 1: return "lbu\t%0,%1";
> +           case 2: return "lhu\t%0,%1";
> +           case 4: return "lw\t%0,%1";
> +           case 8: return "ld\t%0,%1";
> +           }
> +       }
>
>        if (src_code == CONST_INT)
>         {
> @@ -2887,13 +3233,24 @@ riscv_output_move (rtx dest, rtx src)
>               }
>         }
>        if (dest_code == MEM)
> -       switch (width)
> -         {
> -         case 1: return "sb\t%z1,%0";
> -         case 2: return "sh\t%z1,%0";
> -         case 4: return "sw\t%z1,%0";
> -         case 8: return "sd\t%z1,%0";
> -         }
> +       {
> +         const char *insn = NULL;
> +         insn = riscv_output_move_index (XEXP (dest, 0),
> +                                         GET_MODE (dest), false);
> +         if (!insn)
> +           insn = riscv_output_move_modify (XEXP (dest, 0),
> +                                            GET_MODE (dest), false);
> +         if (insn)
> +           return insn;

and those logic also extract to thead_riscv_output_move.

> +
> +         switch (width)
> +           {
> +           case 1: return "sb\t%z1,%0";
> +           case 2: return "sh\t%z1,%0";
> +           case 4: return "sw\t%z1,%0";
> +           case 8: return "sd\t%z1,%0";
> +           }
> +       }
>      }
>    if (src_code == REG && FP_REG_P (REGNO (src)))
>      {
> @@ -2911,28 +3268,32 @@ riscv_output_move (rtx dest, rtx src)
>           }
>
>        if (dest_code == MEM)
> -       switch (width)
> -         {
> -         case 2:
> -           return "fsh\t%1,%0";
> -         case 4:
> -           return "fsw\t%1,%0";
> -         case 8:
> -           return "fsd\t%1,%0";
> -         }
> +       {
> +         switch (width)
> +           {
> +           case 2:
> +             return "fsh\t%1,%0";
> +           case 4:
> +             return "fsw\t%1,%0";
> +           case 8:
> +             return "fsd\t%1,%0";
> +           }
> +       }

Separated NFC patch plz.

>      }
>    if (dest_code == REG && FP_REG_P (REGNO (dest)))
>      {
>        if (src_code == MEM)
> -       switch (width)
> -         {
> -         case 2:
> -           return "flh\t%0,%1";
> -         case 4:
> -           return "flw\t%0,%1";
> -         case 8:
> -           return "fld\t%0,%1";
> -         }
> +       {
> +         switch (width)
> +           {
> +           case 2:
> +             return "flh\t%0,%1";
> +           case 4:
> +             return "flw\t%0,%1";
> +           case 8:
> +             return "fld\t%0,%1";
> +           }
> +       }

Separated NFC patch plz.

>      }
>    if (dest_code == REG && GP_REG_P (REGNO (dest)) && src_code == CONST_POLY_INT)
>      {
> @@ -4881,6 +5242,19 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
>        case ADDRESS_SYMBOLIC:
>         output_addr_const (file, riscv_strip_unspec_address (x));
>         return;
> +
> +      case ADDRESS_REG_REG:
> +      case ADDRESS_REG_UREG:
> +       fprintf (file, "%s,%s,%u", reg_names[REGNO (addr.reg)],
> +                                  reg_names[REGNO (addr.offset)],
> +                                  addr.shift);
> +       return;
> +
> +      case ADDRESS_REG_WB:
> +       fprintf (file, "(%s),%ld,%u", reg_names[REGNO (addr.reg)],
> +                                     (long) INTVAL (addr.offset) >> addr.shift,
> +                                     addr.shift);
> +       return;
>        }
>    gcc_unreachable ();
>  }
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index 5bc7f2f467d..199bb30162e 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -535,7 +535,8 @@ enum reg_class
>     factor or added to another register (as well as added to a
>     displacement).  */
>
> -#define INDEX_REG_CLASS NO_REGS
> +#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX) ? \
> +                       GR_REGS : NO_REGS)

Introduce riscv_index_reg_class function

>
>  /* We generally want to put call-clobbered registers ahead of
>     call-saved ones.  (IRA expects this.)  */
> @@ -705,7 +706,10 @@ typedef struct {
>
>  /* Addressing modes, and classification of registers for them.  */
>
> -#define REGNO_OK_FOR_INDEX_P(REGNO) 0
> +#define REGNO_OK_FOR_INDEX_P(REGNO) \
> +  ((TARGET_XTHEADMEMIDX) ? \
> +  riscv_regno_mode_ok_for_base_p (REGNO, VOIDmode, 1) : 0)

Introduce riscv_regno_mode_ok_for_index_p function

> +
>  #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
>    riscv_regno_mode_ok_for_base_p (REGNO, MODE, 1)
>
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 61f175bb62b..df31a1fffff 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -1360,12 +1360,17 @@ (define_expand "zero_extendsidi2"
>    "TARGET_64BIT")
>
>  (define_insn_and_split "*zero_extendsidi2_internal"
> -  [(set (match_operand:DI     0 "register_operand"     "=r,r")
> +  [(set (match_operand:DI     0 "register_operand"     "=r,r,r,r,r,r")
>         (zero_extend:DI
> -           (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
> -  "TARGET_64BIT && !TARGET_ZBA"
> +           (match_operand:SI 1
> +           "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
> +  "TARGET_64BIT && !(TARGET_ZBA || TARGET_ZBB)"
>    "@
>     #
> +   th.lurwu\t%0,%1
> +   th.lrwu\t%0,%1
> +   th.lwuia\t%0,%1
> +   th.lwuib\t%0,%1
>     lwu\t%0,%1"
>    "&& reload_completed
>     && REG_P (operands[1])
> @@ -1375,7 +1380,7 @@ (define_insn_and_split "*zero_extendsidi2_internal"
>     (set (match_dup 0)
>         (lshiftrt:DI (match_dup 0) (const_int 32)))]
>    { operands[1] = gen_lowpart (DImode, operands[1]); }
> -  [(set_attr "move_type" "shift_shift,load")
> +  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
>     (set_attr "mode" "DI")])


Could you use ext attr to control that?

e.g.

(set_attr "ext" "base,XTheadMemIdx,XTheadMemIdx,XTheadMemIdx,XTheadMemIdx,base")



>
>  (define_expand "zero_extendhi<GPR:mode>2"
> @@ -1384,13 +1389,18 @@ (define_expand "zero_extendhi<GPR:mode>2"
>             (match_operand:HI 1 "nonimmediate_operand")))]
>    "")
>
> -(define_insn_and_split "*zero_extendhi<GPR:mode>2"
> -  [(set (match_operand:GPR    0 "register_operand"     "=r,r")
> +(define_insn_and_split "*zero_extendhi<GPR:mode>2_internal"
> +  [(set (match_operand:GPR    0 "register_operand"     "=r,r,r,r,r,r")
>         (zero_extend:GPR
> -           (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
> -  "!TARGET_ZBB"
> +           (match_operand:HI 1
> +           "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
> +  "!(TARGET_ZBA || TARGET_ZBB)"
>    "@
>     #
> +   th.lurhu\t%0,%1
> +   th.lrhu\t%0,%1
> +   th.lhuia\t%0,%1
> +   th.lhuib\t%0,%1
>     lhu\t%0,%1"
>    "&& reload_completed
>     && REG_P (operands[1])
> @@ -1401,20 +1411,25 @@ (define_insn_and_split "*zero_extendhi<GPR:mode>2"
>         (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
>    {
>      operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
> -    operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
> +    operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode) - 16);
>    }
> -  [(set_attr "move_type" "shift_shift,load")
> +  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
>     (set_attr "mode" "<GPR:MODE>")])

Use ext attribute here too.

>
>  (define_insn "zero_extendqi<SUPERQI:mode>2"
> -  [(set (match_operand:SUPERQI 0 "register_operand"    "=r,r")
> +  [(set (match_operand:SUPERQI 0 "register_operand"    "=r,r,r,r,r,r")
>         (zero_extend:SUPERQI
> -           (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
> +           (match_operand:QI 1
> +           "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
>    ""
>    "@
>     andi\t%0,%1,0xff
> +   th.lurbu\t%0,%1
> +   th.lrbu\t%0,%1
> +   th.lbuia\t%0,%1
> +   th.lbuib\t%0,%1
>     lbu\t%0,%1"
> -  [(set_attr "move_type" "andi,load")
> +  [(set_attr "move_type" "andi,load,load,load,load,load")
>     (set_attr "mode" "<SUPERQI:MODE>")])

Ditto.

>  ;;
> @@ -1425,14 +1440,19 @@ (define_insn "zero_extendqi<SUPERQI:mode>2"
>  ;;  ....................
>
>  (define_insn "extendsidi2"
> -  [(set (match_operand:DI     0 "register_operand"     "=r,r")
> +  [(set (match_operand:DI     0 "register_operand"     "=r,r,r,r,r,r")
>         (sign_extend:DI
> -           (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
> +           (match_operand:SI 1
> +           "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
>    "TARGET_64BIT"
>    "@
>     sext.w\t%0,%1
> +   th.lurw\t%0,%1
> +   th.lrw\t%0,%1
> +   th.lwia\t%0,%1
> +   th.lwib\t%0,%1
>     lw\t%0,%1"
> -  [(set_attr "move_type" "move,load")
> +  [(set_attr "move_type" "move,load,load,load,load,load")
>     (set_attr "mode" "DI")])

Ditto.

>  (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
> @@ -1441,12 +1461,17 @@ (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
>    "")
>
>  (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
> -  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
> +  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r,r,r,r,r")
>         (sign_extend:SUPERQI
> -           (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
> +           (match_operand:SHORT 1
> +           "nonimmediate_operand" " r,Qmu,Qmr,Qma,Qmb,m")))]
>    "!TARGET_ZBB"
>    "@
>     #
> +   th.lur<SHORT:size>\t%0,%1
> +   th.lr<SHORT:size>\t%0,%1
> +   th.l<SHORT:size>ia\t%0,%1
> +   th.l<SHORT:size>ib\t%0,%1
>     l<SHORT:size>\t%0,%1"
>    "&& reload_completed
>     && REG_P (operands[1])
> @@ -1459,7 +1484,7 @@ (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
>    operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
>                          - GET_MODE_BITSIZE (<SHORT:MODE>mode));
>  }
> -  [(set_attr "move_type" "shift_shift,load")
> +  [(set_attr "move_type" "shift_shift,load,load,load,load,load")
>     (set_attr "mode" "SI")])

Ditto.

>
>  (define_insn "extendhfsf2"
> @@ -1507,7 +1532,8 @@ (define_insn "*movhf_hardfloat"
>     && (register_operand (operands[0], HFmode)
>         || reg_or_0_operand (operands[1], HFmode))"
>    { return riscv_output_move (operands[0], operands[1]); }
> -  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> +  [(set_attr "move_type"
> +            "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
>     (set_attr "mode" "HF")])

It seems just NFC, don't do that within this patch, plz split that
into a separated NFC patch.

>  (define_insn "*movhf_softfloat"
> @@ -1836,7 +1862,8 @@ (define_insn "*movsf_hardfloat"
>     && (register_operand (operands[0], SFmode)
>         || reg_or_0_operand (operands[1], SFmode))"
>    { return riscv_output_move (operands[0], operands[1]); }
> -  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> +  [(set_attr "move_type"
> +            "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
>     (set_attr "mode" "SF")])
>
>  (define_insn "*movsf_softfloat"

Same here.

> @@ -1860,7 +1887,6 @@ (define_expand "movdf"
>      DONE;
>  })
>
> -

Same here.

>  ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
>  ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
>  (define_insn "*movdf_hardfloat_rv32"
> @@ -1870,7 +1896,8 @@ (define_insn "*movdf_hardfloat_rv32"
>     && (register_operand (operands[0], DFmode)
>         || reg_or_0_operand (operands[1], DFmode))"
>    { return riscv_output_move (operands[0], operands[1]); }
> -  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> +  [(set_attr "move_type"
> +            "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")

Same here.

>     (set_attr "mode" "DF")])
>
>  (define_insn "*movdf_hardfloat_rv64"
> @@ -1880,7 +1907,8 @@ (define_insn "*movdf_hardfloat_rv64"
>     && (register_operand (operands[0], DFmode)
>         || reg_or_0_operand (operands[1], DFmode))"
>    { return riscv_output_move (operands[0], operands[1]); }
> -  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> +  [(set_attr "move_type"
> +            "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")

Same here.

>     (set_attr "mode" "DF")])
>
>  (define_insn "*movdf_softfloat"
> @@ -2187,7 +2215,7 @@ (define_split
>         (and:GPR (match_operand:GPR 1 "register_operand")
>                  (match_operand:GPR 2 "p2m1_shift_operand")))
>     (clobber (match_operand:GPR 3 "register_operand"))]
> -  ""
> +  "!TARGET_XTHEADMEMIDX"
>   [(set (match_dup 3)
>         (ashift:GPR (match_dup 1) (match_dup 2)))
>    (set (match_dup 0)

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

* Re: [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx ISA extension
  2023-02-24  7:53   ` Kito Cheng
@ 2023-02-24  9:46     ` Kito Cheng
  0 siblings, 0 replies; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  9:46 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Jim Wilson, Palmer Dabbelt, Andrew Waterman,
	Philipp Tomsich, Jeff Law, Cooper Qu, Lifang Xia, Yunhai Shang,
	Zhiwei Liu, moiz.hussain

> > +(define_memory_constraint "Qmx"
> > +  "@internal
> > +   An address valid for GPR."
> > +  (and (match_code "mem")
> > +       (match_test "!riscv_legitimize_address_index_p (
> > +                   XEXP (op, 0), GET_MODE (op), false)")))
>
> Check TARGET_XTHEADFMEMIDX, and I don't quite understand why it

I changed my mind, don't check TARGET_XTHEADFMEMIDX here,
check ext in the pattern instead.

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

* Re: [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension
  2023-02-24  6:52   ` Andrew Pinski
@ 2023-02-24  9:54     ` Kito Cheng
  2023-02-24 10:05       ` Christoph Müllner
  0 siblings, 1 reply; 30+ messages in thread
From: Kito Cheng @ 2023-02-24  9:54 UTC (permalink / raw)
  To: Andrew Pinski
  Cc: Christoph Muellner, gcc-patches, Kito Cheng, Jim Wilson,
	Palmer Dabbelt, Andrew Waterman, Philipp Tomsich, Jeff Law,
	Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu

My impression is that md patterns will use first-match patterns? so
the zba will get higher priority than xtheadba if both patterns are
matched?

On Fri, Feb 24, 2023 at 2:52 PM Andrew Pinski via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Thu, Feb 23, 2023 at 9:55 PM Christoph Muellner
> <christoph.muellner@vrull.eu> wrote:
> >
> > From: Christoph Müllner <christoph.muellner@vrull.eu>
> >
> > This patch adds support for the XTheadBa ISA extension.
> > The new INSN pattern is defined in a new file to separate
> > this vendor extension from the standard extensions.
>
> How does this interact with doing -march=rv32gc_xtheadba_zba ?
> Seems like it might be better handle that case correctly. I suspect
> these all XThreadB* extensions have a similar problem too.
>
> Thanks,
> Andrew Pinski
>
> >
> > gcc/ChangeLog:
> >
> >         * config/riscv/riscv.md: Include thead.md
> >         * config/riscv/thead.md: New file.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.target/riscv/xtheadba-addsl.c: New test.
> >
> > Changes in v3:
> > - Fix operand order for th.addsl.
> >
> > Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > ---
> >  gcc/config/riscv/riscv.md                     |  1 +
> >  gcc/config/riscv/thead.md                     | 31 +++++++++++
> >  .../gcc.target/riscv/xtheadba-addsl.c         | 55 +++++++++++++++++++
> >  3 files changed, 87 insertions(+)
> >  create mode 100644 gcc/config/riscv/thead.md
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> >
> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > index 05924e9bbf1..d6c2265e9d4 100644
> > --- a/gcc/config/riscv/riscv.md
> > +++ b/gcc/config/riscv/riscv.md
> > @@ -3093,4 +3093,5 @@ (define_insn "riscv_prefetchi_<mode>"
> >  (include "pic.md")
> >  (include "generic.md")
> >  (include "sifive-7.md")
> > +(include "thead.md")
> >  (include "vector.md")
> > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > new file mode 100644
> > index 00000000000..158e9124c3a
> > --- /dev/null
> > +++ b/gcc/config/riscv/thead.md
> > @@ -0,0 +1,31 @@
> > +;; Machine description for T-Head vendor extensions
> > +;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
> > +
> > +;; This file is part of GCC.
> > +
> > +;; GCC is free software; you can redistribute it and/or modify
> > +;; it under the terms of the GNU General Public License as published by
> > +;; the Free Software Foundation; either version 3, or (at your option)
> > +;; any later version.
> > +
> > +;; GCC is distributed in the hope that it will be useful,
> > +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +;; GNU General Public License for more details.
> > +
> > +;; You should have received a copy of the GNU General Public License
> > +;; along with GCC; see the file COPYING3.  If not see
> > +;; <http://www.gnu.org/licenses/>.
> > +
> > +;; XTheadBa
> > +
> > +(define_insn "*th_addsl"
> > +  [(set (match_operand:X 0 "register_operand" "=r")
> > +       (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
> > +                         (match_operand:QI 2 "immediate_operand" "I"))
> > +               (match_operand:X 3 "register_operand" "r")))]
> > +  "TARGET_XTHEADBA
> > +   && (INTVAL (operands[2]) >= 0) && (INTVAL (operands[2]) <= 3)"
> > +  "th.addsl\t%0,%3,%1,%2"
> > +  [(set_attr "type" "bitmanip")
> > +   (set_attr "mode" "<X:MODE>")])
> > diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > new file mode 100644
> > index 00000000000..5004735a246
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > @@ -0,0 +1,55 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
> > +/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
> > +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
> > +
> > +long
> > +test_1 (long a, long b)
> > +{
> > +  /* th.addsl aX, aX, 1  */
> > +  return a + (b << 1);
> > +}
> > +
> > +int
> > +foos (short *x, int n)
> > +{
> > +  /* th.addsl aX, aX, 1  */
> > +  return x[n];
> > +}
> > +
> > +long
> > +test_2 (long a, long b)
> > +{
> > +  /* th.addsl aX, aX, 2  */
> > +  return a + (b << 2);
> > +}
> > +
> > +int
> > +fooi (int *x, int n)
> > +{
> > +  /* th.addsl aX, aX, 2  */
> > +  return x[n];
> > +}
> > +
> > +long
> > +test_3 (long a, long b)
> > +{
> > +  /* th.addsl aX, aX, 3  */
> > +  return a + (b << 3);
> > +}
> > +
> > +long
> > +fool (long *x, int n)
> > +{
> > +  /* th.addsl aX, aX, 2 (rv32)  */
> > +  /* th.addsl aX, aX, 3 (rv64)  */
> > +  return x[n];
> > +}
> > +
> > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,1" 2 } } */
> > +
> > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 3 { target { rv32 } } } } */
> > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 2 { target { rv64 } } } } */
> > +
> > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 1 { target { rv32 } } } } */
> > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 2 { target { rv64 } } } } */
> > --
> > 2.39.2
> >

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

* Re: [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension
  2023-02-24  9:54     ` Kito Cheng
@ 2023-02-24 10:05       ` Christoph Müllner
  2023-02-24 10:47         ` Christoph Müllner
  0 siblings, 1 reply; 30+ messages in thread
From: Christoph Müllner @ 2023-02-24 10:05 UTC (permalink / raw)
  To: Kito Cheng
  Cc: Andrew Pinski, gcc-patches, Kito Cheng, Jim Wilson,
	Palmer Dabbelt, Andrew Waterman, Philipp Tomsich, Jeff Law,
	Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu

On Fri, Feb 24, 2023 at 10:54 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> My impression is that md patterns will use first-match patterns? so
> the zba will get higher priority than xtheadba if both patterns are
> matched?

Yes, I was just about to write this.

/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zba_xtheadba -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c

The resulting xtheadba-addsl.s file has:
        .attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0_zba1p0_xtheadba1p0"
[...]
        sh1add  a0,a1,a0

So the standard extension will be preferred over the custom extension.


>
> On Fri, Feb 24, 2023 at 2:52 PM Andrew Pinski via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > On Thu, Feb 23, 2023 at 9:55 PM Christoph Muellner
> > <christoph.muellner@vrull.eu> wrote:
> > >
> > > From: Christoph Müllner <christoph.muellner@vrull.eu>
> > >
> > > This patch adds support for the XTheadBa ISA extension.
> > > The new INSN pattern is defined in a new file to separate
> > > this vendor extension from the standard extensions.
> >
> > How does this interact with doing -march=rv32gc_xtheadba_zba ?
> > Seems like it might be better handle that case correctly. I suspect
> > these all XThreadB* extensions have a similar problem too.
> >
> > Thanks,
> > Andrew Pinski
> >
> > >
> > > gcc/ChangeLog:
> > >
> > >         * config/riscv/riscv.md: Include thead.md
> > >         * config/riscv/thead.md: New file.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >         * gcc.target/riscv/xtheadba-addsl.c: New test.
> > >
> > > Changes in v3:
> > > - Fix operand order for th.addsl.
> > >
> > > Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > > ---
> > >  gcc/config/riscv/riscv.md                     |  1 +
> > >  gcc/config/riscv/thead.md                     | 31 +++++++++++
> > >  .../gcc.target/riscv/xtheadba-addsl.c         | 55 +++++++++++++++++++
> > >  3 files changed, 87 insertions(+)
> > >  create mode 100644 gcc/config/riscv/thead.md
> > >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > >
> > > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > > index 05924e9bbf1..d6c2265e9d4 100644
> > > --- a/gcc/config/riscv/riscv.md
> > > +++ b/gcc/config/riscv/riscv.md
> > > @@ -3093,4 +3093,5 @@ (define_insn "riscv_prefetchi_<mode>"
> > >  (include "pic.md")
> > >  (include "generic.md")
> > >  (include "sifive-7.md")
> > > +(include "thead.md")
> > >  (include "vector.md")
> > > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > > new file mode 100644
> > > index 00000000000..158e9124c3a
> > > --- /dev/null
> > > +++ b/gcc/config/riscv/thead.md
> > > @@ -0,0 +1,31 @@
> > > +;; Machine description for T-Head vendor extensions
> > > +;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
> > > +
> > > +;; This file is part of GCC.
> > > +
> > > +;; GCC is free software; you can redistribute it and/or modify
> > > +;; it under the terms of the GNU General Public License as published by
> > > +;; the Free Software Foundation; either version 3, or (at your option)
> > > +;; any later version.
> > > +
> > > +;; GCC is distributed in the hope that it will be useful,
> > > +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > > +;; GNU General Public License for more details.
> > > +
> > > +;; You should have received a copy of the GNU General Public License
> > > +;; along with GCC; see the file COPYING3.  If not see
> > > +;; <http://www.gnu.org/licenses/>.
> > > +
> > > +;; XTheadBa
> > > +
> > > +(define_insn "*th_addsl"
> > > +  [(set (match_operand:X 0 "register_operand" "=r")
> > > +       (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
> > > +                         (match_operand:QI 2 "immediate_operand" "I"))
> > > +               (match_operand:X 3 "register_operand" "r")))]
> > > +  "TARGET_XTHEADBA
> > > +   && (INTVAL (operands[2]) >= 0) && (INTVAL (operands[2]) <= 3)"
> > > +  "th.addsl\t%0,%3,%1,%2"
> > > +  [(set_attr "type" "bitmanip")
> > > +   (set_attr "mode" "<X:MODE>")])
> > > diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > > new file mode 100644
> > > index 00000000000..5004735a246
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > > @@ -0,0 +1,55 @@
> > > +/* { dg-do compile } */
> > > +/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
> > > +/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
> > > +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
> > > +
> > > +long
> > > +test_1 (long a, long b)
> > > +{
> > > +  /* th.addsl aX, aX, 1  */
> > > +  return a + (b << 1);
> > > +}
> > > +
> > > +int
> > > +foos (short *x, int n)
> > > +{
> > > +  /* th.addsl aX, aX, 1  */
> > > +  return x[n];
> > > +}
> > > +
> > > +long
> > > +test_2 (long a, long b)
> > > +{
> > > +  /* th.addsl aX, aX, 2  */
> > > +  return a + (b << 2);
> > > +}
> > > +
> > > +int
> > > +fooi (int *x, int n)
> > > +{
> > > +  /* th.addsl aX, aX, 2  */
> > > +  return x[n];
> > > +}
> > > +
> > > +long
> > > +test_3 (long a, long b)
> > > +{
> > > +  /* th.addsl aX, aX, 3  */
> > > +  return a + (b << 3);
> > > +}
> > > +
> > > +long
> > > +fool (long *x, int n)
> > > +{
> > > +  /* th.addsl aX, aX, 2 (rv32)  */
> > > +  /* th.addsl aX, aX, 3 (rv64)  */
> > > +  return x[n];
> > > +}
> > > +
> > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,1" 2 } } */
> > > +
> > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 3 { target { rv32 } } } } */
> > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 2 { target { rv64 } } } } */
> > > +
> > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 1 { target { rv32 } } } } */
> > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 2 { target { rv64 } } } } */
> > > --
> > > 2.39.2
> > >

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-24  7:36   ` Kito Cheng
@ 2023-02-24 10:21     ` Christoph Müllner
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-02-24 10:21 UTC (permalink / raw)
  To: Kito Cheng
  Cc: gcc-patches, Jim Wilson, Palmer Dabbelt, Andrew Waterman,
	Philipp Tomsich, Jeff Law, Cooper Qu, Lifang Xia, Yunhai Shang,
	Zhiwei Liu

On Fri, Feb 24, 2023 at 8:37 AM Kito Cheng <kito.cheng@sifive.com> wrote:
>
> > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > index 158e9124c3a..2c684885850 100644
> > --- a/gcc/config/riscv/thead.md
> > +++ b/gcc/config/riscv/thead.md
> > @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
> >    "th.addsl\t%0,%3,%1,%2"
> >    [(set_attr "type" "bitmanip")
> >     (set_attr "mode" "<X:MODE>")])
> > +
> > +;; XTheadBs
> > +
> > +(define_insn "*th_tst"
> > +  [(set (match_operand:X 0 "register_operand" "=r")
> > +       (zero_extract:X (match_operand:X 1 "register_operand" "r")
> > +                       (const_int 1)
> > +                       (match_operand 2 "immediate_operand" "i")))]
> > +  "TARGET_XTHEADBS"
>
> Add range check like *bexti pattern?
>
> TARGET_XTHEADBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)

Ok.

Thanks,
Christoph

>
> > +  "th.tst\t%0,%1,%2"
> > +  [(set_attr "type" "bitmanip")])

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

* Re: [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension
  2023-02-24 10:05       ` Christoph Müllner
@ 2023-02-24 10:47         ` Christoph Müllner
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-02-24 10:47 UTC (permalink / raw)
  To: Kito Cheng
  Cc: Andrew Pinski, gcc-patches, Kito Cheng, Jim Wilson,
	Palmer Dabbelt, Andrew Waterman, Philipp Tomsich, Jeff Law,
	Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu

On Fri, Feb 24, 2023 at 11:05 AM Christoph Müllner
<christoph.muellner@vrull.eu> wrote:
>
> On Fri, Feb 24, 2023 at 10:54 AM Kito Cheng <kito.cheng@gmail.com> wrote:
> >
> > My impression is that md patterns will use first-match patterns? so
> > the zba will get higher priority than xtheadba if both patterns are
> > matched?
>
> Yes, I was just about to write this.
>
> /opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
> -march=rv64gc_zba_xtheadba -mtune=thead-c906 -S
> ./gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
>
> The resulting xtheadba-addsl.s file has:
>         .attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0_zba1p0_xtheadba1p0"
> [...]
>         sh1add  a0,a1,a0
>
> So the standard extension will be preferred over the custom extension.

I tested now with all of them (RV32 and RV64):

/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zba_xtheadba -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
/opt/riscv-thead/bin/riscv64-unknown-linux-gnu-gcc -O2
-march=rv64gc_zbb_xtheadbs -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c

/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zba_xtheadba -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbb -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
/opt/riscv-thead32/bin/riscv32-unknown-linux-gnu-gcc -O2
-march=rv32gc_zbb_xtheadbs -mtune=thead-c906 -S
./gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c

All behave ok (also when dropping the xtheadb* from the -march).

Is it ok to leave this as is?

Thanks,
Christoph

>
>
> >
> > On Fri, Feb 24, 2023 at 2:52 PM Andrew Pinski via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> > >
> > > On Thu, Feb 23, 2023 at 9:55 PM Christoph Muellner
> > > <christoph.muellner@vrull.eu> wrote:
> > > >
> > > > From: Christoph Müllner <christoph.muellner@vrull.eu>
> > > >
> > > > This patch adds support for the XTheadBa ISA extension.
> > > > The new INSN pattern is defined in a new file to separate
> > > > this vendor extension from the standard extensions.
> > >
> > > How does this interact with doing -march=rv32gc_xtheadba_zba ?
> > > Seems like it might be better handle that case correctly. I suspect
> > > these all XThreadB* extensions have a similar problem too.
> > >
> > > Thanks,
> > > Andrew Pinski
> > >
> > > >
> > > > gcc/ChangeLog:
> > > >
> > > >         * config/riscv/riscv.md: Include thead.md
> > > >         * config/riscv/thead.md: New file.
> > > >
> > > > gcc/testsuite/ChangeLog:
> > > >
> > > >         * gcc.target/riscv/xtheadba-addsl.c: New test.
> > > >
> > > > Changes in v3:
> > > > - Fix operand order for th.addsl.
> > > >
> > > > Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > > > ---
> > > >  gcc/config/riscv/riscv.md                     |  1 +
> > > >  gcc/config/riscv/thead.md                     | 31 +++++++++++
> > > >  .../gcc.target/riscv/xtheadba-addsl.c         | 55 +++++++++++++++++++
> > > >  3 files changed, 87 insertions(+)
> > > >  create mode 100644 gcc/config/riscv/thead.md
> > > >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > > >
> > > > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > > > index 05924e9bbf1..d6c2265e9d4 100644
> > > > --- a/gcc/config/riscv/riscv.md
> > > > +++ b/gcc/config/riscv/riscv.md
> > > > @@ -3093,4 +3093,5 @@ (define_insn "riscv_prefetchi_<mode>"
> > > >  (include "pic.md")
> > > >  (include "generic.md")
> > > >  (include "sifive-7.md")
> > > > +(include "thead.md")
> > > >  (include "vector.md")
> > > > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > > > new file mode 100644
> > > > index 00000000000..158e9124c3a
> > > > --- /dev/null
> > > > +++ b/gcc/config/riscv/thead.md
> > > > @@ -0,0 +1,31 @@
> > > > +;; Machine description for T-Head vendor extensions
> > > > +;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
> > > > +
> > > > +;; This file is part of GCC.
> > > > +
> > > > +;; GCC is free software; you can redistribute it and/or modify
> > > > +;; it under the terms of the GNU General Public License as published by
> > > > +;; the Free Software Foundation; either version 3, or (at your option)
> > > > +;; any later version.
> > > > +
> > > > +;; GCC is distributed in the hope that it will be useful,
> > > > +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > > +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > > > +;; GNU General Public License for more details.
> > > > +
> > > > +;; You should have received a copy of the GNU General Public License
> > > > +;; along with GCC; see the file COPYING3.  If not see
> > > > +;; <http://www.gnu.org/licenses/>.
> > > > +
> > > > +;; XTheadBa
> > > > +
> > > > +(define_insn "*th_addsl"
> > > > +  [(set (match_operand:X 0 "register_operand" "=r")
> > > > +       (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
> > > > +                         (match_operand:QI 2 "immediate_operand" "I"))
> > > > +               (match_operand:X 3 "register_operand" "r")))]
> > > > +  "TARGET_XTHEADBA
> > > > +   && (INTVAL (operands[2]) >= 0) && (INTVAL (operands[2]) <= 3)"
> > > > +  "th.addsl\t%0,%3,%1,%2"
> > > > +  [(set_attr "type" "bitmanip")
> > > > +   (set_attr "mode" "<X:MODE>")])
> > > > diff --git a/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > > > new file mode 100644
> > > > index 00000000000..5004735a246
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> > > > @@ -0,0 +1,55 @@
> > > > +/* { dg-do compile } */
> > > > +/* { dg-options "-march=rv32gc_xtheadba" { target { rv32 } } } */
> > > > +/* { dg-options "-march=rv64gc_xtheadba" { target { rv64 } } } */
> > > > +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
> > > > +
> > > > +long
> > > > +test_1 (long a, long b)
> > > > +{
> > > > +  /* th.addsl aX, aX, 1  */
> > > > +  return a + (b << 1);
> > > > +}
> > > > +
> > > > +int
> > > > +foos (short *x, int n)
> > > > +{
> > > > +  /* th.addsl aX, aX, 1  */
> > > > +  return x[n];
> > > > +}
> > > > +
> > > > +long
> > > > +test_2 (long a, long b)
> > > > +{
> > > > +  /* th.addsl aX, aX, 2  */
> > > > +  return a + (b << 2);
> > > > +}
> > > > +
> > > > +int
> > > > +fooi (int *x, int n)
> > > > +{
> > > > +  /* th.addsl aX, aX, 2  */
> > > > +  return x[n];
> > > > +}
> > > > +
> > > > +long
> > > > +test_3 (long a, long b)
> > > > +{
> > > > +  /* th.addsl aX, aX, 3  */
> > > > +  return a + (b << 3);
> > > > +}
> > > > +
> > > > +long
> > > > +fool (long *x, int n)
> > > > +{
> > > > +  /* th.addsl aX, aX, 2 (rv32)  */
> > > > +  /* th.addsl aX, aX, 3 (rv64)  */
> > > > +  return x[n];
> > > > +}
> > > > +
> > > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,1" 2 } } */
> > > > +
> > > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 3 { target { rv32 } } } } */
> > > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,2" 2 { target { rv64 } } } } */
> > > > +
> > > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 1 { target { rv32 } } } } */
> > > > +/* { dg-final { scan-assembler-times "th.addsl\[ \t\]*a\[0-9\]+,a\[0-9\]+,a\[0-9\]+,3" 2 { target { rv64 } } } } */
> > > > --
> > > > 2.39.2
> > > >

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

* Re: [PATCH v3 00/11] RISC-V: Add XThead* extension support
  2023-02-24  8:08 ` [PATCH v3 00/11] RISC-V: Add XThead* extension support Kito Cheng
@ 2023-02-24 11:27   ` Christoph Müllner
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-02-24 11:27 UTC (permalink / raw)
  To: Kito Cheng
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Fri, Feb 24, 2023 at 9:09 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Hi Christoph:
>
> OK for trunk for the 1~8, feel free to commit 1~8 after you address
> those minor comments, and could you also prepare release notes for
> those extensions?

I addressed the comment regarding XTheadBs.
But I have not done anything regarding XTheadB* and Zb*.

Release notes patch can be found here:
  https://gcc.gnu.org/pipermail/gcc-patches/2023-February/612763.html

> And 9~11 needs to take a few more rounds of review and test.

I've seen the comments regarding patch 10 and 11.
We will try to clean this up asap.

In the patch for XTheadMemPair there was this nasty typo in one of the tests,
is there anything else that is needed?
I believe that patch should be in a better shape than the last two patches
and it is much less invasive.
Further similar code can be found in other backends.

Thanks,
Christoph

>
>
>
>
> On Fri, Feb 24, 2023 at 1:52 PM Christoph Muellner
> <christoph.muellner@vrull.eu> wrote:
> >
> > From: Christoph Müllner <christoph.muellner@vrull.eu>
> >
> > This series introduces support for the T-Head specific RISC-V ISA extensions
> > which are available e.g. on the T-Head XuanTie C906.
> >
> > The ISA spec can be found here:
> >   https://github.com/T-head-Semi/thead-extension-spec
> >
> > This series adds support for the following XThead* extensions:
> > * XTheadBa
> > * XTheadBb
> > * XTheadBs
> > * XTheadCmo
> > * XTheadCondMov
> > * XTheadFMemIdx
> > * XTheadFmv
> > * XTheadInt
> > * XTheadMac
> > * XTheadMemIdx
> > * XTheadMemPair
> > * XTheadSync
> >
> > All extensions are properly integrated and the included tests
> > demonstrate the improvements of the generated code.
> >
> > The series also introduces support for "-mcpu=thead-c906", which also
> > enables all available XThead* ISA extensions of the T-Head C906.
> >
> > All patches have been tested and don't introduce regressions for RV32 or RV64.
> > The patches have also been tested with SPEC CPU2017 on QEMU and real HW
> > (D1 board).
> >
> > Support patches for these extensions for Binutils, QEMU, and LLVM have
> > already been merged in the corresponding upstream projects.
> >
> > Changes in v3:
> > - Bugfix in XTheadBa
> > - Rewrite of XTheadMemPair
> > - Inclusion of XTheadMemIdx and XTheadFMemIdx
> >
> > Christoph Müllner (9):
> >   riscv: Add basic XThead* vendor extension support
> >   riscv: riscv-cores.def: Add T-Head XuanTie C906
> >   riscv: thead: Add support for the XTheadBa ISA extension
> >   riscv: thead: Add support for the XTheadBs ISA extension
> >   riscv: thead: Add support for the XTheadBb ISA extension
> >   riscv: thead: Add support for the XTheadCondMov ISA extensions
> >   riscv: thead: Add support for the XTheadMac ISA extension
> >   riscv: thead: Add support for the XTheadFmv ISA extension
> >   riscv: thead: Add support for the XTheadMemPair ISA extension
> >
> > moiz.hussain (2):
> >   riscv: thead: Add support for the XTheadMemIdx ISA extension
> >   riscv: thead: Add support for the XTheadFMemIdx ISA extension
> >
> >  gcc/common/config/riscv/riscv-common.cc       |   26 +
> >  gcc/config/riscv/bitmanip.md                  |   52 +-
> >  gcc/config/riscv/constraints.md               |   43 +
> >  gcc/config/riscv/iterators.md                 |    4 +
> >  gcc/config/riscv/peephole.md                  |   56 +
> >  gcc/config/riscv/riscv-cores.def              |    4 +
> >  gcc/config/riscv/riscv-opts.h                 |   29 +
> >  gcc/config/riscv/riscv-protos.h               |   28 +-
> >  gcc/config/riscv/riscv.cc                     | 1090 +++++++++++++++--
> >  gcc/config/riscv/riscv.h                      |    8 +-
> >  gcc/config/riscv/riscv.md                     |  169 ++-
> >  gcc/config/riscv/riscv.opt                    |    3 +
> >  gcc/config/riscv/thead.md                     |  351 ++++++
> >  .../gcc.target/riscv/mcpu-thead-c906.c        |   28 +
> >  .../gcc.target/riscv/xtheadba-addsl.c         |   55 +
> >  gcc/testsuite/gcc.target/riscv/xtheadba.c     |   14 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c |   20 +
> >  .../gcc.target/riscv/xtheadbb-extu-2.c        |   22 +
> >  .../gcc.target/riscv/xtheadbb-extu.c          |   22 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c |   18 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c |   45 +
> >  .../gcc.target/riscv/xtheadbb-srri.c          |   21 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbb.c     |   14 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c |   13 +
> >  gcc/testsuite/gcc.target/riscv/xtheadbs.c     |   14 +
> >  gcc/testsuite/gcc.target/riscv/xtheadcmo.c    |   14 +
> >  .../riscv/xtheadcondmov-mveqz-imm-eqz.c       |   38 +
> >  .../riscv/xtheadcondmov-mveqz-imm-not.c       |   38 +
> >  .../riscv/xtheadcondmov-mveqz-reg-eqz.c       |   38 +
> >  .../riscv/xtheadcondmov-mveqz-reg-not.c       |   38 +
> >  .../riscv/xtheadcondmov-mvnez-imm-cond.c      |   38 +
> >  .../riscv/xtheadcondmov-mvnez-imm-nez.c       |   38 +
> >  .../riscv/xtheadcondmov-mvnez-reg-cond.c      |   38 +
> >  .../riscv/xtheadcondmov-mvnez-reg-nez.c       |   38 +
> >  .../gcc.target/riscv/xtheadcondmov.c          |   14 +
> >  .../riscv/xtheadfmemidx-fldr-fstr.c           |   58 +
> >  .../gcc.target/riscv/xtheadfmemidx.c          |   14 +
> >  .../gcc.target/riscv/xtheadfmv-fmv.c          |   24 +
> >  gcc/testsuite/gcc.target/riscv/xtheadfmv.c    |   14 +
> >  gcc/testsuite/gcc.target/riscv/xtheadint.c    |   14 +
> >  .../gcc.target/riscv/xtheadmac-mula-muls.c    |   43 +
> >  gcc/testsuite/gcc.target/riscv/xtheadmac.c    |   14 +
> >  .../gcc.target/riscv/xtheadmemidx-ldi-sdi.c   |   72 ++
> >  .../riscv/xtheadmemidx-ldr-str-32.c           |   23 +
> >  .../riscv/xtheadmemidx-ldr-str-64.c           |   53 +
> >  .../gcc.target/riscv/xtheadmemidx-macros.h    |  110 ++
> >  gcc/testsuite/gcc.target/riscv/xtheadmemidx.c |   14 +
> >  .../gcc.target/riscv/xtheadmempair-1.c        |   98 ++
> >  .../gcc.target/riscv/xtheadmempair-2.c        |   84 ++
> >  .../gcc.target/riscv/xtheadmempair-3.c        |   29 +
> >  .../gcc.target/riscv/xtheadmempair.c          |   13 +
> >  gcc/testsuite/gcc.target/riscv/xtheadsync.c   |   14 +
> >  52 files changed, 3048 insertions(+), 124 deletions(-)
> >  create mode 100644 gcc/config/riscv/thead.md
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/mcpu-thead-c906.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba-addsl.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadba.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ext.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu-2.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-extu.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-ff1.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-rev.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb-srri.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbb.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs-tst.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadbs.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcmo.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-eqz.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-imm-not.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-eqz.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mveqz-reg-not.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-cond.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-imm-nez.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-cond.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov-mvnez-reg-nez.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadcondmov.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx-fldr-fstr.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmemidx.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadfmv.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadint.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac-mula-muls.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmac.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldi-sdi.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-32.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-ldr-str-64.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx-macros.h
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmemidx.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-1.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-2.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair-3.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadmempair.c
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/xtheadsync.c
> >
> > --
> > 2.39.2
> >

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

* Re: [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair ISA extension
  2023-02-24  5:51 ` [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair " Christoph Muellner
  2023-02-24  9:00   ` Kito Cheng
@ 2023-02-24 15:48   ` Kito Cheng
  1 sibling, 0 replies; 30+ messages in thread
From: Kito Cheng @ 2023-02-24 15:48 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

Could you move those thead_* and th_* functions into thead.cc

> +static bool
> +thead_mempair_operand_p (rtx mem, machine_mode mode)
> +{
> +  if (!MEM_SIZE_KNOWN_P (mem))
> +    return false;
> +
> +  /* Only DI or SI mempair instructions exist.  */

add gcc_assert (mode == SImode || mode == DImode); here

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-24  5:51 ` [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs " Christoph Muellner
  2023-02-24  7:36   ` Kito Cheng
@ 2023-02-25 23:42   ` Hans-Peter Nilsson
  2023-02-28 17:49     ` Christoph Müllner
  1 sibling, 1 reply; 30+ messages in thread
From: Hans-Peter Nilsson @ 2023-02-25 23:42 UTC (permalink / raw)
  To: Christoph Muellner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Fri, 24 Feb 2023, Christoph Muellner wrote:
> diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> index 158e9124c3a..2c684885850 100644
> --- a/gcc/config/riscv/thead.md
> +++ b/gcc/config/riscv/thead.md
> @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
>    "th.addsl\t%0,%3,%1,%2"
>    [(set_attr "type" "bitmanip")
>     (set_attr "mode" "<X:MODE>")])
> +
> +;; XTheadBs
> +
> +(define_insn "*th_tst"
> +  [(set (match_operand:X 0 "register_operand" "=r")
> +	(zero_extract:X (match_operand:X 1 "register_operand" "r")
> +			(const_int 1)
> +			(match_operand 2 "immediate_operand" "i")))]

(Here and same elsewhere.)

You're unlikely to get other constant operands in that pattern, 
but FWIW, the actual matching pair for just CONST_INT is 
"const_int_operand" for the predicate and "n" for the 
constraint.  Using the right predicate and constraint will also 
help the generated part of recog be a few nanoseconds faster. ;)

brgds, H-P

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-25 23:42   ` Hans-Peter Nilsson
@ 2023-02-28 17:49     ` Christoph Müllner
  2023-03-01  0:19       ` Hans-Peter Nilsson
  0 siblings, 1 reply; 30+ messages in thread
From: Christoph Müllner @ 2023-02-28 17:49 UTC (permalink / raw)
  To: Hans-Peter Nilsson
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Sun, Feb 26, 2023 at 12:42 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
> On Fri, 24 Feb 2023, Christoph Muellner wrote:
> > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > index 158e9124c3a..2c684885850 100644
> > --- a/gcc/config/riscv/thead.md
> > +++ b/gcc/config/riscv/thead.md
> > @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
> >    "th.addsl\t%0,%3,%1,%2"
> >    [(set_attr "type" "bitmanip")
> >     (set_attr "mode" "<X:MODE>")])
> > +
> > +;; XTheadBs
> > +
> > +(define_insn "*th_tst"
> > +  [(set (match_operand:X 0 "register_operand" "=r")
> > +     (zero_extract:X (match_operand:X 1 "register_operand" "r")
> > +                     (const_int 1)
> > +                     (match_operand 2 "immediate_operand" "i")))]
>
> (Here and same elsewhere.)
>
> You're unlikely to get other constant operands in that pattern,
> but FWIW, the actual matching pair for just CONST_INT is
> "const_int_operand" for the predicate and "n" for the
> constraint.  Using the right predicate and constraint will also
> help the generated part of recog be a few nanoseconds faster. ;)

Thank you for that comment!
I think what you mean would look like this:

(define_insn "*th_tst"
  [(set (match_operand:X 0 "register_operand" "=r")
    (zero_extract:X (match_operand:X 1 "register_operand" "r")
            (match_operand 3 "const_int_operand" "n")
            (match_operand 2 "immediate_operand" "i")))]
  "TARGET_XTHEADBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)
   && UINTVAL (operands[3]) == 1"
  "th.tst\t%0,%1,%2"
  [(set_attr "type" "bitmanip")])

So while we have more generic form in the pattern, the condition needs
to check that the operand is equal to 1.

I can change this in the patch (I don't have strong opinions about
this and I do care about the nanosecond).
However, I think this goes beyond this patchset.
Because a single git grep shows many examples of "const_int " matches
in GCC's backends.
Examples can be found in gcc/config/riscv/bitmanip.md,
gcc/config/aarch64/aarch64.md,...
So it feels like changing the patch to use const_int_operand would go
against common practice.

@Kito: Any preferences about this?

Thanks,
Christoph

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-02-28 17:49     ` Christoph Müllner
@ 2023-03-01  0:19       ` Hans-Peter Nilsson
  2023-03-01  7:49         ` Christoph Müllner
  0 siblings, 1 reply; 30+ messages in thread
From: Hans-Peter Nilsson @ 2023-03-01  0:19 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu



On Tue, 28 Feb 2023, Christoph Müllner wrote:

> On Sun, Feb 26, 2023 at 12:42 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> >
> > On Fri, 24 Feb 2023, Christoph Muellner wrote:
> > > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > > index 158e9124c3a..2c684885850 100644
> > > --- a/gcc/config/riscv/thead.md
> > > +++ b/gcc/config/riscv/thead.md
> > > @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
> > >    "th.addsl\t%0,%3,%1,%2"
> > >    [(set_attr "type" "bitmanip")
> > >     (set_attr "mode" "<X:MODE>")])
> > > +
> > > +;; XTheadBs
> > > +
> > > +(define_insn "*th_tst"
> > > +  [(set (match_operand:X 0 "register_operand" "=r")
> > > +     (zero_extract:X (match_operand:X 1 "register_operand" "r")
> > > +                     (const_int 1)
> > > +                     (match_operand 2 "immediate_operand" "i")))]
> >
> > (Here and same elsewhere.)
> >
> > You're unlikely to get other constant operands in that pattern,
> > but FWIW, the actual matching pair for just CONST_INT is
> > "const_int_operand" for the predicate and "n" for the
> > constraint.  Using the right predicate and constraint will also
> > help the generated part of recog be a few nanoseconds faster. ;)
> 
> Thank you for that comment!
> I think what you mean would look like this:
> 
> (define_insn "*th_tst"
>   [(set (match_operand:X 0 "register_operand" "=r")
>     (zero_extract:X (match_operand:X 1 "register_operand" "r")
>             (match_operand 3 "const_int_operand" "n")
>             (match_operand 2 "immediate_operand" "i")))]

No; misunderstanding.  Keep the (const_int 1) but replace
(match_operand 2 "immediate_operand" "i") with
(match_operand 2 "const_int_operand" "n")

brgds, H-P

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

* Re: [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs ISA extension
  2023-03-01  0:19       ` Hans-Peter Nilsson
@ 2023-03-01  7:49         ` Christoph Müllner
  0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-03-01  7:49 UTC (permalink / raw)
  To: Hans-Peter Nilsson
  Cc: gcc-patches, Kito Cheng, Jim Wilson, Palmer Dabbelt,
	Andrew Waterman, Philipp Tomsich, Jeff Law, Cooper Qu,
	Lifang Xia, Yunhai Shang, Zhiwei Liu

On Wed, Mar 1, 2023 at 1:19 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
>
>
>
> On Tue, 28 Feb 2023, Christoph Müllner wrote:
>
> > On Sun, Feb 26, 2023 at 12:42 AM Hans-Peter Nilsson <hp@bitrange.com> wrote:
> > >
> > > On Fri, 24 Feb 2023, Christoph Muellner wrote:
> > > > diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
> > > > index 158e9124c3a..2c684885850 100644
> > > > --- a/gcc/config/riscv/thead.md
> > > > +++ b/gcc/config/riscv/thead.md
> > > > @@ -29,3 +29,14 @@ (define_insn "*th_addsl"
> > > >    "th.addsl\t%0,%3,%1,%2"
> > > >    [(set_attr "type" "bitmanip")
> > > >     (set_attr "mode" "<X:MODE>")])
> > > > +
> > > > +;; XTheadBs
> > > > +
> > > > +(define_insn "*th_tst"
> > > > +  [(set (match_operand:X 0 "register_operand" "=r")
> > > > +     (zero_extract:X (match_operand:X 1 "register_operand" "r")
> > > > +                     (const_int 1)
> > > > +                     (match_operand 2 "immediate_operand" "i")))]
> > >
> > > (Here and same elsewhere.)
> > >
> > > You're unlikely to get other constant operands in that pattern,
> > > but FWIW, the actual matching pair for just CONST_INT is
> > > "const_int_operand" for the predicate and "n" for the
> > > constraint.  Using the right predicate and constraint will also
> > > help the generated part of recog be a few nanoseconds faster. ;)
> >
> > Thank you for that comment!
> > I think what you mean would look like this:
> >
> > (define_insn "*th_tst"
> >   [(set (match_operand:X 0 "register_operand" "=r")
> >     (zero_extract:X (match_operand:X 1 "register_operand" "r")
> >             (match_operand 3 "const_int_operand" "n")
> >             (match_operand 2 "immediate_operand" "i")))]
>
> No; misunderstanding.  Keep the (const_int 1) but replace
> (match_operand 2 "immediate_operand" "i") with
> (match_operand 2 "const_int_operand" "n")

Ah, yes, this makes sense!

Thanks!


>
> brgds, H-P

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

end of thread, other threads:[~2023-03-01  7:49 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-24  5:51 [PATCH v3 00/11] RISC-V: Add XThead* extension support Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 01/11] riscv: Add basic XThead* vendor " Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 02/11] riscv: riscv-cores.def: Add T-Head XuanTie C906 Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 03/11] riscv: thead: Add support for the XTheadBa ISA extension Christoph Muellner
2023-02-24  6:52   ` Andrew Pinski
2023-02-24  9:54     ` Kito Cheng
2023-02-24 10:05       ` Christoph Müllner
2023-02-24 10:47         ` Christoph Müllner
2023-02-24  5:51 ` [PATCH v3 04/11] riscv: thead: Add support for the XTheadBs " Christoph Muellner
2023-02-24  7:36   ` Kito Cheng
2023-02-24 10:21     ` Christoph Müllner
2023-02-25 23:42   ` Hans-Peter Nilsson
2023-02-28 17:49     ` Christoph Müllner
2023-03-01  0:19       ` Hans-Peter Nilsson
2023-03-01  7:49         ` Christoph Müllner
2023-02-24  5:51 ` [PATCH v3 05/11] riscv: thead: Add support for the XTheadBb " Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 06/11] riscv: thead: Add support for the XTheadCondMov ISA extensions Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 07/11] riscv: thead: Add support for the XTheadMac ISA extension Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 08/11] riscv: thead: Add support for the XTheadFmv " Christoph Muellner
2023-02-24  5:51 ` [PATCH v3 09/11] riscv: thead: Add support for the XTheadMemPair " Christoph Muellner
2023-02-24  9:00   ` Kito Cheng
2023-02-24  9:33     ` Christoph Müllner
2023-02-24 15:48   ` Kito Cheng
2023-02-24  5:51 ` [PATCH v3 10/11] riscv: thead: Add support for the XTheadMemIdx " Christoph Muellner
2023-02-24  9:46   ` Kito Cheng
2023-02-24  5:51 ` [PATCH v3 11/11] riscv: thead: Add support for the XTheadFMemIdx " Christoph Muellner
2023-02-24  7:53   ` Kito Cheng
2023-02-24  9:46     ` Kito Cheng
2023-02-24  8:08 ` [PATCH v3 00/11] RISC-V: Add XThead* extension support Kito Cheng
2023-02-24 11:27   ` Christoph Müllner

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).