public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] amdgcn: Add instruction patterns for conditional min/max operations
@ 2023-03-01 16:56 Paul-Antoine Arras
  2023-03-02 17:18 ` Andrew Stubbs
  0 siblings, 1 reply; 4+ messages in thread
From: Paul-Antoine Arras @ 2023-03-01 16:56 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 273 bytes --]

This patch introduces instruction patterns for conditional min and max
operations (cond_{f|s|u}{max|min}) in the GCN machine description. It 
also allows the exec register to be saved in SGPRs to avoid spilling to 
memory.
Tested on GCN3 Fiji gfx803.

OK for trunk?
-- 
PA

[-- Attachment #2: 0001-amdgcn-Add-instruction-patterns-for-conditional-min-.patch --]
[-- Type: text/x-patch, Size: 85051 bytes --]

From 1cd86b4420d9d42bcde83d0ac52a03a07d4aa819 Mon Sep 17 00:00:00 2001
From: Paul-Antoine Arras <pa@codesourcery.com>
Date: Wed, 1 Mar 2023 17:20:21 +0100
Subject: [PATCH] amdgcn: Add instruction patterns for conditional min/max
 operations

gcc/ChangeLog:

	* config/gcn/gcn-valu.md (<expander><mode>3_exec): Add patterns for
	{s|u}{max|min} in QI, HI and DI modes.
	(<expander><mode>3): Add pattern for {s|u}{max|min} in DI mode.
	(cond_<fexpander><mode>): Add pattern for cond_f{max|min}.
	(cond_<expander><mode>): Add pattern for cond_{s|u}{max|min}.
	* config/gcn/gcn.cc (gcn_spill_class): Allow the exec register to be
	saved in SGPRs.

gcc/testsuite/ChangeLog:

	* gcc.target/gcn/cond_fmaxnm_1.c: New test.
	* gcc.target/gcn/cond_fmaxnm_1_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_2.c: New test.
	* gcc.target/gcn/cond_fmaxnm_2_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_3.c: New test.
	* gcc.target/gcn/cond_fmaxnm_3_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_4.c: New test.
	* gcc.target/gcn/cond_fmaxnm_4_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_5.c: New test.
	* gcc.target/gcn/cond_fmaxnm_5_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_6.c: New test.
	* gcc.target/gcn/cond_fmaxnm_6_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_7.c: New test.
	* gcc.target/gcn/cond_fmaxnm_7_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_8.c: New test.
	* gcc.target/gcn/cond_fmaxnm_8_run.c: New test.
	* gcc.target/gcn/cond_fminnm_1.c: New test.
	* gcc.target/gcn/cond_fminnm_1_run.c: New test.
	* gcc.target/gcn/cond_fminnm_2.c: New test.
	* gcc.target/gcn/cond_fminnm_2_run.c: New test.
	* gcc.target/gcn/cond_fminnm_3.c: New test.
	* gcc.target/gcn/cond_fminnm_3_run.c: New test.
	* gcc.target/gcn/cond_fminnm_4.c: New test.
	* gcc.target/gcn/cond_fminnm_4_run.c: New test.
	* gcc.target/gcn/cond_fminnm_5.c: New test.
	* gcc.target/gcn/cond_fminnm_5_run.c: New test.
	* gcc.target/gcn/cond_fminnm_6.c: New test.
	* gcc.target/gcn/cond_fminnm_6_run.c: New test.
	* gcc.target/gcn/cond_fminnm_7.c: New test.
	* gcc.target/gcn/cond_fminnm_7_run.c: New test.
	* gcc.target/gcn/cond_fminnm_8.c: New test.
	* gcc.target/gcn/cond_fminnm_8_run.c: New test.
	* gcc.target/gcn/cond_smax_1.c: New test.
	* gcc.target/gcn/cond_smax_1_run.c: New test.
	* gcc.target/gcn/cond_smin_1.c: New test.
	* gcc.target/gcn/cond_smin_1_run.c: New test.
	* gcc.target/gcn/cond_umax_1.c: New test.
	* gcc.target/gcn/cond_umax_1_run.c: New test.
	* gcc.target/gcn/cond_umin_1.c: New test.
	* gcc.target/gcn/cond_umin_1_run.c: New test.
	* gcc.target/gcn/smax_1.c: New test.
	* gcc.target/gcn/smax_1_run.c: New test.
	* gcc.target/gcn/smin_1.c: New test.
	* gcc.target/gcn/smin_1_run.c: New test.
	* gcc.target/gcn/umax_1.c: New test.
	* gcc.target/gcn/umax_1_run.c: New test.
	* gcc.target/gcn/umin_1.c: New test.
	* gcc.target/gcn/umin_1_run.c: New test.
---
 gcc/config/gcn/gcn-valu.md                    | 134 +++++++++++++++++-
 gcc/config/gcn/gcn.cc                         |   2 +-
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c  |  36 +++++
 .../gcc.target/gcn/cond_fmaxnm_1_run.c        |  32 +++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c  |  35 +++++
 .../gcc.target/gcn/cond_fmaxnm_2_run.c        |  31 ++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c  |  37 +++++
 .../gcc.target/gcn/cond_fmaxnm_3_run.c        |  32 +++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c  |  37 +++++
 .../gcc.target/gcn/cond_fmaxnm_4_run.c        |  32 +++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_5_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_6_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_7_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_8_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_1_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_2_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c  |  12 ++
 .../gcc.target/gcn/cond_fminnm_3_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c  |  12 ++
 .../gcc.target/gcn/cond_fminnm_4_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_5_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_6_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_7_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_8_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_smax_1.c    |  59 ++++++++
 .../gcc.target/gcn/cond_smax_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_smin_1.c    |  57 ++++++++
 .../gcc.target/gcn/cond_smin_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_umax_1.c    |  54 +++++++
 .../gcc.target/gcn/cond_umax_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_umin_1.c    |  53 +++++++
 .../gcc.target/gcn/cond_umin_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/smax_1.c         |  50 +++++++
 gcc/testsuite/gcc.target/gcn/smax_1_run.c     |  49 +++++++
 gcc/testsuite/gcc.target/gcn/smin_1.c         |  50 +++++++
 gcc/testsuite/gcc.target/gcn/smin_1_run.c     |  49 +++++++
 gcc/testsuite/gcc.target/gcn/umax_1.c         |  47 ++++++
 gcc/testsuite/gcc.target/gcn/umax_1_run.c     |  49 +++++++
 gcc/testsuite/gcc.target/gcn/umin_1.c         |  47 ++++++
 gcc/testsuite/gcc.target/gcn/umin_1_run.c     |  49 +++++++
 50 files changed, 1403 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1_run.c

diff --git gcc/config/gcn/gcn-valu.md gcc/config/gcn/gcn-valu.md
index 47d9d87d58a..13d7013de75 100644
--- gcc/config/gcn/gcn-valu.md
+++ gcc/config/gcn/gcn-valu.md
@@ -2358,6 +2358,34 @@ (define_expand "<expander><mode>3"
     DONE;
   })
 
+(define_expand "<expander><mode>3_exec"
+  [(set (match_operand:V_QIHI 0 "gcn_valu_dst_operand")
+	(vec_merge:V_QIHI
+	  (minmaxop:V_QIHI
+	    (match_operand:V_QIHI 1 "gcn_valu_src0_operand")
+	    (match_operand:V_QIHI 2 "gcn_valu_src1com_operand"))
+	  (match_operand:V_QIHI 3 "gcn_register_or_unspec_operand" "U0")
+	  (match_operand:DI 4 "gcn_exec_reg_operand" "e")))]
+  ""
+  {
+    enum {smin, umin, smax, umax};
+    bool unsignedp = (<code> == umax || <code> == umin);
+    rtx insi1 = gen_reg_rtx (<VnSI>mode);
+    rtx insi2 = gen_reg_rtx (<VnSI>mode);
+    rtx outsi = gen_reg_rtx (<VnSI>mode);
+    rtx out = operands[0];
+    rtx exec = operands[4];
+    rtx tmp = gen_reg_rtx (<MODE>mode);
+
+    convert_move (insi1, operands[1], unsignedp);
+    convert_move (insi2, operands[2], unsignedp);
+    emit_insn (gen_<code><vnsi>3_exec (outsi, insi1, insi2,
+                                      gcn_gen_undef(<VnSI>mode), exec));
+    convert_move (tmp, outsi, unsignedp);
+    emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec));
+    DONE;
+  })
+
 (define_insn "<expander><vnsi>3<exec>"
   [(set (match_operand:V_SI 0 "gcn_valu_dst_operand"	   "=  v,RD")
 	(minmaxop:V_SI
@@ -2370,6 +2398,69 @@ (define_insn "<expander><vnsi>3<exec>"
   [(set_attr "type" "vop2,ds")
    (set_attr "length" "8,8")])
 
+(define_insn_and_split "<expander><mode>3"
+  [(set (match_operand:V_DI 0 "register_operand"      "=  v")
+	(minmaxop:V_DI
+	  (match_operand:V_DI 1 "gcn_alu_operand"     "%  v")
+          (match_operand:V_DI 2 "gcn_alu_operand"     "   v")))
+    (clobber (reg:DI VCC_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  {
+    rtx out = operands[0];
+    rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+
+    enum {smin, smax, umin, umax};
+    bool minp = (<code> == smin || <code> == umin);
+    if (<code> == smin || <code> == smax)
+      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) :
+                                    gen_rtx_GT (VOIDmode, 0, 0), operands[1], operands[2]));
+    else
+      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) :
+                                    gen_rtx_GTU (VOIDmode, 0, 0), operands[1], operands[2]));
+    emit_insn (gen_vcond_mask_<mode>di (out, operands[1], operands[2], vcc));
+  }
+  [(set_attr "type" "mult")])
+
+(define_insn_and_split "<expander><mode>3_exec"
+  [(set (match_operand:V_DI 0 "register_operand"                 "=  v")
+	(vec_merge:V_DI
+          (minmaxop:V_DI
+            (match_operand:V_DI 1 "gcn_alu_operand"              "%  v")
+            (match_operand:V_DI 2 "gcn_alu_operand"              "   v"))
+          (match_operand:V_DI 3 "gcn_register_or_unspec_operand" "  U0")
+          (match_operand:DI 4 "gcn_exec_reg_operand"  "+e")))
+    (clobber (match_scratch:<VnDI> 5		      "= &v"))
+    (clobber (reg:DI VCC_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  {
+    rtx out = operands[0];
+    rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+    rtx exec = operands[4];
+    rtx tmp = operands[5];
+
+    enum {smin, smax, umin, umax};
+    bool minp = (<code> == smin || <code> == umin);
+    if (<code> == smin || <code> == smax)
+      emit_insn (gen_vec_cmp<mode>di_exec (vcc,
+                                         minp ? gen_rtx_LT (VOIDmode, 0, 0) :
+                                         gen_rtx_GT (VOIDmode, 0, 0), operands[1],
+                                         operands[2], exec));
+    else
+      emit_insn (gen_vec_cmp<mode>di_exec (vcc,
+                                         minp ? gen_rtx_LTU (VOIDmode, 0, 0) :
+                                         gen_rtx_GTU (VOIDmode, 0, 0), operands[1],
+                                         operands[2], exec));
+    emit_insn (gen_vcond_mask_<mode>di (tmp, operands[1], operands[2], vcc));
+    emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec));
+  }
+  [(set_attr "type" "mult")])
+
 ;; }}}
 ;; {{{ Int unops
 
@@ -3468,7 +3559,48 @@ (define_expand "cond_<expander><mode>"
     DONE;
   })
 
-;; TODO smin umin smax umax
+(define_code_iterator cond_fminmaxop [smin smax])
+
+(define_expand "cond_<fexpander><mode>"
+  [(match_operand:V_FP 0 "register_operand")
+   (match_operand:DI 1 "register_operand")
+   (cond_fminmaxop:V_FP
+     (match_operand:V_FP 2 "gcn_alu_operand")
+     (match_operand:V_FP 3 "gcn_alu_operand"))
+   (match_operand:V_FP 4 "register_operand")]
+  ""
+  {
+    operands[1] = force_reg (DImode, operands[1]);
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+
+    emit_insn (gen_<fexpander><mode>3_exec (operands[0], operands[2],
+					   operands[3], operands[4],
+					   operands[1]));
+    DONE;
+  })
+
+(define_code_iterator cond_minmaxop [smin smax umin umax])
+
+(define_expand "cond_<expander><mode>"
+  [(match_operand:V_INT 0 "register_operand")
+   (match_operand:DI 1 "register_operand")
+   (cond_minmaxop:V_INT
+     (match_operand:V_INT 2 "gcn_alu_operand")
+     (match_operand:V_INT 3 "gcn_alu_operand"))
+   (match_operand:V_INT 4 "register_operand")]
+  ""
+  {
+    operands[1] = force_reg (DImode, operands[1]);
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+    rtx tmp = gen_reg_rtx (<MODE>mode);
+
+    emit_insn (gen_<expander><mode>3_exec (tmp, operands[2],
+					   operands[3], gcn_gen_undef(<MODE>mode),
+					   operands[1]));
+    emit_insn (gen_vcond_mask_<mode>di (operands[0], tmp, operands[4], operands[1]));
+    DONE;
+  })
+
 (define_code_iterator cond_bitop [and ior xor])
 
 (define_expand "cond_<expander><mode>"
diff --git gcc/config/gcn/gcn.cc gcc/config/gcn/gcn.cc
index 23ab01e75d8..b4216b73522 100644
--- gcc/config/gcn/gcn.cc
+++ gcc/config/gcn/gcn.cc
@@ -797,7 +797,7 @@ static reg_class_t
 gcn_spill_class (reg_class_t c, machine_mode /*mode */ )
 {
   if (reg_classes_intersect_p (ALL_CONDITIONAL_REGS, c)
-      || c == VCC_CONDITIONAL_REG)
+      || c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG)
     return SGPR_REGS;
   else
     return NO_REGS;
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
new file mode 100644
index 00000000000..61c0798b30d
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)	\
+  void __attribute__ ((noipa))				\
+  test_##TYPE##_##NAME (TYPE *__restrict x,		\
+			TYPE *__restrict y,		\
+			PRED_TYPE *__restrict pred,	\
+			int n)				\
+  {							\
+    for (int i = 0; i < n; ++i)				\
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : y[i];	\
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \
+  T (FN, TYPE, PRED_TYPE, zero, 0) \
+  T (FN, TYPE, PRED_TYPE, one, 1) \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T) \
+  TEST_TYPE (T, FN (f32), float, int32_t) \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
new file mode 100644
index 00000000000..ed4b471ca4d
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_1.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)			\
+  {									\
+    TYPE x[N], y[N];							\
+    PRED_TYPE pred[N];							\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	y[i] = i * i;							\
+	pred[i] = i % 3;						\
+      }									\
+    test_##TYPE##_##NAME (x, y, pred, N);				\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : y[i];		\
+	if (x[i] != expected)						\
+	  __builtin_abort ();						\
+	asm volatile ("" ::: "memory");					\
+      }									\
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
new file mode 100644
index 00000000000..3d25ffcfe94
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, NAME, CONST)			\
+  void __attribute__ ((noipa))				\
+  test_##TYPE##_##NAME (TYPE *__restrict x,		\
+			TYPE *__restrict y,		\
+			TYPE *__restrict z,		\
+			int n)				\
+  {							\
+    for (int i = 0; i < n; ++i)				\
+      x[i] = y[i] < 8 ? FN (z[i], CONST) : y[i];	\
+  }
+
+#define TEST_TYPE(T, FN, TYPE) \
+  T (FN, TYPE, zero, 0) \
+  T (FN, TYPE, one, 1) \
+  T (FN, TYPE, two, 2)
+
+#define TEST_ALL(T) \
+  TEST_TYPE (T, FN (f32), float) \
+  TEST_TYPE (T, FN (f64), double)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
new file mode 100644
index 00000000000..970fd6cfe5a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_2.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, NAME, CONST)				\
+  {									\
+    TYPE x[N], y[N], z[N];						\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	y[i] = i % 13;							\
+	z[i] = i * i;							\
+      }									\
+    test_##TYPE##_##NAME (x, y, z, N);					\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	TYPE expected = y[i] < 8 ? FN (z[i], CONST) : y[i];		\
+	if (x[i] != expected)						\
+	  __builtin_abort ();						\
+	asm volatile ("" ::: "memory");					\
+      }									\
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
new file mode 100644
index 00000000000..55543fec4b0
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)	\
+  void __attribute__ ((noipa))				\
+  test_##TYPE##_##NAME (TYPE *__restrict x,		\
+			TYPE *__restrict y,		\
+			PRED_TYPE *__restrict pred,	\
+			int n)				\
+  {							\
+    for (int i = 0; i < n; ++i)				\
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : 4;	\
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \
+  T (FN, TYPE, PRED_TYPE, zero, 0) \
+  T (FN, TYPE, PRED_TYPE, one, 1) \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T) \
+  TEST_TYPE (T, FN (f32), float, int32_t) \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
new file mode 100644
index 00000000000..469bee10678
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_3.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)	       	\
+  {								\
+    TYPE x[N], y[N];						\
+    PRED_TYPE pred[N];						\
+    for (int i = 0; i < N; ++i)					\
+      {								\
+	y[i] = i * i;						\
+	pred[i] = i % 3;					\
+      }								\
+    test_##TYPE##_##NAME (x, y, pred, N);			\
+    for (int i = 0; i < N; ++i)					\
+      {								\
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 4;	\
+	if (x[i] != expected)					\
+	  __builtin_abort ();					\
+	asm volatile ("" ::: "memory");				\
+      }								\
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
new file mode 100644
index 00000000000..65fc2a9b30d
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)	\
+  void __attribute__ ((noipa))				\
+  test_##TYPE##_##NAME (TYPE *__restrict x,		\
+			TYPE *__restrict y,		\
+			PRED_TYPE *__restrict pred,	\
+			int n)				\
+  {							\
+    for (int i = 0; i < n; ++i)				\
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : 0;	\
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \
+  T (FN, TYPE, PRED_TYPE, zero, 0) \
+  T (FN, TYPE, PRED_TYPE, one, 1) \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T) \
+  TEST_TYPE (T, FN (f32), float, int32_t) \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
new file mode 100644
index 00000000000..874d1d3bb54
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_4.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)			\
+  {									\
+    TYPE x[N], y[N];							\
+    PRED_TYPE pred[N];							\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	y[i] = i * i;							\
+	pred[i] = i % 3;						\
+      }									\
+    test_##TYPE##_##NAME (x, y, pred, N);				\
+    for (int i = 0; i < N; ++i)						\
+      {									\
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 0;		\
+	if (x[i] != expected)						\
+	  __builtin_abort ();						\
+	asm volatile ("" ::: "memory");					\
+      }									\
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
new file mode 100644
index 00000000000..a4d7ab991de
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
new file mode 100644
index 00000000000..8c0bc2ae876
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
new file mode 100644
index 00000000000..6c64a01bcbb
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
new file mode 100644
index 00000000000..5c5db46b390
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
new file mode 100644
index 00000000000..bdb3f2f99ef
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
new file mode 100644
index 00000000000..0abe626fdfb
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
new file mode 100644
index 00000000000..c11633b5236
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
new file mode 100644
index 00000000000..43b892f922e
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
new file mode 100644
index 00000000000..bb456887568
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
new file mode 100644
index 00000000000..6dd9d499b35
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
new file mode 100644
index 00000000000..502f8987494
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
new file mode 100644
index 00000000000..72784290113
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
new file mode 100644
index 00000000000..2ea1eb2ec2c
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
new file mode 100644
index 00000000000..8c994cae202
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
new file mode 100644
index 00000000000..3673ecafc2d
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
new file mode 100644
index 00000000000..728f4136015
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
new file mode 100644
index 00000000000..ac98941a373
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
new file mode 100644
index 00000000000..9236ab5b211
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
new file mode 100644
index 00000000000..7f4dba0d314
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
new file mode 100644
index 00000000000..a5f90d9e76a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
new file mode 100644
index 00000000000..5faf0c5cc59
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
new file mode 100644
index 00000000000..d7ad738db5c
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
new file mode 100644
index 00000000000..89d93ac596a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
new file mode 100644
index 00000000000..3d92353ac55
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1.c gcc/testsuite/gcc.target/gcn/cond_smax_1.c
new file mode 100644
index 00000000000..181abd209b5
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smax_1.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,             \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != -1) ? (x[i] > y[i] ? x[i] : y[i]) : -4;  \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,      \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != -1)                                                  \
+		 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE)             \
+		 : -4;                                                     \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)			\
+  REG (TYPE);				\
+  IMM (0, TYPE, 0);		\
+  IMM (86, TYPE, 86);		\
+  IMM (109, TYPE, 109);		\
+  IMM (141, TYPE, 141);		\
+  IMM (92137445376, TYPE, 92137445376);                                                        \
+  IMM (-1, TYPE, minus1);		\
+  IMM (-110, TYPE, minus110);	\
+  IMM (-141, TYPE, minus141); \
+  IMM (-92137445376, TYPE, minus92137445376);      
+
+
+#define TEST_ALL(REG, IMM) \
+  DO_ARITH_OPS (REG, IMM, int8_t) \
+  DO_ARITH_OPS (REG, IMM, int16_t) \
+  DO_ARITH_OPS (REG, IMM, int32_t) \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL(DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per test case < 64 bits */
+/* { dg-final { scan-assembler-times {smaxv64si3_exec} 30 } } */
+/* { dg-final { scan-assembler-not {smaxv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
+/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
new file mode 100644
index 00000000000..c951e614579
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_smax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != -1 ? (x[i] > y[i] ? x[i] : y[i]) : -4;        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != -1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1.c gcc/testsuite/gcc.target/gcn/cond_smin_1.c
new file mode 100644
index 00000000000..8d75b2c47b8
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != -1) ? (x[i] < y[i] ? x[i] : y[i]) : -4;               \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,        \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i]                                                                     \
+	= (pred[i] != -1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;  \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);  \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141); \
+  IMM (-92137445376, TYPE, minus92137445376); 
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per test case < 64 bits */
+/* { dg-final { scan-assembler-times {sminv64si3_exec} 30 } } */
+/* { dg-final { scan-assembler-not {sminv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
+/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
new file mode 100644
index 00000000000..4d654e75226
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_smin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != -1 ? (x[i] < y[i] ? x[i] : y[i]) : -4;        \
+	if (x[i] != expected)                                                 \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != -1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1.c gcc/testsuite/gcc.target/gcn/cond_umax_1.c
new file mode 100644
index 00000000000..389228f9e4a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] > y[i] ? x[i] : y[i]) : 4;                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* Two per test case < 64 bits with wide-enough type:*/
+/* { dg-final { scan-assembler-times {umaxv64si3_exec} 20 } } */
+/* { dg-final { scan-assembler-not {umaxv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+
diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
new file mode 100644
index 00000000000..0abcf46dd6f
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_umax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? (x[i] > y[i] ? x[i] : y[i]) : 4;        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != 1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1.c gcc/testsuite/gcc.target/gcn/cond_umin_1.c
new file mode 100644
index 00000000000..a04b5635090
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] < y[i] ? x[i] : y[i]) : 4;                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* Two per test case < 64 bits with wide-enough type:*/
+/* { dg-final { scan-assembler-times {uminv64si3_exec} 20 } } */
+/* { dg-final { scan-assembler-not {uminv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
new file mode 100644
index 00000000000..eda49ebc681
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_umin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? (x[i] < y[i] ? x[i] : y[i]) : 4;        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != 1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smax_1.c gcc/testsuite/gcc.target/gcn/smax_1.c
new file mode 100644
index 00000000000..32ed3a4eb84
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smax_1.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,             \
+		       int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > y[i] ? x[i] : y[i];  \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x,      \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;                                                     \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)			\
+  REG (TYPE);				\
+  IMM (0, TYPE, 0);		\
+  IMM (86, TYPE, 86);		\
+  IMM (109, TYPE, 109);		\
+  IMM (141, TYPE, 141);		\
+  IMM (92137445376, TYPE, 92137445376);                                                        \
+  IMM (-1, TYPE, minus1);		\
+  IMM (-110, TYPE, minus110);	\
+  IMM (-141, TYPE, minus141); \
+  IMM (-92137445376, TYPE, minus92137445376);      
+
+
+#define TEST_ALL(REG, IMM) \
+  DO_ARITH_OPS (REG, IMM, int8_t) \
+  DO_ARITH_OPS (REG, IMM, int16_t) \
+  DO_ARITH_OPS (REG, IMM, int32_t) \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL(DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smax_1_run.c gcc/testsuite/gcc.target/gcn/smax_1_run.c
new file mode 100644
index 00000000000..f12fef1d697
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smax_1_run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "smax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > y[i] ? x[i] : y[i];        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smin_1.c gcc/testsuite/gcc.target/gcn/smin_1.c
new file mode 100644
index 00000000000..e70b7b1fb1e
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smin_1.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < y[i] ? x[i] : y[i];               \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x,        \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i]                                                                     \
+	= x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;  \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);  \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141); \
+  IMM (-92137445376, TYPE, minus92137445376); 
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
+
+/* Two per test case:*/
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smin_1_run.c gcc/testsuite/gcc.target/gcn/smin_1_run.c
new file mode 100644
index 00000000000..b57de12c17f
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smin_1_run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "smin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < y[i] ? x[i] : y[i];        \
+	if (x[i] != expected)                                                 \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/umax_1.c gcc/testsuite/gcc.target/gcn/umax_1.c
new file mode 100644
index 00000000000..3bed8353a2b
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umax_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > y[i] ? x[i] : y[i];                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
diff --git gcc/testsuite/gcc.target/gcn/umax_1_run.c gcc/testsuite/gcc.target/gcn/umax_1_run.c
new file mode 100644
index 00000000000..d047b7a0576
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umax_1_run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "umax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > y[i] ? x[i] : y[i];        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/umin_1.c gcc/testsuite/gcc.target/gcn/umin_1.c
new file mode 100644
index 00000000000..c4f11f2adfb
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umin_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < y[i] ? x[i] : y[i];                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
diff --git gcc/testsuite/gcc.target/gcn/umin_1_run.c gcc/testsuite/gcc.target/gcn/umin_1_run.c
new file mode 100644
index 00000000000..77a5df95b46
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umin_1_run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "umin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < y[i] ? x[i] : y[i];        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
-- 
2.39.2


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

* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations
  2023-03-01 16:56 [PATCH] amdgcn: Add instruction patterns for conditional min/max operations Paul-Antoine Arras
@ 2023-03-02 17:18 ` Andrew Stubbs
  2023-03-03 17:05   ` Paul-Antoine Arras
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew Stubbs @ 2023-03-02 17:18 UTC (permalink / raw)
  To: Paul-Antoine Arras, gcc-patches

On 01/03/2023 16:56, Paul-Antoine Arras wrote:
> This patch introduces instruction patterns for conditional min and max
> operations (cond_{f|s|u}{max|min}) in the GCN machine description. It 
> also allows the exec register to be saved in SGPRs to avoid spilling to 
> memory.
> Tested on GCN3 Fiji gfx803.
> 
> OK for trunk?

Not quite yet, but it's only a few cosmetic issues, I think.

> +(define_insn_and_split "<expander><mode>3"
> +  [(set (match_operand:V_DI 0 "register_operand"      "=  v")
> +	(minmaxop:V_DI
> +	  (match_operand:V_DI 1 "gcn_alu_operand"     "%  v")
> +          (match_operand:V_DI 2 "gcn_alu_operand"     "   v")))
> +    (clobber (reg:DI VCC_REG))]

No need to make it commutative when the two operands have the same 
constraints. There's a few more instances of this later.

> +    if (<code> == smin || <code> == smax)
> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) :
> +                                    gen_rtx_GT (VOIDmode, 0, 0), operands[1], operands[2]));
> +    else
> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) :
> +                                    gen_rtx_GTU (VOIDmode, 0, 0), operands[1], operands[2]));
> +

Long lines need to be wrapped, here and elsewhere.

Andrew

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

* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations
  2023-03-02 17:18 ` Andrew Stubbs
