* [PATCH] amdgcn: Add instruction patterns for conditional min/max operations @ 2023-03-01 16:56 Paul-Antoine Arras 2023-03-02 17:18 ` Andrew Stubbs 0 siblings, 1 reply; 4+ messages in thread From: Paul-Antoine Arras @ 2023-03-01 16:56 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 273 bytes --] This patch introduces instruction patterns for conditional min and max operations (cond_{f|s|u}{max|min}) in the GCN machine description. It also allows the exec register to be saved in SGPRs to avoid spilling to memory. Tested on GCN3 Fiji gfx803. OK for trunk? -- PA [-- Attachment #2: 0001-amdgcn-Add-instruction-patterns-for-conditional-min-.patch --] [-- Type: text/x-patch, Size: 85051 bytes --] From 1cd86b4420d9d42bcde83d0ac52a03a07d4aa819 Mon Sep 17 00:00:00 2001 From: Paul-Antoine Arras <pa@codesourcery.com> Date: Wed, 1 Mar 2023 17:20:21 +0100 Subject: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations gcc/ChangeLog: * config/gcn/gcn-valu.md (<expander><mode>3_exec): Add patterns for {s|u}{max|min} in QI, HI and DI modes. (<expander><mode>3): Add pattern for {s|u}{max|min} in DI mode. (cond_<fexpander><mode>): Add pattern for cond_f{max|min}. (cond_<expander><mode>): Add pattern for cond_{s|u}{max|min}. * config/gcn/gcn.cc (gcn_spill_class): Allow the exec register to be saved in SGPRs. gcc/testsuite/ChangeLog: * gcc.target/gcn/cond_fmaxnm_1.c: New test. * gcc.target/gcn/cond_fmaxnm_1_run.c: New test. * gcc.target/gcn/cond_fmaxnm_2.c: New test. * gcc.target/gcn/cond_fmaxnm_2_run.c: New test. * gcc.target/gcn/cond_fmaxnm_3.c: New test. * gcc.target/gcn/cond_fmaxnm_3_run.c: New test. * gcc.target/gcn/cond_fmaxnm_4.c: New test. * gcc.target/gcn/cond_fmaxnm_4_run.c: New test. * gcc.target/gcn/cond_fmaxnm_5.c: New test. * gcc.target/gcn/cond_fmaxnm_5_run.c: New test. * gcc.target/gcn/cond_fmaxnm_6.c: New test. * gcc.target/gcn/cond_fmaxnm_6_run.c: New test. * gcc.target/gcn/cond_fmaxnm_7.c: New test. * gcc.target/gcn/cond_fmaxnm_7_run.c: New test. * gcc.target/gcn/cond_fmaxnm_8.c: New test. * gcc.target/gcn/cond_fmaxnm_8_run.c: New test. * gcc.target/gcn/cond_fminnm_1.c: New test. * gcc.target/gcn/cond_fminnm_1_run.c: New test. * gcc.target/gcn/cond_fminnm_2.c: New test. * gcc.target/gcn/cond_fminnm_2_run.c: New test. * gcc.target/gcn/cond_fminnm_3.c: New test. * gcc.target/gcn/cond_fminnm_3_run.c: New test. * gcc.target/gcn/cond_fminnm_4.c: New test. * gcc.target/gcn/cond_fminnm_4_run.c: New test. * gcc.target/gcn/cond_fminnm_5.c: New test. * gcc.target/gcn/cond_fminnm_5_run.c: New test. * gcc.target/gcn/cond_fminnm_6.c: New test. * gcc.target/gcn/cond_fminnm_6_run.c: New test. * gcc.target/gcn/cond_fminnm_7.c: New test. * gcc.target/gcn/cond_fminnm_7_run.c: New test. * gcc.target/gcn/cond_fminnm_8.c: New test. * gcc.target/gcn/cond_fminnm_8_run.c: New test. * gcc.target/gcn/cond_smax_1.c: New test. * gcc.target/gcn/cond_smax_1_run.c: New test. * gcc.target/gcn/cond_smin_1.c: New test. * gcc.target/gcn/cond_smin_1_run.c: New test. * gcc.target/gcn/cond_umax_1.c: New test. * gcc.target/gcn/cond_umax_1_run.c: New test. * gcc.target/gcn/cond_umin_1.c: New test. * gcc.target/gcn/cond_umin_1_run.c: New test. * gcc.target/gcn/smax_1.c: New test. * gcc.target/gcn/smax_1_run.c: New test. * gcc.target/gcn/smin_1.c: New test. * gcc.target/gcn/smin_1_run.c: New test. * gcc.target/gcn/umax_1.c: New test. * gcc.target/gcn/umax_1_run.c: New test. * gcc.target/gcn/umin_1.c: New test. * gcc.target/gcn/umin_1_run.c: New test. --- gcc/config/gcn/gcn-valu.md | 134 +++++++++++++++++- gcc/config/gcn/gcn.cc | 2 +- gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c | 36 +++++ .../gcc.target/gcn/cond_fmaxnm_1_run.c | 32 +++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c | 35 +++++ .../gcc.target/gcn/cond_fmaxnm_2_run.c | 31 ++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c | 37 +++++ .../gcc.target/gcn/cond_fmaxnm_3_run.c | 32 +++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c | 37 +++++ .../gcc.target/gcn/cond_fmaxnm_4_run.c | 32 +++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_5_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_6_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_7_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_8_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c | 10 ++ .../gcc.target/gcn/cond_fminnm_1_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c | 10 ++ .../gcc.target/gcn/cond_fminnm_2_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c | 12 ++ .../gcc.target/gcn/cond_fminnm_3_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c | 12 ++ .../gcc.target/gcn/cond_fminnm_4_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c | 10 ++ .../gcc.target/gcn/cond_fminnm_5_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c | 10 ++ .../gcc.target/gcn/cond_fminnm_6_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c | 10 ++ .../gcc.target/gcn/cond_fminnm_7_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c | 10 ++ .../gcc.target/gcn/cond_fminnm_8_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_smax_1.c | 59 ++++++++ .../gcc.target/gcn/cond_smax_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c | 57 ++++++++ .../gcc.target/gcn/cond_smin_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c | 54 +++++++ .../gcc.target/gcn/cond_umax_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c | 53 +++++++ .../gcc.target/gcn/cond_umin_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/smax_1.c | 50 +++++++ gcc/testsuite/gcc.target/gcn/smax_1_run.c | 49 +++++++ gcc/testsuite/gcc.target/gcn/smin_1.c | 50 +++++++ gcc/testsuite/gcc.target/gcn/smin_1_run.c | 49 +++++++ gcc/testsuite/gcc.target/gcn/umax_1.c | 47 ++++++ gcc/testsuite/gcc.target/gcn/umax_1_run.c | 49 +++++++ gcc/testsuite/gcc.target/gcn/umin_1.c | 47 ++++++ gcc/testsuite/gcc.target/gcn/umin_1_run.c | 49 +++++++ 50 files changed, 1403 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1_run.c diff --git gcc/config/gcn/gcn-valu.md gcc/config/gcn/gcn-valu.md index 47d9d87d58a..13d7013de75 100644 --- gcc/config/gcn/gcn-valu.md +++ gcc/config/gcn/gcn-valu.md @@ -2358,6 +2358,34 @@ (define_expand "<expander><mode>3" DONE; }) +(define_expand "<expander><mode>3_exec" + [(set (match_operand:V_QIHI 0 "gcn_valu_dst_operand") + (vec_merge:V_QIHI + (minmaxop:V_QIHI + (match_operand:V_QIHI 1 "gcn_valu_src0_operand") + (match_operand:V_QIHI 2 "gcn_valu_src1com_operand")) + (match_operand:V_QIHI 3 "gcn_register_or_unspec_operand" "U0") + (match_operand:DI 4 "gcn_exec_reg_operand" "e")))] + "" + { + enum {smin, umin, smax, umax}; + bool unsignedp = (<code> == umax || <code> == umin); + rtx insi1 = gen_reg_rtx (<VnSI>mode); + rtx insi2 = gen_reg_rtx (<VnSI>mode); + rtx outsi = gen_reg_rtx (<VnSI>mode); + rtx out = operands[0]; + rtx exec = operands[4]; + rtx tmp = gen_reg_rtx (<MODE>mode); + + convert_move (insi1, operands[1], unsignedp); + convert_move (insi2, operands[2], unsignedp); + emit_insn (gen_<code><vnsi>3_exec (outsi, insi1, insi2, + gcn_gen_undef(<VnSI>mode), exec)); + convert_move (tmp, outsi, unsignedp); + emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec)); + DONE; + }) + (define_insn "<expander><vnsi>3<exec>" [(set (match_operand:V_SI 0 "gcn_valu_dst_operand" "= v,RD") (minmaxop:V_SI @@ -2370,6 +2398,69 @@ (define_insn "<expander><vnsi>3<exec>" [(set_attr "type" "vop2,ds") (set_attr "length" "8,8")]) +(define_insn_and_split "<expander><mode>3" + [(set (match_operand:V_DI 0 "register_operand" "= v") + (minmaxop:V_DI + (match_operand:V_DI 1 "gcn_alu_operand" "% v") + (match_operand:V_DI 2 "gcn_alu_operand" " v"))) + (clobber (reg:DI VCC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] + { + rtx out = operands[0]; + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + + enum {smin, smax, umin, umax}; + bool minp = (<code> == smin || <code> == umin); + if (<code> == smin || <code> == smax) + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) : + gen_rtx_GT (VOIDmode, 0, 0), operands[1], operands[2])); + else + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) : + gen_rtx_GTU (VOIDmode, 0, 0), operands[1], operands[2])); + emit_insn (gen_vcond_mask_<mode>di (out, operands[1], operands[2], vcc)); + } + [(set_attr "type" "mult")]) + +(define_insn_and_split "<expander><mode>3_exec" + [(set (match_operand:V_DI 0 "register_operand" "= v") + (vec_merge:V_DI + (minmaxop:V_DI + (match_operand:V_DI 1 "gcn_alu_operand" "% v") + (match_operand:V_DI 2 "gcn_alu_operand" " v")) + (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0") + (match_operand:DI 4 "gcn_exec_reg_operand" "+e"))) + (clobber (match_scratch:<VnDI> 5 "= &v")) + (clobber (reg:DI VCC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] + { + rtx out = operands[0]; + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + rtx exec = operands[4]; + rtx tmp = operands[5]; + + enum {smin, smax, umin, umax}; + bool minp = (<code> == smin || <code> == umin); + if (<code> == smin || <code> == smax) + emit_insn (gen_vec_cmp<mode>di_exec (vcc, + minp ? gen_rtx_LT (VOIDmode, 0, 0) : + gen_rtx_GT (VOIDmode, 0, 0), operands[1], + operands[2], exec)); + else + emit_insn (gen_vec_cmp<mode>di_exec (vcc, + minp ? gen_rtx_LTU (VOIDmode, 0, 0) : + gen_rtx_GTU (VOIDmode, 0, 0), operands[1], + operands[2], exec)); + emit_insn (gen_vcond_mask_<mode>di (tmp, operands[1], operands[2], vcc)); + emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec)); + } + [(set_attr "type" "mult")]) + ;; }}} ;; {{{ Int unops @@ -3468,7 +3559,48 @@ (define_expand "cond_<expander><mode>" DONE; }) -;; TODO smin umin smax umax +(define_code_iterator cond_fminmaxop [smin smax]) + +(define_expand "cond_<fexpander><mode>" + [(match_operand:V_FP 0 "register_operand") + (match_operand:DI 1 "register_operand") + (cond_fminmaxop:V_FP + (match_operand:V_FP 2 "gcn_alu_operand") + (match_operand:V_FP 3 "gcn_alu_operand")) + (match_operand:V_FP 4 "register_operand")] + "" + { + operands[1] = force_reg (DImode, operands[1]); + operands[2] = force_reg (<MODE>mode, operands[2]); + + emit_insn (gen_<fexpander><mode>3_exec (operands[0], operands[2], + operands[3], operands[4], + operands[1])); + DONE; + }) + +(define_code_iterator cond_minmaxop [smin smax umin umax]) + +(define_expand "cond_<expander><mode>" + [(match_operand:V_INT 0 "register_operand") + (match_operand:DI 1 "register_operand") + (cond_minmaxop:V_INT + (match_operand:V_INT 2 "gcn_alu_operand") + (match_operand:V_INT 3 "gcn_alu_operand")) + (match_operand:V_INT 4 "register_operand")] + "" + { + operands[1] = force_reg (DImode, operands[1]); + operands[2] = force_reg (<MODE>mode, operands[2]); + rtx tmp = gen_reg_rtx (<MODE>mode); + + emit_insn (gen_<expander><mode>3_exec (tmp, operands[2], + operands[3], gcn_gen_undef(<MODE>mode), + operands[1])); + emit_insn (gen_vcond_mask_<mode>di (operands[0], tmp, operands[4], operands[1])); + DONE; + }) + (define_code_iterator cond_bitop [and ior xor]) (define_expand "cond_<expander><mode>" diff --git gcc/config/gcn/gcn.cc gcc/config/gcn/gcn.cc index 23ab01e75d8..b4216b73522 100644 --- gcc/config/gcn/gcn.cc +++ gcc/config/gcn/gcn.cc @@ -797,7 +797,7 @@ static reg_class_t gcn_spill_class (reg_class_t c, machine_mode /*mode */ ) { if (reg_classes_intersect_p (ALL_CONDITIONAL_REGS, c) - || c == VCC_CONDITIONAL_REG) + || c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG) return SGPR_REGS; else return NO_REGS; diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c new file mode 100644 index 00000000000..61c0798b30d --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, \ + TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, \ + int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : y[i]; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c new file mode 100644 index 00000000000..ed4b471ca4d --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_1.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c new file mode 100644 index 00000000000..3d25ffcfe94 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, \ + TYPE *__restrict y, \ + TYPE *__restrict z, \ + int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = y[i] < 8 ? FN (z[i], CONST) : y[i]; \ + } + +#define TEST_TYPE(T, FN, TYPE) \ + T (FN, TYPE, zero, 0) \ + T (FN, TYPE, one, 1) \ + T (FN, TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float) \ + TEST_TYPE (T, FN (f64), double) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c new file mode 100644 index 00000000000..970fd6cfe5a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_2.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N], z[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i % 13; \ + z[i] = i * i; \ + } \ + test_##TYPE##_##NAME (x, y, z, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = y[i] < 8 ? FN (z[i], CONST) : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c new file mode 100644 index 00000000000..55543fec4b0 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, \ + TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, \ + int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : 4; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c new file mode 100644 index 00000000000..469bee10678 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_3.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c new file mode 100644 index 00000000000..65fc2a9b30d --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, \ + TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, \ + int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : 0; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c new file mode 100644 index 00000000000..874d1d3bb54 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_4.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 0; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c new file mode 100644 index 00000000000..a4d7ab991de --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c new file mode 100644 index 00000000000..8c0bc2ae876 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c new file mode 100644 index 00000000000..6c64a01bcbb --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c new file mode 100644 index 00000000000..5c5db46b390 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c new file mode 100644 index 00000000000..bdb3f2f99ef --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c new file mode 100644 index 00000000000..0abe626fdfb --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c new file mode 100644 index 00000000000..c11633b5236 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c new file mode 100644 index 00000000000..43b892f922e --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c new file mode 100644 index 00000000000..bb456887568 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c new file mode 100644 index 00000000000..6dd9d499b35 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c new file mode 100644 index 00000000000..502f8987494 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c new file mode 100644 index 00000000000..72784290113 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c new file mode 100644 index 00000000000..2ea1eb2ec2c --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c new file mode 100644 index 00000000000..8c994cae202 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c new file mode 100644 index 00000000000..3673ecafc2d --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c new file mode 100644 index 00000000000..728f4136015 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c new file mode 100644 index 00000000000..ac98941a373 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c new file mode 100644 index 00000000000..9236ab5b211 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c new file mode 100644 index 00000000000..7f4dba0d314 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c new file mode 100644 index 00000000000..a5f90d9e76a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c new file mode 100644 index 00000000000..5faf0c5cc59 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c new file mode 100644 index 00000000000..d7ad738db5c --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c new file mode 100644 index 00000000000..89d93ac596a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c new file mode 100644 index 00000000000..3d92353ac55 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1.c gcc/testsuite/gcc.target/gcn/cond_smax_1.c new file mode 100644 index 00000000000..181abd209b5 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smax_1.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != -1) ? (x[i] > y[i] ? x[i] : y[i]) : -4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != -1) \ + ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) \ + : -4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL(DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per test case < 64 bits */ +/* { dg-final { scan-assembler-times {smaxv64si3_exec} 30 } } */ +/* { dg-final { scan-assembler-not {smaxv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ +/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c new file mode 100644 index 00000000000..c951e614579 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_smax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != -1 ? (x[i] > y[i] ? x[i] : y[i]) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##NAME##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != -1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1.c gcc/testsuite/gcc.target/gcn/cond_smin_1.c new file mode 100644 index 00000000000..8d75b2c47b8 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != -1) ? (x[i] < y[i] ? x[i] : y[i]) : -4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] \ + = (pred[i] != -1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per test case < 64 bits */ +/* { dg-final { scan-assembler-times {sminv64si3_exec} 30 } } */ +/* { dg-final { scan-assembler-not {sminv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ +/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c new file mode 100644 index 00000000000..4d654e75226 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_smin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != -1 ? (x[i] < y[i] ? x[i] : y[i]) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##NAME##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != -1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1.c gcc/testsuite/gcc.target/gcn/cond_umax_1.c new file mode 100644 index 00000000000..389228f9e4a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] > y[i] ? x[i] : y[i]) : 4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* Two per test case < 64 bits with wide-enough type:*/ +/* { dg-final { scan-assembler-times {umaxv64si3_exec} 20 } } */ +/* { dg-final { scan-assembler-not {umaxv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ + diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c new file mode 100644 index 00000000000..0abcf46dd6f --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_umax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? (x[i] > y[i] ? x[i] : y[i]) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##VALUE##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != 1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1.c gcc/testsuite/gcc.target/gcn/cond_umin_1.c new file mode 100644 index 00000000000..a04b5635090 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] < y[i] ? x[i] : y[i]) : 4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* Two per test case < 64 bits with wide-enough type:*/ +/* { dg-final { scan-assembler-times {uminv64si3_exec} 20 } } */ +/* { dg-final { scan-assembler-not {uminv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c new file mode 100644 index 00000000000..eda49ebc681 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_umin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? (x[i] < y[i] ? x[i] : y[i]) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##VALUE##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != 1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smax_1.c gcc/testsuite/gcc.target/gcn/smax_1.c new file mode 100644 index 00000000000..32ed3a4eb84 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smax_1.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL(DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smax_1_run.c gcc/testsuite/gcc.target/gcn/smax_1_run.c new file mode 100644 index 00000000000..f12fef1d697 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smax_1_run.c @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "smax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##NAME##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smin_1.c gcc/testsuite/gcc.target/gcn/smin_1.c new file mode 100644 index 00000000000..e70b7b1fb1e --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smin_1.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] \ + = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ + +/* Two per test case:*/ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smin_1_run.c gcc/testsuite/gcc.target/gcn/smin_1_run.c new file mode 100644 index 00000000000..b57de12c17f --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smin_1_run.c @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "smin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##NAME##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/umax_1.c gcc/testsuite/gcc.target/gcn/umax_1.c new file mode 100644 index 00000000000..3bed8353a2b --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umax_1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ diff --git gcc/testsuite/gcc.target/gcn/umax_1_run.c gcc/testsuite/gcc.target/gcn/umax_1_run.c new file mode 100644 index 00000000000..d047b7a0576 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umax_1_run.c @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "umax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##VALUE##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/umin_1.c gcc/testsuite/gcc.target/gcn/umin_1.c new file mode 100644 index 00000000000..c4f11f2adfb --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umin_1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ diff --git gcc/testsuite/gcc.target/gcn/umin_1_run.c gcc/testsuite/gcc.target/gcn/umin_1_run.c new file mode 100644 index 00000000000..77a5df95b46 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umin_1_run.c @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "umin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##VALUE##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file -- 2.39.2 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations 2023-03-01 16:56 [PATCH] amdgcn: Add instruction patterns for conditional min/max operations Paul-Antoine Arras @ 2023-03-02 17:18 ` Andrew Stubbs 2023-03-03 17:05 ` Paul-Antoine Arras 0 siblings, 1 reply; 4+ messages in thread From: Andrew Stubbs @ 2023-03-02 17:18 UTC (permalink / raw) To: Paul-Antoine Arras, gcc-patches On 01/03/2023 16:56, Paul-Antoine Arras wrote: > This patch introduces instruction patterns for conditional min and max > operations (cond_{f|s|u}{max|min}) in the GCN machine description. It > also allows the exec register to be saved in SGPRs to avoid spilling to > memory. > Tested on GCN3 Fiji gfx803. > > OK for trunk? Not quite yet, but it's only a few cosmetic issues, I think. > +(define_insn_and_split "<expander><mode>3" > + [(set (match_operand:V_DI 0 "register_operand" "= v") > + (minmaxop:V_DI > + (match_operand:V_DI 1 "gcn_alu_operand" "% v") > + (match_operand:V_DI 2 "gcn_alu_operand" " v"))) > + (clobber (reg:DI VCC_REG))] No need to make it commutative when the two operands have the same constraints. There's a few more instances of this later. > + if (<code> == smin || <code> == smax) > + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) : > + gen_rtx_GT (VOIDmode, 0, 0), operands[1], operands[2])); > + else > + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) : > + gen_rtx_GTU (VOIDmode, 0, 0), operands[1], operands[2])); > + Long lines need to be wrapped, here and elsewhere. Andrew ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations 2023-03-02 17:18 ` Andrew Stubbs @ 2023-03-03 17:05 ` Paul-Antoine Arras 2023-03-06 13:27 ` Andrew Stubbs 0 siblings, 1 reply; 4+ messages in thread From: Paul-Antoine Arras @ 2023-03-03 17:05 UTC (permalink / raw) To: Andrew Stubbs, gcc-patches [-- Attachment #1: Type: text/plain, Size: 1613 bytes --] Le 02/03/2023 à 18:18, Andrew Stubbs a écrit : > On 01/03/2023 16:56, Paul-Antoine Arras wrote: >> This patch introduces instruction patterns for conditional min and max >> operations (cond_{f|s|u}{max|min}) in the GCN machine description. It >> also allows the exec register to be saved in SGPRs to avoid spilling >> to memory. >> Tested on GCN3 Fiji gfx803. >> >> OK for trunk? > > Not quite yet, but it's only a few cosmetic issues, I think. > >> +(define_insn_and_split "<expander><mode>3" >> + [(set (match_operand:V_DI 0 "register_operand" "= v") >> + (minmaxop:V_DI >> + (match_operand:V_DI 1 "gcn_alu_operand" "% v") >> + (match_operand:V_DI 2 "gcn_alu_operand" " v"))) >> + (clobber (reg:DI VCC_REG))] > > No need to make it commutative when the two operands have the same > constraints. There's a few more instances of this later. > >> + if (<code> == smin || <code> == smax) >> + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT >> (VOIDmode, 0, 0) : >> + gen_rtx_GT (VOIDmode, 0, 0), >> operands[1], operands[2])); >> + else >> + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU >> (VOIDmode, 0, 0) : >> + gen_rtx_GTU (VOIDmode, 0, 0), >> operands[1], operands[2])); >> + > > Long lines need to be wrapped, here and elsewhere. The amended patch attached should fix those issues. Let me know if it looks good to you. -- PA [-- Attachment #2: 0001-amdgcn-Add-instruction-patterns-for-conditional-min-.patch --] [-- Type: text/x-patch, Size: 91396 bytes --] From cdb2d170091d87b0a5968cca49fc34ac434bb54c Mon Sep 17 00:00:00 2001 From: Paul-Antoine Arras <pa@codesourcery.com> Date: Wed, 1 Mar 2023 17:20:21 +0100 Subject: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations gcc/ChangeLog: * config/gcn/gcn-valu.md (<expander><mode>3_exec): Add patterns for {s|u}{max|min} in QI, HI and DI modes. (<expander><mode>3): Add pattern for {s|u}{max|min} in DI mode. (cond_<fexpander><mode>): Add pattern for cond_f{max|min}. (cond_<expander><mode>): Add pattern for cond_{s|u}{max|min}. * config/gcn/gcn.cc (gcn_spill_class): Allow the exec register to be saved in SGPRs. gcc/testsuite/ChangeLog: * gcc.target/gcn/cond_fmaxnm_1.c: New test. * gcc.target/gcn/cond_fmaxnm_1_run.c: New test. * gcc.target/gcn/cond_fmaxnm_2.c: New test. * gcc.target/gcn/cond_fmaxnm_2_run.c: New test. * gcc.target/gcn/cond_fmaxnm_3.c: New test. * gcc.target/gcn/cond_fmaxnm_3_run.c: New test. * gcc.target/gcn/cond_fmaxnm_4.c: New test. * gcc.target/gcn/cond_fmaxnm_4_run.c: New test. * gcc.target/gcn/cond_fmaxnm_5.c: New test. * gcc.target/gcn/cond_fmaxnm_5_run.c: New test. * gcc.target/gcn/cond_fmaxnm_6.c: New test. * gcc.target/gcn/cond_fmaxnm_6_run.c: New test. * gcc.target/gcn/cond_fmaxnm_7.c: New test. * gcc.target/gcn/cond_fmaxnm_7_run.c: New test. * gcc.target/gcn/cond_fmaxnm_8.c: New test. * gcc.target/gcn/cond_fmaxnm_8_run.c: New test. * gcc.target/gcn/cond_fminnm_1.c: New test. * gcc.target/gcn/cond_fminnm_1_run.c: New test. * gcc.target/gcn/cond_fminnm_2.c: New test. * gcc.target/gcn/cond_fminnm_2_run.c: New test. * gcc.target/gcn/cond_fminnm_3.c: New test. * gcc.target/gcn/cond_fminnm_3_run.c: New test. * gcc.target/gcn/cond_fminnm_4.c: New test. * gcc.target/gcn/cond_fminnm_4_run.c: New test. * gcc.target/gcn/cond_fminnm_5.c: New test. * gcc.target/gcn/cond_fminnm_5_run.c: New test. * gcc.target/gcn/cond_fminnm_6.c: New test. * gcc.target/gcn/cond_fminnm_6_run.c: New test. * gcc.target/gcn/cond_fminnm_7.c: New test. * gcc.target/gcn/cond_fminnm_7_run.c: New test. * gcc.target/gcn/cond_fminnm_8.c: New test. * gcc.target/gcn/cond_fminnm_8_run.c: New test. * gcc.target/gcn/cond_smax_1.c: New test. * gcc.target/gcn/cond_smax_1_run.c: New test. * gcc.target/gcn/cond_smin_1.c: New test. * gcc.target/gcn/cond_smin_1_run.c: New test. * gcc.target/gcn/cond_umax_1.c: New test. * gcc.target/gcn/cond_umax_1_run.c: New test. * gcc.target/gcn/cond_umin_1.c: New test. * gcc.target/gcn/cond_umin_1_run.c: New test. * gcc.target/gcn/smax_1.c: New test. * gcc.target/gcn/smax_1_run.c: New test. * gcc.target/gcn/smin_1.c: New test. * gcc.target/gcn/smin_1_run.c: New test. * gcc.target/gcn/umax_1.c: New test. * gcc.target/gcn/umax_1_run.c: New test. * gcc.target/gcn/umin_1.c: New test. * gcc.target/gcn/umin_1_run.c: New test. --- gcc/config/gcn/gcn-valu.md | 137 +++++++++++++++++- gcc/config/gcn/gcn.cc | 2 +- gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c | 33 +++++ .../gcc.target/gcn/cond_fmaxnm_1_run.c | 32 ++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c | 33 +++++ .../gcc.target/gcn/cond_fmaxnm_2_run.c | 31 ++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c | 35 +++++ .../gcc.target/gcn/cond_fmaxnm_3_run.c | 32 ++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c | 35 +++++ .../gcc.target/gcn/cond_fmaxnm_4_run.c | 32 ++++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_5_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_6_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_7_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c | 9 ++ .../gcc.target/gcn/cond_fmaxnm_8_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c | 10 ++ .../gcc.target/gcn/cond_fminnm_1_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c | 10 ++ .../gcc.target/gcn/cond_fminnm_2_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c | 12 ++ .../gcc.target/gcn/cond_fminnm_3_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c | 12 ++ .../gcc.target/gcn/cond_fminnm_4_run.c | 5 + gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c | 10 ++ .../gcc.target/gcn/cond_fminnm_5_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c | 10 ++ .../gcc.target/gcn/cond_fminnm_6_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c | 10 ++ .../gcc.target/gcn/cond_fminnm_7_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c | 10 ++ .../gcc.target/gcn/cond_fminnm_8_run.c | 4 + gcc/testsuite/gcc.target/gcn/cond_smax_1.c | 57 ++++++++ .../gcc.target/gcn/cond_smax_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c | 57 ++++++++ .../gcc.target/gcn/cond_smin_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c | 54 +++++++ .../gcc.target/gcn/cond_umax_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c | 53 +++++++ .../gcc.target/gcn/cond_umin_1_run.c | 53 +++++++ gcc/testsuite/gcc.target/gcn/smax_1.c | 47 ++++++ gcc/testsuite/gcc.target/gcn/smax_1_run.c | 48 ++++++ gcc/testsuite/gcc.target/gcn/smin_1.c | 47 ++++++ gcc/testsuite/gcc.target/gcn/smin_1_run.c | 48 ++++++ gcc/testsuite/gcc.target/gcn/umax_1.c | 45 ++++++ gcc/testsuite/gcc.target/gcn/umax_1_run.c | 48 ++++++ gcc/testsuite/gcc.target/gcn/umin_1.c | 45 ++++++ gcc/testsuite/gcc.target/gcn/umin_1_run.c | 48 ++++++ 50 files changed, 1381 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/smax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/smin_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/umax_1_run.c create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1.c create mode 100644 gcc/testsuite/gcc.target/gcn/umin_1_run.c diff --git gcc/config/gcn/gcn-valu.md gcc/config/gcn/gcn-valu.md index 47d9d87d58a..75e9a59600b 100644 --- gcc/config/gcn/gcn-valu.md +++ gcc/config/gcn/gcn-valu.md @@ -2358,6 +2358,34 @@ (define_expand "<expander><mode>3" DONE; }) +(define_expand "<expander><mode>3_exec" + [(set (match_operand:V_QIHI 0 "gcn_valu_dst_operand") + (vec_merge:V_QIHI + (minmaxop:V_QIHI + (match_operand:V_QIHI 1 "gcn_valu_src0_operand") + (match_operand:V_QIHI 2 "gcn_valu_src1com_operand")) + (match_operand:V_QIHI 3 "gcn_register_or_unspec_operand" "U0") + (match_operand:DI 4 "gcn_exec_reg_operand" "e")))] + "" + { + enum {smin, umin, smax, umax}; + bool unsignedp = (<code> == umax || <code> == umin); + rtx insi1 = gen_reg_rtx (<VnSI>mode); + rtx insi2 = gen_reg_rtx (<VnSI>mode); + rtx outsi = gen_reg_rtx (<VnSI>mode); + rtx out = operands[0]; + rtx exec = operands[4]; + rtx tmp = gen_reg_rtx (<MODE>mode); + + convert_move (insi1, operands[1], unsignedp); + convert_move (insi2, operands[2], unsignedp); + emit_insn (gen_<code><vnsi>3_exec (outsi, insi1, insi2, + gcn_gen_undef(<VnSI>mode), exec)); + convert_move (tmp, outsi, unsignedp); + emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec)); + DONE; + }) + (define_insn "<expander><vnsi>3<exec>" [(set (match_operand:V_SI 0 "gcn_valu_dst_operand" "= v,RD") (minmaxop:V_SI @@ -2370,6 +2398,71 @@ (define_insn "<expander><vnsi>3<exec>" [(set_attr "type" "vop2,ds") (set_attr "length" "8,8")]) +(define_insn_and_split "<expander><mode>3" + [(set (match_operand:V_DI 0 "register_operand" "=v") + (minmaxop:V_DI + (match_operand:V_DI 1 "gcn_alu_operand" " v") + (match_operand:V_DI 2 "gcn_alu_operand" " v"))) + (clobber (reg:DI VCC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] + { + rtx out = operands[0]; + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + + enum {smin, smax, umin, umax}; + bool minp = (<code> == smin || <code> == umin); + if (<code> == smin || <code> == smax) + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT (VOIDmode, 0, 0) : + gen_rtx_GT (VOIDmode, 0, 0), operands[1], + operands[2])); + else + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU (VOIDmode, 0, 0) : + gen_rtx_GTU (VOIDmode, 0, 0), operands[1], + operands[2])); + emit_insn (gen_vcond_mask_<mode>di (out, operands[1], operands[2], vcc)); + } + [(set_attr "type" "mult")]) + +(define_insn_and_split "<expander><mode>3_exec" + [(set (match_operand:V_DI 0 "register_operand" "= v") + (vec_merge:V_DI + (minmaxop:V_DI + (match_operand:V_DI 1 "gcn_alu_operand" " v") + (match_operand:V_DI 2 "gcn_alu_operand" " v")) + (match_operand:V_DI 3 "gcn_register_or_unspec_operand" " U0") + (match_operand:DI 4 "gcn_exec_reg_operand" "+e"))) + (clobber (match_scratch:<VnDI> 5 "= &v")) + (clobber (reg:DI VCC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] + { + rtx out = operands[0]; + rtx vcc = gen_rtx_REG (DImode, VCC_REG); + rtx exec = operands[4]; + rtx tmp = operands[5]; + + enum {smin, smax, umin, umax}; + bool minp = (<code> == smin || <code> == umin); + if (<code> == smin || <code> == smax) + emit_insn (gen_vec_cmp<mode>di_exec (vcc, + minp ? gen_rtx_LT (VOIDmode, 0, 0) : + gen_rtx_GT (VOIDmode, 0, 0), + operands[1], operands[2], exec)); + else + emit_insn (gen_vec_cmp<mode>di_exec (vcc, + minp ? gen_rtx_LTU (VOIDmode, 0, 0) : + gen_rtx_GTU (VOIDmode, 0, 0), + operands[1], operands[2], exec)); + emit_insn (gen_vcond_mask_<mode>di (tmp, operands[1], operands[2], vcc)); + emit_insn (gen_mov<mode>_exec (out, tmp, operands[3], exec)); + } + [(set_attr "type" "mult")]) + ;; }}} ;; {{{ Int unops @@ -3468,7 +3561,49 @@ (define_expand "cond_<expander><mode>" DONE; }) -;; TODO smin umin smax umax +(define_code_iterator cond_fminmaxop [smin smax]) + +(define_expand "cond_<fexpander><mode>" + [(match_operand:V_FP 0 "register_operand") + (match_operand:DI 1 "register_operand") + (cond_fminmaxop:V_FP + (match_operand:V_FP 2 "gcn_alu_operand") + (match_operand:V_FP 3 "gcn_alu_operand")) + (match_operand:V_FP 4 "register_operand")] + "" + { + operands[1] = force_reg (DImode, operands[1]); + operands[2] = force_reg (<MODE>mode, operands[2]); + + emit_insn (gen_<fexpander><mode>3_exec (operands[0], operands[2], + operands[3], operands[4], + operands[1])); + DONE; + }) + +(define_code_iterator cond_minmaxop [smin smax umin umax]) + +(define_expand "cond_<expander><mode>" + [(match_operand:V_INT 0 "register_operand") + (match_operand:DI 1 "register_operand") + (cond_minmaxop:V_INT + (match_operand:V_INT 2 "gcn_alu_operand") + (match_operand:V_INT 3 "gcn_alu_operand")) + (match_operand:V_INT 4 "register_operand")] + "" + { + operands[1] = force_reg (DImode, operands[1]); + operands[2] = force_reg (<MODE>mode, operands[2]); + rtx tmp = gen_reg_rtx (<MODE>mode); + + emit_insn (gen_<expander><mode>3_exec (tmp, operands[2], operands[3], + gcn_gen_undef(<MODE>mode), + operands[1])); + emit_insn (gen_vcond_mask_<mode>di (operands[0], tmp, operands[4], + operands[1])); + DONE; + }) + (define_code_iterator cond_bitop [and ior xor]) (define_expand "cond_<expander><mode>" diff --git gcc/config/gcn/gcn.cc gcc/config/gcn/gcn.cc index 23ab01e75d8..b4216b73522 100644 --- gcc/config/gcn/gcn.cc +++ gcc/config/gcn/gcn.cc @@ -797,7 +797,7 @@ static reg_class_t gcn_spill_class (reg_class_t c, machine_mode /*mode */ ) { if (reg_classes_intersect_p (ALL_CONDITIONAL_REGS, c) - || c == VCC_CONDITIONAL_REG) + || c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG) return SGPR_REGS; else return NO_REGS; diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c new file mode 100644 index 00000000000..17c49bdc518 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : y[i]; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c new file mode 100644 index 00000000000..1e4c81c17a9 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_1_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_1.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c new file mode 100644 index 00000000000..406df48962a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict z, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = y[i] < 8 ? FN (z[i], CONST) : y[i]; \ + } + +#define TEST_TYPE(T, FN, TYPE) \ + T (FN, TYPE, zero, 0) \ + T (FN, TYPE, one, 1) \ + T (FN, TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float) \ + TEST_TYPE (T, FN (f64), double) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c new file mode 100644 index 00000000000..05d18f41f06 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_2_run.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_2.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N], z[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i % 13; \ + z[i] = i * i; \ + } \ + test_##TYPE##_##NAME (x, y, z, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = y[i] < 8 ? FN (z[i], CONST) : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c new file mode 100644 index 00000000000..45b8b7883ba --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : 4; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c new file mode 100644 index 00000000000..23dd00b0b13 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_3_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_3.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c new file mode 100644 index 00000000000..416aea89e6e --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#include <stdint.h> + +#ifndef FN +#define FN(X) __builtin_fmax##X +#endif + +#define DEF_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##NAME (TYPE *__restrict x, TYPE *__restrict y, \ + PRED_TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + x[i] = pred[i] != 1 ? FN (y[i], CONST) : 0; \ + } + +#define TEST_TYPE(T, FN, TYPE, PRED_TYPE) \ + T (FN, TYPE, PRED_TYPE, zero, 0) \ + T (FN, TYPE, PRED_TYPE, one, 1) \ + T (FN, TYPE, PRED_TYPE, two, 2) + +#define TEST_ALL(T) \ + TEST_TYPE (T, FN (f32), float, int32_t) \ + TEST_TYPE (T, FN (f64), double, int64_t) + +TEST_ALL (DEF_LOOP) + +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c new file mode 100644 index 00000000000..1db583242ba --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_4_run.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#include "cond_fmaxnm_4.c" + +#define N 99 + +#define TEST_LOOP(FN, TYPE, PRED_TYPE, NAME, CONST) \ + { \ + TYPE x[N], y[N]; \ + PRED_TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + test_##TYPE##_##NAME (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? FN (y[i], CONST) : 0; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c new file mode 100644 index 00000000000..a4d7ab991de --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c new file mode 100644 index 00000000000..8c0bc2ae876 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_5_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c new file mode 100644 index 00000000000..6c64a01bcbb --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c new file mode 100644 index 00000000000..5c5db46b390 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_6_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c new file mode 100644 index 00000000000..bdb3f2f99ef --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c new file mode 100644 index 00000000000..0abe626fdfb --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_7_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c new file mode 100644 index 00000000000..c11633b5236 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {smaxv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {smaxv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c new file mode 100644 index 00000000000..43b892f922e --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fmaxnm_8_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fmaxnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c new file mode 100644 index 00000000000..bb456887568 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c new file mode 100644 index 00000000000..6dd9d499b35 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_1_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c new file mode 100644 index 00000000000..502f8987494 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c new file mode 100644 index 00000000000..72784290113 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_2_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c new file mode 100644 index 00000000000..2ea1eb2ec2c --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c new file mode 100644 index 00000000000..8c994cae202 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_3_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c new file mode 100644 index 00000000000..3673ecafc2d --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64sf_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64sf3} 3 } } */ +/* { dg-final { scan-assembler-times {movv64df_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c new file mode 100644 index 00000000000..728f4136015 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_4_run.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize -ffast-math" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c new file mode 100644 index 00000000000..ac98941a373 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_1.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c new file mode 100644 index 00000000000..9236ab5b211 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_5_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_1_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c new file mode 100644 index 00000000000..7f4dba0d314 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_2.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c new file mode 100644 index 00000000000..a5f90d9e76a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_6_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_2_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c new file mode 100644 index 00000000000..5faf0c5cc59 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_3.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c new file mode 100644 index 00000000000..d7ad738db5c --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_7_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_3_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c new file mode 100644 index 00000000000..89d93ac596a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#define FN(X) __builtin_fmin##X +#include "cond_fmaxnm_4.c" + +/* { dg-final { scan-assembler-times {sminv64sf3_exec} 3 } } */ +/* { dg-final { scan-assembler-times {sminv64df3_exec} 3 } } */ + +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_..} } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c new file mode 100644 index 00000000000..3d92353ac55 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_fminnm_8_run.c @@ -0,0 +1,4 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_fminnm_4_run.c" diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1.c gcc/testsuite/gcc.target/gcn/cond_smax_1.c new file mode 100644 index 00000000000..342b5e827d2 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smax_1.c @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != -1) ? (x[i] > y[i] ? x[i] : y[i]) : -4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] \ + = (pred[i] != -1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per test case < 64 bits */ +/* { dg-final { scan-assembler-times {smaxv64si3_exec} 30 } } */ +/* { dg-final { scan-assembler-not {smaxv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ +/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c new file mode 100644 index 00000000000..c951e614579 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smax_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_smax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != -1 ? (x[i] > y[i] ? x[i] : y[i]) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##NAME##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != -1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1.c gcc/testsuite/gcc.target/gcn/cond_smin_1.c new file mode 100644 index 00000000000..ad8b583448b --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smin_1.c @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != -1) ? (x[i] < y[i] ? x[i] : y[i]) : -4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] \ + = (pred[i] != -1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per test case < 64 bits */ +/* { dg-final { scan-assembler-times {sminv64si3_exec} 30 } } */ +/* { dg-final { scan-assembler-not {sminv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ +/* { dg-final { scan-assembler-not {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], -1} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c new file mode 100644 index 00000000000..bfdb7d1b9e8 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_smin_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_smin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != -1 ? (x[i] < y[i] ? x[i] : y[i]) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##NAME##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != -1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : -4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1.c gcc/testsuite/gcc.target/gcn/cond_umax_1.c new file mode 100644 index 00000000000..389228f9e4a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umax_1.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] > y[i] ? x[i] : y[i]) : 4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* Two per test case < 64 bits with wide-enough type:*/ +/* { dg-final { scan-assembler-times {umaxv64si3_exec} 20 } } */ +/* { dg-final { scan-assembler-not {umaxv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ + diff --git gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c new file mode 100644 index 00000000000..2396c2452d7 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umax_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_umax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? (x[i] > y[i] ? x[i] : y[i]) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##VALUE##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != 1 ? (x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1.c gcc/testsuite/gcc.target/gcn/cond_umin_1.c new file mode 100644 index 00000000000..65759d695ad --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umin_1.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, \ + TYPE *__restrict pred, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] < y[i] ? x[i] : y[i]) : 4; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, TYPE *__restrict pred, \ + int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = (pred[i] != 1) ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* Two per test case < 64 bits with wide-enough type:*/ +/* { dg-final { scan-assembler-times {uminv64si3_exec} 20 } } */ +/* { dg-final { scan-assembler-not {uminv64si3/0} } } */ +/* { dg-final { scan-assembler-not {\tv_writelane_b32\tv[0-9]+, vcc_??, 0} } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ +/* { dg-final { scan-assembler-not {\ts_cmpk_lg_u32\tvcc_lo, 0} } } */ + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_ne_u64\ts\[[0-9]+:[0-9]+\], v\[[0-9]+:[0-9]+\], 1} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ diff --git gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c new file mode 100644 index 00000000000..ef6f03948ea --- /dev/null +++ gcc/testsuite/gcc.target/gcn/cond_umin_1_run.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "cond_umin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varith_##TYPE##_reg (x, y, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = i % 3 != 1 ? (x[i] < y[i] ? x[i] : y[i]) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + TYPE pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + pred[i] = i % 3; \ + } \ + varithimm_##VALUE##_##TYPE (x, pred, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected \ + = i % 3 != 1 ? (x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE) : 4; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smax_1.c gcc/testsuite/gcc.target/gcn/smax_1.c new file mode 100644 index 00000000000..46c21f73132 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smax_1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */ + +/* Two per test case: */ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smax_1_run.c gcc/testsuite/gcc.target/gcn/smax_1_run.c new file mode 100644 index 00000000000..4f975916229 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smax_1_run.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "smax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##NAME##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smin_1.c gcc/testsuite/gcc.target/gcn/smin_1.c new file mode 100644 index 00000000000..8d6edfaa3d1 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smin_1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + void __attribute__ ((noclone)) \ + varithimm_##NAME##_##TYPE (TYPE *__restrict x, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (0, TYPE, 0); \ + IMM (86, TYPE, 86); \ + IMM (109, TYPE, 109); \ + IMM (141, TYPE, 141); \ + IMM (92137445376, TYPE, 92137445376); \ + IMM (-1, TYPE, minus1); \ + IMM (-110, TYPE, minus110); \ + IMM (-141, TYPE, minus141); \ + IMM (-92137445376, TYPE, minus92137445376); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, int8_t) \ + DO_ARITH_OPS (REG, IMM, int16_t) \ + DO_ARITH_OPS (REG, IMM, int32_t) \ + DO_ARITH_OPS (REG, IMM, int64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 10 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_i64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 10 } } */ + +/* Two per test case:*/ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 80 } } */ \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/smin_1_run.c gcc/testsuite/gcc.target/gcn/smin_1_run.c new file mode 100644 index 00000000000..6758d571fe2 --- /dev/null +++ gcc/testsuite/gcc.target/gcn/smin_1_run.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "smin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE, NAME) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##NAME##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/umax_1.c gcc/testsuite/gcc.target/gcn/umax_1.c new file mode 100644 index 00000000000..dc4b9842d9a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umax_1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmp_gt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ diff --git gcc/testsuite/gcc.target/gcn/umax_1_run.c gcc/testsuite/gcc.target/gcn/umax_1_run.c new file mode 100644 index 00000000000..b8ff54044fd --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umax_1_run.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "umax_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##VALUE##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] > (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file diff --git gcc/testsuite/gcc.target/gcn/umin_1.c gcc/testsuite/gcc.target/gcn/umin_1.c new file mode 100644 index 00000000000..d07f7ec083b --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umin_1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -dp" } */ + +#include <stdint.h> + +#define DO_REGREG_OPS(TYPE) \ + void __attribute__ ((noclone)) \ + varith_##TYPE##_reg (TYPE *__restrict x, TYPE *__restrict y, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < y[i] ? x[i] : y[i]; \ + } + +#define DO_IMMEDIATE_OPS(VALUE, TYPE) \ + void __attribute__ ((noclone)) \ + varithimm_##VALUE##_##TYPE (TYPE *__restrict x, int count) \ + { \ + for (int i = 0; i < count; ++i) \ + x[i] = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + } + +#define DO_ARITH_OPS(REG, IMM, TYPE) \ + REG (TYPE); \ + IMM (2, TYPE); \ + IMM (86, TYPE); \ + IMM (109, TYPE); \ + IMM (141, TYPE); \ + IMM (229, TYPE); \ + IMM (255, TYPE); \ + IMM (992137445376, TYPE); + +#define TEST_ALL(REG, IMM) \ + DO_ARITH_OPS (REG, IMM, uint8_t) \ + DO_ARITH_OPS (REG, IMM, uint16_t) \ + DO_ARITH_OPS (REG, IMM, uint32_t) \ + DO_ARITH_OPS (REG, IMM, uint64_t) + +TEST_ALL (DO_REGREG_OPS, DO_IMMEDIATE_OPS) + +/* One per 64-bit test case: */ +/* { dg-final { scan-assembler-times {vec_cmpv64didi} 8 } } */ +/* { dg-final { scan-assembler-times {\tv_cmp_lt_u64\tvcc, v[[0-9]+:[0-9]+], v[[0-9]+:[0-9]+]} 8 } } */ + +/* Two per test case with wide-enough type:*/ +/* { dg-final { scan-assembler-times {\tv_cmpx_gt_i32\tvcc, s[0-9]+, v[0-9]+} 56 } } */ diff --git gcc/testsuite/gcc.target/gcn/umin_1_run.c gcc/testsuite/gcc.target/gcn/umin_1_run.c new file mode 100644 index 00000000000..a15d7b3982a --- /dev/null +++ gcc/testsuite/gcc.target/gcn/umin_1_run.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "umin_1.c" + +#define N 99 + +#define TEST_REGREG_OPS(TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i % 13; \ + y[i] = i * i; \ + } \ + varith_##TYPE##_reg (x, y, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < y[i] ? x[i] : y[i]; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +#define TEST_IMMEDIATE_OPS(VALUE, TYPE) \ + { \ + TYPE x[N], y[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + x[i] = i * i; \ + } \ + varithimm_##VALUE##_##TYPE (x, N); \ + for (int i = 0; i < N; ++i) \ + { \ + TYPE expected = x[i] < (TYPE) VALUE ? x[i] : (TYPE) VALUE; \ + if (x[i] != expected) \ + __builtin_abort (); \ + asm volatile ("" ::: "memory"); \ + } \ + } + +int +main (void) +{ + TEST_ALL (TEST_REGREG_OPS, TEST_IMMEDIATE_OPS) + return 0; +} \ No newline at end of file -- 2.39.2 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] amdgcn: Add instruction patterns for conditional min/max operations 2023-03-03 17:05 ` Paul-Antoine Arras @ 2023-03-06 13:27 ` Andrew Stubbs 0 siblings, 0 replies; 4+ messages in thread From: Andrew Stubbs @ 2023-03-06 13:27 UTC (permalink / raw) To: Paul-Antoine Arras, gcc-patches On 03/03/2023 17:05, Paul-Antoine Arras wrote: > Le 02/03/2023 à 18:18, Andrew Stubbs a écrit : >> On 01/03/2023 16:56, Paul-Antoine Arras wrote: >>> This patch introduces instruction patterns for conditional min and max >>> operations (cond_{f|s|u}{max|min}) in the GCN machine description. It >>> also allows the exec register to be saved in SGPRs to avoid spilling >>> to memory. >>> Tested on GCN3 Fiji gfx803. >>> >>> OK for trunk? >> >> Not quite yet, but it's only a few cosmetic issues, I think. >> >>> +(define_insn_and_split "<expander><mode>3" >>> + [(set (match_operand:V_DI 0 "register_operand" "= v") >>> + (minmaxop:V_DI >>> + (match_operand:V_DI 1 "gcn_alu_operand" "% v") >>> + (match_operand:V_DI 2 "gcn_alu_operand" " v"))) >>> + (clobber (reg:DI VCC_REG))] >> >> No need to make it commutative when the two operands have the same >> constraints. There's a few more instances of this later. >> >>> + if (<code> == smin || <code> == smax) >>> + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LT >>> (VOIDmode, 0, 0) : >>> + gen_rtx_GT (VOIDmode, 0, 0), >>> operands[1], operands[2])); >>> + else >>> + emit_insn (gen_vec_cmp<mode>di (vcc, minp ? gen_rtx_LTU >>> (VOIDmode, 0, 0) : >>> + gen_rtx_GTU (VOIDmode, 0, 0), >>> operands[1], operands[2])); >>> + >> >> Long lines need to be wrapped, here and elsewhere. > > The amended patch attached should fix those issues. Let me know if it > looks good to you. OK to commit, thanks. Andrew ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-03-06 13:27 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-03-01 16:56 [PATCH] amdgcn: Add instruction patterns for conditional min/max operations Paul-Antoine Arras 2023-03-02 17:18 ` Andrew Stubbs 2023-03-03 17:05 ` Paul-Antoine Arras 2023-03-06 13:27 ` Andrew Stubbs
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).