[rs6000] Refactor FP vector comparison operators
authorKewen Lin <linkw@gcc.gnu.org>
Mon, 25 Nov 2019 05:15:30 +0000 (05:15 +0000)
committerKewen Lin <linkw@gcc.gnu.org>
Mon, 25 Nov 2019 05:15:30 +0000 (05:15 +0000)
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

gcc/ChangeLog
gcc/config/rs6000/vector.md

index ca1527e81ecb3d52e2d362649067a1bdbfeca61f..f37b9866a8d98ae42f9b5b0d75c160f847ce3178 100644 (file)
@@ -1,3 +1,26 @@
+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
index b132037290ec40c97838f0ac0122a9373d69e56d..75c4a99e2a0738ec699a2a35dcdcb98c57c1892d 100644 (file)
                                 (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])
+
 \f
 ;; Vector move instructions.  Little-endian VSX loads and stores require
 ;; special handling to circumvent "element endianness."
   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")
   "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")
   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