From: Kewen Lin Date: Fri, 8 Nov 2019 07:37:07 +0000 (+0000) Subject: [rs6000]Fix PR92132 by adding vec_cmp and vcond_mask supports X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bc5b2b688150f96bd2b75aa1b7fc4d9d53712955;p=gcc.git [rs6000]Fix PR92132 by adding vec_cmp and vcond_mask supports To support full condition reduction vectorization, we have to define vec_cmp* and vcond_mask_*. This patch is to add related expands. Also add the missing vector fp comparison RTL pattern supports like: ungt, unge, unlt, unle, ne, lt and le. gcc/ChangeLog 2019-11-08 Kewen Lin PR target/92132 * config/rs6000/predicates.md (signed_or_equality_comparison_operator): New predicate. (unsigned_or_equality_comparison_operator): Likewise. * config/rs6000/rs6000.md (one_cmpl2): Remove expand. (one_cmpl3_internal): Rename to one_cmpl2. * config/rs6000/vector.md (vcond_mask_ for VEC_I and VEC_I): New expand. (vec_cmp for VEC_I and VEC_I): Likewise. (vec_cmpu for VEC_I and VEC_I): Likewise. (vcond_mask_ for VEC_F): New expand for float vector modes and same-size integer vector modes. (vec_cmp for VEC_F): Likewise. (vector_lt for VEC_F): New expand. (vector_le for VEC_F): Likewise. (vector_ne for VEC_F): Likewise. (vector_unge for VEC_F): Likewise. (vector_ungt for VEC_F): Likewise. (vector_unle for VEC_F): Likewise. (vector_unlt for VEC_F): Likewise. (vector_uneq): Expose name. (vector_ltgt): Likewise. (vector_unordered): Likewise. (vector_ordered): Likewise. gcc/testsuite/ChangeLog 2019-11-08 Kewen Lin 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. From-SVN: r277947 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9a33aa1ebe3..0780b31a42e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2019-11-08 Kewen Lin + + PR target/92132 + * config/rs6000/predicates.md + (signed_or_equality_comparison_operator): New predicate. + (unsigned_or_equality_comparison_operator): Likewise. + * config/rs6000/rs6000.md (one_cmpl2): Remove expand. + (one_cmpl3_internal): Rename to one_cmpl2. + * config/rs6000/vector.md + (vcond_mask_ for VEC_I and VEC_I): New expand. + (vec_cmp for VEC_I and VEC_I): Likewise. + (vec_cmpu for VEC_I and VEC_I): Likewise. + (vcond_mask_ for VEC_F): New expand for float + vector modes and same-size integer vector modes. + (vec_cmp for VEC_F): Likewise. + (vector_lt for VEC_F): New expand. + (vector_le for VEC_F): Likewise. + (vector_ne for VEC_F): Likewise. + (vector_unge for VEC_F): Likewise. + (vector_ungt for VEC_F): Likewise. + (vector_unle for VEC_F): Likewise. + (vector_unlt for VEC_F): Likewise. + (vector_uneq): Expose name. + (vector_ltgt): Likewise. + (vector_unordered): Likewise. + (vector_ordered): Likewise. + 2019-11-08 Hongtao Liu PR target/92295 diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 6c3f2e2eddd..51cdd3a129d 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1147,6 +1147,16 @@ (define_predicate "signed_comparison_operator" (match_code "lt,gt,le,ge")) +;; Return 1 if OP is a signed comparison or an equality operator. +(define_predicate "signed_or_equality_comparison_operator" + (ior (match_operand 0 "equality_operator") + (match_operand 0 "signed_comparison_operator"))) + +;; Return 1 if OP is an unsigned comparison or an equality operator. +(define_predicate "unsigned_or_equality_comparison_operator" + (ior (match_operand 0 "equality_operator") + (match_operand 0 "unsigned_comparison_operator"))) + ;; Return 1 if OP is a comparison operation that is valid for an SCC insn -- ;; it must be a positive comparison. (define_predicate "scc_comparison_operator" diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index a3c909fabfb..fb18681da5d 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6504,12 +6504,6 @@ "" "") -(define_expand "one_cmpl2" - [(set (match_operand:BOOL_128 0 "vlogical_operand") - (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand")))] - "" - "") - (define_expand "nor3" [(set (match_operand:BOOL_128 0 "vlogical_operand") (and:BOOL_128 @@ -6804,7 +6798,7 @@ (const_string "16")))]) ;; 128-bit one's complement -(define_insn_and_split "*one_cmpl3_internal" +(define_insn_and_split "one_cmpl2" [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") (not:BOOL_128 (match_operand:BOOL_128 1 "vlogical_operand" "")))] diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index 886cbad1655..b132037290e 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -493,6 +493,260 @@ 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_" + [(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)" +{ + emit_insn (gen_vector_select_ (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_" + [(match_operand:VEC_F 0 "vfloat_operand") + (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand") + (match_operand: 3 "vint_operand")] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_select_ (operands[0], operands[2], operands[1], + gen_lowpart (mode, operands[3]))); + DONE; +}) + +;; For signed integer vectors comparison. +(define_expand "vec_cmp" + [(set (match_operand:VEC_I 0 "vint_operand") + (match_operator 1 "signed_or_equality_comparison_operator" + [(match_operand:VEC_I 2 "vint_operand") + (match_operand:VEC_I 3 "vint_operand")]))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx tmp = gen_reg_rtx (mode); + switch (code) + { + case NE: + emit_insn (gen_vector_eq (operands[0], operands[2], operands[3])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + break; + case EQ: + emit_insn (gen_vector_eq (operands[0], operands[2], operands[3])); + break; + case GE: + emit_insn (gen_vector_nlt (operands[0],operands[2], operands[3], + tmp)); + break; + case GT: + emit_insn (gen_vector_gt (operands[0], operands[2], operands[3])); + break; + case LE: + emit_insn (gen_vector_ngt (operands[0], operands[2], operands[3], + tmp)); + break; + case LT: + emit_insn (gen_vector_gt (operands[0], operands[3], operands[2])); + break; + default: + gcc_unreachable (); + break; + } + DONE; +}) + +;; For unsigned integer vectors comparison. +(define_expand "vec_cmpu" + [(set (match_operand:VEC_I 0 "vint_operand") + (match_operator 1 "unsigned_or_equality_comparison_operator" + [(match_operand:VEC_I 2 "vint_operand") + (match_operand:VEC_I 3 "vint_operand")]))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx tmp = gen_reg_rtx (mode); + switch (code) + { + case NE: + emit_insn (gen_vector_eq (operands[0], operands[2], operands[3])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + break; + case EQ: + emit_insn (gen_vector_eq (operands[0], operands[2], operands[3])); + break; + case GEU: + emit_insn (gen_vector_nltu (operands[0], operands[2], operands[3], + tmp)); + break; + case GTU: + emit_insn (gen_vector_gtu (operands[0], operands[2], operands[3])); + break; + case LEU: + emit_insn (gen_vector_ngtu (operands[0], operands[2], operands[3], + tmp)); + break; + case LTU: + emit_insn (gen_vector_gtu (operands[0], operands[3], operands[2])); + break; + default: + gcc_unreachable (); + break; + } + DONE; +}) + +;; For float point vectors comparison. +(define_expand "vec_cmp" + [(set (match_operand: 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)" +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx res = gen_reg_rtx (mode); + switch (code) + { + case NE: + emit_insn (gen_vector_ne (res, operands[2], operands[3])); + break; + case EQ: + emit_insn (gen_vector_eq (res, operands[2], operands[3])); + break; + case GE: + emit_insn (gen_vector_ge (res, operands[2], operands[3])); + break; + case GT: + emit_insn (gen_vector_gt (res, operands[2], operands[3])); + break; + case LE: + emit_insn (gen_vector_le (res, operands[2], operands[3])); + break; + case LT: + emit_insn (gen_vector_lt (res, operands[2], operands[3])); + break; + case LTGT: + emit_insn (gen_vector_ltgt (res, operands[2], operands[3])); + break; + case UNORDERED: + emit_insn (gen_vector_unordered (res, operands[2], operands[3])); + break; + case ORDERED: + emit_insn (gen_vector_ordered (res, operands[2], operands[3])); + break; + case UNEQ: + emit_insn (gen_vector_uneq (res, operands[2], operands[3])); + break; + case UNGE: + emit_insn (gen_vector_unge (res, operands[2], operands[3])); + break; + case UNGT: + emit_insn (gen_vector_ungt (res, operands[2], operands[3])); + break; + case UNLE: + emit_insn (gen_vector_unle (res, operands[2], operands[3])); + break; + case UNLT: + emit_insn (gen_vector_unlt (res, operands[2], operands[3])); + break; + + default: + gcc_unreachable (); + } + + emit_insn (gen_move_insn (operands[0], gen_lowpart (mode, res))); + DONE; +}) + +; lt(a,b) = gt(b,a) +(define_expand "vector_lt" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (lt:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_gt (operands[0], operands[2], operands[1])); + DONE; +}) + +; le(a,b) = ge(b,a) +(define_expand "vector_le" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (le:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_ge (operands[0], operands[2], operands[1])); + DONE; +}) + +; ne(a,b) = ~eq(a,b) +(define_expand "vector_ne" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (ne:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_eq (operands[0], operands[1], operands[2])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + DONE; +}) + +; unge(a,b) = ~gt(b,a) +(define_expand "vector_unge" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (unge:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_gt (operands[0], operands[2], operands[1])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + DONE; +}) + +; ungt(a,b) = ~ge(b,a) +(define_expand "vector_ungt" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (ungt:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_ge (operands[0], operands[2], operands[1])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + DONE; +}) + +; unle(a,b) = ~gt(a,b) +(define_expand "vector_unle" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (unle:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_gt (operands[0], operands[1], operands[2])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + DONE; +}) + +; unlt(a,b) = ~ge(a,b) +(define_expand "vector_unlt" + [(set (match_operand:VEC_F 0 "vfloat_operand") + (unlt:VEC_F (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +{ + emit_insn (gen_vector_ge (operands[0], operands[1], operands[2])); + emit_insn (gen_one_cmpl2 (operands[0], operands[0])); + DONE; +}) + (define_expand "vector_eq" [(set (match_operand:VEC_C 0 "vlogical_operand") (eq:VEC_C (match_operand:VEC_C 1 "vlogical_operand") @@ -575,7 +829,7 @@ operands[3] = gen_reg_rtx_and_attrs (operands[0]); }) -(define_insn_and_split "*vector_uneq" +(define_insn_and_split "vector_uneq" [(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 +850,7 @@ operands[4] = gen_reg_rtx (mode); }) -(define_insn_and_split "*vector_ltgt" +(define_insn_and_split "vector_ltgt" [(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 +871,7 @@ operands[4] = gen_reg_rtx (mode); }) -(define_insn_and_split "*vector_ordered" +(define_insn_and_split "vector_ordered" [(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 +892,7 @@ operands[4] = gen_reg_rtx (mode); }) -(define_insn_and_split "*vector_unordered" +(define_insn_and_split "vector_unordered" [(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/ChangeLog b/gcc/testsuite/ChangeLog index dec89484145..9fbff8b363a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-11-08 Kewen Lin + + 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. + 2019-11-08 Hongtao Liu * gcc.target/i386/pr92295.c: New test. 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 00000000000..1023e8cd9d8 --- /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 + +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 00000000000..db7b9ad7a17 --- /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 + +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 00000000000..a786811a57f --- /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 + +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 00000000000..dd3c0307535 --- /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 + +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" } } */