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
From cdb2d170091d87b0a5968cca49fc34ac434bb54c Mon Sep 17 00:00:00 2001
From: Paul-Antoine Arras <p...@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