public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/omp/gcc-13] amdgcn: implement vector div and mod libfuncs
@ 2023-06-20  9:51 Andrew Stubbs
  0 siblings, 0 replies; only message in thread
From: Andrew Stubbs @ 2023-06-20  9:51 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:50b2cd7e29e91ea5029cbfa9a5eec1b81eb4cf26

commit 50b2cd7e29e91ea5029cbfa9a5eec1b81eb4cf26
Author: Andrew Stubbs <ams@codesourcery.com>
Date:   Thu Apr 27 15:34:28 2023 +0100

    amdgcn: implement vector div and mod libfuncs
    
    Also divmod, but only for scalar modes, for now (because there are no complex
    int vectors yet).
    
    gcc/ChangeLog:
    
            * config/gcn/gcn.cc (gcn_expand_divmod_libfunc): New function.
            (gcn_init_libfuncs): Add div and mod functions for all modes.
            Add placeholders for divmod functions.
            (TARGET_EXPAND_DIVMOD_LIBFUNC): Define.
    
    libgcc/ChangeLog:
    
            * config/gcn/lib2-divmod-di.c: Reimplement like lib2-divmod.c.
            * config/gcn/lib2-divmod.c: Likewise.
            * config/gcn/lib2-gcn.h: Add new types and prototypes for all the
            new vector libfuncs.
            * config/gcn/t-amdgcn: Add new files.
            * config/gcn/amdgcn_veclib.h: New file.
            * config/gcn/lib2-vec_divmod-di.c: New file.
            * config/gcn/lib2-vec_divmod-hi.c: New file.
            * config/gcn/lib2-vec_divmod-qi.c: New file.
            * config/gcn/lib2-vec_divmod.c: New file.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/predcom-2.c: Avoid vectors on amdgcn.
            * gcc.dg/unroll-8.c: Likewise.
            * gcc.dg/vect/slp-26.c: Change expected results on amdgdn.
            * lib/target-supports.exp
            (check_effective_target_vect_int_mod): Add amdgcn.
            (check_effective_target_divmod): Likewise.
            * gcc.target/gcn/simd-math-3-16.c: New test.
            * gcc.target/gcn/simd-math-3-2.c: New test.
            * gcc.target/gcn/simd-math-3-32.c: New test.
            * gcc.target/gcn/simd-math-3-4.c: New test.
            * gcc.target/gcn/simd-math-3-8.c: New test.
            * gcc.target/gcn/simd-math-3-char-16.c: New test.
            * gcc.target/gcn/simd-math-3-char-2.c: New test.
            * gcc.target/gcn/simd-math-3-char-32.c: New test.
            * gcc.target/gcn/simd-math-3-char-4.c: New test.
            * gcc.target/gcn/simd-math-3-char-8.c: New test.
            * gcc.target/gcn/simd-math-3-char-run-16.c: New test.
            * gcc.target/gcn/simd-math-3-char-run-2.c: New test.
            * gcc.target/gcn/simd-math-3-char-run-32.c: New test.
            * gcc.target/gcn/simd-math-3-char-run-4.c: New test.
            * gcc.target/gcn/simd-math-3-char-run-8.c: New test.
            * gcc.target/gcn/simd-math-3-char-run.c: New test.
            * gcc.target/gcn/simd-math-3-char.c: New test.
            * gcc.target/gcn/simd-math-3-long-16.c: New test.
            * gcc.target/gcn/simd-math-3-long-2.c: New test.
            * gcc.target/gcn/simd-math-3-long-32.c: New test.
            * gcc.target/gcn/simd-math-3-long-4.c: New test.
            * gcc.target/gcn/simd-math-3-long-8.c: New test.
            * gcc.target/gcn/simd-math-3-long-run-16.c: New test.
            * gcc.target/gcn/simd-math-3-long-run-2.c: New test.
            * gcc.target/gcn/simd-math-3-long-run-32.c: New test.
            * gcc.target/gcn/simd-math-3-long-run-4.c: New test.
            * gcc.target/gcn/simd-math-3-long-run-8.c: New test.
            * gcc.target/gcn/simd-math-3-long-run.c: New test.
            * gcc.target/gcn/simd-math-3-long.c: New test.
            * gcc.target/gcn/simd-math-3-run-16.c: New test.
            * gcc.target/gcn/simd-math-3-run-2.c: New test.
            * gcc.target/gcn/simd-math-3-run-32.c: New test.
            * gcc.target/gcn/simd-math-3-run-4.c: New test.
            * gcc.target/gcn/simd-math-3-run-8.c: New test.
            * gcc.target/gcn/simd-math-3-run.c: New test.
            * gcc.target/gcn/simd-math-3-short-16.c: New test.
            * gcc.target/gcn/simd-math-3-short-2.c: New test.
            * gcc.target/gcn/simd-math-3-short-32.c: New test.
            * gcc.target/gcn/simd-math-3-short-4.c: New test.
            * gcc.target/gcn/simd-math-3-short-8.c: New test.
            * gcc.target/gcn/simd-math-3-short-run-16.c: New test.
            * gcc.target/gcn/simd-math-3-short-run-2.c: New test.
            * gcc.target/gcn/simd-math-3-short-run-32.c: New test.
            * gcc.target/gcn/simd-math-3-short-run-4.c: New test.
            * gcc.target/gcn/simd-math-3-short-run-8.c: New test.
            * gcc.target/gcn/simd-math-3-short-run.c: New test.
            * gcc.target/gcn/simd-math-3-short.c: New test.
            * gcc.target/gcn/simd-math-3.c: New test.
            * gcc.target/gcn/simd-math-4-char-run.c: New test.
            * gcc.target/gcn/simd-math-4-char.c: New test.
            * gcc.target/gcn/simd-math-4-long-run.c: New test.
            * gcc.target/gcn/simd-math-4-long.c: New test.
            * gcc.target/gcn/simd-math-4-run.c: New test.
            * gcc.target/gcn/simd-math-4-short-run.c: New test.
            * gcc.target/gcn/simd-math-4-short.c: New test.
            * gcc.target/gcn/simd-math-4.c: New test.
            * gcc.target/gcn/simd-math-5-16.c: New test.
            * gcc.target/gcn/simd-math-5-32.c: New test.
            * gcc.target/gcn/simd-math-5-4.c: New test.
            * gcc.target/gcn/simd-math-5-8.c: New test.
            * gcc.target/gcn/simd-math-5-char-16.c: New test.
            * gcc.target/gcn/simd-math-5-char-32.c: New test.
            * gcc.target/gcn/simd-math-5-char-4.c: New test.
            * gcc.target/gcn/simd-math-5-char-8.c: New test.
            * gcc.target/gcn/simd-math-5-char-run-16.c: New test.
            * gcc.target/gcn/simd-math-5-char-run-32.c: New test.
            * gcc.target/gcn/simd-math-5-char-run-4.c: New test.
            * gcc.target/gcn/simd-math-5-char-run-8.c: New test.
            * gcc.target/gcn/simd-math-5-char-run.c: New test.
            * gcc.target/gcn/simd-math-5-char.c: New test.
            * gcc.target/gcn/simd-math-5-long-16.c: New test.
            * gcc.target/gcn/simd-math-5-long-32.c: New test.
            * gcc.target/gcn/simd-math-5-long-4.c: New test.
            * gcc.target/gcn/simd-math-5-long-8.c: New test.
            * gcc.target/gcn/simd-math-5-long-run-16.c: New test.
            * gcc.target/gcn/simd-math-5-long-run-32.c: New test.
            * gcc.target/gcn/simd-math-5-long-run-4.c: New test.
            * gcc.target/gcn/simd-math-5-long-run-8.c: New test.
            * gcc.target/gcn/simd-math-5-long-run.c: New test.
            * gcc.target/gcn/simd-math-5-long.c: New test.
            * gcc.target/gcn/simd-math-5-run-16.c: New test.
            * gcc.target/gcn/simd-math-5-run-32.c: New test.
            * gcc.target/gcn/simd-math-5-run-4.c: New test.
            * gcc.target/gcn/simd-math-5-run-8.c: New test.
            * gcc.target/gcn/simd-math-5-run.c: New test.
            * gcc.target/gcn/simd-math-5-short-16.c: New test.
            * gcc.target/gcn/simd-math-5-short-32.c: New test.
            * gcc.target/gcn/simd-math-5-short-4.c: New test.
            * gcc.target/gcn/simd-math-5-short-8.c: New test.
            * gcc.target/gcn/simd-math-5-short-run-16.c: New test.
            * gcc.target/gcn/simd-math-5-short-run-32.c: New test.
            * gcc.target/gcn/simd-math-5-short-run-4.c: New test.
            * gcc.target/gcn/simd-math-5-short-run-8.c: New test.
            * gcc.target/gcn/simd-math-5-short-run.c: New test.
            * gcc.target/gcn/simd-math-5-short.c: New test.
            * gcc.target/gcn/simd-math-5.c: New test.
    
    (cherry picked from commit d9d6774527bccc5ce0394851aa232f8abdaade4c)

Diff:
---
 gcc/ChangeLog.omp                                  |  10 +
 gcc/config/gcn/gcn.cc                              | 244 ++++++++++++++++
 gcc/testsuite/ChangeLog.omp                        | 108 +++++++
 gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c          |   1 +
 gcc/testsuite/gcc.dg/unroll-8.c                    |   2 +
 gcc/testsuite/gcc.dg/vect/slp-26.c                 |   8 +-
 gcc/testsuite/gcc.target/gcn/simd-math-3-16.c      |  13 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-2.c       |  13 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-32.c      |  13 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-4.c       |  13 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-8.c       |  13 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char-16.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char-2.c  |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char-32.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char-4.c  |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char-8.c  |  11 +
 .../gcc.target/gcn/simd-math-3-char-run-16.c       |   2 +
 .../gcc.target/gcn/simd-math-3-char-run-2.c        |   2 +
 .../gcc.target/gcn/simd-math-3-char-run-32.c       |   2 +
 .../gcc.target/gcn/simd-math-3-char-run-4.c        |   2 +
 .../gcc.target/gcn/simd-math-3-char-run-8.c        |   2 +
 .../gcc.target/gcn/simd-math-3-char-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-char.c    |  10 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long-16.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long-2.c  |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long-32.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long-4.c  |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long-8.c  |  11 +
 .../gcc.target/gcn/simd-math-3-long-run-16.c       |   2 +
 .../gcc.target/gcn/simd-math-3-long-run-2.c        |   2 +
 .../gcc.target/gcn/simd-math-3-long-run-32.c       |   2 +
 .../gcc.target/gcn/simd-math-3-long-run-4.c        |   2 +
 .../gcc.target/gcn/simd-math-3-long-run-8.c        |   2 +
 .../gcc.target/gcn/simd-math-3-long-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-long.c    |  10 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run-16.c  |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run-2.c   |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run-32.c  |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run-4.c   |   3 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run-8.c   |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-run.c     |   2 +
 .../gcc.target/gcn/simd-math-3-short-16.c          |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-short-2.c |  11 +
 .../gcc.target/gcn/simd-math-3-short-32.c          |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-short-4.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-short-8.c |  11 +
 .../gcc.target/gcn/simd-math-3-short-run-16.c      |   2 +
 .../gcc.target/gcn/simd-math-3-short-run-2.c       |   2 +
 .../gcc.target/gcn/simd-math-3-short-run-32.c      |   2 +
 .../gcc.target/gcn/simd-math-3-short-run-4.c       |   2 +
 .../gcc.target/gcn/simd-math-3-short-run-8.c       |   2 +
 .../gcc.target/gcn/simd-math-3-short-run.c         |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-3-short.c   |  10 +
 gcc/testsuite/gcc.target/gcn/simd-math-3.c         | 186 ++++++++++++
 .../gcc.target/gcn/simd-math-4-char-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-4-char.c    |   9 +
 .../gcc.target/gcn/simd-math-4-long-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-4-long.c    |   9 +
 gcc/testsuite/gcc.target/gcn/simd-math-4-run.c     |   2 +
 .../gcc.target/gcn/simd-math-4-short-run.c         |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-4-short.c   |   9 +
 gcc/testsuite/gcc.target/gcn/simd-math-4.c         |  99 +++++++
 gcc/testsuite/gcc.target/gcn/simd-math-5-16.c      |   8 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-32.c      |   8 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-4.c       |   8 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-8.c       |   8 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-char-16.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-char-32.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-char-4.c  |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-char-8.c  |  11 +
 .../gcc.target/gcn/simd-math-5-char-run-16.c       |   2 +
 .../gcc.target/gcn/simd-math-5-char-run-32.c       |   2 +
 .../gcc.target/gcn/simd-math-5-char-run-4.c        |   2 +
 .../gcc.target/gcn/simd-math-5-char-run-8.c        |   2 +
 .../gcc.target/gcn/simd-math-5-char-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-char.c    |  10 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-long-16.c |   9 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-long-32.c |   9 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-long-4.c  |   9 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-long-8.c  |   9 +
 .../gcc.target/gcn/simd-math-5-long-run-16.c       |   2 +
 .../gcc.target/gcn/simd-math-5-long-run-32.c       |   2 +
 .../gcc.target/gcn/simd-math-5-long-run-4.c        |   2 +
 .../gcc.target/gcn/simd-math-5-long-run-8.c        |   2 +
 .../gcc.target/gcn/simd-math-5-long-run.c          |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-long.c    |   8 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-run-16.c  |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-run-32.c  |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-run-4.c   |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-run-8.c   |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-run.c     |   2 +
 .../gcc.target/gcn/simd-math-5-short-16.c          |  11 +
 .../gcc.target/gcn/simd-math-5-short-32.c          |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-short-4.c |  11 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-short-8.c |  11 +
 .../gcc.target/gcn/simd-math-5-short-run-16.c      |   2 +
 .../gcc.target/gcn/simd-math-5-short-run-32.c      |   2 +
 .../gcc.target/gcn/simd-math-5-short-run-4.c       |   2 +
 .../gcc.target/gcn/simd-math-5-short-run-8.c       |   2 +
 .../gcc.target/gcn/simd-math-5-short-run.c         |   2 +
 gcc/testsuite/gcc.target/gcn/simd-math-5-short.c   |  10 +
 gcc/testsuite/gcc.target/gcn/simd-math-5.c         |  88 ++++++
 gcc/testsuite/lib/target-supports.exp              |   8 +-
 libgcc/ChangeLog.omp                               |  16 +
 libgcc/config/gcn/amdgcn_veclib.h                  | 322 +++++++++++++++++++++
 libgcc/config/gcn/lib2-divmod-di.c                 | 105 ++++++-
 libgcc/config/gcn/lib2-divmod.c                    |  82 +++---
 libgcc/config/gcn/lib2-gcn.h                       | 114 ++++++++
 libgcc/config/gcn/lib2-vec_divmod-di.c             | 118 ++++++++
 libgcc/config/gcn/lib2-vec_divmod-hi.c             | 118 ++++++++
 libgcc/config/gcn/lib2-vec_divmod-qi.c             | 118 ++++++++
 libgcc/config/gcn/lib2-vec_divmod.c                | 118 ++++++++
 libgcc/config/gcn/t-amdgcn                         |   4 +
 113 files changed, 2383 insertions(+), 54 deletions(-)

diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp
index 10cdd421b1a..3485a64b64f 100644
--- a/gcc/ChangeLog.omp
+++ b/gcc/ChangeLog.omp
@@ -1,3 +1,13 @@
+2023-06-20  Andrew Stubbs  <ams@codesourcery.com>
+
+	Backport from mainline:
+	2023-06-19  Andrew Stubbs  <ams@codesourcery.com>
+
+	* config/gcn/gcn.cc (gcn_expand_divmod_libfunc): New function.
+	(gcn_init_libfuncs): Add div and mod functions for all modes.
+	Add placeholders for divmod functions.
+	(TARGET_EXPAND_DIVMOD_LIBFUNC): Define.
+
 2023-06-20  Andrew Stubbs  <ams@codesourcery.com>
 
 	Backport from mainline:
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index f019051c010..4b7f8725a41 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -3817,6 +3817,47 @@ gcn_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
 					      TRAMPOLINE_SIZE)));
 }
 
+/* Implement TARGET_EXPAND_DIVMOD_LIBFUNC.
+
+   There are divmod libfuncs for all modes except TImode.  They return the
+   two values packed into a larger integer/vector.  */
+
+void
+gcn_expand_divmod_libfunc (rtx libfunc, machine_mode mode, rtx op0, rtx op1,
+			   rtx *quot, rtx *rem)
+{
+  machine_mode innermode = (VECTOR_MODE_P (mode)
+			    ? GET_MODE_INNER (mode) : mode);
+  machine_mode wideinnermode = VOIDmode;
+  machine_mode widemode = VOIDmode;
+
+  switch (innermode)
+    {
+    case E_QImode:
+    case E_HImode:
+    case E_SImode:
+      wideinnermode = DImode;
+      break;
+    case E_DImode:
+      wideinnermode = TImode;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (VECTOR_MODE_P (mode))
+    widemode = VnMODE (GET_MODE_NUNITS (mode), wideinnermode);
+  else
+    widemode = wideinnermode;
+
+  emit_library_call_value (libfunc, gen_rtx_REG (widemode, RETURN_VALUE_REG),
+			   LCT_NORMAL, widemode, op0, mode, op1, mode);
+
+  *quot = gen_rtx_REG (mode, RETURN_VALUE_REG);
+  *rem = gen_rtx_REG (mode,
+		      RETURN_VALUE_REG + (wideinnermode == TImode ? 2 : 1));
+}
+
 /* }}}  */
 /* {{{ Miscellaneous.  */
 
@@ -4255,6 +4296,207 @@ gcn_init_libfuncs (void)
   set_optab_libfunc (popcount_optab, TImode, "__popcountti2");
   set_optab_libfunc (parity_optab, TImode, "__parityti2");
   set_optab_libfunc (bswap_optab, TImode, "__bswapti2");
+
+  set_optab_libfunc (sdivmod_optab, SImode, "__divmodsi4");
+  set_optab_libfunc (udivmod_optab, SImode, "__udivmodsi4");
+  set_optab_libfunc (sdivmod_optab, DImode, "__divmoddi4");
+  set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4");
+
+  set_optab_libfunc (sdiv_optab, V2QImode, "__divv2qi3");
+  set_optab_libfunc (udiv_optab, V2QImode, "__udivv2qi3");
+  set_optab_libfunc (smod_optab, V2QImode, "__modv2qi3");
+  set_optab_libfunc (umod_optab, V2QImode, "__umodv2qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V2QImode, "__divmodv2qi4");
+  set_optab_libfunc (udivmod_optab, V2QImode, "__udivmodv2qi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V4QImode, "__divv4qi3");
+  set_optab_libfunc (udiv_optab, V4QImode, "__udivv4qi3");
+  set_optab_libfunc (smod_optab, V4QImode, "__modv4qi3");
+  set_optab_libfunc (umod_optab, V4QImode, "__umodv4qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V4QImode, "__divmodv4qi4");
+  set_optab_libfunc (udivmod_optab, V4QImode, "__udivmodv4qi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V8QImode, "__divv8qi3");
+  set_optab_libfunc (udiv_optab, V8QImode, "__udivv8qi3");
+  set_optab_libfunc (smod_optab, V8QImode, "__modv8qi3");
+  set_optab_libfunc (umod_optab, V8QImode, "__umodv8qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V8QImode, "__divmodv8qi4");
+  set_optab_libfunc (udivmod_optab, V8QImode, "__udivmodv8qi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V16QImode, "__divv16qi3");
+  set_optab_libfunc (udiv_optab, V16QImode, "__udivv16qi3");
+  set_optab_libfunc (smod_optab, V16QImode, "__modv16qi3");
+  set_optab_libfunc (umod_optab, V16QImode, "__umodv16qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V16QImode, "__divmodv16qi4");
+  set_optab_libfunc (udivmod_optab, V16QImode, "__udivmodv16qi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V32QImode, "__divv32qi3");
+  set_optab_libfunc (udiv_optab, V32QImode, "__udivv32qi3");
+  set_optab_libfunc (smod_optab, V32QImode, "__modv32qi3");
+  set_optab_libfunc (umod_optab, V32QImode, "__umodv32qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V32QImode, "__divmodv32qi4");
+  set_optab_libfunc (udivmod_optab, V32QImode, "__udivmodv32qi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V64QImode, "__divv64qi3");
+  set_optab_libfunc (udiv_optab, V64QImode, "__udivv64qi3");
+  set_optab_libfunc (smod_optab, V64QImode, "__modv64qi3");
+  set_optab_libfunc (umod_optab, V64QImode, "__umodv64qi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V64QImode, "__divmodv64qi4");
+  set_optab_libfunc (udivmod_optab, V64QImode, "__udivmodv64qi4");
+#endif
+
+  set_optab_libfunc (sdiv_optab, V2HImode, "__divv2hi3");
+  set_optab_libfunc (udiv_optab, V2HImode, "__udivv2hi3");
+  set_optab_libfunc (smod_optab, V2HImode, "__modv2hi3");
+  set_optab_libfunc (umod_optab, V2HImode, "__umodv2hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V2HImode, "__divmodv2hi4");
+  set_optab_libfunc (udivmod_optab, V2HImode, "__udivmodv2hi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V4HImode, "__divv4hi3");
+  set_optab_libfunc (udiv_optab, V4HImode, "__udivv4hi3");
+  set_optab_libfunc (smod_optab, V4HImode, "__modv4hi3");
+  set_optab_libfunc (umod_optab, V4HImode, "__umodv4hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V4HImode, "__divmodv4hi4");
+  set_optab_libfunc (udivmod_optab, V4HImode, "__udivmodv4hi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V8HImode, "__divv8hi3");
+  set_optab_libfunc (udiv_optab, V8HImode, "__udivv8hi3");
+  set_optab_libfunc (smod_optab, V8HImode, "__modv8hi3");
+  set_optab_libfunc (umod_optab, V8HImode, "__umodv8hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V8HImode, "__divmodv8hi4");
+  set_optab_libfunc (udivmod_optab, V8HImode, "__udivmodv8hi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V16HImode, "__divv16hi3");
+  set_optab_libfunc (udiv_optab, V16HImode, "__udivv16hi3");
+  set_optab_libfunc (smod_optab, V16HImode, "__modv16hi3");
+  set_optab_libfunc (umod_optab, V16HImode, "__umodv16hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V16HImode, "__divmodv16hi4");
+  set_optab_libfunc (udivmod_optab, V16HImode, "__udivmodv16hi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V32HImode, "__divv32hi3");
+  set_optab_libfunc (udiv_optab, V32HImode, "__udivv32hi3");
+  set_optab_libfunc (smod_optab, V32HImode, "__modv32hi3");
+  set_optab_libfunc (umod_optab, V32HImode, "__umodv32hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V32HImode, "__divmodv32hi4");
+  set_optab_libfunc (udivmod_optab, V32HImode, "__udivmodv32hi4");
+#endif
+  set_optab_libfunc (sdiv_optab, V64HImode, "__divv64hi3");
+  set_optab_libfunc (udiv_optab, V64HImode, "__udivv64hi3");
+  set_optab_libfunc (smod_optab, V64HImode, "__modv64hi3");
+  set_optab_libfunc (umod_optab, V64HImode, "__umodv64hi3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V64HImode, "__divmodv64hi4");
+  set_optab_libfunc (udivmod_optab, V64HImode, "__udivmodv64hi4");
+#endif
+
+  set_optab_libfunc (sdiv_optab, V2SImode, "__divv2si3");
+  set_optab_libfunc (udiv_optab, V2SImode, "__udivv2si3");
+  set_optab_libfunc (smod_optab, V2SImode, "__modv2si3");
+  set_optab_libfunc (umod_optab, V2SImode, "__umodv2si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V2SImode, "__divmodv2si4");
+  set_optab_libfunc (udivmod_optab, V2SImode, "__udivmodv2si4");
+#endif
+  set_optab_libfunc (sdiv_optab, V4SImode, "__divv4si3");
+  set_optab_libfunc (udiv_optab, V4SImode, "__udivv4si3");
+  set_optab_libfunc (smod_optab, V4SImode, "__modv4si3");
+  set_optab_libfunc (umod_optab, V4SImode, "__umodv4si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V4SImode, "__divmodv4si4");
+  set_optab_libfunc (udivmod_optab, V4SImode, "__udivmodv4si4");
+#endif
+  set_optab_libfunc (sdiv_optab, V8SImode, "__divv8si3");
+  set_optab_libfunc (udiv_optab, V8SImode, "__udivv8si3");
+  set_optab_libfunc (smod_optab, V8SImode, "__modv8si3");
+  set_optab_libfunc (umod_optab, V8SImode, "__umodv8si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V8SImode, "__divmodv8si4");
+  set_optab_libfunc (udivmod_optab, V8SImode, "__udivmodv8si4");
+#endif
+  set_optab_libfunc (sdiv_optab, V16SImode, "__divv16si3");
+  set_optab_libfunc (udiv_optab, V16SImode, "__udivv16si3");
+  set_optab_libfunc (smod_optab, V16SImode, "__modv16si3");
+  set_optab_libfunc (umod_optab, V16SImode, "__umodv16si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V16SImode, "__divmodv16si4");
+  set_optab_libfunc (udivmod_optab, V16SImode, "__udivmodv16si4");
+#endif
+  set_optab_libfunc (sdiv_optab, V32SImode, "__divv32si3");
+  set_optab_libfunc (udiv_optab, V32SImode, "__udivv32si3");
+  set_optab_libfunc (smod_optab, V32SImode, "__modv32si3");
+  set_optab_libfunc (umod_optab, V32SImode, "__umodv32si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V32SImode, "__divmodv32si4");
+  set_optab_libfunc (udivmod_optab, V32SImode, "__udivmodv32si4");
+#endif
+  set_optab_libfunc (sdiv_optab, V64SImode, "__divv64si3");
+  set_optab_libfunc (udiv_optab, V64SImode, "__udivv64si3");
+  set_optab_libfunc (smod_optab, V64SImode, "__modv64si3");
+  set_optab_libfunc (umod_optab, V64SImode, "__umodv64si3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V64SImode, "__divmodv64si4");
+  set_optab_libfunc (udivmod_optab, V64SImode, "__udivmodv64si4");
+#endif
+
+  set_optab_libfunc (sdiv_optab, V2DImode, "__divv2di3");
+  set_optab_libfunc (udiv_optab, V2DImode, "__udivv2di3");
+  set_optab_libfunc (smod_optab, V2DImode, "__modv2di3");
+  set_optab_libfunc (umod_optab, V2DImode, "__umodv2di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V2DImode, "__divmodv2di4");
+  set_optab_libfunc (udivmod_optab, V2DImode, "__udivmodv2di4");
+#endif
+  set_optab_libfunc (sdiv_optab, V4DImode, "__divv4di3");
+  set_optab_libfunc (udiv_optab, V4DImode, "__udivv4di3");
+  set_optab_libfunc (smod_optab, V4DImode, "__modv4di3");
+  set_optab_libfunc (umod_optab, V4DImode, "__umodv4di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V4DImode, "__divmodv4di4");
+  set_optab_libfunc (udivmod_optab, V4DImode, "__udivmodv4di4");
+#endif
+  set_optab_libfunc (sdiv_optab, V8DImode, "__divv8di3");
+  set_optab_libfunc (udiv_optab, V8DImode, "__udivv8di3");
+  set_optab_libfunc (smod_optab, V8DImode, "__modv8di3");
+  set_optab_libfunc (umod_optab, V8DImode, "__umodv8di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V8DImode, "__divmodv8di4");
+  set_optab_libfunc (udivmod_optab, V8DImode, "__udivmodv8di4");
+#endif
+  set_optab_libfunc (sdiv_optab, V16DImode, "__divv16di3");
+  set_optab_libfunc (udiv_optab, V16DImode, "__udivv16di3");
+  set_optab_libfunc (smod_optab, V16DImode, "__modv16di3");
+  set_optab_libfunc (umod_optab, V16DImode, "__umodv16di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V16DImode, "__divmodv16di4");
+  set_optab_libfunc (udivmod_optab, V16DImode, "__udivmodv16di4");
+#endif
+  set_optab_libfunc (sdiv_optab, V32DImode, "__divv32di3");
+  set_optab_libfunc (udiv_optab, V32DImode, "__udivv32di3");
+  set_optab_libfunc (smod_optab, V32DImode, "__modv32di3");
+  set_optab_libfunc (umod_optab, V32DImode, "__umodv32di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V32DImode, "__divmodv32di4");
+  set_optab_libfunc (udivmod_optab, V32DImode, "__udivmodv32di4");
+#endif
+  set_optab_libfunc (sdiv_optab, V64DImode, "__divv64di3");
+  set_optab_libfunc (udiv_optab, V64DImode, "__udivv64di3");
+  set_optab_libfunc (smod_optab, V64DImode, "__modv64di3");
+  set_optab_libfunc (umod_optab, V64DImode, "__umodv64di3");
+#if 0
+  set_optab_libfunc (sdivmod_optab, V64DImode, "__divmodv64di4");
+  set_optab_libfunc (udivmod_optab, V64DImode, "__udivmodv64di4");
+#endif
 }
 
 /* Expand the CMP_SWAP GCN builtins.  We have our own versions that do
@@ -7541,6 +7783,8 @@ gcn_dwarf_register_span (rtx rtl)
 #define TARGET_EMUTLS_VAR_INIT gcn_emutls_var_init
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN gcn_expand_builtin
+#undef  TARGET_EXPAND_DIVMOD_LIBFUNC
+#define TARGET_EXPAND_DIVMOD_LIBFUNC gcn_expand_divmod_libfunc
 #undef  TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED gcn_frame_pointer_rqd
 #undef  TARGET_FUNCTION_ARG
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index ba530d3f6c4..5676db7a4e7 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,111 @@
+2023-06-20  Andrew Stubbs  <ams@codesourcery.com>
+
+	Backport from mainline:
+	2023-06-19  Andrew Stubbs  <ams@codesourcery.com>
+
+	* gcc.dg/tree-ssa/predcom-2.c: Avoid vectors on amdgcn.
+	* gcc.dg/unroll-8.c: Likewise.
+	* gcc.dg/vect/slp-26.c: Change expected results on amdgdn.
+	* lib/target-supports.exp
+	(check_effective_target_vect_int_mod): Add amdgcn.
+	(check_effective_target_divmod): Likewise.
+	* gcc.target/gcn/simd-math-3-16.c: New test.
+	* gcc.target/gcn/simd-math-3-2.c: New test.
+	* gcc.target/gcn/simd-math-3-32.c: New test.
+	* gcc.target/gcn/simd-math-3-4.c: New test.
+	* gcc.target/gcn/simd-math-3-8.c: New test.
+	* gcc.target/gcn/simd-math-3-char-16.c: New test.
+	* gcc.target/gcn/simd-math-3-char-2.c: New test.
+	* gcc.target/gcn/simd-math-3-char-32.c: New test.
+	* gcc.target/gcn/simd-math-3-char-4.c: New test.
+	* gcc.target/gcn/simd-math-3-char-8.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run-16.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run-2.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run-32.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run-4.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run-8.c: New test.
+	* gcc.target/gcn/simd-math-3-char-run.c: New test.
+	* gcc.target/gcn/simd-math-3-char.c: New test.
+	* gcc.target/gcn/simd-math-3-long-16.c: New test.
+	* gcc.target/gcn/simd-math-3-long-2.c: New test.
+	* gcc.target/gcn/simd-math-3-long-32.c: New test.
+	* gcc.target/gcn/simd-math-3-long-4.c: New test.
+	* gcc.target/gcn/simd-math-3-long-8.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run-16.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run-2.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run-32.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run-4.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run-8.c: New test.
+	* gcc.target/gcn/simd-math-3-long-run.c: New test.
+	* gcc.target/gcn/simd-math-3-long.c: New test.
+	* gcc.target/gcn/simd-math-3-run-16.c: New test.
+	* gcc.target/gcn/simd-math-3-run-2.c: New test.
+	* gcc.target/gcn/simd-math-3-run-32.c: New test.
+	* gcc.target/gcn/simd-math-3-run-4.c: New test.
+	* gcc.target/gcn/simd-math-3-run-8.c: New test.
+	* gcc.target/gcn/simd-math-3-run.c: New test.
+	* gcc.target/gcn/simd-math-3-short-16.c: New test.
+	* gcc.target/gcn/simd-math-3-short-2.c: New test.
+	* gcc.target/gcn/simd-math-3-short-32.c: New test.
+	* gcc.target/gcn/simd-math-3-short-4.c: New test.
+	* gcc.target/gcn/simd-math-3-short-8.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run-16.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run-2.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run-32.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run-4.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run-8.c: New test.
+	* gcc.target/gcn/simd-math-3-short-run.c: New test.
+	* gcc.target/gcn/simd-math-3-short.c: New test.
+	* gcc.target/gcn/simd-math-3.c: New test.
+	* gcc.target/gcn/simd-math-4-char-run.c: New test.
+	* gcc.target/gcn/simd-math-4-char.c: New test.
+	* gcc.target/gcn/simd-math-4-long-run.c: New test.
+	* gcc.target/gcn/simd-math-4-long.c: New test.
+	* gcc.target/gcn/simd-math-4-run.c: New test.
+	* gcc.target/gcn/simd-math-4-short-run.c: New test.
+	* gcc.target/gcn/simd-math-4-short.c: New test.
+	* gcc.target/gcn/simd-math-4.c: New test.
+	* gcc.target/gcn/simd-math-5-16.c: New test.
+	* gcc.target/gcn/simd-math-5-32.c: New test.
+	* gcc.target/gcn/simd-math-5-4.c: New test.
+	* gcc.target/gcn/simd-math-5-8.c: New test.
+	* gcc.target/gcn/simd-math-5-char-16.c: New test.
+	* gcc.target/gcn/simd-math-5-char-32.c: New test.
+	* gcc.target/gcn/simd-math-5-char-4.c: New test.
+	* gcc.target/gcn/simd-math-5-char-8.c: New test.
+	* gcc.target/gcn/simd-math-5-char-run-16.c: New test.
+	* gcc.target/gcn/simd-math-5-char-run-32.c: New test.
+	* gcc.target/gcn/simd-math-5-char-run-4.c: New test.
+	* gcc.target/gcn/simd-math-5-char-run-8.c: New test.
+	* gcc.target/gcn/simd-math-5-char-run.c: New test.
+	* gcc.target/gcn/simd-math-5-char.c: New test.
+	* gcc.target/gcn/simd-math-5-long-16.c: New test.
+	* gcc.target/gcn/simd-math-5-long-32.c: New test.
+	* gcc.target/gcn/simd-math-5-long-4.c: New test.
+	* gcc.target/gcn/simd-math-5-long-8.c: New test.
+	* gcc.target/gcn/simd-math-5-long-run-16.c: New test.
+	* gcc.target/gcn/simd-math-5-long-run-32.c: New test.
+	* gcc.target/gcn/simd-math-5-long-run-4.c: New test.
+	* gcc.target/gcn/simd-math-5-long-run-8.c: New test.
+	* gcc.target/gcn/simd-math-5-long-run.c: New test.
+	* gcc.target/gcn/simd-math-5-long.c: New test.
+	* gcc.target/gcn/simd-math-5-run-16.c: New test.
+	* gcc.target/gcn/simd-math-5-run-32.c: New test.
+	* gcc.target/gcn/simd-math-5-run-4.c: New test.
+	* gcc.target/gcn/simd-math-5-run-8.c: New test.
+	* gcc.target/gcn/simd-math-5-run.c: New test.
+	* gcc.target/gcn/simd-math-5-short-16.c: New test.
+	* gcc.target/gcn/simd-math-5-short-32.c: New test.
+	* gcc.target/gcn/simd-math-5-short-4.c: New test.
+	* gcc.target/gcn/simd-math-5-short-8.c: New test.
+	* gcc.target/gcn/simd-math-5-short-run-16.c: New test.
+	* gcc.target/gcn/simd-math-5-short-run-32.c: New test.
+	* gcc.target/gcn/simd-math-5-short-run-4.c: New test.
+	* gcc.target/gcn/simd-math-5-short-run-8.c: New test.
+	* gcc.target/gcn/simd-math-5-short-run.c: New test.
+	* gcc.target/gcn/simd-math-5-short.c: New test.
+	* gcc.target/gcn/simd-math-5.c: New test.
+
 2023-06-19  Julian Brown  <julian@codesourcery.com>
 
 	* c-c++-common/goacc/combined-reduction.c: Adjust scan output.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c
index d8fe51c5a6c..1c54679c022 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c
@@ -1,5 +1,6 @@
 /* { dg-do run } */
 /* { dg-options "-O2 -funroll-loops --param max-unroll-times=8 -fpredictive-commoning -fdump-tree-pcom-details -fno-tree-pre" } */
+/* { dg-additional-options "-fno-tree-vectorize" { target amdgcn-*-* } } */
 
 void abort (void);
 
diff --git a/gcc/testsuite/gcc.dg/unroll-8.c b/gcc/testsuite/gcc.dg/unroll-8.c
index b16df672833..2c73c7d3e9b 100644
--- a/gcc/testsuite/gcc.dg/unroll-8.c
+++ b/gcc/testsuite/gcc.dg/unroll-8.c
@@ -1,5 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -fdump-rtl-loop2_unroll -funroll-loops" } */
+/* { dg-additional-options "-fno-tree-vectorize" { target amdgcn-*-* } } */
+
 struct a {int a[7];};
 int t(struct a *a, int n)
 {
diff --git a/gcc/testsuite/gcc.dg/vect/slp-26.c b/gcc/testsuite/gcc.dg/vect/slp-26.c
index 01f4e4ee32e..f8b49ff603c 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-26.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-26.c
@@ -46,7 +46,7 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! mips_msa } } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { mips_msa } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! mips_msa } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { mips_msa } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { mips_msa || amdgcn-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { mips_msa || amdgcn-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { mips_msa || amdgcn-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { mips_msa || amdgcn-*-* } } } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-16.c
new file mode 100644
index 00000000000..20fa12f0efc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-16.c
@@ -0,0 +1,13 @@
+#define STYPE v16si
+#define UTYPE v16usi
+#define N 16
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv16si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-2.c
new file mode 100644
index 00000000000..3baffe9ef01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-2.c
@@ -0,0 +1,13 @@
+#define STYPE v2si
+#define UTYPE v2usi
+#define N 2
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv2si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv2si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv2si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv2si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv2si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv2si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-32.c
new file mode 100644
index 00000000000..eab48158405
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-32.c
@@ -0,0 +1,13 @@
+#define STYPE v32si
+#define UTYPE v32usi
+#define N 32
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv32si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-4.c
new file mode 100644
index 00000000000..370ca63554b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-4.c
@@ -0,0 +1,13 @@
+#define STYPE v4si
+#define UTYPE v4usi
+#define N 4
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv4si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-8.c
new file mode 100644
index 00000000000..833608eaf2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-8.c
@@ -0,0 +1,13 @@
+#define STYPE v8si
+#define UTYPE v8usi
+#define N 8
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv8si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-16.c
new file mode 100644
index 00000000000..f156d49cd2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-16.c
@@ -0,0 +1,11 @@
+#define STYPE v16qi
+#define UTYPE v16uqi
+#define N 16
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv16qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv16qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-2.c
new file mode 100644
index 00000000000..be4b9050fcd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-2.c
@@ -0,0 +1,11 @@
+#define STYPE v2qi
+#define UTYPE v2uqi
+#define N 2
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv2qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv2qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv2qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv2qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv2qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv2qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-32.c
new file mode 100644
index 00000000000..b0cadecb0d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-32.c
@@ -0,0 +1,11 @@
+#define STYPE v32qi
+#define UTYPE v32uqi
+#define N 32
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv32qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv32qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-4.c
new file mode 100644
index 00000000000..4dc7c783d35
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-4.c
@@ -0,0 +1,11 @@
+#define STYPE v4qi
+#define UTYPE v4uqi
+#define N 4
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv4qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv4qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-8.c
new file mode 100644
index 00000000000..ea3753aaaf8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-8.c
@@ -0,0 +1,11 @@
+#define STYPE v8qi
+#define UTYPE v8uqi
+#define N 8
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv8qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv8qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-16.c
new file mode 100644
index 00000000000..159b9802b07
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-2.c
new file mode 100644
index 00000000000..6e730d07a03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-2.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char-2.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-32.c
new file mode 100644
index 00000000000..8e4932bf5b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-4.c
new file mode 100644
index 00000000000..d07a4318390
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-8.c
new file mode 100644
index 00000000000..64f789a4528
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run.c
new file mode 100644
index 00000000000..4e2d4c0a19a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-char.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-char.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-char.c
new file mode 100644
index 00000000000..478d09e2ec7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-char.c
@@ -0,0 +1,10 @@
+#define STYPE v64qi
+#define UTYPE v64uqi
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64qi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-16.c
new file mode 100644
index 00000000000..530f29e3778
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-16.c
@@ -0,0 +1,11 @@
+#define STYPE v16di
+#define UTYPE v16udi
+#define N 16
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv16di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv16di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-2.c
new file mode 100644
index 00000000000..1c3e833c733
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-2.c
@@ -0,0 +1,11 @@
+#define STYPE v2di
+#define UTYPE v2udi
+#define N 2
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv2di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv2di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv2di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv2di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv2di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv2di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-32.c
new file mode 100644
index 00000000000..c8556a85ffd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-32.c
@@ -0,0 +1,11 @@
+#define STYPE v32di
+#define UTYPE v32udi
+#define N 32
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv32di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv32di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-4.c
new file mode 100644
index 00000000000..514396c565d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-4.c
@@ -0,0 +1,11 @@
+#define STYPE v4di
+#define UTYPE v4udi
+#define N 4
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv4di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv4di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-8.c
new file mode 100644
index 00000000000..428e3a5a807
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-8.c
@@ -0,0 +1,11 @@
+#define STYPE v8di
+#define UTYPE v8udi
+#define N 8
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv8di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv8di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-16.c
new file mode 100644
index 00000000000..7ce9c92a7a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-2.c
new file mode 100644
index 00000000000..20996a56f5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-2.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long-2.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-32.c
new file mode 100644
index 00000000000..1ca25ac9b51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-4.c
new file mode 100644
index 00000000000..b31769ad0bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-8.c
new file mode 100644
index 00000000000..930256a0fc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run.c
new file mode 100644
index 00000000000..363e42573d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-long.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-long.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-long.c
new file mode 100644
index 00000000000..321297b75ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-long.c
@@ -0,0 +1,10 @@
+#define STYPE v64di
+#define UTYPE v64udi
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64di3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-16.c
new file mode 100644
index 00000000000..ae8cdbffa1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-2.c
new file mode 100644
index 00000000000..7d80382f23b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-2.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-2.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-32.c
new file mode 100644
index 00000000000..127fd36f0f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-4.c
new file mode 100644
index 00000000000..e1d5b5de5c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-4.c
@@ -0,0 +1,3 @@
+/* { dg-do run } */
+#include "simd-math-3-4.c"
+
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-8.c
new file mode 100644
index 00000000000..ec98b60ae2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-run.c
new file mode 100644
index 00000000000..aca508cbc25
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-16.c
new file mode 100644
index 00000000000..80f04149035
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-16.c
@@ -0,0 +1,11 @@
+#define STYPE v16hi
+#define UTYPE v16uhi
+#define N 16
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv16hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv16hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-2.c
new file mode 100644
index 00000000000..37e5008a871
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-2.c
@@ -0,0 +1,11 @@
+#define STYPE v2hi
+#define UTYPE v2uhi
+#define N 2
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv2hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv2hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv2hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv2hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv2hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv2hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-32.c
new file mode 100644
index 00000000000..79aada0ea5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-32.c
@@ -0,0 +1,11 @@
+#define STYPE v32hi
+#define UTYPE v32uhi
+#define N 32
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv32hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv32hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-4.c
new file mode 100644
index 00000000000..014acacd2ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-4.c
@@ -0,0 +1,11 @@
+#define STYPE v4hi
+#define UTYPE v4uhi
+#define N 4
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv4hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv4hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-8.c
new file mode 100644
index 00000000000..308b72b53e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-8.c
@@ -0,0 +1,11 @@
+#define STYPE v8hi
+#define UTYPE v8uhi
+#define N 8
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv8hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv8hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-16.c
new file mode 100644
index 00000000000..8ca866ce21f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-2.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-2.c
new file mode 100644
index 00000000000..6c6d8b68f28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-2.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short-2.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-32.c
new file mode 100644
index 00000000000..8c30ebc5528
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-4.c
new file mode 100644
index 00000000000..e70697e6e42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-8.c
new file mode 100644
index 00000000000..9cb9a6fe297
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run.c
new file mode 100644
index 00000000000..08f72671e96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-3-short.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3-short.c b/gcc/testsuite/gcc.target/gcn/simd-math-3-short.c
new file mode 100644
index 00000000000..1ade288f389
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3-short.c
@@ -0,0 +1,10 @@
+#define STYPE v64hi
+#define UTYPE v64uhi
+#include "simd-math-3.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64hi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-3.c b/gcc/testsuite/gcc.target/gcn/simd-math-3.c
new file mode 100644
index 00000000000..def83852461
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-3.c
@@ -0,0 +1,186 @@
+/* Test that signed and unsigned division and modulus use the correct
+   vector routines and give the correct results.  */
+
+/* Setting it this way ensures the run tests use the same flag as the
+   compile tests.  */
+#pragma GCC optimize("O2")
+
+typedef signed char v2qi __attribute__ ((vector_size (2)));
+typedef signed char v4qi __attribute__ ((vector_size (4)));
+typedef signed char v8qi __attribute__ ((vector_size (8)));
+typedef signed char v16qi __attribute__ ((vector_size (16)));
+typedef signed char v32qi __attribute__ ((vector_size (32)));
+typedef signed char v64qi __attribute__ ((vector_size (64)));
+
+typedef unsigned char v2uqi __attribute__ ((vector_size (2)));
+typedef unsigned char v4uqi __attribute__ ((vector_size (4)));
+typedef unsigned char v8uqi __attribute__ ((vector_size (8)));
+typedef unsigned char v16uqi __attribute__ ((vector_size (16)));
+typedef unsigned char v32uqi __attribute__ ((vector_size (32)));
+typedef unsigned char v64uqi __attribute__ ((vector_size (64)));
+
+typedef short v2hi __attribute__ ((vector_size (4)));
+typedef short v4hi __attribute__ ((vector_size (8)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+typedef short v16hi __attribute__ ((vector_size (32)));
+typedef short v32hi __attribute__ ((vector_size (64)));
+typedef short v64hi __attribute__ ((vector_size (128)));
+
+typedef unsigned short v2uhi __attribute__ ((vector_size (4)));
+typedef unsigned short v4uhi __attribute__ ((vector_size (8)));
+typedef unsigned short v8uhi __attribute__ ((vector_size (16)));
+typedef unsigned short v16uhi __attribute__ ((vector_size (32)));
+typedef unsigned short v32uhi __attribute__ ((vector_size (64)));
+typedef unsigned short v64uhi __attribute__ ((vector_size (128)));
+
+typedef int v2si __attribute__ ((vector_size (8)));
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef int v8si __attribute__ ((vector_size (32)));
+typedef int v16si __attribute__ ((vector_size (64)));
+typedef int v32si __attribute__ ((vector_size (128)));
+typedef int v64si __attribute__ ((vector_size (256)));
+
+typedef unsigned int v2usi __attribute__ ((vector_size (8)));
+typedef unsigned int v4usi __attribute__ ((vector_size (16)));
+typedef unsigned int v8usi __attribute__ ((vector_size (32)));
+typedef unsigned int v16usi __attribute__ ((vector_size (64)));
+typedef unsigned int v32usi __attribute__ ((vector_size (128)));
+typedef unsigned int v64usi __attribute__ ((vector_size (256)));
+
+typedef long v2di __attribute__ ((vector_size (16)));
+typedef long v4di __attribute__ ((vector_size (32)));
+typedef long v8di __attribute__ ((vector_size (64)));
+typedef long v16di __attribute__ ((vector_size (128)));
+typedef long v32di __attribute__ ((vector_size (256)));
+typedef long v64di __attribute__ ((vector_size (512)));
+
+typedef unsigned long v2udi __attribute__ ((vector_size (16)));
+typedef unsigned long v4udi __attribute__ ((vector_size (32)));
+typedef unsigned long v8udi __attribute__ ((vector_size (64)));
+typedef unsigned long v16udi __attribute__ ((vector_size (128)));
+typedef unsigned long v32udi __attribute__ ((vector_size (256)));
+typedef unsigned long v64udi __attribute__ ((vector_size (512)));
+
+#ifndef STYPE
+#define STYPE v64si
+#define UTYPE v64usi
+#endif
+#ifndef N
+#define N 64
+#endif
+
+STYPE a;
+STYPE b;
+UTYPE ua;
+UTYPE ub;
+
+int main()
+{
+  int i;
+  STYPE squot, srem;
+  UTYPE usquot, usrem;
+  STYPE vquot, vrem;
+  UTYPE uvquot, uvrem;
+  STYPE vquot2, vrem2;
+  UTYPE uvquot2, uvrem2;
+  STYPE refquot, refrem;
+  UTYPE urefquot, urefrem;
+
+  for (i = 0; i < N; i++)
+    {
+      a[i] = i * (i >> 2) + (i >> 1);
+      ua[i] = a[i];
+      b[i] = i;
+      ub[i] = i;
+    }
+
+  for (i = 0; i < N; i++)
+    {
+      /* Calculate reference values using regular scalar div and mod.  */
+      refquot[i] = a[i] / b[i];
+      __asm__ ("" ::: "memory");
+      refrem[i] = a[i] % b[i];
+      urefquot[i] = ua[i] / ub[i];
+      __asm__ ("" ::: "memory");
+      urefrem[i] = ua[i] % ub[i];
+    }
+
+  __asm__ ("" ::: "memory");
+  /* Scalar with divmod.  */
+  for (i = 0; i < N; i++)
+    {
+      squot[i] = a[i] / b[i];
+      srem[i] = a[i] % b[i];
+      usquot[i] = ua[i] / ub[i];
+      usrem[i] = ua[i] % ub[i];
+    }
+
+  __asm__ ("" ::: "memory");
+  /* Vectorized with divmod.  */
+  vquot = a / b;
+  vrem = a % b;
+  uvquot = ua / ub;
+  uvrem = ua % ub;
+
+  __asm__ ("" ::: "memory");
+  /* Vectorized with separte div and mod.  */
+  vquot2 = a / b;
+  __asm__ ("" ::: "memory");
+  vrem2 = a % b;
+  uvquot2 = ua / ub;
+  __asm__ ("" ::: "memory");
+  uvrem2 = ua % ub;
+
+#ifdef DEBUG
+#define DUMP(VAR) \
+  __builtin_printf ("%8s: ", #VAR); \
+  for (i = 0; i < N; i++) \
+    __builtin_printf ("%d ", (int)VAR[i]); \
+  __builtin_printf ("\n");
+  DUMP (refquot)
+  DUMP (squot)
+  DUMP (vquot)
+  DUMP (vquot2)
+  __builtin_printf ("\n");
+  DUMP (urefquot)
+  DUMP (usquot)
+  DUMP (uvquot)
+  DUMP (uvquot2)
+  __builtin_printf ("\n");
+  DUMP (refrem)
+  DUMP (srem)
+  DUMP (vrem)
+  DUMP (vrem2)
+  __builtin_printf ("\n");
+  DUMP (urefrem)
+  DUMP (usrem)
+  DUMP (uvrem)
+  DUMP (uvrem2)
+  __builtin_printf ("\n");
+#endif
+
+  for (i = 0; i < N; i++)
+    if (squot[i] != refquot[i]
+	|| vquot[i] != refquot[i]
+	|| vquot2[i] != refquot[i]
+	|| usquot[i] != urefquot[i]
+	|| uvquot[i] != urefquot[i]
+	|| uvquot2[i] != urefquot[i]
+	|| srem[i] != refrem[i]
+	|| vrem[i] != refrem[i]
+	|| vrem2[i] != refrem[i]
+	|| usrem[i] != urefrem[i]
+	|| uvrem[i] != urefrem[i]
+	|| uvrem2[i] != urefrem[i])
+      __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {__divmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__modv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 1 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-char-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-char-run.c
new file mode 100644
index 00000000000..b328a3eeec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-char-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-4-char.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-char.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-char.c
new file mode 100644
index 00000000000..df24bd4e56d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-char.c
@@ -0,0 +1,9 @@
+#define TYPE v64qi
+#include "simd-math-4.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64qi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64qi4@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-long-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-long-run.c
new file mode 100644
index 00000000000..34cbc467709
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-long-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-4-long.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-long.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-long.c
new file mode 100644
index 00000000000..768a0dfc848
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-long.c
@@ -0,0 +1,9 @@
+#define TYPE v64di
+#include "simd-math-4.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64di4@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-run.c
new file mode 100644
index 00000000000..3b98c0e7738
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-short-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-short-run.c
new file mode 100644
index 00000000000..4cbeb97432e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-short-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-4-short.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4-short.c b/gcc/testsuite/gcc.target/gcn/simd-math-4-short.c
new file mode 100644
index 00000000000..f010942ffad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4-short.c
@@ -0,0 +1,9 @@
+#define TYPE v64hi
+#include "simd-math-4.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64hi4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64hi4@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-4.c
new file mode 100644
index 00000000000..833dfe2a866
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-4.c
@@ -0,0 +1,99 @@
+/* Test that signed division and modulus give the correct result with
+   different variations of signedness.  */
+
+/* Setting it this way ensures the run tests use the same flag as the
+   compile tests.  */
+#pragma GCC optimize("O2")
+
+typedef char v64qi __attribute__ ((vector_size (64)));
+typedef short v64hi __attribute__ ((vector_size (128)));
+typedef int v64si __attribute__ ((vector_size (256)));
+typedef long v64di __attribute__ ((vector_size (512)));
+
+#ifndef TYPE
+#define TYPE v64si
+#endif
+#define N 64
+
+TYPE a;
+TYPE b;
+
+int main()
+{
+  int i;
+  TYPE squot, srem;
+  TYPE usquot, usrem;
+  TYPE vquot, vrem;
+  TYPE vquot2, vrem2;
+  TYPE refquot, refrem;
+
+  for (i = 0; i < 64; i++)
+    {
+      a[i] = i * (i >> 2) * (i&1 ? -1 : 1);
+      b[i] = i * (i&2 ? -1 : 1);
+    }
+
+  for (i = 0; i < N; i++)
+    {
+      /* Calculate reference values using regular scalar div and mod.  */
+      refquot[i] = a[i] / b[i];
+      __asm__ ("" ::: "memory");
+      refrem[i] = a[i] % b[i];
+    }
+
+  __asm__ ("" ::: "memory");
+  /* Scalar with divmod.  */
+  for (i = 0; i < N; i++)
+    {
+      squot[i] = a[i] / b[i];
+      srem[i] = a[i] % b[i];
+    }
+
+  __asm__ ("" ::: "memory");
+  /* Vectorized with divmod.  */
+  vquot = a / b;
+  vrem = a % b;
+
+  __asm__ ("" ::: "memory");
+  /* Vectorized with separte div and mod.  */
+  vquot2 = a / b;
+  __asm__ ("" ::: "memory");
+  vrem2 = a % b;
+
+#ifdef DEBUG
+#define DUMP(VAR) \
+  __builtin_printf ("%8s: ", #VAR); \
+  for (i = 0; i < N; i++) \
+    __builtin_printf ("%d ", (int)VAR[i]); \
+  __builtin_printf ("\n");
+  DUMP (refquot)
+  DUMP (squot)
+  DUMP (vquot)
+  DUMP (vquot2)
+  __builtin_printf ("\n");
+  DUMP (refrem)
+  DUMP (srem)
+  DUMP (vrem)
+  DUMP (vrem2)
+  __builtin_printf ("\n");
+#endif
+
+  for (i = 0; i < N; i++)
+    if (squot[i] != refquot[i]
+	|| vquot[i] != refquot[i]
+	|| vquot2[i] != refquot[i]
+	|| srem[i] != refrem[i]
+	|| vrem[i] != refrem[i]
+	|| vrem2[i] != refrem[i])
+      __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {__divmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64si4@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-16.c
new file mode 100644
index 00000000000..41c116758b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-16.c
@@ -0,0 +1,8 @@
+#define N 16
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16si3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-32.c
new file mode 100644
index 00000000000..3fb92b2aab2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-32.c
@@ -0,0 +1,8 @@
+#define N 32
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32si3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-4.c
new file mode 100644
index 00000000000..ffcd5120178
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-4.c
@@ -0,0 +1,8 @@
+#define N 4
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4si3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-8.c
new file mode 100644
index 00000000000..5d855b62752
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-8.c
@@ -0,0 +1,8 @@
+#define N 8
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8si3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-16.c
new file mode 100644
index 00000000000..0ebf640dc8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-16.c
@@ -0,0 +1,11 @@
+#define TYPE char
+#define N 16
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses HImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod16.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv16qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv16qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv16qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-32.c
new file mode 100644
index 00000000000..0905f31048c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-32.c
@@ -0,0 +1,11 @@
+#define TYPE char
+#define N 32
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses HImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod32.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv32qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv32qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv32qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-4.c
new file mode 100644
index 00000000000..772fe37fe81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-4.c
@@ -0,0 +1,11 @@
+#define TYPE char
+#define N 4
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses HImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod4.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv4qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv4qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv4qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-8.c
new file mode 100644
index 00000000000..539ce9a7f91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-8.c
@@ -0,0 +1,11 @@
+#define TYPE char
+#define N 8
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses HImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod8.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv8qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv8qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv8qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-16.c
new file mode 100644
index 00000000000..0f1af0858ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-char-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-32.c
new file mode 100644
index 00000000000..a2794c84a83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-char-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-4.c
new file mode 100644
index 00000000000..a8e418770ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-char-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-8.c
new file mode 100644
index 00000000000..7a6a95922cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-char-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run.c
new file mode 100644
index 00000000000..d3ca775f6a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-char.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-char.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-char.c
new file mode 100644
index 00000000000..2321c8390c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-char.c
@@ -0,0 +1,10 @@
+#define TYPE char
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses HImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv64qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv64qi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64qi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64qi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-16.c
new file mode 100644
index 00000000000..659907d8d52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-16.c
@@ -0,0 +1,9 @@
+#define TYPE long
+#define N 16
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv16di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv16di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv16di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-32.c
new file mode 100644
index 00000000000..b03fd092470
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-32.c
@@ -0,0 +1,9 @@
+#define TYPE long
+#define N 32
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv32di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv32di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv32di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-4.c
new file mode 100644
index 00000000000..a8877b6c63b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-4.c
@@ -0,0 +1,9 @@
+#define TYPE long
+#define N 4
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv4di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv4di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv4di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-8.c
new file mode 100644
index 00000000000..5b1106c73af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-8.c
@@ -0,0 +1,9 @@
+#define TYPE long
+#define N 8
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv8di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv8di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv8di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-16.c
new file mode 100644
index 00000000000..20919255404
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-32.c
new file mode 100644
index 00000000000..c7ff7ca52b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-4.c
new file mode 100644
index 00000000000..c6cf3344ec4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-8.c
new file mode 100644
index 00000000000..85fdf6ffe1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run.c
new file mode 100644
index 00000000000..b948fa08c7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-long.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-long.c
new file mode 100644
index 00000000000..37b6cef691e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-long.c
@@ -0,0 +1,8 @@
+#define TYPE long
+#include "simd-math-5.c"
+
+/* { dg-final { scan-assembler-times {__divmodv64di4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64di3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64di3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64di3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-16.c
new file mode 100644
index 00000000000..20919255404
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-32.c
new file mode 100644
index 00000000000..c7ff7ca52b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-4.c
new file mode 100644
index 00000000000..c6cf3344ec4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-8.c
new file mode 100644
index 00000000000..85fdf6ffe1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-long-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-run.c
new file mode 100644
index 00000000000..de6504c737c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-16.c
new file mode 100644
index 00000000000..5d5953bc604
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-16.c
@@ -0,0 +1,11 @@
+#define TYPE short
+#define N 16
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses SImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod16.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv16si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv16hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv16hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv16hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv16hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-32.c
new file mode 100644
index 00000000000..bf8a3addfc4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-32.c
@@ -0,0 +1,11 @@
+#define TYPE short
+#define N 32
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses SImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod32.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv32si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv32hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv32hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv32hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv32hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-4.c
new file mode 100644
index 00000000000..a2cb46c8646
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-4.c
@@ -0,0 +1,11 @@
+#define TYPE short
+#define N 4
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses SImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod4.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv4si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv4hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv4hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv4hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv4hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-8.c
new file mode 100644
index 00000000000..fa343e5262e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-8.c
@@ -0,0 +1,11 @@
+#define TYPE short
+#define N 8
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses SImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmod8.i4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv8si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv8hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv8hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv8hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv8hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-16.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-16.c
new file mode 100644
index 00000000000..3fc946e2e09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-16.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-short-16.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-32.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-32.c
new file mode 100644
index 00000000000..34b1d75fa8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-32.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-short-32.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-4.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-4.c
new file mode 100644
index 00000000000..09385c78bc4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-4.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-short-4.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-8.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-8.c
new file mode 100644
index 00000000000..1de4d2631b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run-8.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-short-8.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run.c
new file mode 100644
index 00000000000..2e0c490fdd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short-run.c
@@ -0,0 +1,2 @@
+/* { dg-do run } */
+#include "simd-math-5-short.c"
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5-short.c b/gcc/testsuite/gcc.target/gcn/simd-math-5-short.c
new file mode 100644
index 00000000000..84cdc9b5fdd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5-short.c
@@ -0,0 +1,10 @@
+#define TYPE short
+#include "simd-math-5.c"
+
+/* C integer promotion means that div uses SImode and divmod doesn't match.  */
+/* { dg-final { scan-assembler-times {__divmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__divv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__divv64hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__udivv64hi3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64hi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64hi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/gcc.target/gcn/simd-math-5.c b/gcc/testsuite/gcc.target/gcn/simd-math-5.c
new file mode 100644
index 00000000000..bc181b45e1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/gcn/simd-math-5.c
@@ -0,0 +1,88 @@
+/* Test that the auto-vectorizer uses the libgcc vectorized division and
+   modulus functions.  */
+
+/* Setting it this way ensures the run tests use the same flag as the
+   compile tests.  */
+#pragma GCC optimize("O2")
+
+#ifndef TYPE
+#define TYPE int
+#endif
+#ifndef N
+#define N 64
+#endif
+
+TYPE a[N];
+TYPE b[N];
+
+int main()
+{
+  int i;
+  TYPE quot[N], rem[N];
+  TYPE quot2[N], rem2[N];
+  TYPE refquot[N], refrem[N];
+
+  for (i = 0; i < N; i++)
+    {
+      a[i] = i * (i >> 2) + (i >> 1);
+      b[i] = i;
+    }
+  __asm__ ("" ::: "memory");
+
+  /* Vector divmod.  */
+  for (i = 0; i < N; i++)
+    {
+      quot[i] = (TYPE)a[i] / (TYPE)b[i];
+      rem[i] = (TYPE)a[i] % (TYPE)b[i];
+    }
+  __asm__ ("" ::: "memory");
+
+  /* Vector div.  */
+  for (i = 0; i < N; i++)
+    quot2[i] = (TYPE)a[i] / (TYPE)b[i];
+  __asm__ ("" ::: "memory");
+
+  /* Vector mod.  */
+  for (i = 0; i < N; i++)
+    rem2[i] = (TYPE)a[i] % (TYPE)b[i];
+
+  /* Calculate reference values with no vectorization.  */
+  for (i = 0; i < N; i++)
+    {
+      refquot[i] = (TYPE)a[i] / (TYPE)b[i];
+      __asm__ ("" ::: "memory");
+      refrem[i] = (TYPE)a[i] % (TYPE)b[i];
+    }
+
+#ifdef DEBUG
+#define DUMP(VAR) \
+  __builtin_printf ("%8s: ", #VAR); \
+  for (i = 0; i < N; i++) \
+    __builtin_printf ("%d ", (int)VAR[i]); \
+  __builtin_printf ("\n");
+  DUMP (refquot)
+  DUMP (quot)
+  DUMP (quot2)
+  __builtin_printf ("\n");
+  DUMP (refrem)
+  DUMP (rem)
+  DUMP (rem2)
+#endif
+
+  for (i = 0; i < N; i++)
+    if (quot[i] != refquot[i]
+	|| quot2[i] != refquot[i]
+	|| rem[i] != refrem[i]
+	|| rem2[i] != refrem[i])
+      __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {__divmodv64si4@rel32@lo} 1 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times {__udivmodv64si4@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivv64si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__modv64si3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__umodv64si3@rel32@lo} 0 } } */
+/* { dg-final { scan-assembler-times {__divsi3@rel32@lo} 1 } } */
+/* { dg-final { scan-assembler-times {__udivsi3@rel32@lo} 0 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index c8ecb9fcfcc..d6134046fc5 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -8441,8 +8441,9 @@ proc check_effective_target_vect_long_mult { } {
 
 proc check_effective_target_vect_int_mod { } {
     return [check_cached_effective_target_indexed vect_int_mod {
-      expr { [istarget powerpc*-*-*]
-	     && [check_effective_target_has_arch_pwr10] }}]
+      expr { ([istarget powerpc*-*-*]
+	      && [check_effective_target_has_arch_pwr10])
+             || [istarget amdgcn-*-*] }}]
 }
 
 # Return 1 if the target supports vector even/odd elements extraction, 0 otherwise.
@@ -11574,7 +11575,8 @@ proc check_effective_target_divmod { } {
     #TODO: Add checks for all targets that have either hardware divmod insn
     # or define libfunc for divmod.
     if { [istarget arm*-*-*]
-	 || [istarget i?86-*-*] || [istarget x86_64-*-*] } {
+	 || [istarget i?86-*-*] || [istarget x86_64-*-*]
+         || [istarget amdgcn-*-*] } {
 	return 1
     }
     return 0
diff --git a/libgcc/ChangeLog.omp b/libgcc/ChangeLog.omp
index 866da56e547..d093ff2ec41 100644
--- a/libgcc/ChangeLog.omp
+++ b/libgcc/ChangeLog.omp
@@ -1,3 +1,19 @@
+2023-06-20  Andrew Stubbs  <ams@codesourcery.com>
+
+	Backport from mainline:
+	2023-06-19  Andrew Stubbs  <ams@codesourcery.com>
+
+	* config/gcn/lib2-divmod-di.c: Reimplement like lib2-divmod.c.
+	* config/gcn/lib2-divmod.c: Likewise.
+	* config/gcn/lib2-gcn.h: Add new types and prototypes for all the
+	new vector libfuncs.
+	* config/gcn/t-amdgcn: Add new files.
+	* config/gcn/amdgcn_veclib.h: New file.
+	* config/gcn/lib2-vec_divmod-di.c: New file.
+	* config/gcn/lib2-vec_divmod-hi.c: New file.
+	* config/gcn/lib2-vec_divmod-qi.c: New file.
+	* config/gcn/lib2-vec_divmod.c: New file.
+
 2023-06-20  Andrew Stubbs  <ams@codesourcery.com>
 
 	Backport from mainline:
diff --git a/libgcc/config/gcn/amdgcn_veclib.h b/libgcc/config/gcn/amdgcn_veclib.h
new file mode 100644
index 00000000000..15ea20bcd55
--- /dev/null
+++ b/libgcc/config/gcn/amdgcn_veclib.h
@@ -0,0 +1,322 @@
+/* Macro library used to help during conversion of scalar math functions to
+   vectorized SIMD equivalents on AMD GCN.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+   Contributed by Siemens.
+  
+   This file 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.
+
+   This file 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+typedef union {
+  v2sf t_v2sf;
+  v4sf t_v4sf;
+  v8sf t_v8sf;
+  v16sf t_v16sf;
+  v32sf t_v32sf;
+  v64sf t_v64sf;
+
+  v2df t_v2df;
+  v4df t_v4df;
+  v8df t_v8df;
+  v16df t_v16df;
+  v32df t_v32df;
+  v64df t_v64df;
+
+  v64qi t_v64qi;
+  v64hi t_v64hi;
+
+  v2si t_v2si;
+  v4si t_v4si;
+  v8si t_v8si;
+  v16si t_v16si;
+  v32si t_v32si;
+  v64si t_v64si;
+
+  v64usi t_v64usi;
+
+  v2di t_v2di;
+  v4di t_v4di;
+  v8di t_v8di;
+  v16di t_v16di;
+  v32di t_v32di;
+  v64di t_v64di;
+} vector_union;
+
+/* Cast between vectors with a different number of elements, or type.  */
+
+#define VGPR_CAST(to_t, from) \
+({ \
+  to_t __res; \
+  __asm__ ("" : "=v"(__res) : "0"(from)); \
+  __res; \
+})
+
+#define PACK_SI_PAIR(low, high) \
+({ \
+  v64udi __res; \
+  asm ("v_mov_b32\t%L0, %1\n\t" \
+       "v_mov_b32\t%H0, %2" \
+       : "=&v"(__res) : "v0"(low), "v"(high), "e"(-1L)); \
+  __res; \
+ })
+
+#define UNPACK_SI_LOW(to_t, pair) VGPR_CAST(to_t, pair)
+#define UNPACK_SI_HIGH(to_t, pair) \
+({ \
+  to_t __res; \
+  asm ("v_mov_b32\t%0, %H1" : "=v"(__res) : "v"(pair), "e"(-1L)); \
+  __res; \
+ })
+
+#define PACK_DI_PAIR(low, high) \
+({ \
+  v64uti __res; \
+  asm ("v_mov_b32\t%L0, %L1\n\t" \
+       "v_mov_b32\t%H0, %H1\n\t" \
+       "v_mov_b32\t%J0, %L2\n\t" \
+       "v_mov_b32\t%K0, %H2" \
+       : "=&v"(__res) : "v0"(low), "v"(high), "e"(-1L)); \
+  __res; \
+ })
+
+#define UNPACK_DI_LOW(to_t, pair) VGPR_CAST(to_t, pair)
+#define UNPACK_DI_HIGH(to_t, pair) \
+({ \
+  to_t __res; \
+  asm ("v_mov_b32\t%L0, %J1\n\t" \
+       "v_mov_b32\t%H0, %K1" : "=v"(__res) : "v"(pair), "e"(-1L)); \
+  __res; \
+ })
+
+#define NO_COND __mask
+
+/* Note - __mask is _not_ accounted for in VECTOR_MERGE!  */
+#define VECTOR_MERGE(vec1, vec2, cond) \
+({ \
+  _Static_assert (__builtin_types_compatible_p (typeof (vec1), typeof (vec2))); \
+  union { \
+    typeof (vec1) val; \
+    v64qi t_v64qi; \
+    v64hi t_v64hi; \
+    v64si t_v64si; \
+    v64di t_v64di; \
+  } __vec1, __vec2, __res; \
+  __vec1.val = (vec1); \
+  __vec2.val = (vec2); \
+  __builtin_choose_expr ( \
+        sizeof (vec1) == sizeof (v64si), \
+        ({ \
+          v64si __bitmask = __builtin_convertvector ((cond), v64si); \
+          __res.t_v64si = (__vec1.t_v64si & __bitmask) \
+                          | (__vec2.t_v64si & ~__bitmask); \
+        }), \
+	__builtin_choose_expr ( \
+	  sizeof (vec1) == sizeof (v64hi), \
+	  ({ \
+	    v64hi __bitmask = __builtin_convertvector ((cond), v64hi); \
+	    __res.t_v64hi = (__vec1.t_v64hi & __bitmask) \
+			    | (__vec2.t_v64hi & ~__bitmask); \
+	   }), \
+	   __builtin_choose_expr ( \
+	     sizeof (vec1) == sizeof (v64qi), \
+	     ({ \
+	     v64qi __bitmask = __builtin_convertvector ((cond), v64qi); \
+	     __res.t_v64qi = (__vec1.t_v64qi & __bitmask) \
+			      | (__vec2.t_v64qi & ~__bitmask); \
+	     }), \
+	     ({ \
+	      v64di __bitmask = __builtin_convertvector ((cond), v64di); \
+	      __res.t_v64di = (__vec1.t_v64di & __bitmask) \
+			      | (__vec2.t_v64di & ~__bitmask); \
+	      })))); \
+  __res.val; \
+})
+
+#define VECTOR_COND_MOVE(var, val, cond) \
+do { \
+  _Static_assert (__builtin_types_compatible_p (typeof (var), typeof (val))); \
+  __auto_type __cond = __builtin_convertvector ((cond), typeof (__mask)); \
+  var = VECTOR_MERGE ((val), var, __cond & __mask); \
+} while (0)
+
+#define VECTOR_IF(cond, cond_var) \
+{ \
+  __auto_type cond_var = (cond); \
+  __auto_type __inv_cond __attribute__((unused)) = ~cond_var; \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+#define VECTOR_ELSEIF(cond, cond_var) \
+  } \
+  cond_var = __inv_cond & (cond); \
+  __inv_cond &= ~(cond); \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+#define VECTOR_ELSE(cond_var) \
+  } \
+  cond_var = __inv_cond; \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+#define VECTOR_IF2(cond, cond_var, prev_cond_var) \
+{ \
+  __auto_type cond_var = (cond) & __builtin_convertvector (prev_cond_var, typeof (cond)); \
+  __auto_type __inv_cond __attribute__((unused)) = ~cond_var; \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+#define VECTOR_ELSEIF2(cond, cond_var, prev_cond_var) \
+  } \
+  cond_var = (cond) & __inv_cond & __builtin_convertvector (prev_cond_var, typeof (cond)); \
+  __inv_cond &= ~(cond); \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+#define VECTOR_ELSE2(cond_var, prev_cond_var) \
+  } \
+  cond_var = __inv_cond & __builtin_convertvector (prev_cond_var, typeof (__inv_cond)); \
+  if (!ALL_ZEROES_P (cond_var)) \
+  {
+
+
+#define VECTOR_ENDIF \
+  } \
+}
+
+#define VECTOR_INIT_AUX(x, type) \
+({ \
+  typeof (x) __e = (x); \
+  type __tmp = { \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e, \
+    __e, __e, __e, __e, __e, __e, __e, __e }; \
+  __tmp; \
+})
+
+#define VECTOR_INIT(x) \
+  (_Generic ((x), int: VECTOR_INIT_AUX ((x), v64si), \
+                  unsigned: VECTOR_INIT_AUX ((x), v64usi), \
+                  char: VECTOR_INIT_AUX ((x), v64qi), \
+                  unsigned char: VECTOR_INIT_AUX ((x), v64uqi), \
+                  short: VECTOR_INIT_AUX ((x), v64hi), \
+                  unsigned short: VECTOR_INIT_AUX ((x), v64uhi), \
+                  long: VECTOR_INIT_AUX ((x), v64di), \
+                  unsigned long: VECTOR_INIT_AUX ((x), v64udi), \
+                  float: VECTOR_INIT_AUX ((x), v64sf), \
+                  double: VECTOR_INIT_AUX ((x), v64df)))
+
+
+#if defined (__GCN3__) || defined (__GCN5__) \
+    || defined (__CDNA1__) || defined (__CDNA2__)
+#define CDNA3_PLUS 0
+#else
+#define CDNA3_PLUS 1
+#endif
+
+#define VECTOR_INIT_MASK(COUNT) \
+({ \
+  MASKMODE __mask; \
+  int count = (COUNT); \
+  if (count == 64) \
+    { \
+      if (sizeof (MASKMODE) < 512 || CDNA3_PLUS) \
+	asm ("v_mov%B0\t%0, -1" : "=v"(__mask) : "e"(-1L)); \
+      else \
+	asm ("v_mov_b32\t%L0, -1\n\t" \
+	     "v_mov_b32\t%H0, -1" : "=v"(__mask) : "e"(-1L)); \
+    } \
+  else \
+    { \
+      long bitmask = (count == 64 ? -1 : (1<<count)-1); \
+      if (sizeof (MASKMODE) < 512 || CDNA3_PLUS) \
+        { \
+	  asm ("v_mov%B0\t%0, 0" : "=v"(__mask) : "e"(-1L)); \
+	  asm ("v_mov%B0\t%0, -1" : "+v"(__mask) : "e"(bitmask)); \
+	} \
+      else \
+        { \
+	  asm ("v_mov_b32\t%L0, 0\n\t" \
+	       "v_mov_b32\t%H0, 0" : "=v"(__mask) : "e"(-1L)); \
+	  asm ("v_mov_b32\t%L0, -1\n\t" \
+	       "v_mov_b32\t%H0, -1" : "+v"(__mask) : "e"(bitmask)); \
+	} \
+    } \
+  __mask; \
+})
+
+#define ALL_ZEROES_P(x) (COND_TO_BITMASK(x) == 0)
+
+#define COND_TO_BITMASK(x) \
+({ \
+  long __tmp = 0; \
+  __auto_type __x = __builtin_convertvector((x), typeof (__mask)) & __mask; \
+  __builtin_choose_expr (sizeof (__mask) != 512, \
+                         ({ asm ("v_cmp_ne_u32_e64 %0, %1, 0" \
+                                 : "=Sg" (__tmp) \
+                                 : "v" (__x)); }), \
+                         ({ asm ("v_cmp_ne_u64_e64 %0, %1, 0" \
+                                 : "=Sg" (__tmp) \
+                                 : "v" (__x)); })); \
+  __tmp; \
+})
+
+#define VECTOR_WHILE(cond, cond_var, prev_cond_var) \
+{ \
+  __auto_type cond_var = prev_cond_var; \
+  for (;;) { \
+    cond_var &= (cond); \
+    if (ALL_ZEROES_P (cond_var)) \
+      break;
+
+#define VECTOR_ENDWHILE \
+  } \
+}
+
+#define DEF_VARIANT(FUN, SUFFIX, OTYPE, TYPE, COUNT) \
+v##COUNT##OTYPE \
+FUN##v##COUNT##SUFFIX (v##COUNT##TYPE __arg1, v##COUNT##TYPE __arg2) \
+{ \
+  __auto_type __upsized_arg1 = VGPR_CAST (v64##TYPE, __arg1); \
+  __auto_type __upsized_arg2 = VGPR_CAST (v64##TYPE, __arg2); \
+  __auto_type __mask = VECTOR_INIT_MASK (COUNT); \
+  __auto_type __result = FUN##v64##SUFFIX##_aux (__upsized_arg1, __upsized_arg2, __mask); \
+  return VGPR_CAST (v##COUNT##OTYPE, __result); \
+}
+
+#define DEF_VARIANTS(FUN, SUFFIX, TYPE) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 2) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 4) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 8) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 16) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 32) \
+  DEF_VARIANT (FUN, SUFFIX, TYPE, TYPE, 64)
+
+#define DEF_VARIANTS_B(FUN, SUFFIX, OTYPE, TYPE) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 2) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 4) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 8) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 16) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 32) \
+  DEF_VARIANT (FUN, SUFFIX, OTYPE, TYPE, 64)
diff --git a/libgcc/config/gcn/lib2-divmod-di.c b/libgcc/config/gcn/lib2-divmod-di.c
index a9023770c27..d0385f3b28c 100644
--- a/libgcc/config/gcn/lib2-divmod-di.c
+++ b/libgcc/config/gcn/lib2-divmod-di.c
@@ -22,14 +22,101 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #include "lib2-gcn.h"
 
-/* We really want DImode here: override LIBGCC2_UNITS_PER_WORD.  */
-#define LIBGCC2_UNITS_PER_WORD 4
-#define TARGET_HAS_NO_HW_DIVIDE
+/* 64-bit SI divide and modulo as used in gcn.  */
 
-#define L_divmoddi4
-#define L_divdi3
-#define L_moddi3
-#define L_udivdi3
-#define L_umoddi3
+union pack {
+  UTItype ti;
+  struct {DItype quot, rem;} pair;
+};
+union upack {
+  UTItype ti;
+  struct {UDItype quot, rem;} pair;
+};
+
+UTItype
+__udivmoddi4 (UDItype num, UDItype den)
+{
+  UDItype bit = 1;
+  union upack res = {0};
+
+  while (den < num && bit && !(den & (1L<<63)))
+    {
+      den <<=1;
+      bit <<=1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res.pair.quot |= bit;
+	}
+      bit >>=1;
+      den >>=1;
+    }
+  res.pair.rem = num;
+  return res.ti;
+}
+
+UTItype
+__divmoddi4 (DItype a, DItype b)
+{
+  word_type nega = 0, negb = 0;
+  union pack res;
+
+  if (a < 0)
+    {
+      a = -a;
+      nega = 1;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      negb = 1;
+    }
+
+  res.ti = __udivmoddi4 (a, b);
+
+  if (nega)
+    res.pair.rem = -res.pair.rem;
+  if (nega ^ negb)
+    res.pair.quot = -res.pair.quot;
+
+  return res.ti;
+}
+
+
+DItype
+__divdi3 (DItype a, DItype b)
+{
+  union pack u;
+  u.ti = __divmoddi4 (a, b);
+  return u.pair.quot;
+}
+
+DItype
+__moddi3 (DItype a, DItype b)
+{
+  union pack u;
+  u.ti = __divmoddi4 (a, b);
+  return u.pair.rem;
+}
+
+
+UDItype
+__udivdi3 (UDItype a, UDItype b)
+{
+  union pack u;
+  u.ti = __udivmoddi4 (a, b);
+  return u.pair.quot;
+}
+
+UDItype
+__umoddi3 (UDItype a, UDItype b)
+{
+  union pack u;
+ u.ti = __udivmoddi4 (a, b);
+ return u.pair.rem;
+}
 
-#include "libgcc2.c"
diff --git a/libgcc/config/gcn/lib2-divmod.c b/libgcc/config/gcn/lib2-divmod.c
index c350f7858f1..d701d1a4f58 100644
--- a/libgcc/config/gcn/lib2-divmod.c
+++ b/libgcc/config/gcn/lib2-divmod.c
@@ -24,11 +24,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 /* 32-bit SI divide and modulo as used in gcn.  */
 
-static USItype
-udivmodsi4 (USItype num, USItype den, word_type modwanted)
+union pack {
+  UDItype di;
+  struct {SItype quot, rem;} pair;
+};
+union upack {
+  UDItype di;
+  struct {USItype quot, rem;} pair;
+};
+
+UDItype
+__udivmodsi4 (USItype num, USItype den)
 {
   USItype bit = 1;
-  USItype res = 0;
+  union upack res = {0};
 
   while (den < num && bit && !(den & (1L<<31)))
     {
@@ -40,78 +49,75 @@ udivmodsi4 (USItype num, USItype den, word_type modwanted)
       if (num >= den)
 	{
 	  num -= den;
-	  res |= bit;
+	  res.pair.quot |= bit;
 	}
       bit >>=1;
       den >>=1;
     }
-  if (modwanted)
-    return num;
-  return res;
+  res.pair.rem = num;
+  return res.di;
 }
 
-
-SItype
-__divsi3 (SItype a, SItype b)
+UDItype
+__divmodsi4 (SItype a, SItype b)
 {
-  word_type neg = 0;
-  SItype res;
+  word_type nega = 0, negb = 0;
+  union pack res;
 
   if (a < 0)
     {
       a = -a;
-      neg = !neg;
+      nega = 1;
     }
 
   if (b < 0)
     {
       b = -b;
-      neg = !neg;
+      negb = 1;
     }
 
-  res = udivmodsi4 (a, b, 0);
+  res.di = __udivmodsi4 (a, b);
 
-  if (neg)
-    res = -res;
+  if (nega)
+    res.pair.rem = -res.pair.rem;
+  if (nega ^ negb)
+    res.pair.quot = -res.pair.quot;
 
-  return res;
+  return res.di;
 }
 
 
 SItype
-__modsi3 (SItype a, SItype b)
+__divsi3 (SItype a, SItype b)
 {
-  word_type neg = 0;
-  SItype res;
-
-  if (a < 0)
-    {
-      a = -a;
-      neg = 1;
-    }
-
-  if (b < 0)
-    b = -b;
-
-  res = udivmodsi4 (a, b, 1);
-
-  if (neg)
-    res = -res;
+  union pack u;
+  u.di = __divmodsi4 (a, b);
+  return u.pair.quot;
+}
 
-  return res;
+SItype
+__modsi3 (SItype a, SItype b)
+{
+  union pack u;
+  u.di = __divmodsi4 (a, b);
+  return u.pair.rem;
 }
 
 
 USItype
 __udivsi3 (USItype a, USItype b)
 {
-  return udivmodsi4 (a, b, 0);
+  union pack u;
+  u.di = __udivmodsi4 (a, b);
+  return u.pair.quot;
 }
 
 
 USItype
 __umodsi3 (USItype a, USItype b)
 {
-  return udivmodsi4 (a, b, 1);
+  union pack u;
+ u.di = __udivmodsi4 (a, b);
+ return u.pair.rem;
 }
 
diff --git a/libgcc/config/gcn/lib2-gcn.h b/libgcc/config/gcn/lib2-gcn.h
index 67ad9bafc19..dc071c0f727 100644
--- a/libgcc/config/gcn/lib2-gcn.h
+++ b/libgcc/config/gcn/lib2-gcn.h
@@ -35,15 +35,129 @@ typedef int TItype __attribute__ ((mode (TI)));
 typedef unsigned int UTItype __attribute__ ((mode (TI)));
 typedef int word_type __attribute__ ((mode (__word__)));
 
+typedef float v2sf __attribute__ ((vector_size (8)));
+typedef float v4sf __attribute__ ((vector_size (16)));
+typedef float v8sf __attribute__ ((vector_size (32)));
+typedef float v16sf __attribute__ ((vector_size (64)));
+typedef float v32sf __attribute__ ((vector_size (128)));
+typedef float v64sf __attribute__ ((vector_size (256)));
+
+typedef double v2df __attribute__ ((vector_size (16)));
+typedef double v4df __attribute__ ((vector_size (32)));
+typedef double v8df __attribute__ ((vector_size (64)));
+typedef double v16df __attribute__ ((vector_size (128)));
+typedef double v32df __attribute__ ((vector_size (256)));
+typedef double v64df __attribute__ ((vector_size (512)));
+
+typedef signed char v2qi __attribute__ ((vector_size (2)));
+typedef signed char v4qi __attribute__ ((vector_size (4)));
+typedef signed char v8qi __attribute__ ((vector_size (8)));
+typedef signed char v16qi __attribute__ ((vector_size (16)));
+typedef signed char v32qi __attribute__ ((vector_size (32)));
+typedef signed char v64qi __attribute__ ((vector_size (64)));
+
+typedef unsigned char v2uqi __attribute__ ((vector_size (2)));
+typedef unsigned char v4uqi __attribute__ ((vector_size (4)));
+typedef unsigned char v8uqi __attribute__ ((vector_size (8)));
+typedef unsigned char v16uqi __attribute__ ((vector_size (16)));
+typedef unsigned char v32uqi __attribute__ ((vector_size (32)));
+typedef unsigned char v64uqi __attribute__ ((vector_size (64)));
+
+typedef short v2hi __attribute__ ((vector_size (4)));
+typedef short v4hi __attribute__ ((vector_size (8)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+typedef short v16hi __attribute__ ((vector_size (32)));
+typedef short v32hi __attribute__ ((vector_size (64)));
+typedef short v64hi __attribute__ ((vector_size (128)));
+
+typedef unsigned short v2uhi __attribute__ ((vector_size (4)));
+typedef unsigned short v4uhi __attribute__ ((vector_size (8)));
+typedef unsigned short v8uhi __attribute__ ((vector_size (16)));
+typedef unsigned short v16uhi __attribute__ ((vector_size (32)));
+typedef unsigned short v32uhi __attribute__ ((vector_size (64)));
+typedef unsigned short v64uhi __attribute__ ((vector_size (128)));
+
+typedef int v2si __attribute__ ((vector_size (8)));
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef int v8si __attribute__ ((vector_size (32)));
+typedef int v16si __attribute__ ((vector_size (64)));
+typedef int v32si __attribute__ ((vector_size (128)));
+typedef int v64si __attribute__ ((vector_size (256)));
+
+typedef unsigned int v2usi __attribute__ ((vector_size (8)));
+typedef unsigned int v4usi __attribute__ ((vector_size (16)));
+typedef unsigned int v8usi __attribute__ ((vector_size (32)));
+typedef unsigned int v16usi __attribute__ ((vector_size (64)));
+typedef unsigned int v32usi __attribute__ ((vector_size (128)));
+typedef unsigned int v64usi __attribute__ ((vector_size (256)));
+
+typedef long v2di __attribute__ ((vector_size (16)));
+typedef long v4di __attribute__ ((vector_size (32)));
+typedef long v8di __attribute__ ((vector_size (64)));
+typedef long v16di __attribute__ ((vector_size (128)));
+typedef long v32di __attribute__ ((vector_size (256)));
+typedef long v64di __attribute__ ((vector_size (512)));
+
+typedef unsigned long v2udi __attribute__ ((vector_size (16)));
+typedef unsigned long v4udi __attribute__ ((vector_size (32)));
+typedef unsigned long v8udi __attribute__ ((vector_size (64)));
+typedef unsigned long v16udi __attribute__ ((vector_size (128)));
+typedef unsigned long v32udi __attribute__ ((vector_size (256)));
+typedef unsigned long v64udi __attribute__ ((vector_size (512)));
+
+typedef UTItype v2uti __attribute__ ((vector_size (32)));
+typedef UTItype v4uti __attribute__ ((vector_size (64)));
+typedef UTItype v8uti __attribute__ ((vector_size (128)));
+typedef UTItype v16uti __attribute__ ((vector_size (256)));
+typedef UTItype v32uti __attribute__ ((vector_size (512)));
+typedef UTItype v64uti __attribute__ ((vector_size (1024)));
+
 /* Exported functions.  */
 extern DItype __divdi3 (DItype, DItype);
 extern DItype __moddi3 (DItype, DItype);
+extern UTItype __divmoddi4 (DItype, DItype);
 extern UDItype __udivdi3 (UDItype, UDItype);
 extern UDItype __umoddi3 (UDItype, UDItype);
+extern UTItype __udivmoddi4 (UDItype, UDItype);
 extern SItype __divsi3 (SItype, SItype);
 extern SItype __modsi3 (SItype, SItype);
+extern UDItype __divmodsi4 (SItype, SItype);
 extern USItype __udivsi3 (USItype, USItype);
 extern USItype __umodsi3 (USItype, USItype);
+extern UDItype __udivmodsi4 (USItype, USItype);
 extern SItype __mulsi3 (SItype, SItype);
 
+#define VECTOR_PROTOTYPES(SIZE) \
+  extern v##SIZE##qi  __divv##SIZE##qi3     (v##SIZE##qi,  v##SIZE##qi);  \
+  extern v##SIZE##qi  __modv##SIZE##qi3     (v##SIZE##qi,  v##SIZE##qi);  \
+  extern v##SIZE##udi __divmodv##SIZE##qi4  (v##SIZE##qi,  v##SIZE##qi);  \
+  extern v##SIZE##uqi __udivv##SIZE##qi3    (v##SIZE##uqi, v##SIZE##uqi); \
+  extern v##SIZE##uqi __umodv##SIZE##qi3    (v##SIZE##uqi, v##SIZE##uqi); \
+  extern v##SIZE##udi __udivmodv##SIZE##qi4 (v##SIZE##uqi, v##SIZE##uqi);  \
+  extern v##SIZE##hi  __divv##SIZE##hi3     (v##SIZE##hi,  v##SIZE##hi);  \
+  extern v##SIZE##hi  __modv##SIZE##hi3     (v##SIZE##hi,  v##SIZE##hi);  \
+  extern v##SIZE##udi __divmodv##SIZE##hi4  (v##SIZE##hi,  v##SIZE##hi);  \
+  extern v##SIZE##uhi __udivv##SIZE##hi3    (v##SIZE##uhi, v##SIZE##uhi); \
+  extern v##SIZE##uhi __umodv##SIZE##hi3    (v##SIZE##uhi, v##SIZE##uhi); \
+  extern v##SIZE##udi __udivmodv##SIZE##hi4 (v##SIZE##uhi, v##SIZE##uhi); \
+  extern v##SIZE##si  __divv##SIZE##si3     (v##SIZE##si,  v##SIZE##si);  \
+  extern v##SIZE##si  __modv##SIZE##si3     (v##SIZE##si,  v##SIZE##si);  \
+  extern v##SIZE##udi __divmodv##SIZE##si4  (v##SIZE##si,  v##SIZE##si);  \
+  extern v##SIZE##usi __udivv##SIZE##si3    (v##SIZE##usi, v##SIZE##usi); \
+  extern v##SIZE##usi __umodv##SIZE##si3    (v##SIZE##usi, v##SIZE##usi); \
+  extern v##SIZE##udi __udivmodv##SIZE##si4 (v##SIZE##usi, v##SIZE##usi); \
+  extern v##SIZE##di  __divv##SIZE##di3     (v##SIZE##di,  v##SIZE##di);  \
+  extern v##SIZE##di  __modv##SIZE##di3     (v##SIZE##di,  v##SIZE##di);  \
+  extern v##SIZE##uti __divmodv##SIZE##di4  (v##SIZE##di,  v##SIZE##di);  \
+  extern v##SIZE##udi __udivv##SIZE##di3    (v##SIZE##udi, v##SIZE##udi); \
+  extern v##SIZE##udi __umodv##SIZE##di3    (v##SIZE##udi, v##SIZE##udi); \
+  extern v##SIZE##uti __udivmodv##SIZE##di4 (v##SIZE##udi, v##SIZE##udi);
+VECTOR_PROTOTYPES (2)
+VECTOR_PROTOTYPES (4)
+VECTOR_PROTOTYPES (8)
+VECTOR_PROTOTYPES (16)
+VECTOR_PROTOTYPES (32)
+VECTOR_PROTOTYPES (64)
+#undef VECTOR_PROTOTYPES
+
 #endif /* LIB2_GCN_H */
diff --git a/libgcc/config/gcn/lib2-vec_divmod-di.c b/libgcc/config/gcn/lib2-vec_divmod-di.c
new file mode 100644
index 00000000000..8f4a035f198
--- /dev/null
+++ b/libgcc/config/gcn/lib2-vec_divmod-di.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file 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.
+
+This file 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-gcn.h"
+
+/* 64-bit V64SI divide and modulo as used in gcn.
+   This is a simple conversion from lib2-divmod.c.  */
+
+#define MASKMODE v64di
+#include "amdgcn_veclib.h"
+
+static v64uti
+__udivmodv64di4_aux (v64udi num, v64udi den, v64di __mask)
+{
+  v64udi bit = VECTOR_INIT (1UL);
+  v64udi res = VECTOR_INIT (0UL);
+
+  VECTOR_WHILE ((den < num) & (bit != 0) & ((den & (1L<<31)) == 0),
+		cond, NO_COND)
+    VECTOR_COND_MOVE (den, den << 1, cond);
+    VECTOR_COND_MOVE (bit, bit << 1, cond);
+  VECTOR_ENDWHILE
+  VECTOR_WHILE (bit != 0, loopcond, NO_COND)
+    VECTOR_IF2 (num >= den, ifcond, loopcond)
+      VECTOR_COND_MOVE (num, num - den, ifcond);
+      VECTOR_COND_MOVE (res, res | bit, ifcond);
+    VECTOR_ENDIF
+    VECTOR_COND_MOVE (bit, bit >> 1, loopcond);
+    VECTOR_COND_MOVE (den, den >> 1, loopcond);
+  VECTOR_ENDWHILE
+
+  return PACK_DI_PAIR (res, num);
+}
+
+static v64uti
+__divmodv64di4_aux (v64di a, v64di b, v64di __mask)
+{
+  v64di nega = VECTOR_INIT (0L);
+  v64di negb = VECTOR_INIT (0L);
+
+  VECTOR_IF (a < 0, cond)
+    VECTOR_COND_MOVE (a, -a, cond);
+    nega = cond;
+  VECTOR_ENDIF
+
+  VECTOR_IF (b < 0, cond)
+    VECTOR_COND_MOVE (b, -b, cond);
+    negb = cond;
+  VECTOR_ENDIF
+
+  v64udi ua = __builtin_convertvector (a, v64udi);
+  v64udi ub = __builtin_convertvector (b, v64udi);
+  v64uti pair = __udivmodv64di4_aux (ua, ub, __mask);
+
+  v64di quot = UNPACK_DI_LOW (v64di, pair);
+  v64di rem = UNPACK_DI_HIGH (v64di, pair);
+  VECTOR_COND_MOVE (quot, -quot, nega ^ negb);
+  VECTOR_COND_MOVE (rem, -rem, nega);
+  pair = PACK_DI_PAIR (quot, rem);
+
+  return pair;
+}
+
+
+static inline v64di
+__divv64di3_aux (v64di a, v64di b, v64di __mask)
+{
+  v64uti pair = __divmodv64di4_aux (a, b, __mask);
+  return UNPACK_DI_LOW (v64di, pair);
+}
+
+static inline v64di
+__modv64di3_aux (v64di a, v64di b, v64di __mask)
+{
+  v64uti pair = __divmodv64di4_aux (a, b, __mask);
+  return UNPACK_DI_HIGH (v64di, pair);
+}
+
+
+static inline v64udi
+__udivv64di3_aux (v64udi a, v64udi b, v64di __mask)
+{
+  v64uti pair = __udivmodv64di4_aux (a, b, __mask);
+  return UNPACK_DI_LOW (v64udi, pair);
+}
+
+static inline v64udi
+__umodv64di3_aux (v64udi a, v64udi b, v64di __mask)
+{
+  v64uti pair = __udivmodv64di4_aux (a, b, __mask);
+  return UNPACK_DI_HIGH (v64udi, pair);
+}
+
+DEF_VARIANTS (__div, di3, di)
+DEF_VARIANTS (__mod, di3, di)
+DEF_VARIANTS_B (__divmod, di4, uti, di)
+DEF_VARIANTS (__udiv, di3, udi)
+DEF_VARIANTS (__umod, di3, udi)
+DEF_VARIANTS_B (__udivmod, di4, uti, udi)
diff --git a/libgcc/config/gcn/lib2-vec_divmod-hi.c b/libgcc/config/gcn/lib2-vec_divmod-hi.c
new file mode 100644
index 00000000000..175ddf84bb2
--- /dev/null
+++ b/libgcc/config/gcn/lib2-vec_divmod-hi.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file 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.
+
+This file 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-gcn.h"
+
+/* 16-bit V64HI divide and modulo as used in gcn.
+   This is a simple conversion from lib2-divmod.c.  */
+
+#define MASKMODE v64hi
+#include "amdgcn_veclib.h"
+
+static v64udi
+__udivmodv64hi4_aux (v64uhi num, v64uhi den, v64hi __mask)
+{
+  v64uhi bit = VECTOR_INIT ((unsigned short)1U);
+  v64uhi res = VECTOR_INIT ((unsigned short)0U);
+
+  VECTOR_WHILE ((den < num) & (bit != 0) & ((den & (1L<<15)) == 0),
+		cond, NO_COND)
+    VECTOR_COND_MOVE (den, den << 1, cond);
+    VECTOR_COND_MOVE (bit, bit << 1, cond);
+  VECTOR_ENDWHILE
+  VECTOR_WHILE (bit != 0, loopcond, NO_COND)
+    VECTOR_IF2 (num >= den, ifcond, loopcond)
+      VECTOR_COND_MOVE (num, num - den, ifcond);
+      VECTOR_COND_MOVE (res, res | bit, ifcond);
+    VECTOR_ENDIF
+    VECTOR_COND_MOVE (bit, bit >> 1, loopcond);
+    VECTOR_COND_MOVE (den, den >> 1, loopcond);
+  VECTOR_ENDWHILE
+
+  return PACK_SI_PAIR (res, num);
+}
+
+static v64udi
+__divmodv64hi4_aux (v64hi a, v64hi b,  v64hi __mask)
+{
+  v64hi nega = VECTOR_INIT ((short)0);
+  v64hi negb = VECTOR_INIT ((short)0);
+
+  VECTOR_IF (a < 0, cond)
+    VECTOR_COND_MOVE (a, -a, cond);
+    nega = cond;
+  VECTOR_ENDIF
+
+  VECTOR_IF (b < 0, cond)
+    VECTOR_COND_MOVE (b, -b, cond);
+    negb = cond;
+  VECTOR_ENDIF
+
+  v64uhi ua = __builtin_convertvector (a, v64uhi);
+  v64uhi ub = __builtin_convertvector (b, v64uhi);
+  v64udi pair = __udivmodv64hi4_aux (ua, ub, __mask);
+
+  v64hi quot = UNPACK_SI_LOW (v64hi, pair);
+  v64hi rem = UNPACK_SI_HIGH (v64hi, pair);
+  VECTOR_COND_MOVE (quot, -quot, nega ^ negb);
+  VECTOR_COND_MOVE (rem, -rem, nega);
+  pair = PACK_SI_PAIR (quot, rem);
+
+  return pair;
+}
+
+
+static inline v64hi
+__divv64hi3_aux (v64hi a, v64hi b, v64hi __mask)
+{
+  v64udi pair = __divmodv64hi4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64hi, pair);
+}
+
+static inline v64hi
+__modv64hi3_aux (v64hi a, v64hi b, v64hi __mask)
+{
+  v64udi pair = __divmodv64hi4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64hi, pair);
+}
+
+
+static inline v64uhi
+__udivv64hi3_aux (v64uhi a, v64uhi b, v64hi __mask)
+{
+  v64udi pair = __udivmodv64hi4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64uhi, pair);
+}
+
+static inline v64uhi
+__umodv64hi3_aux (v64uhi a, v64uhi b, v64hi __mask)
+{
+  v64udi pair = __udivmodv64hi4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64uhi, pair);
+}
+
+DEF_VARIANTS (__div, hi3, hi)
+DEF_VARIANTS (__mod, hi3, hi)
+DEF_VARIANTS_B (__divmod, hi4, udi, hi)
+DEF_VARIANTS (__udiv, hi3, uhi)
+DEF_VARIANTS (__umod, hi3, uhi)
+DEF_VARIANTS_B (__udivmod, hi4, udi, uhi)
diff --git a/libgcc/config/gcn/lib2-vec_divmod-qi.c b/libgcc/config/gcn/lib2-vec_divmod-qi.c
new file mode 100644
index 00000000000..ff6b5c2e7d8
--- /dev/null
+++ b/libgcc/config/gcn/lib2-vec_divmod-qi.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file 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.
+
+This file 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-gcn.h"
+
+/* 8-bit V64QI divide and modulo as used in gcn.
+   This is a simple conversion from lib2-divmod.c.  */
+
+#define MASKMODE v64qi
+#include "amdgcn_veclib.h"
+
+static v64udi
+__udivmodv64qi4_aux (v64uqi num, v64uqi den, v64qi __mask)
+{
+  v64uqi bit = VECTOR_INIT ((unsigned char)1U);
+  v64uqi res = VECTOR_INIT ((unsigned char)0U);
+
+  VECTOR_WHILE ((den < num) & (bit != 0) & ((den & (1<<7)) == 0),
+		cond, NO_COND)
+    VECTOR_COND_MOVE (den, den << 1, cond);
+    VECTOR_COND_MOVE (bit, bit << 1, cond);
+  VECTOR_ENDWHILE
+  VECTOR_WHILE (bit != 0, loopcond, NO_COND)
+    VECTOR_IF2 (num >= den, ifcond, loopcond)
+      VECTOR_COND_MOVE (num, num - den, ifcond);
+      VECTOR_COND_MOVE (res, res | bit, ifcond);
+    VECTOR_ENDIF
+    VECTOR_COND_MOVE (bit, bit >> 1, loopcond);
+    VECTOR_COND_MOVE (den, den >> 1, loopcond);
+  VECTOR_ENDWHILE
+
+  return PACK_SI_PAIR (res, num);
+}
+
+static v64udi
+__divmodv64qi4_aux (v64qi a, v64qi b, v64qi __mask)
+{
+  v64qi nega = VECTOR_INIT ((char)0);
+  v64qi negb = VECTOR_INIT ((char)0);
+
+  VECTOR_IF (a < 0, cond)
+    VECTOR_COND_MOVE (a, -a, cond);
+    nega = cond;
+  VECTOR_ENDIF
+
+  VECTOR_IF (b < 0, cond)
+    VECTOR_COND_MOVE (b, -b, cond);
+    negb = cond;
+  VECTOR_ENDIF
+
+  v64uqi ua = __builtin_convertvector (a, v64uqi);
+  v64uqi ub = __builtin_convertvector (b, v64uqi);
+  v64udi pair = __udivmodv64qi4_aux (ua, ub, __mask);
+
+  v64qi quot = UNPACK_SI_LOW (v64qi, pair);
+  v64qi rem = UNPACK_SI_HIGH (v64qi, pair);
+  VECTOR_COND_MOVE (quot, -quot, nega ^ negb);
+  VECTOR_COND_MOVE (rem, -rem, nega);
+  pair = PACK_SI_PAIR (quot, rem);
+
+  return pair;
+}
+
+
+static inline v64qi
+__divv64qi3_aux (v64qi a, v64qi b, v64qi __mask)
+{
+  v64udi pair = __divmodv64qi4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64qi, pair);
+}
+
+static inline v64qi
+__modv64qi3_aux (v64qi a, v64qi b, v64qi __mask)
+{
+  v64udi pair = __divmodv64qi4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64qi, pair);
+}
+
+
+static inline v64uqi
+__udivv64qi3_aux (v64uqi a, v64uqi b, v64qi __mask)
+{
+  v64udi pair = __udivmodv64qi4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64uqi, pair);
+}
+
+static inline v64uqi
+__umodv64qi3_aux (v64uqi a, v64uqi b, v64qi __mask)
+{
+  v64udi pair = __udivmodv64qi4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64uqi, pair);
+}
+
+DEF_VARIANTS (__div, qi3, qi)
+DEF_VARIANTS (__mod, qi3, qi)
+DEF_VARIANTS_B (__divmod, qi4, udi, qi)
+DEF_VARIANTS (__udiv, qi3, uqi)
+DEF_VARIANTS (__umod, qi3, uqi)
+DEF_VARIANTS_B (__udivmod, qi4, udi, uqi)
diff --git a/libgcc/config/gcn/lib2-vec_divmod.c b/libgcc/config/gcn/lib2-vec_divmod.c
new file mode 100644
index 00000000000..e1667668e68
--- /dev/null
+++ b/libgcc/config/gcn/lib2-vec_divmod.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file 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.
+
+This file 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-gcn.h"
+
+/* 32-bit V64SI divide and modulo as used in gcn.
+   This is a simple conversion from lib2-divmod.c.  */
+
+#define MASKMODE v64si
+#include "amdgcn_veclib.h"
+
+static v64udi
+__udivmodv64si4_aux (v64usi num, v64usi den, v64si __mask)
+{
+  v64usi bit = VECTOR_INIT (1U);
+  v64usi res = VECTOR_INIT (0U);
+
+  VECTOR_WHILE ((den < num) & (bit != 0) & ((den & (1L<<31)) == 0),
+		cond, NO_COND)
+    VECTOR_COND_MOVE (den, den << 1, cond);
+    VECTOR_COND_MOVE (bit, bit << 1, cond);
+  VECTOR_ENDWHILE
+  VECTOR_WHILE (bit != 0, loopcond, NO_COND)
+    VECTOR_IF2 (num >= den, ifcond, loopcond)
+      VECTOR_COND_MOVE (num, num - den, ifcond);
+      VECTOR_COND_MOVE (res, res | bit, ifcond);
+    VECTOR_ENDIF
+    VECTOR_COND_MOVE (bit, bit >> 1, loopcond);
+    VECTOR_COND_MOVE (den, den >> 1, loopcond);
+  VECTOR_ENDWHILE
+
+  return PACK_SI_PAIR (res, num);
+}
+
+static v64udi
+__divmodv64si4_aux (v64si a, v64si b, v64si __mask)
+{
+  v64si nega = VECTOR_INIT (0);
+  v64si negb = VECTOR_INIT (0);
+
+  VECTOR_IF (a < 0, cond)
+    VECTOR_COND_MOVE (a, -a, cond);
+    nega = cond;
+  VECTOR_ENDIF
+
+  VECTOR_IF (b < 0, cond)
+    VECTOR_COND_MOVE (b, -b, cond);
+    negb = cond;
+  VECTOR_ENDIF
+
+  v64usi ua = __builtin_convertvector (a, v64usi);
+  v64usi ub = __builtin_convertvector (b, v64usi);
+  v64udi pair = __udivmodv64si4_aux (ua, ub, __mask);
+
+  v64si quot = UNPACK_SI_LOW (v64si, pair);
+  v64si rem = UNPACK_SI_HIGH (v64si, pair);
+  VECTOR_COND_MOVE (quot, -quot, nega ^ negb);
+  VECTOR_COND_MOVE (rem, -rem, nega);
+  pair = PACK_SI_PAIR (quot, rem);
+
+  return pair;
+}
+
+
+static inline v64si
+__divv64si3_aux (v64si a, v64si b, v64si __mask)
+{
+  v64udi pair = __divmodv64si4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64si, pair);
+}
+
+static inline v64si
+__modv64si3_aux (v64si a, v64si b, v64si __mask)
+{
+  v64udi pair = __divmodv64si4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64si, pair);
+}
+
+
+static inline v64usi
+__udivv64si3_aux (v64usi a, v64usi b, v64si __mask)
+{
+  v64udi pair = __udivmodv64si4_aux (a, b, __mask);
+  return UNPACK_SI_LOW (v64usi, pair);
+}
+
+static inline v64usi
+__umodv64si3_aux (v64usi a, v64usi b, v64si __mask)
+{
+  v64udi pair = __udivmodv64si4_aux (a, b, __mask);
+  return UNPACK_SI_HIGH (v64usi, pair);
+}
+
+DEF_VARIANTS (__div, si3, si)
+DEF_VARIANTS (__mod, si3, si)
+DEF_VARIANTS_B (__divmod, si4, udi, si)
+DEF_VARIANTS (__udiv, si3, usi)
+DEF_VARIANTS (__umod, si3, usi)
+DEF_VARIANTS_B (__udivmod, si4, udi, usi)
diff --git a/libgcc/config/gcn/t-amdgcn b/libgcc/config/gcn/t-amdgcn
index e64953e6185..d1d9a4f92b5 100644
--- a/libgcc/config/gcn/t-amdgcn
+++ b/libgcc/config/gcn/t-amdgcn
@@ -1,6 +1,10 @@
 LIB2ADD += $(srcdir)/config/gcn/atomic.c \
 	   $(srcdir)/config/gcn/lib2-divmod.c \
 	   $(srcdir)/config/gcn/lib2-divmod-di.c \
+	   $(srcdir)/config/gcn/lib2-vec_divmod.c \
+	   $(srcdir)/config/gcn/lib2-vec_divmod-qi.c \
+	   $(srcdir)/config/gcn/lib2-vec_divmod-hi.c \
+	   $(srcdir)/config/gcn/lib2-vec_divmod-di.c \
 	   $(srcdir)/config/gcn/lib2-bswapti2.c \
 	   $(srcdir)/config/gcn/unwind-gcn.c

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-06-20  9:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-20  9:51 [gcc/devel/omp/gcc-13] amdgcn: implement vector div and mod libfuncs Andrew Stubbs

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