@ 2023-03-03 17:05   ` Paul-Antoine Arras
  2023-03-06 13:27     ` Andrew Stubbs
  0 siblings, 1 reply; 4+ messages in thread
From: Paul-Antoine Arras @ 2023-03-03 17:05 UTC (permalink / raw)
  To: Andrew Stubbs, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1613 bytes --]

Le 02/03/2023 à 18:18, Andrew Stubbs a écrit :
> On 01/03/2023 16:56, Paul-Antoine Arras wrote:
>> This patch introduces instruction patterns for conditional min and max
>> operations (cond_{f|s|u}{max|min}) in the GCN machine description. It 
>> also allows the exec register to be saved in SGPRs to avoid spilling 
>> to memory.
>> Tested on GCN3 Fiji gfx803.
>>
>> OK for trunk?
> 
> Not quite yet, but it's only a few cosmetic issues, I think.
> 
>> +(define_insn_and_split "<expander><mode>3"
>> +  [(set (match_operand:V_DI 0 "register_operand"      "=  v")
>> +    (minmaxop:V_DI
>> +      (match_operand:V_DI 1 "gcn_alu_operand"     "%  v")
>> +          (match_operand:V_DI 2 "gcn_alu_operand"     "   v")))
>> +    (clobber (reg:DI VCC_REG))]
> 
> No need to make it commutative when the two operands have the same 
> constraints. There's a few more instances of this later.
> 
>> +    if (<code> == smin || <code> == smax)
>> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT 
>> (VOIDmode, 0, 0) :
>> +                                    gen_rtx_GT (VOIDmode, 0, 0), 
>> operands[1], operands[2]));
>> +    else
>> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU 
>> (VOIDmode, 0, 0) :
>> +                                    gen_rtx_GTU (VOIDmode, 0, 0), 
>> operands[1], operands[2]));
>> +
> 
> Long lines need to be wrapped, here and elsewhere.

The amended patch attached should fix those issues. Let me know if it 
looks good to you.
-- 
PA

[-- Attachment #2: 0001-amdgcn-Add-instruction-patterns-for-conditional-min-.patch --]
[-- Type: text/x-patch, Size: 91396 bytes --]

From cdb2d170091d87b0a5968cca49fc34ac434bb54c Mon Sep 17 00:00:00 2001
From: Paul-Antoine Arras <pa@codesourcery.com>
Date: Wed, 1 Mar 2023 17:20:21 +0100
Subject: [PATCH] amdgcn: Add instruction patterns for conditional min/max
 operations

gcc/ChangeLog:

	* config/gcn/gcn-valu.md (<expander><mode>3_exec): Add patterns for
	{s|u}{max|min} in QI, HI and DI modes.
	(<expander><mode>3): Add pattern for {s|u}{max|min} in DI mode.
	(cond_<fexpander><mode>): Add pattern for cond_f{max|min}.
	(cond_<expander><mode>): Add pattern for cond_{s|u}{max|min}.
	* config/gcn/gcn.cc (gcn_spill_class): Allow the exec register to be
	saved in SGPRs.

gcc/testsuite/ChangeLog:

	* gcc.target/gcn/cond_fmaxnm_1.c: New test.
	* gcc.target/gcn/cond_fmaxnm_1_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_2.c: New test.
	* gcc.target/gcn/cond_fmaxnm_2_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_3.c: New test.
	* gcc.target/gcn/cond_fmaxnm_3_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_4.c: New test.
	* gcc.target/gcn/cond_fmaxnm_4_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_5.c: New test.
	* gcc.target/gcn/cond_fmaxnm_5_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_6.c: New test.
	* gcc.target/gcn/cond_fmaxnm_6_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_7.c: New test.
	* gcc.target/gcn/cond_fmaxnm_7_run.c: New test.
	* gcc.target/gcn/cond_fmaxnm_8.c: New test.
	* gcc.target/gcn/cond_fmaxnm_8_run.c: New test.
	* gcc.target/gcn/cond_fminnm_1.c: New test.
	* gcc.target/gcn/cond_fminnm_1_run.c: New test.
	* gcc.target/gcn/cond_fminnm_2.c: New test.
	* gcc.target/gcn/cond_fminnm_2_run.c: New test.
	* gcc.target/gcn/cond_fminnm_3.c: New test.
	* gcc.target/gcn/cond_fminnm_3_run.c: New test.
	* gcc.target/gcn/cond_fminnm_4.c: New test.
	* gcc.target/gcn/cond_fminnm_4_run.c: New test.
	* gcc.target/gcn/cond_fminnm_5.c: New test.
	* gcc.target/gcn/cond_fminnm_5_run.c: New test.
	* gcc.target/gcn/cond_fminnm_6.c: New test.
	* gcc.target/gcn/cond_fminnm_6_run.c: New test.
	* gcc.target/gcn/cond_fminnm_7.c: New test.
	* gcc.target/gcn/cond_fminnm_7_run.c: New test.
	* gcc.target/gcn/cond_fminnm_8.c: New test.
	* gcc.target/gcn/cond_fminnm_8_run.c: New test.
	* gcc.target/gcn/cond_smax_1.c: New test.
	* gcc.target/gcn/cond_smax_1_run.c: New test.
	* gcc.target/gcn/cond_smin_1.c: New test.
	* gcc.target/gcn/cond_smin_1_run.c: New test.
	* gcc.target/gcn/cond_umax_1.c: New test.
	* gcc.target/gcn/cond_umax_1_run.c: New test.
	* gcc.target/gcn/cond_umin_1.c: New test.
	* gcc.target/gcn/cond_umin_1_run.c: New test.
	* gcc.target/gcn/smax_1.c: New test.
	* gcc.target/gcn/smax_1_run.c: New test.
	* gcc.target/gcn/smin_1.c: New test.
	* gcc.target/gcn/smin_1_run.c: New test.
	* gcc.target/gcn/umax_1.c: New test.
	* gcc.target/gcn/umax_1_run.c: New test.
	* gcc.target/gcn/umin_1.c: New test.
	* gcc.target/gcn/umin_1_run.c: New test.
---
 gcc/config/gcn/gcn-valu.md                    | 137 +++++++++++++++++-
 gcc/config/gcn/gcn.cc                         |   2 +-
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c  |  33 +++++
 .../gcc.target/gcn/cond_fmaxnm_1_run.c        |  32 ++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c  |  33 +++++
 .../gcc.target/gcn/cond_fmaxnm_2_run.c        |  31 ++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c  |  35 +++++
 .../gcc.target/gcn/cond_fmaxnm_3_run.c        |  32 ++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c  |  35 +++++
 .../gcc.target/gcn/cond_fmaxnm_4_run.c        |  32 ++++
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_5_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_6_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_7_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c  |   9 ++
 .../gcc.target/gcn/cond_fmaxnm_8_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_1_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_2_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c  |  12 ++
 .../gcc.target/gcn/cond_fminnm_3_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c  |  12 ++
 .../gcc.target/gcn/cond_fminnm_4_run.c        |   5 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_5_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_6_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_7_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c  |  10 ++
 .../gcc.target/gcn/cond_fminnm_8_run.c        |   4 +
 gcc/testsuite/gcc.target/gcn/cond_smax_1.c    |  57 ++++++++
 .../gcc.target/gcn/cond_smax_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_smin_1.c    |  57 ++++++++
 .../gcc.target/gcn/cond_smin_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_umax_1.c    |  54 +++++++
 .../gcc.target/gcn/cond_umax_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/cond_umin_1.c    |  53 +++++++
 .../gcc.target/gcn/cond_umin_1_run.c          |  53 +++++++
 gcc/testsuite/gcc.target/gcn/smax_1.c         |  47 ++++++
 gcc/testsuite/gcc.target/gcn/smax_1_run.c     |  48 ++++++
 gcc/testsuite/gcc.target/gcn/smin_1.c         |  47 ++++++
 gcc/testsuite/gcc.target/gcn/smin_1_run.c     |  48 ++++++
 gcc/testsuite/gcc.target/gcn/umax_1.c         |  45 ++++++
 gcc/testsuite/gcc.target/gcn/umax_1_run.c     |  48 ++++++
 gcc/testsuite/gcc.target/gcn/umin_1.c         |  45 ++++++
 gcc/testsuite/gcc.target/gcn/umin_1_run.c     |  48 ++++++
 50 files changed, 1381 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1_run.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1.c
 create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1_run.c

diff --git gcc/config/gcn/gcn-valu.md gcc/config/gcn/gcn-valu.md
index 47d9d87d58a..75e9a59600b 100644
--- gcc/config/gcn/gcn-valu.md
+++ gcc/config/gcn/gcn-valu.md
@@ -2358,6 +2358,34 @@ (define_expand "<expander><mode>3"
     DONE;
   })
 
