Commit bceb7181 by Kewen Lin

[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
parent ee1bc59e
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.
2019-11-24 Jerry DeLisle <jvdelisle@gcc.ngu.org>
PR fortran/92100
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment