amdgcn: Add instruction patterns for conditional min/max operations

Message ID 1f1f9f15-e12e-ec4e-7b74-ba7bf3b64449@codesourcery.com
State Committed
Headers
Series amdgcn: Add instruction patterns for conditional min/max operations |

Commit Message

Paul-Antoine Arras March 1, 2023, 4:56 p.m. UTC
  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?
  

Comments

Andrew Stubbs March 2, 2023, 5:18 p.m. UTC | #1
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
  
Paul-Antoine Arras March 3, 2023, 5:05 p.m. UTC | #2
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.
  
Andrew Stubbs March 6, 2023, 1:27 p.m. UTC | #3
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
  

Patch

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