diff options
author | Kewen Lin <linkw@gcc.gnu.org> | 2019-11-25 05:15:30 +0000 |
---|---|---|
committer | Kewen Lin <linkw@gcc.gnu.org> | 2019-11-25 05:15:30 +0000 |
commit | bceb7181c852f0829ff4b8b4c86bd949eceda7bf (patch) | |
tree | b9e36546d879d2c54793cd54e960a304272d67a3 /gcc/config | |
parent | ee1bc59e9d1b95102fb7092409885b3dcce9ea2a (diff) | |
download | gcc-bceb7181c852f0829ff4b8b4c86bd949eceda7bf.zip gcc-bceb7181c852f0829ff4b8b4c86bd949eceda7bf.tar.gz gcc-bceb7181c852f0829ff4b8b4c86bd949eceda7bf.tar.bz2 |
[rs6000] Refactor FP vector comparison operators
This is a subsequent patch to refactor the existing float point
vector comparison operator supports. The patch to fix PR92132
supplemented vector float point comparison by exposing the names
for unordered/ordered/uneq/ltgt and adding ungt/unge/unlt/unle/
ne. As Segher pointed out, some patterns can be refactored
together. The main link on this is:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00452.html
gcc/ChangeLog
2019-11-25 Kewen Lin <linkw@gcc.gnu.org>
* config/rs6000/vector.md (vector_fp_comparison_simple): New code iterator.
(vector_fp_comparison_complex): Likewise.
(vector_<code><mode> for VEC_F and vector_fp_comparison_simple): New
define_and_split.
(vector_<code><mode> for VEC_F and vector_fp_comparison_complex): Likewise.
(vector_lt<mode> for VEC_F): Refactor with vector_fp_comparison_simple.
(vector_le<mode> for VEC_F): Likewise.
(vector_unge<mode> for VEC_F): Likewise.
(vector_unle<mode> for VEC_F): Likewise.
(vector_ne<mode> for VEC_F): Likewise.
(vector_ungt<mode> for VEC_F): Likewise.
(vector_unlt<mode> for VEC_F): Likewise.
(vector_ltgt<mode> for VEC_F): Refactor with vector_fp_comparison_complex.
(vector_ordered<mode> for VEC_F): Likewise.
(vector_uneq<mode> for VEC_F): Likewise.
(vector_unordered<mode> for VEC_F): Likewise.
From-SVN: r278665
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rs6000/vector.md | 265 |
1 files changed, 105 insertions, 160 deletions
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index b132037..75c4a99 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -107,6 +107,12 @@ (smin "smin") (smax "smax")]) +;; code iterators and attributes for vector FP comparison operators: +(define_code_iterator + vector_fp_comparison_simple [lt le ne ungt unge unlt unle]) +(define_code_iterator + vector_fp_comparison_complex [ltgt uneq unordered ordered]) + ;; Vector move instructions. Little-endian VSX loads and stores require ;; special handling to circumvent "element endianness." @@ -665,88 +671,6 @@ DONE; }) -; lt(a,b) = gt(b,a) -(define_expand "vector_lt<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[1])); - DONE; -}) - -; le(a,b) = ge(b,a) -(define_expand "vector_le<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_ge<mode> (operands[0], operands[2], operands[1])); - DONE; -}) - -; ne(a,b) = ~eq(a,b) -(define_expand "vector_ne<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_eq<mode> (operands[0], operands[1], operands[2])); - emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); - DONE; -}) - -; unge(a,b) = ~gt(b,a) -(define_expand "vector_unge<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_gt<mode> (operands[0], operands[2], operands[1])); - emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); - DONE; -}) - -; ungt(a,b) = ~ge(b,a) -(define_expand "vector_ungt<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_ge<mode> (operands[0], operands[2], operands[1])); - emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); - DONE; -}) - -; unle(a,b) = ~gt(a,b) -(define_expand "vector_unle<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_gt<mode> (operands[0], operands[1], operands[2])); - emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0])); - DONE; -}) - -; unlt(a,b) = ~ge(a,b) -(define_expand "vector_unlt<mode>" - [(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>mode)" -{ - emit_insn (gen_vector_ge<mode> (operands[0], operands[1], operands[2])); - emit_insn (gen_one_cmpl<mode>2 (operands[0], 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") @@ -761,13 +685,6 @@ "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" "") -(define_expand "vector_ge<mode>" - [(set (match_operand:VEC_F 0 "vlogical_operand") - (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand") - (match_operand:VEC_F 2 "vlogical_operand")))] - "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" - "") - ; >= for integer vectors: swap operands and apply not-greater-than (define_expand "vector_nlt<mode>" [(set (match_operand:VEC_I 3 "vlogical_operand") @@ -829,88 +746,116 @@ operands[3] = gen_reg_rtx_and_attrs (operands[0]); }) -(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")))] - "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" - "#" - "" - [(set (match_dup 3) - (gt:VEC_F (match_dup 1) - (match_dup 2))) - (set (match_dup 4) - (gt:VEC_F (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (and:VEC_F (not:VEC_F (match_dup 3)) - (not:VEC_F (match_dup 4))))] -{ - operands[3] = gen_reg_rtx (<MODE>mode); - operands[4] = gen_reg_rtx (<MODE>mode); -}) +; There are 14 possible vector FP comparison operators, gt and eq of them have +; been expanded above, so just support 12 remaining operators here. -(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")))] +; For ge: +(define_expand "vector_ge<mode>" + [(set (match_operand:VEC_F 0 "vlogical_operand") + (ge:VEC_F (match_operand:VEC_F 1 "vlogical_operand") + (match_operand:VEC_F 2 "vlogical_operand")))] "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" - "#" - "" - [(set (match_dup 3) - (gt:VEC_F (match_dup 1) - (match_dup 2))) - (set (match_dup 4) - (gt:VEC_F (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (ior:VEC_F (match_dup 3) - (match_dup 4)))] -{ - operands[3] = gen_reg_rtx (<MODE>mode); - operands[4] = gen_reg_rtx (<MODE>mode); -}) + "") -(define_insn_and_split "vector_ordered<mode>" +; For lt/le/ne/ungt/unge/unlt/unle: +; lt(a,b) = gt(b,a) +; le(a,b) = ge(b,a) +; unge(a,b) = ~lt(a,b) +; unle(a,b) = ~gt(a,b) +; ne(a,b) = ~eq(a,b) +; ungt(a,b) = ~le(a,b) +; unlt(a,b) = ~ge(a,b) +(define_insn_and_split "vector_<code><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")))] - "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" + (vector_fp_comparison_simple:VEC_F + (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" "#" - "" - [(set (match_dup 3) - (ge:VEC_F (match_dup 1) - (match_dup 2))) - (set (match_dup 4) - (ge:VEC_F (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (ior:VEC_F (match_dup 3) - (match_dup 4)))] + "&& can_create_pseudo_p ()" + [(pc)] { - operands[3] = gen_reg_rtx (<MODE>mode); - operands[4] = gen_reg_rtx (<MODE>mode); + enum rtx_code cond = <CODE>; + bool need_invert = false; + + if (cond == UNLE || cond == UNLT || cond == NE || cond == UNGE + || cond == UNGT) + { + cond = reverse_condition_maybe_unordered (cond); + need_invert = true; + } + + if (cond == LT || cond == LE) + { + cond = swap_condition (cond); + std::swap (operands[1], operands[2]); + } + + gcc_assert (cond == EQ || cond == GE || cond == GT); + + rtx comp = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); + + if (need_invert) + { + rtx res = gen_reg_rtx (<MODE>mode); + emit_insn (gen_rtx_SET (res, comp)); + emit_insn (gen_one_cmpl<mode>2 (operands[0], res)); + } + else + emit_insn (gen_rtx_SET (operands[0], comp)); + + DONE; }) -(define_insn_and_split "vector_unordered<mode>" +; For ltgt/uneq/ordered/unordered: +; ltgt: gt(a,b) | gt(b,a) +; uneq: ~(gt(a,b) | gt(b,a)) +; ordered: ge(a,b) | ge(b,a) +; unordered: ~(ge(a,b) | ge(b,a)) +(define_insn_and_split "vector_<code><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")))] - "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" + (vector_fp_comparison_complex:VEC_F + (match_operand:VEC_F 1 "vfloat_operand") + (match_operand:VEC_F 2 "vfloat_operand")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode) && can_create_pseudo_p ()" "#" - "" - [(set (match_dup 3) - (ge:VEC_F (match_dup 1) - (match_dup 2))) - (set (match_dup 4) - (ge:VEC_F (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (and:VEC_F (not:VEC_F (match_dup 3)) - (not:VEC_F (match_dup 4))))] + "&& can_create_pseudo_p ()" + [(pc)] { - operands[3] = gen_reg_rtx (<MODE>mode); - operands[4] = gen_reg_rtx (<MODE>mode); + enum rtx_code cond = <CODE>; + bool need_invert = false; + + if (cond == UNORDERED || cond == UNEQ) + { + cond = reverse_condition_maybe_unordered (cond); + need_invert = true; + } + + if (cond == LTGT) + cond = GT; + else if (cond == ORDERED) + cond = GE; + else + gcc_unreachable (); + + rtx comp1 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[1], operands[2]); + rtx res1 = gen_reg_rtx (<MODE>mode); + emit_insn (gen_rtx_SET (res1, comp1)); + rtx comp2 = gen_rtx_fmt_ee (cond, <MODE>mode, operands[2], operands[1]); + rtx res2 = gen_reg_rtx (<MODE>mode); + emit_insn (gen_rtx_SET (res2, comp2)); + + if (need_invert) + { + rtx not1 = gen_rtx_fmt_e (NOT, <MODE>mode, res1); + rtx not2 = gen_rtx_fmt_e (NOT, <MODE>mode, res2); + rtx comp3 = gen_rtx_fmt_ee (AND, <MODE>mode, not1, not2); + emit_insn (gen_rtx_SET (operands[0], comp3)); + } + else + emit_insn (gen_ior<mode>3 (operands[0], res1, res2)); + + DONE; }) ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask |