Fixed one place without consistent mode. Bootstrapped and regress testing passed on powerpc64le-linux.
Thanks! Kewen --- gcc/ChangeLog 2019-10-25 Kewen Lin <li...@gcc.gnu.org> PR target/92132 * config/rs6000/rs6000.md (one_cmpl<mode>3_internal): Expose name. * config/rs6000/vector.md (fpcmpun): New code_iterator. (vcond_mask_<mode><mode>): New expand. (vcond_mask_<mode><VEC_int>): Likewise. (vec_cmp<mode><mode>): Likewise. (vec_cmpu<mode><mode>): Likewise. (vec_cmp<mode><VEC_int>): Likewise. (vector_{ungt,unge,unlt,unle}<mode>): Likewise. (vector_uneq<mode>): Expose name. (vector_ltgt<mode>): Likewise. (vector_unordered<mode>): Likewise. (vector_ordered<mode>): Likewise. gcc/testsuite/ChangeLog 2019-10-25 Kewen Lin <li...@gcc.gnu.org> PR target/92132 * gcc.target/powerpc/pr92132-fp-1.c: New test. * gcc.target/powerpc/pr92132-fp-2.c: New test. * gcc.target/powerpc/pr92132-int-1.c: New test. * gcc.target/powerpc/pr92132-int-2.c: New test.
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index d0cca1e..2a68548 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6800,7 +6800,7 @@ (const_string "16")))]) ;; 128-bit one's complement -(define_insn_and_split "*one_cmpl<mode>3_internal" +(define_insn_and_split "one_cmpl<mode>3_internal" [(set (match_operand:BOOL_128 0 "vlogical_operand" "=<BOOL_REGS_OUTPUT>") (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "<BOOL_REGS_UNARY>")))] diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index 886cbad..0ef64eb 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -107,6 +107,8 @@ (smin "smin") (smax "smax")]) +(define_code_iterator fpcmpun [ungt unge unlt unle]) + ;; Vector move instructions. Little-endian VSX loads and stores require ;; special handling to circumvent "element endianness." @@ -493,6 +495,241 @@ FAIL; }) +;; To support vector condition vectorization, define vcond_mask and vec_cmp. + +;; Same mode for condition true/false values and predicate operand. +(define_expand "vcond_mask_<mode><mode>" + [(match_operand:VEC_I 0 "vint_operand") + (match_operand:VEC_I 1 "vint_operand") + (match_operand:VEC_I 2 "vint_operand") + (match_operand:VEC_I 3 "vint_operand")] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], + operands[3])); + DONE; +}) + +;; Condition true/false values are float but predicate operand is of +;; type integer vector with same element size. +(define_expand "vcond_mask_<mode><VEC_int>" + [(match_operand:VEC_F 0 "vfloat_operand") + (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand") + (match_operand:<VEC_INT> 3 "vint_operand")] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + emit_insn (gen_vector_select_<mode> (operands[0], operands[2], operands[1], + gen_lowpart (<MODE>mode, operands[3]))); + DONE; +}) + +;; For signed integer vectors comparison. +(define_expand "vec_cmp<mode><mode>" + [(set (match_operand:VEC_I 0 "vint_operand") + (match_operator 1 "comparison_operator" + [(match_operand:VEC_I 2 "vint_operand") + (match_operand:VEC_I 3 "vint_operand")]))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx tmp = gen_reg_rtx (<MODE>mode); + switch (code) + { + case NE: + emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); + emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); + break; + case EQ: + emit_insn (gen_vector_eq<mode> (operands[0], operands[2], operands[3])); + break; + case GE: + emit_insn ( + gen_vector_nlt<mode> (operands[0], operands[2], operands[3], tmp)); + break; + case GT: + emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[3])); + break; + case LE: + emit_insn ( + gen_vector_ngt<mode> (operands[0], operands[2], operands[3], tmp)); + break; + case LT: + emit_insn (gen_vector_gt<mode> (operands[0], operands[3], operands[2])); + break; + case GEU: + emit_insn ( + gen_vector_nltu<mode> (operands[0], operands[2], operands[3], tmp)); + break; + case GTU: + emit_insn (gen_vector_gtu<mode> (operands[0], operands[2], operands[3])); + break; + case LEU: + emit_insn ( + gen_vector_ngtu<mode> (operands[0], operands[2], operands[3], tmp)); + break; + case LTU: + emit_insn (gen_vector_gtu<mode> (operands[0], operands[3], operands[2])); + break; + default: + gcc_unreachable (); + break; + } + DONE; +}) + +;; For unsigned integer vectors comparison. +(define_expand "vec_cmpu<mode><mode>" + [(set (match_operand:VEC_I 0 "vint_operand") + (match_operator 1 "comparison_operator" + [(match_operand:VEC_I 2 "vint_operand") + (match_operand:VEC_I 3 "vint_operand")]))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + emit_insn (gen_vec_cmp<mode><mode> (operands[0], operands[1], + operands[2], operands[3])); + DONE; +}) + +;; For float point vectors comparison. +(define_expand "vec_cmp<mode><VEC_int>" + [(set (match_operand:<VEC_INT> 0 "vint_operand") + (match_operator 1 "comparison_operator" + [(match_operand:VEC_F 2 "vfloat_operand") + (match_operand:VEC_F 3 "vfloat_operand")]))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx res = gen_reg_rtx (<MODE>mode); + switch (code) + { + case NE: + emit_insn (gen_vector_eq<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + emit_insn (gen_one_cmpl<VEC_int>2 (operands[0], operands[0])); + break; + case EQ: + emit_insn (gen_vector_eq<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case GE: + emit_insn (gen_vector_ge<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case GT: + emit_insn (gen_vector_gt<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case LE: + emit_insn (gen_vector_ge<mode> (res, operands[3], operands[2])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case LT: + emit_insn (gen_vector_gt<mode> (res, operands[3], operands[2])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case LTGT: + emit_insn (gen_vector_ltgt<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNORDERED: + emit_insn (gen_vector_unordered<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case ORDERED: + emit_insn (gen_vector_ordered<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNEQ: + emit_insn (gen_vector_uneq<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNGE: + emit_insn (gen_vector_unge<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNGT: + emit_insn (gen_vector_ungt<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNLE: + emit_insn (gen_vector_unle<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + case UNLT: + emit_insn (gen_vector_unlt<mode> (res, operands[2], operands[3])); + emit_insn ( + gen_move_insn (operands[0], gen_lowpart (<VEC_INT>mode, res))); + break; + + default: + gcc_unreachable (); + } + DONE; +}) + +;; For below vector_UN<cc><mode>: +;; op3 = (op1 >= op1) # !isNaN (op1) +;; op4 = (op2 >= op2) # !isNaN (op2) +;; op5 = !(op3 & op4) # isNaN (op1) || isNaN (op2) +;; op3 = op3 & op1 # isNaN (op1)? 0.0 : op1 +;; op4 = op4 & op2 # isNaN (op2)? 0.0 : op2 +;; op0 = op3 <cc> op4 # normal cmp if no NaNs +;; op0 = op5 | op0 # UNORDERED | normal cmp + +(define_expand "vector_<code><mode>" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (fpcmpun:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" +{ + rtx op3 = gen_reg_rtx (<MODE>mode); + rtx op4 = gen_reg_rtx (<MODE>mode); + rtx op5 = gen_reg_rtx (<MODE>mode); + + emit_insn (gen_vector_ge<mode> (op3, operands[1], operands[1])); + emit_insn (gen_vector_ge<mode> (op4, operands[2], operands[2])); + emit_insn (gen_and<mode>3 (op5, op3, op4)); + emit_insn (gen_one_cmpl<mode>3_internal (op5, op5)); + emit_insn (gen_and<mode>3 (op3, op3, operands[1])); + emit_insn (gen_and<mode>3 (op4, op4, operands[2])); + + switch (<CODE>) + { + case UNLT: + std::swap (op3, op4); + /* Fall through. */ + case UNGT: + emit_insn (gen_vector_gt<mode> (operands[0], op3, op4)); + break; + case UNLE: + std::swap (op3, op4); + /* Fall through. */ + case UNGE: + emit_insn (gen_vector_ge<mode> (operands[0], op3, op4)); + break; + default: + gcc_unreachable (); + } + + emit_insn (gen_ior<mode>3 (operands[0], op5, operands[0])); + DONE; +}) + + (define_expand "vector_eq<mode>" [(set (match_operand:VEC_C 0 "vlogical_operand") (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand") @@ -575,7 +812,7 @@ operands[3] = gen_reg_rtx_and_attrs (operands[0]); }) -(define_insn_and_split "*vector_uneq<mode>" +(define_insn_and_split "vector_uneq<mode>" [(set (match_operand:VEC_F 0 "vfloat_operand") (uneq:VEC_F (match_operand:VEC_F 1 "vfloat_operand") (match_operand:VEC_F 2 "vfloat_operand")))] @@ -596,7 +833,7 @@ operands[4] = gen_reg_rtx (<MODE>mode); }) -(define_insn_and_split "*vector_ltgt<mode>" +(define_insn_and_split "vector_ltgt<mode>" [(set (match_operand:VEC_F 0 "vfloat_operand") (ltgt:VEC_F (match_operand:VEC_F 1 "vfloat_operand") (match_operand:VEC_F 2 "vfloat_operand")))] @@ -617,7 +854,7 @@ operands[4] = gen_reg_rtx (<MODE>mode); }) -(define_insn_and_split "*vector_ordered<mode>" +(define_insn_and_split "vector_ordered<mode>" [(set (match_operand:VEC_F 0 "vfloat_operand") (ordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand") (match_operand:VEC_F 2 "vfloat_operand")))] @@ -638,7 +875,7 @@ operands[4] = gen_reg_rtx (<MODE>mode); }) -(define_insn_and_split "*vector_unordered<mode>" +(define_insn_and_split "vector_unordered<mode>" [(set (match_operand:VEC_F 0 "vfloat_operand") (unordered:VEC_F (match_operand:VEC_F 1 "vfloat_operand") (match_operand:VEC_F 2 "vfloat_operand")))] diff --git a/gcc/testsuite/gcc.target/powerpc/pr92132-fp-1.c b/gcc/testsuite/gcc.target/powerpc/pr92132-fp-1.c new file mode 100644 index 0000000..1023e8c --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr92132-fp-1.c @@ -0,0 +1,297 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-O2 -ftree-vectorize -mvsx -fno-vect-cost-model -fdump-tree-vect-details" } */ + +/* To test condition reduction vectorization, where comparison operands are of + double type and condition true/false values are integer type. Cover all + float point comparison codes. */ + +#include <math.h> + +extern void +abort (void) __attribute__ ((noreturn)); + +#define N 27 +#define FP_TYPE double + +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (!__builtin_islessgreater ((a), (b))) +#define UNGT(a, b) (!__builtin_islessequal ((a), (b))) +#define UNGE(a, b) (!__builtin_isless ((a), (b))) +#define UNLT(a, b) (!__builtin_isgreaterequal ((a), (b))) +#define UNLE(a, b) (!__builtin_isgreater ((a), (b))) + +__attribute__ ((noinline)) int +test_eq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] == min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ne (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] != min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_gt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] > min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] >= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_lt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] < min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_le (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] <= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ltgt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (LTGT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ord (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (ORD (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unord (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNORD (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_uneq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNEQ (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ungt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNGT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNGE (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unlt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNLT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unle (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNLE (a[i], min_v)) + last = i; + + return last; +} + +int +main (void) +{ + int ret = 0; + + FP_TYPE a1[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, 24, 25, 26, 27}; + + FP_TYPE a2[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, NAN, 25, 26, 27}; + + FP_TYPE a3[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7}; + + FP_TYPE a4[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, NAN, 6, 7}; + + FP_TYPE a5[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, NAN, 10, 10}; + + ret = test_eq (a1, 10); + if (ret != 19) + abort (); + + ret = test_ne (a1, 10); + if (ret != 26) + abort (); + + ret = test_gt (a3, 10); + if (ret != 19) + abort (); + + ret = test_ge (a3, 10); + if (ret != 19) + abort (); + + ret = test_lt (a1, 10); + if (ret != 18) + abort (); + + ret = test_le (a1, 10); + if (ret != 19) + abort (); + + ret = test_ltgt (a3, 10); + if (ret != 26) + abort (); + + ret = test_ltgt (a5, 10); + if (ret != 23) + abort (); + + ret = test_unord (a5, 10); + if (ret != 24) + abort (); + + ret = test_ord (a5, 10); + if (ret != 26) + abort (); + + ret = test_uneq (a1, 10); + if (ret != 19) + abort (); + + ret = test_uneq (a4, 10); + if (ret != 24) + abort (); + + ret = test_ungt (a3, 10); + if (ret != 19) + abort (); + + ret = test_ungt (a4, 10); + if (ret != 24) + abort (); + + ret = test_unge (a3, 10); + if (ret != 19) + abort (); + + ret = test_ungt (a4, 10); + if (ret != 24) + abort (); + + ret = test_unlt (a1, 10); + if (ret != 18) + abort (); + + ret = test_unlt (a2, 10); + if (ret != 23) + abort (); + + ret = test_unle (a1, 10); + if (ret != 19) + abort (); + + ret = test_unle (a2, 10); + if (ret != 23) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 14 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr92132-fp-2.c b/gcc/testsuite/gcc.target/powerpc/pr92132-fp-2.c new file mode 100644 index 0000000..db7b9ad --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr92132-fp-2.c @@ -0,0 +1,297 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vmx_hw } */ +/* { dg-options "-O2 -ftree-vectorize -maltivec -fno-vect-cost-model -fdump-tree-vect-details" } */ + +/* To test condition reduction vectorization, where comparison operands are of + float type and condition true/false values are integer type. Cover all + float point comparison codes. */ + +#include <math.h> + +extern void +abort (void) __attribute__ ((noreturn)); + +#define N 27 +#define FP_TYPE float + +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (!__builtin_islessgreater ((a), (b))) +#define UNGT(a, b) (!__builtin_islessequal ((a), (b))) +#define UNGE(a, b) (!__builtin_isless ((a), (b))) +#define UNLT(a, b) (!__builtin_isgreaterequal ((a), (b))) +#define UNLE(a, b) (!__builtin_isgreater ((a), (b))) + +__attribute__ ((noinline)) int +test_eq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] == min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ne (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] != min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_gt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] > min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] >= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_lt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] < min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_le (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] <= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ltgt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (LTGT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ord (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (ORD (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unord (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNORD (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_uneq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNEQ (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ungt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNGT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNGE (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unlt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNLT (a[i], min_v)) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_unle (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (UNLE (a[i], min_v)) + last = i; + + return last; +} + +int +main (void) +{ + int ret = 0; + + FP_TYPE a1[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, 24, 25, 26, 27}; + + FP_TYPE a2[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, NAN, 25, 26, 27}; + + FP_TYPE a3[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7}; + + FP_TYPE a4[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, NAN, 6, 7}; + + FP_TYPE a5[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, NAN, 10, 10}; + + ret = test_eq (a1, 10); + if (ret != 19) + abort (); + + ret = test_ne (a1, 10); + if (ret != 26) + abort (); + + ret = test_gt (a3, 10); + if (ret != 19) + abort (); + + ret = test_ge (a3, 10); + if (ret != 19) + abort (); + + ret = test_lt (a1, 10); + if (ret != 18) + abort (); + + ret = test_le (a1, 10); + if (ret != 19) + abort (); + + ret = test_ltgt (a3, 10); + if (ret != 26) + abort (); + + ret = test_ltgt (a5, 10); + if (ret != 23) + abort (); + + ret = test_unord (a5, 10); + if (ret != 24) + abort (); + + ret = test_ord (a5, 10); + if (ret != 26) + abort (); + + ret = test_uneq (a1, 10); + if (ret != 19) + abort (); + + ret = test_uneq (a4, 10); + if (ret != 24) + abort (); + + ret = test_ungt (a3, 10); + if (ret != 19) + abort (); + + ret = test_ungt (a4, 10); + if (ret != 24) + abort (); + + ret = test_unge (a3, 10); + if (ret != 19) + abort (); + + ret = test_ungt (a4, 10); + if (ret != 24) + abort (); + + ret = test_unlt (a1, 10); + if (ret != 18) + abort (); + + ret = test_unlt (a2, 10); + if (ret != 23) + abort (); + + ret = test_unle (a1, 10); + if (ret != 19) + abort (); + + ret = test_unle (a2, 10); + if (ret != 23) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 14 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr92132-int-1.c b/gcc/testsuite/gcc.target/powerpc/pr92132-int-1.c new file mode 100644 index 0000000..a786811 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr92132-int-1.c @@ -0,0 +1,126 @@ +/* { dg-do run } */ +/* { dg-require-effective-target p8vector_hw } */ +/* { dg-options "-O2 -ftree-vectorize -mdejagnu-cpu=power8 -fno-vect-cost-model -fdump-tree-vect-details" } */ + +/* To test condition reduction vectorization, where comparison operands are of + signed long long type and condition true/false values are integer type. */ + +#include <math.h> + +extern void +abort (void) __attribute__ ((noreturn)); + +#define N 27 +#define FP_TYPE signed long long + +__attribute__ ((noinline)) int +test_eq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] == min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ne (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] != min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_gt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] > min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] >= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_lt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] < min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_le (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] <= min_v) + last = i; + + return last; +} + +int +main (void) +{ + int ret = 0; + + FP_TYPE a1[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, 24, 25, 26, 27}; + + FP_TYPE a2[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7}; + + ret = test_eq (a1, 10); + if (ret != 19) + abort (); + + ret = test_ne (a1, 10); + if (ret != 26) + abort (); + + ret = test_gt (a2, 10); + if (ret != 19) + abort (); + + ret = test_ge (a2, 10); + if (ret != 19) + abort (); + + ret = test_lt (a1, 10); + if (ret != 18) + abort (); + + ret = test_le (a1, 10); + if (ret != 19) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 6 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr92132-int-2.c b/gcc/testsuite/gcc.target/powerpc/pr92132-int-2.c new file mode 100644 index 0000000..dd3c030 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr92132-int-2.c @@ -0,0 +1,126 @@ +/* { dg-do run } */ +/* { dg-require-effective-target p8vector_hw } */ +/* { dg-options "-O2 -ftree-vectorize -mdejagnu-cpu=power8 -fno-vect-cost-model -fdump-tree-vect-details" } */ + +/* To test condition reduction vectorization, where comparison operands are of + unsigned long long type and condition true/false values are integer type. */ + +#include <math.h> + +extern void +abort (void) __attribute__ ((noreturn)); + +#define N 27 +#define FP_TYPE unsigned long long + +__attribute__ ((noinline)) int +test_eq (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] == min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ne (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] != min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_gt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] > min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_ge (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] >= min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_lt (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] < min_v) + last = i; + + return last; +} + +__attribute__ ((noinline)) int +test_le (FP_TYPE *a, FP_TYPE min_v) +{ + int last = 0; + + for (int i = 0; i < N; i++) + if (a[i] <= min_v) + last = i; + + return last; +} + +int +main (void) +{ + int ret = 0; + + FP_TYPE a1[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 21, 22, 23, 24, 25, 26, 27}; + + FP_TYPE a2[N] = {21, 22, 23, 24, 25, 26, 27, 28, 29, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7}; + + ret = test_eq (a1, 10); + if (ret != 19) + abort (); + + ret = test_ne (a1, 10); + if (ret != 26) + abort (); + + ret = test_gt (a2, 10); + if (ret != 19) + abort (); + + ret = test_ge (a2, 10); + if (ret != 19) + abort (); + + ret = test_lt (a1, 10); + if (ret != 18) + abort (); + + ret = test_le (a1, 10); + if (ret != 19) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 6 "vect" } } */