aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorKewen Lin <linkw@gcc.gnu.org>2019-11-25 05:15:30 +0000
committerKewen Lin <linkw@gcc.gnu.org>2019-11-25 05:15:30 +0000
commitbceb7181c852f0829ff4b8b4c86bd949eceda7bf (patch)
treeb9e36546d879d2c54793cd54e960a304272d67a3 /gcc/config
parentee1bc59e9d1b95102fb7092409885b3dcce9ea2a (diff)
downloadgcc-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.md265
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