+(define_expand "<expander><mode>3_exec"
+  [(set (match_operand:V_QIHI 0 "gcn_valu_dst_operand")
+	(vec_merge:V_QIHI
+	  (minmaxop:V_QIHI
+	    (match_operand:V_QIHI 1 "gcn_valu_src0_operand")
+	    (match_operand:V_QIHI 2 "gcn_valu_src1com_operand"))
+	  (match_operand:V_QIHI 3 "gcn_register_or_unspec_operand" "U0")
+	  (match_operand:DI 4 "gcn_exec_reg_operand" "e")))]
+  ""
+  {
+    enum {smin, umin, smax, umax};
+    bool unsignedp = (<code> == umax || <code> == umin);
+    rtx insi1 = gen_reg_rtx (<VnSI>mode);
+    rtx insi2 = gen_reg_rtx (<VnSI>mode);
+    rtx outsi = gen_reg_rtx (<VnSI>mode);
+    rtx out = operands[0];
+    rtx exec = operands[4];
+    rtx tmp = gen_reg_rtx (<MODE>mode);
+
+    convert_move (insi1, operands[1], unsignedp);
+    convert_move (insi2, operands[2], unsignedp);
+    emit_insn (gen_<code><vnsi>3_exec (outsi, insi1, insi2,
+                                       gcn_gen_undef(<VnSI>mode), exec));
+    convert_move (tmp, outsi, unsignedp);
+    emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec));
+    DONE;
+  })
+
 (define_insn "<expander><vnsi>3<exec>"
   [(set (match_operand:V_SI 0 "gcn_valu_dst_operand"	   "=  v,RD")
 	(minmaxop:V_SI
@@ -2370,6 +2398,71 @@ (define_insn "<expander><vnsi>3<exec>"
   [(set_attr "type" "vop2,ds")
    (set_attr "length" "8,8")])
 
+(define_insn_and_split "<expander><mode>3"
+  [(set (match_operand:V_DI 0 "register_operand"      "=v")
+	(minmaxop:V_DI
+	  (match_operand:V_DI 1 "gcn_alu_operand"     " v")
+	  (match_operand:V_DI 2 "gcn_alu_operand"     " v")))
+    (clobber (reg:DI VCC_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  {
+    rtx out = operands[0];
+    rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+
+    enum {smin, smax, umin, umax};
+    bool minp = (<code> == smin || <code> == umin);
+    if (<code> == smin || <code> == smax)
+      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) :
+                                      gen_rtx_GT (VOIDmode, 0, 0), operands[1],
+                                      operands[2]));
+    else
+      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) :
+                                      gen_rtx_GTU (VOIDmode, 0, 0), operands[1],
+                                      operands[2]));
+    emit_insn (gen_vcond_mask_<mode>di (out, operands[1], operands[2], vcc));
+  }
+  [(set_attr "type" "mult")])
+
+(define_insn_and_split "<expander><mode>3_exec"
+  [(set (match_operand:V_DI 0 "register_operand"                 "= v")
+	(vec_merge:V_DI
+          (minmaxop:V_DI
+            (match_operand:V_DI 1 "gcn_alu_operand"              "  v")
+            (match_operand:V_DI 2 "gcn_alu_operand"              "  v"))
+          (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0")
+          (match_operand:DI 4 "gcn_exec_reg_operand"  "+e")))
+    (clobber (match_scratch:<VnDI> 5		      "= &v"))
+    (clobber (reg:DI VCC_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+  {
+    rtx out = operands[0];
+    rtx vcc = gen_rtx_REG (DImode, VCC_REG);
+    rtx exec = operands[4];
+    rtx tmp = operands[5];
+
+    enum {smin, smax, umin, umax};
+    bool minp = (<code> == smin || <code> == umin);
+    if (<code> == smin || <code> == smax)
+      emit_insn (gen_vec_cmp<mode>di_exec (vcc,
+                                           minp ? gen_rtx_LT (VOIDmode, 0, 0) :
+                                           gen_rtx_GT (VOIDmode, 0, 0),
+                                           operands[1], operands[2], exec));
+    else
+      emit_insn (gen_vec_cmp<mode>di_exec (vcc,
+                                           minp ? gen_rtx_LTU (VOIDmode, 0, 0) :
+                                           gen_rtx_GTU (VOIDmode, 0, 0),
+                                           operands[1], operands[2], exec));
+    emit_insn (gen_vcond_mask_<mode>di (tmp, operands[1], operands[2], vcc));
+    emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec));
+  }
+  [(set_attr "type" "mult")])
+
 ;; }}}
 ;; {{{ Int unops
 
@@ -3468,7 +3561,49 @@ (define_expand "cond_<expander><mode>"
     DONE;
   })
 
-;; TODO smin umin smax umax
+(define_code_iterator cond_fminmaxop [smin smax])
+
+(define_expand "cond_<fexpander><mode>"
+  [(match_operand:V_FP 0 "register_operand")
+   (match_operand:DI 1 "register_operand")
+   (cond_fminmaxop:V_FP
+     (match_operand:V_FP 2 "gcn_alu_operand")
+     (match_operand:V_FP 3 "gcn_alu_operand"))
+   (match_operand:V_FP 4 "register_operand")]
+  ""
+  {
+    operands[1] = force_reg (DImode, operands[1]);
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+
+    emit_insn (gen_<fexpander><mode>3_exec (operands[0], operands[2],
+					    operands[3], operands[4],
+					    operands[1]));
+    DONE;
+  })
+
+(define_code_iterator cond_minmaxop [smin smax umin umax])
+
+(define_expand "cond_<expander><mode>"
+  [(match_operand:V_INT 0 "register_operand")
+   (match_operand:DI 1 "register_operand")
+   (cond_minmaxop:V_INT
+     (match_operand:V_INT 2 "gcn_alu_operand")
+     (match_operand:V_INT 3 "gcn_alu_operand"))
+   (match_operand:V_INT 4 "register_operand")]
+  ""
+  {
+    operands[1] = force_reg (DImode, operands[1]);
+    operands[2] = force_reg (<MODE>mode, operands[2]);
+    rtx tmp = gen_reg_rtx (<MODE>mode);
+
+    emit_insn (gen_<expander><mode>3_exec (tmp, operands[2], operands[3],
+                                           gcn_gen_undef(<MODE>mode),
+                                           operands[1]));
+    emit_insn (gen_vcond_mask_<mode>di (operands[0], tmp, operands[4],
+                                        operands[1]));
+    DONE;
+  })
+
 (define_code_iterator cond_bitop [and ior xor])
 
 (define_expand "cond_<expander><mode>"
diff --git gcc/config/gcn/gcn.cc gcc/config/gcn/gcn.cc
index 23ab01e75d8..b4216b73522 100644
--- gcc/config/gcn/gcn.cc
+++ gcc/config/gcn/gcn.cc
@@ -797,7 +797,7 @@ static reg_class_t
 gcn_spill_class (reg_class_t c, machine_mode /*mode */ )
 {
   if (reg_classes_intersect_p (ALL_CONDITIONAL_REGS, c)
-      || c == VCC_CONDITIONAL_REG)
+      || c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG)
     return SGPR_REGS;
   else
     return NO_REGS;
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
new file mode 100644
index 00000000000..17c49bdc518
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                             \
+  void __attribute__ ((noipa))                                                 \
+  test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y,                \
+			PRED_TYPE *__restrict pred, int n)                     \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : y[i];                           \
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE)                                      \
+  T (FN, TYPE, PRED_TYPE, zero, 0)                                             \
+  T (FN, TYPE, PRED_TYPE, one, 1)                                              \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T)                                                            \
+  TEST_TYPE (T, FN (f32), float, int32_t)                                      \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
new file mode 100644
index 00000000000..1e4c81c17a9
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_1.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                            \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    PRED_TYPE pred[N];                                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    test_##TYPE##_##NAME (x, y, pred, N);                                      \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : y[i];                  \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
new file mode 100644
index 00000000000..406df48962a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, NAME, CONST)                                        \
+  void __attribute__ ((noipa))                                                 \
+  test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y,                \
+			TYPE *__restrict z, int n)                             \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      x[i] = y[i] < 8 ? FN (z[i], CONST) : y[i];                               \
+  }
+
+#define TEST_TYPE(T, FN, TYPE)                                                 \
+  T (FN, TYPE, zero, 0)                                                        \
+  T (FN, TYPE, one, 1)                                                         \
+  T (FN, TYPE, two, 2)
+
+#define TEST_ALL(T)                                                            \
+  TEST_TYPE (T, FN (f32), float)                                               \
+  TEST_TYPE (T, FN (f64), double)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
new file mode 100644
index 00000000000..05d18f41f06
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_2.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, NAME, CONST)                                       \
+  {                                                                            \
+    TYPE x[N], y[N], z[N];                                                     \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	y[i] = i % 13;                                                         \
+	z[i] = i * i;                                                          \
+      }                                                                        \
+    test_##TYPE##_##NAME (x, y, z, N);                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = y[i] < 8 ? FN (z[i], CONST) : y[i];                    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
new file mode 100644
index 00000000000..45b8b7883ba
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                             \
+  void __attribute__ ((noipa))                                                 \
+  test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y,                \
+			PRED_TYPE *__restrict pred, int n)                     \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : 4;                              \
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE)                                      \
+  T (FN, TYPE, PRED_TYPE, zero, 0)                                             \
+  T (FN, TYPE, PRED_TYPE, one, 1)                                              \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T)                                                            \
+  TEST_TYPE (T, FN (f32), float, int32_t)                                      \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
new file mode 100644
index 00000000000..23dd00b0b13
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_3.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                            \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    PRED_TYPE pred[N];                                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    test_##TYPE##_##NAME (x, y, pred, N);                                      \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 4;                     \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
new file mode 100644
index 00000000000..416aea89e6e
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#include <stdint.h>
+
+#ifndef FN
+#define FN(X) __builtin_fmax##X
+#endif
+
+#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                             \
+  void __attribute__ ((noipa))                                                 \
+  test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y,                \
+			PRED_TYPE *__restrict pred, int n)                     \
+  {                                                                            \
+    for (int i = 0; i < n; ++i)                                                \
+      x[i] = pred[i] != 1 ? FN (y[i], CONST) : 0;                              \
+  }
+
+#define TEST_TYPE(T, FN, TYPE, PRED_TYPE)                                      \
+  T (FN, TYPE, PRED_TYPE, zero, 0)                                             \
+  T (FN, TYPE, PRED_TYPE, one, 1)                                              \
+  T (FN, TYPE, PRED_TYPE, two, 2)
+
+#define TEST_ALL(T)                                                            \
+  TEST_TYPE (T, FN (f32), float, int32_t)                                      \
+  TEST_TYPE (T, FN (f64), double, int64_t)
+
+TEST_ALL (DEF_LOOP)
+
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
new file mode 100644
index 00000000000..1db583242ba
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#include "cond_fmaxnm_4.c"
+
+#define N 99
+
+#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST)                            \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    PRED_TYPE pred[N];                                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    test_##TYPE##_##NAME (x, y, pred, N);                                      \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 0;                     \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_LOOP)
+  return 0;
+}
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
new file mode 100644
index 00000000000..a4d7ab991de
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
new file mode 100644
index 00000000000..8c0bc2ae876
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
new file mode 100644
index 00000000000..6c64a01bcbb
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
new file mode 100644
index 00000000000..5c5db46b390
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
new file mode 100644
index 00000000000..bdb3f2f99ef
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
new file mode 100644
index 00000000000..0abe626fdfb
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
new file mode 100644
index 00000000000..c11633b5236
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
new file mode 100644
index 00000000000..43b892f922e
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
new file mode 100644
index 00000000000..bb456887568
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
new file mode 100644
index 00000000000..6dd9d499b35
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
new file mode 100644
index 00000000000..502f8987494
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
new file mode 100644
index 00000000000..72784290113
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
new file mode 100644
index 00000000000..2ea1eb2ec2c
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
new file mode 100644
index 00000000000..8c994cae202
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
new file mode 100644
index 00000000000..3673ecafc2d
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */
+/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
new file mode 100644
index 00000000000..728f4136015
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
new file mode 100644
index 00000000000..ac98941a373
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
new file mode 100644
index 00000000000..9236ab5b211
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_1_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
new file mode 100644
index 00000000000..7f4dba0d314
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
new file mode 100644
index 00000000000..a5f90d9e76a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_2_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
new file mode 100644
index 00000000000..5faf0c5cc59
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
new file mode 100644
index 00000000000..d7ad738db5c
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_3_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
new file mode 100644
index 00000000000..89d93ac596a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */
+/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
new file mode 100644
index 00000000000..3d92353ac55
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_4_run.c"
diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1.c gcc/testsuite/gcc.target/gcn/cond_smax_1.c
new file mode 100644
index 00000000000..342b5e827d2
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smax_1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != -1) ? (x[i] > y[i] ? x[i] : y[i]) : -4;               \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,        \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i]                                                                     \
+	= (pred[i] != -1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;  \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);                                        \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141);                                                  \
+  IMM (-92137445376, TYPE, minus92137445376);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per test case < 64 bits */
+/* { dg-final { scan-assembler-times {smaxv64si3_exec} 30 } } */
+/* { dg-final { scan-assembler-not {smaxv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
+/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
new file mode 100644
index 00000000000..c951e614579
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_smax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != -1 ? (x[i] > y[i] ? x[i] : y[i]) : -4;        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != -1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1.c gcc/testsuite/gcc.target/gcn/cond_smin_1.c
new file mode 100644
index 00000000000..ad8b583448b
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != -1) ? (x[i] < y[i] ? x[i] : y[i]) : -4;               \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,        \
+			     int count)                                        \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i]                                                                     \
+	= (pred[i] != -1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;  \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);                                        \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141);                                                  \
+  IMM (-92137445376, TYPE, minus92137445376);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per test case < 64 bits */
+/* { dg-final { scan-assembler-times {sminv64si3_exec} 30 } } */
+/* { dg-final { scan-assembler-not {sminv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
+/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
new file mode 100644
index 00000000000..bfdb7d1b9e8
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_smin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != -1 ? (x[i] < y[i] ? x[i] : y[i]) : -4;        \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, pred, N);                                    \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != -1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4;    \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1.c gcc/testsuite/gcc.target/gcn/cond_umax_1.c
new file mode 100644
index 00000000000..389228f9e4a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] > y[i] ? x[i] : y[i]) : 4;                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* Two per test case < 64 bits with wide-enough type:*/
+/* { dg-final { scan-assembler-times {umaxv64si3_exec} 20 } } */
+/* { dg-final { scan-assembler-not {umaxv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+
diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
new file mode 100644
index 00000000000..2396c2452d7
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_umax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? (x[i] > y[i] ? x[i] : y[i]) : 4;          \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                        \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, pred, N);                                   \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != 1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4;      \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1.c gcc/testsuite/gcc.target/gcn/cond_umin_1.c
new file mode 100644
index 00000000000..65759d695ad
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y,                 \
+		       TYPE *__restrict pred, int count)                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] < y[i] ? x[i] : y[i]) : 4;                 \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred,       \
+			      int count)                                       \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = (pred[i] != 1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* Two per test case < 64 bits with wide-enough type:*/
+/* { dg-final { scan-assembler-times {uminv64si3_exec} 20 } } */
+/* { dg-final { scan-assembler-not {uminv64si3/0} } } */
+/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
+/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
new file mode 100644
index 00000000000..ef6f03948ea
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_umin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, pred, N);                                       \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = i % 3 != 1 ? (x[i] < y[i] ? x[i] : y[i]) : 4;          \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                        \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    TYPE pred[N];                                                              \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+	pred[i] = i % 3;                                                       \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, pred, N);                                   \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected                                                          \
+	  = i % 3 != 1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4;      \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smax_1.c gcc/testsuite/gcc.target/gcn/smax_1.c
new file mode 100644
index 00000000000..46c21f73132
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smax_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count)      \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > y[i] ? x[i] : y[i];                                        \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, int count)                    \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;                        \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);                                        \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141);                                                  \
+  IMM (-92137445376, TYPE, minus92137445376);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */
+
+/* Two per test case: */
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smax_1_run.c gcc/testsuite/gcc.target/gcn/smax_1_run.c
new file mode 100644
index 00000000000..4f975916229
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smax_1_run.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "smax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                             \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > y[i] ? x[i] : y[i];                             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, N);                                          \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smin_1.c gcc/testsuite/gcc.target/gcn/smin_1.c
new file mode 100644
index 00000000000..8d6edfaa3d1
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smin_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count)      \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < y[i] ? x[i] : y[i];                                        \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                    \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##NAME##_##TYPE (TYPE *__restrict x, int count)                    \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;                        \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (0, TYPE, 0);                                                            \
+  IMM (86, TYPE, 86);                                                          \
+  IMM (109, TYPE, 109);                                                        \
+  IMM (141, TYPE, 141);                                                        \
+  IMM (92137445376, TYPE, 92137445376);                                        \
+  IMM (-1, TYPE, minus1);                                                      \
+  IMM (-110, TYPE, minus110);                                                  \
+  IMM (-141, TYPE, minus141);                                                  \
+  IMM (-92137445376, TYPE, minus92137445376);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, int8_t)                                              \
+  DO_ARITH_OPS (REG, IMM, int16_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int32_t)                                             \
+  DO_ARITH_OPS (REG, IMM, int64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */
+
+/* Two per test case:*/
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/smin_1_run.c gcc/testsuite/gcc.target/gcn/smin_1_run.c
new file mode 100644
index 00000000000..6758d571fe2
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/smin_1_run.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "smin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                             \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < y[i] ? x[i] : y[i];                             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME)                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##NAME##_##TYPE (x, N);                                          \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/umax_1.c gcc/testsuite/gcc.target/gcn/umax_1.c
new file mode 100644
index 00000000000..dc4b9842d9a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umax_1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count)      \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > y[i] ? x[i] : y[i];                                        \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, int count)                   \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;                        \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
diff --git gcc/testsuite/gcc.target/gcn/umax_1_run.c gcc/testsuite/gcc.target/gcn/umax_1_run.c
new file mode 100644
index 00000000000..b8ff54044fd
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umax_1_run.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "umax_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                             \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > y[i] ? x[i] : y[i];                             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                        \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, N);                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE;             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
diff --git gcc/testsuite/gcc.target/gcn/umin_1.c gcc/testsuite/gcc.target/gcn/umin_1.c
new file mode 100644
index 00000000000..d07f7ec083b
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umin_1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -dp" } */
+
+#include <stdint.h>
+
+#define DO_REGREG_OPS(TYPE)                                                    \
+  void __attribute__ ((noclone))                                               \
+  varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count)      \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < y[i] ? x[i] : y[i];                                        \
+  }
+
+#define DO_IMMEDIATE_OPS(VALUE, TYPE)                                          \
+  void __attribute__ ((noclone))                                               \
+  varithimm_##VALUE##_##TYPE (TYPE *__restrict x, int count)                   \
+  {                                                                            \
+    for (int i = 0; i < count; ++i)                                            \
+      x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;                        \
+  }
+
+#define DO_ARITH_OPS(REG, IMM, TYPE)                                           \
+  REG (TYPE);                                                                  \
+  IMM (2, TYPE);                                                               \
+  IMM (86, TYPE);                                                              \
+  IMM (109, TYPE);                                                             \
+  IMM (141, TYPE);                                                             \
+  IMM (229, TYPE);                                                             \
+  IMM (255, TYPE);                                                             \
+  IMM (992137445376, TYPE);
+
+#define TEST_ALL(REG, IMM)                                                     \
+  DO_ARITH_OPS (REG, IMM, uint8_t)                                             \
+  DO_ARITH_OPS (REG, IMM, uint16_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint32_t)                                            \
+  DO_ARITH_OPS (REG, IMM, uint64_t)
+
+TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS)
+
+/* One per 64-bit test case: */
+/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */
+/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */
+
+/* Two per test case with wide-enough type:*/
+/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */
diff --git gcc/testsuite/gcc.target/gcn/umin_1_run.c gcc/testsuite/gcc.target/gcn/umin_1_run.c
new file mode 100644
index 00000000000..a15d7b3982a
--- /dev/null
+++ gcc/testsuite/gcc.target/gcn/umin_1_run.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "umin_1.c"
+
+#define N 99
+
+#define TEST_REGREG_OPS(TYPE)                                                  \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i % 13;                                                         \
+	y[i] = i * i;                                                          \
+      }                                                                        \
+    varith_##TYPE##_reg (x, y, N);                                             \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < y[i] ? x[i] : y[i];                             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+#define TEST_IMMEDIATE_OPS(VALUE, TYPE)                                        \
+  {                                                                            \
+    TYPE x[N], y[N];                                                           \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	x[i] = i * i;                                                          \
+      }                                                                        \
+    varithimm_##VALUE##_##TYPE (x, N);                                         \
+    for (int i = 0; i < N; ++i)                                                \
+      {                                                                        \
+	TYPE expected = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE;             \
+	if (x[i] != expected)                                                  \
+	  __builtin_abort ();                                                  \
+	asm volatile ("" ::: "memory");                                        \
+      }                                                                        \
+  }
+
+int
+main (void)
+{
+  TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS)
+  return 0;
+}
\ No newline at end of file
-- 
2.39.2


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

* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations
  2023-03-03 17:05   ` Paul-Antoine Arras
@ 2023-03-06 13:27     ` Andrew Stubbs
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Stubbs @ 2023-03-06 13:27 UTC (permalink / raw)
  To: Paul-Antoine Arras, gcc-patches

On 03/03/2023 17:05, Paul-Antoine Arras wrote:
> Le 02/03/2023 à 18:18, Andrew Stubbs a écrit :
>> On 01/03/2023 16:56, Paul-Antoine Arras wrote:
>>> This patch introduces instruction patterns for conditional min and max
>>> operations (cond_{f|s|u}{max|min}) in the GCN machine description. It 
>>> also allows the exec register to be saved in SGPRs to avoid spilling 
>>> to memory.
>>> Tested on GCN3 Fiji gfx803.
>>>
>>> OK for trunk?
>>
>> Not quite yet, but it's only a few cosmetic issues, I think.
>>
>>> +(define_insn_and_split "<expander><mode>3"
>>> +  [(set (match_operand:V_DI 0 "register_operand"      "=  v")
>>> +    (minmaxop:V_DI
>>> +      (match_operand:V_DI 1 "gcn_alu_operand"     "%  v")
>>> +          (match_operand:V_DI 2 "gcn_alu_operand"     "   v")))
>>> +    (clobber (reg:DI VCC_REG))]
>>
>> No need to make it commutative when the two operands have the same 
>> constraints. There's a few more instances of this later.
>>
>>> +    if (<code> == smin || <code> == smax)
>>> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT 
>>> (VOIDmode, 0, 0) :
>>> +                                    gen_rtx_GT (VOIDmode, 0, 0), 
>>> operands[1], operands[2]));
>>> +    else
>>> +      emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU 
>>> (VOIDmode, 0, 0) :
>>> +                                    gen_rtx_GTU (VOIDmode, 0, 0), 
>>> operands[1], operands[2]));
>>> +
>>
>> Long lines need to be wrapped, here and elsewhere.
> 
> The amended patch attached should fix those issues. Let me know if it 
> looks good to you.

OK to commit, thanks.

Andrew

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

end of thread, other threads:[~2023-03-06 13:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-01 16:56 [PATCH] amdgcn: Add instruction patterns for conditional min/max operations Paul-Antoine Arras
2023-03-02 17:18 ` Andrew Stubbs
2023-03-03 17:05   ` Paul-Antoine Arras
2023-03-06 13:27     ` 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).