[AArch64] Use UNSPEC_MERGE_PTRUE for comparisons
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 8 May 2018 09:56:29 +0000 (09:56 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 8 May 2018 09:56:29 +0000 (09:56 +0000)
This patch rewrites the SVE comparison handling so that it uses
UNSPEC_MERGE_PTRUE for comparisons that are known to be predicated
on a PTRUE, for consistency with other patterns.  Specific unspecs
are then only needed for truly predicated floating-point comparisons,
such as those used in the expansion of UNEQ for flag_trapping_math.

The patch also makes sure that the comparison expanders attach
a REG_EQUAL note to instructions that use UNSPEC_MERGE_PTRUE,
so passes can use that as an alternative to the unspec pattern.
(This happens automatically for optabs.  The problem was that
this code emits instruction patterns directly.)

No specific benefit on its own, but it lays the groundwork for
the next patch.

2018-05-08  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* config/aarch64/iterators.md (UNSPEC_COND_LO, UNSPEC_COND_LS)
(UNSPEC_COND_HI, UNSPEC_COND_HS, UNSPEC_COND_UO): Delete.
(SVE_INT_CMP, SVE_FP_CMP): New code iterators.
(cmp_op, sve_imm_con): New code attributes.
(SVE_COND_INT_CMP, imm_con): Delete.
(cmp_op): Remove above unspecs from int attribute.
* config/aarch64/aarch64-sve.md (*vec_cmp<cmp_op>_<mode>): Rename
to...
(*cmp<cmp_op><mode>): ...this.  Use UNSPEC_MERGE_PTRUE instead of
comparison-specific unspecs.
(*vec_cmp<cmp_op>_<mode>_ptest): Rename to...
(*cmp<cmp_op><mode>_ptest): ...this and adjust likewise.
(*vec_cmp<cmp_op>_<mode>_cc): Rename to...
(*cmp<cmp_op><mode>_cc): ...this and adjust likewise.
(*vec_fcm<cmp_op><mode>): Rename to...
(*fcm<cmp_op><mode>): ...this and adjust likewise.
(*vec_fcmuo<mode>): Rename to...
(*fcmuo<mode>): ...this and adjust likewise.
(*pred_fcm<cmp_op><mode>): New pattern.
* config/aarch64/aarch64.c (aarch64_emit_unop, aarch64_emit_binop)
(aarch64_emit_sve_ptrue_op, aarch64_emit_sve_ptrue_op_cc): New
functions.
(aarch64_unspec_cond_code): Remove handling of LTU, GTU, LEU, GEU
and UNORDERED.
(aarch64_gen_unspec_cond, aarch64_emit_unspec_cond): Delete.
(aarch64_emit_sve_predicated_cond): New function.
(aarch64_expand_sve_vec_cmp_int): Use aarch64_emit_sve_ptrue_op_cc.
(aarch64_emit_unspec_cond_or): Replace with...
(aarch64_emit_sve_or_conds): ...this new function.  Use
aarch64_emit_sve_ptrue_op for the individual comparisons and
aarch64_emit_binop to OR them together.
(aarch64_emit_inverted_unspec_cond): Replace with...
(aarch64_emit_sve_inverted_cond): ...this new function.  Use
aarch64_emit_sve_ptrue_op for the comparison and
aarch64_emit_unop to invert the result.
(aarch64_expand_sve_vec_cmp_float): Update after the above
changes.  Use aarch64_emit_sve_ptrue_op for native comparisons.

From-SVN: r260029

gcc/ChangeLog
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/iterators.md

index 868c87d525cbec42c7aaaf9ab8a615fb5197c344..cf85cc838828af1b0167fe80aa32c4c81b16d653 100644 (file)
@@ -1,3 +1,43 @@
+2018-05-08  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * config/aarch64/iterators.md (UNSPEC_COND_LO, UNSPEC_COND_LS)
+       (UNSPEC_COND_HI, UNSPEC_COND_HS, UNSPEC_COND_UO): Delete.
+       (SVE_INT_CMP, SVE_FP_CMP): New code iterators.
+       (cmp_op, sve_imm_con): New code attributes.
+       (SVE_COND_INT_CMP, imm_con): Delete.
+       (cmp_op): Remove above unspecs from int attribute.
+       * config/aarch64/aarch64-sve.md (*vec_cmp<cmp_op>_<mode>): Rename
+       to...
+       (*cmp<cmp_op><mode>): ...this.  Use UNSPEC_MERGE_PTRUE instead of
+       comparison-specific unspecs.
+       (*vec_cmp<cmp_op>_<mode>_ptest): Rename to...
+       (*cmp<cmp_op><mode>_ptest): ...this and adjust likewise.
+       (*vec_cmp<cmp_op>_<mode>_cc): Rename to...
+       (*cmp<cmp_op><mode>_cc): ...this and adjust likewise.
+       (*vec_fcm<cmp_op><mode>): Rename to...
+       (*fcm<cmp_op><mode>): ...this and adjust likewise.
+       (*vec_fcmuo<mode>): Rename to...
+       (*fcmuo<mode>): ...this and adjust likewise.
+       (*pred_fcm<cmp_op><mode>): New pattern.
+       * config/aarch64/aarch64.c (aarch64_emit_unop, aarch64_emit_binop)
+       (aarch64_emit_sve_ptrue_op, aarch64_emit_sve_ptrue_op_cc): New
+       functions.
+       (aarch64_unspec_cond_code): Remove handling of LTU, GTU, LEU, GEU
+       and UNORDERED.
+       (aarch64_gen_unspec_cond, aarch64_emit_unspec_cond): Delete.
+       (aarch64_emit_sve_predicated_cond): New function.
+       (aarch64_expand_sve_vec_cmp_int): Use aarch64_emit_sve_ptrue_op_cc.
+       (aarch64_emit_unspec_cond_or): Replace with...
+       (aarch64_emit_sve_or_conds): ...this new function.  Use
+       aarch64_emit_sve_ptrue_op for the individual comparisons and
+       aarch64_emit_binop to OR them together.
+       (aarch64_emit_inverted_unspec_cond): Replace with...
+       (aarch64_emit_sve_inverted_cond): ...this new function.  Use
+       aarch64_emit_sve_ptrue_op for the comparison and
+       aarch64_emit_unop to invert the result.
+       (aarch64_expand_sve_vec_cmp_float): Update after the above
+       changes.  Use aarch64_emit_sve_ptrue_op for native comparisons.
+
 2018-05-07  Nathan Sidwell  <nathan@acm.org>
 
        * doc/invoke.texi (C++ Dialect Options): Remove -ffor-scope.
index d88553405094853ab58ba1c55cd212092a14116c..7a1f58a8091e6b9702048b8a1669bfcdecb65c55 100644 (file)
   }
 )
 
-;; Predicated integer comparison.
-(define_insn "*vec_cmp<cmp_op>_<mode>"
+;; Integer comparisons predicated with a PTRUE.
+(define_insn "*cmp<cmp_op><mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
        (unspec:<VPRED>
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
-          (match_operand:SVE_I 2 "register_operand" "w, w")
-          (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
-         SVE_COND_INT_CMP))
+          (SVE_INT_CMP:<VPRED>
+            (match_operand:SVE_I 2 "register_operand" "w, w")
+            (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+         UNSPEC_MERGE_PTRUE))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_SVE"
   "@
    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
 )
 
-;; Predicated integer comparison in which only the flags result is interesting.
-(define_insn "*vec_cmp<cmp_op>_<mode>_ptest"
+;; Integer comparisons predicated with a PTRUE in which only the flags result
+;; is interesting.
+(define_insn "*cmp<cmp_op><mode>_ptest"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
          (unspec:SI
            [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
             (unspec:<VPRED>
               [(match_dup 1)
-               (match_operand:SVE_I 2 "register_operand" "w, w")
-               (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
-              SVE_COND_INT_CMP)]
+               (SVE_INT_CMP:<VPRED>
+                 (match_operand:SVE_I 2 "register_operand" "w, w")
+                 (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+              UNSPEC_MERGE_PTRUE)]
            UNSPEC_PTEST_PTRUE)
          (const_int 0)))
    (clobber (match_scratch:<VPRED> 0 "=Upa, Upa"))]
    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
 )
 
-;; Predicated comparison in which both the flag and predicate results
-;; are interesting.
-(define_insn "*vec_cmp<cmp_op>_<mode>_cc"
+;; Integer comparisons predicated with a PTRUE in which both the flag and
+;; predicate results are interesting.
+(define_insn "*cmp<cmp_op><mode>_cc"
   [(set (reg:CC CC_REGNUM)
        (compare:CC
          (unspec:SI
            [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
             (unspec:<VPRED>
               [(match_dup 1)
-               (match_operand:SVE_I 2 "register_operand" "w, w")
-               (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
-              SVE_COND_INT_CMP)]
+               (SVE_INT_CMP:<VPRED>
+                 (match_operand:SVE_I 2 "register_operand" "w, w")
+                 (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+              UNSPEC_MERGE_PTRUE)]
            UNSPEC_PTEST_PTRUE)
          (const_int 0)))
    (set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
        (unspec:<VPRED>
          [(match_dup 1)
-          (match_dup 2)
-          (match_dup 3)]
-         SVE_COND_INT_CMP))]
+          (SVE_INT_CMP:<VPRED>
+            (match_dup 2)
+            (match_dup 3))]
+         UNSPEC_MERGE_PTRUE))]
   "TARGET_SVE"
   "@
    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
    cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
 )
 
-;; Predicated floating-point comparison (excluding FCMUO, which doesn't
-;; allow #0.0 as an operand).
-(define_insn "*vec_fcm<cmp_op><mode>"
+;; Floating-point comparisons predicated with a PTRUE.
+(define_insn "*fcm<cmp_op><mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
        (unspec:<VPRED>
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
-          (match_operand:SVE_F 2 "register_operand" "w, w")
-          (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
-         SVE_COND_FP_CMP))]
+          (SVE_FP_CMP:<VPRED>
+            (match_operand:SVE_F 2 "register_operand" "w, w")
+            (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w"))]
+         UNSPEC_MERGE_PTRUE))]
   "TARGET_SVE"
   "@
    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
    fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
 )
 
-;; Predicated FCMUO.
-(define_insn "*vec_fcmuo<mode>"
+(define_insn "*fcmuo<mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
        (unspec:<VPRED>
          [(match_operand:<VPRED> 1 "register_operand" "Upl")
-          (match_operand:SVE_F 2 "register_operand" "w")
-          (match_operand:SVE_F 3 "register_operand" "w")]
-         UNSPEC_COND_UO))]
+          (unordered:<VPRED>
+            (match_operand:SVE_F 2 "register_operand" "w")
+            (match_operand:SVE_F 3 "register_operand" "w"))]
+         UNSPEC_MERGE_PTRUE))]
   "TARGET_SVE"
   "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
 )
 
+;; Predicated floating-point comparisons.  We don't need a version
+;; of this for unordered comparisons.
+(define_insn "*pred_fcm<cmp_op><mode>"
+  [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
+       (unspec:<VPRED>
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (match_operand:SVE_F 2 "register_operand" "w, w")
+          (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
+         SVE_COND_FP_CMP))]
+  "TARGET_SVE"
+  "@
+   fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
+   fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+)
+
 ;; vcond_mask operand order: true, false, mask
 ;; UNSPEC_SEL operand order: mask, true, false (as for VEC_COND_EXPR)
 ;; SEL operand order:        mask, true, false
index 6847b9a683c3c9b3f3824f779875064ac029f70a..a2003fe52875f1653d644347bafd7773d1f01e91 100644 (file)
@@ -1873,6 +1873,27 @@ aarch64_emit_move (rtx dest, rtx src)
          : emit_move_insn_1 (dest, src));
 }
 
+/* Apply UNOPTAB to OP and store the result in DEST.  */
+
+static void
+aarch64_emit_unop (rtx dest, optab unoptab, rtx op)
+{
+  rtx tmp = expand_unop (GET_MODE (dest), unoptab, op, dest, 0);
+  if (dest != tmp)
+    emit_move_insn (dest, tmp);
+}
+
+/* Apply BINOPTAB to OP0 and OP1 and store the result in DEST.  */
+
+static void
+aarch64_emit_binop (rtx dest, optab binoptab, rtx op0, rtx op1)
+{
+  rtx tmp = expand_binop (GET_MODE (dest), binoptab, op0, op1, dest, 0,
+                         OPTAB_DIRECT);
+  if (dest != tmp)
+    emit_move_insn (dest, tmp);
+}
+
 /* Split a 128-bit move operation into two 64-bit move operations,
    taking care to handle partial overlap of register to register
    copies.  Special cases are needed when moving between GP regs and
@@ -15675,6 +15696,34 @@ aarch64_sve_cmp_operand_p (rtx_code op_code, rtx x)
     }
 }
 
+/* Use predicated SVE instructions to implement the equivalent of:
+
+     (set TARGET OP)
+
+   given that PTRUE is an all-true predicate of the appropriate mode.  */
+
+static void
+aarch64_emit_sve_ptrue_op (rtx target, rtx ptrue, rtx op)
+{
+  rtx unspec = gen_rtx_UNSPEC (GET_MODE (target),
+                              gen_rtvec (2, ptrue, op),
+                              UNSPEC_MERGE_PTRUE);
+  rtx_insn *insn = emit_set_insn (target, unspec);
+  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (op));
+}
+
+/* Likewise, but also clobber the condition codes.  */
+
+static void
+aarch64_emit_sve_ptrue_op_cc (rtx target, rtx ptrue, rtx op)
+{
+  rtx unspec = gen_rtx_UNSPEC (GET_MODE (target),
+                              gen_rtvec (2, ptrue, op),
+                              UNSPEC_MERGE_PTRUE);
+  rtx_insn *insn = emit_insn (gen_set_clobber_cc (target, unspec));
+  set_unique_reg_note (insn, REG_EQUAL, copy_rtx (op));
+}
+
 /* Return the UNSPEC_COND_* code for comparison CODE.  */
 
 static unsigned int
@@ -15694,35 +15743,33 @@ aarch64_unspec_cond_code (rtx_code code)
       return UNSPEC_COND_LE;
     case GE:
       return UNSPEC_COND_GE;
-    case LTU:
-      return UNSPEC_COND_LO;
-    case GTU:
-      return UNSPEC_COND_HI;
-    case LEU:
-      return UNSPEC_COND_LS;
-    case GEU:
-      return UNSPEC_COND_HS;
-    case UNORDERED:
-      return UNSPEC_COND_UO;
     default:
       gcc_unreachable ();
     }
 }
 
-/* Return an (unspec:PRED_MODE [PRED OP0 OP1] UNSPEC_COND_<X>) expression,
-   where <X> is the operation associated with comparison CODE.  */
+/* Emit:
 
-static rtx
-aarch64_gen_unspec_cond (rtx_code code, machine_mode pred_mode,
-                        rtx pred, rtx op0, rtx op1)
+      (set TARGET (unspec [PRED OP0 OP1] UNSPEC_COND_<X>))
+
+   where <X> is the operation associated with comparison CODE.  This form
+   of instruction is used when (and (CODE OP0 OP1) PRED) would have different
+   semantics, such as when PRED might not be all-true and when comparing
+   inactive lanes could have side effects.  */
+
+static void
+aarch64_emit_sve_predicated_cond (rtx target, rtx_code code,
+                                 rtx pred, rtx op0, rtx op1)
 {
-  rtvec vec = gen_rtvec (3, pred, op0, op1);
-  return gen_rtx_UNSPEC (pred_mode, vec, aarch64_unspec_cond_code (code));
+  rtx unspec = gen_rtx_UNSPEC (GET_MODE (pred),
+                              gen_rtvec (3, pred, op0, op1),
+                              aarch64_unspec_cond_code (code));
+  emit_set_insn (target, unspec);
 }
 
-/* Expand an SVE integer comparison:
+/* Expand an SVE integer comparison using the SVE equivalent of:
 
-     TARGET = CODE (OP0, OP1).  */
+     (set TARGET (CODE OP0 OP1)).  */
 
 void
 aarch64_expand_sve_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1)
@@ -15734,78 +15781,53 @@ aarch64_expand_sve_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1)
     op1 = force_reg (data_mode, op1);
 
   rtx ptrue = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
-  rtx unspec = aarch64_gen_unspec_cond (code, pred_mode, ptrue, op0, op1);
-  emit_insn (gen_set_clobber_cc (target, unspec));
-}
-
-/* Emit an instruction:
-
-      (set TARGET (unspec:PRED_MODE [PRED OP0 OP1] UNSPEC_COND_<X>))
-
-   where <X> is the operation associated with comparison CODE.  */
-
-static void
-aarch64_emit_unspec_cond (rtx target, rtx_code code, machine_mode pred_mode,
-                         rtx pred, rtx op0, rtx op1)
-{
-  rtx unspec = aarch64_gen_unspec_cond (code, pred_mode, pred, op0, op1);
-  emit_set_insn (target, unspec);
+  rtx cond = gen_rtx_fmt_ee (code, pred_mode, op0, op1);
+  aarch64_emit_sve_ptrue_op_cc (target, ptrue, cond);
 }
 
-/* Emit:
+/* Emit the SVE equivalent of:
 
-      (set TMP1 (unspec:PRED_MODE [PTRUE OP0 OP1] UNSPEC_COND_<X1>))
-      (set TMP2 (unspec:PRED_MODE [PTRUE OP0 OP1] UNSPEC_COND_<X2>))
-      (set TARGET (and:PRED_MODE (ior:PRED_MODE TMP1 TMP2) PTRUE))
+      (set TMP1 (CODE1 OP0 OP1))
+      (set TMP2 (CODE2 OP0 OP1))
+      (set TARGET (ior:PRED_MODE TMP1 TMP2))
 
-   where <Xi> is the operation associated with comparison CODEi.  */
+   PTRUE is an all-true predicate with the same mode as TARGET.  */
 
 static void
-aarch64_emit_unspec_cond_or (rtx target, rtx_code code1, rtx_code code2,
-                            machine_mode pred_mode, rtx ptrue,
-                            rtx op0, rtx op1)
+aarch64_emit_sve_or_conds (rtx target, rtx_code code1, rtx_code code2,
+                          rtx ptrue, rtx op0, rtx op1)
 {
+  machine_mode pred_mode = GET_MODE (ptrue);
   rtx tmp1 = gen_reg_rtx (pred_mode);
-  aarch64_emit_unspec_cond (tmp1, code1, pred_mode, ptrue, op0, op1);
+  aarch64_emit_sve_ptrue_op (tmp1, ptrue,
+                            gen_rtx_fmt_ee (code1, pred_mode, op0, op1));
   rtx tmp2 = gen_reg_rtx (pred_mode);
-  aarch64_emit_unspec_cond (tmp2, code2, pred_mode, ptrue, op0, op1);
-  emit_set_insn (target, gen_rtx_AND (pred_mode,
-                                     gen_rtx_IOR (pred_mode, tmp1, tmp2),
-                                     ptrue));
+  aarch64_emit_sve_ptrue_op (tmp2, ptrue,
+                            gen_rtx_fmt_ee (code2, pred_mode, op0, op1));
+  aarch64_emit_binop (target, ior_optab, tmp1, tmp2);
 }
 
-/* If CAN_INVERT_P, emit an instruction:
+/* Emit the SVE equivalent of:
 
-      (set TARGET (unspec:PRED_MODE [PRED OP0 OP1] UNSPEC_COND_<X>))
+      (set TMP (CODE OP0 OP1))
+      (set TARGET (not TMP))
 
-   where <X> is the operation associated with comparison CODE.  Otherwise
-   emit:
-
-      (set TMP (unspec:PRED_MODE [PRED OP0 OP1] UNSPEC_COND_<X>))
-      (set TARGET (and:PRED_MODE (not:PRED_MODE TMP) PTRUE))
-
-   where the second instructions sets TARGET to the inverse of TMP.  */
+   PTRUE is an all-true predicate with the same mode as TARGET.  */
 
 static void
-aarch64_emit_inverted_unspec_cond (rtx target, rtx_code code,
-                                  machine_mode pred_mode, rtx ptrue, rtx pred,
-                                  rtx op0, rtx op1, bool can_invert_p)
+aarch64_emit_sve_inverted_cond (rtx target, rtx ptrue, rtx_code code,
+                               rtx op0, rtx op1)
 {
-  if (can_invert_p)
-    aarch64_emit_unspec_cond (target, code, pred_mode, pred, op0, op1);
-  else
-    {
-      rtx tmp = gen_reg_rtx (pred_mode);
-      aarch64_emit_unspec_cond (tmp, code, pred_mode, pred, op0, op1);
-      emit_set_insn (target, gen_rtx_AND (pred_mode,
-                                         gen_rtx_NOT (pred_mode, tmp),
-                                         ptrue));
-    }
+  machine_mode pred_mode = GET_MODE (ptrue);
+  rtx tmp = gen_reg_rtx (pred_mode);
+  aarch64_emit_sve_ptrue_op (tmp, ptrue,
+                            gen_rtx_fmt_ee (code, pred_mode, op0, op1));
+  aarch64_emit_unop (target, one_cmpl_optab, tmp);
 }
 
-/* Expand an SVE floating-point comparison:
+/* Expand an SVE floating-point comparison using the SVE equivalent of:
 
-     TARGET = CODE (OP0, OP1)
+     (set TARGET (CODE OP0 OP1))
 
    If CAN_INVERT_P is true, the caller can also handle inverted results;
    return true if the result is in fact inverted.  */
@@ -15823,30 +15845,23 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code,
     case UNORDERED:
       /* UNORDERED has no immediate form.  */
       op1 = force_reg (data_mode, op1);
-      aarch64_emit_unspec_cond (target, code, pred_mode, ptrue, op0, op1);
-      return false;
-
+      /* fall through */
     case LT:
     case LE:
     case GT:
     case GE:
     case EQ:
     case NE:
-      /* There is native support for the comparison.  */
-      aarch64_emit_unspec_cond (target, code, pred_mode, ptrue, op0, op1);
-      return false;
-
-    case ORDERED:
-      /* There is native support for the inverse comparison.  */
-      op1 = force_reg (data_mode, op1);
-      aarch64_emit_inverted_unspec_cond (target, UNORDERED,
-                                        pred_mode, ptrue, ptrue, op0, op1,
-                                        can_invert_p);
-      return can_invert_p;
+      {
+       /* There is native support for the comparison.  */
+       rtx cond = gen_rtx_fmt_ee (code, pred_mode, op0, op1);
+       aarch64_emit_sve_ptrue_op (target, ptrue, cond);
+       return false;
+      }
 
     case LTGT:
       /* This is a trapping operation (LT or GT).  */
-      aarch64_emit_unspec_cond_or (target, LT, GT, pred_mode, ptrue, op0, op1);
+      aarch64_emit_sve_or_conds (target, LT, GT, ptrue, op0, op1);
       return false;
 
     case UNEQ:
@@ -15854,38 +15869,59 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code,
        {
          /* This would trap for signaling NaNs.  */
          op1 = force_reg (data_mode, op1);
-         aarch64_emit_unspec_cond_or (target, UNORDERED, EQ,
-                                      pred_mode, ptrue, op0, op1);
+         aarch64_emit_sve_or_conds (target, UNORDERED, EQ, ptrue, op0, op1);
          return false;
        }
       /* fall through */
-
     case UNLT:
     case UNLE:
     case UNGT:
     case UNGE:
-      {
-       rtx ordered = ptrue;
-       if (flag_trapping_math)
-         {
-           /* Only compare the elements that are known to be ordered.  */
-           ordered = gen_reg_rtx (pred_mode);
-           op1 = force_reg (data_mode, op1);
-           aarch64_emit_inverted_unspec_cond (ordered, UNORDERED, pred_mode,
-                                              ptrue, ptrue, op0, op1, false);
-         }
-       if (code == UNEQ)
-         code = NE;
-       else
-         code = reverse_condition_maybe_unordered (code);
-       aarch64_emit_inverted_unspec_cond (target, code, pred_mode, ptrue,
-                                          ordered, op0, op1, can_invert_p);
-       return can_invert_p;
-      }
+      if (flag_trapping_math)
+       {
+         /* Work out which elements are ordered.  */
+         rtx ordered = gen_reg_rtx (pred_mode);
+         op1 = force_reg (data_mode, op1);
+         aarch64_emit_sve_inverted_cond (ordered, ptrue, UNORDERED, op0, op1);
+
+         /* Test the opposite condition for the ordered elements,
+            then invert the result.  */
+         if (code == UNEQ)
+           code = NE;
+         else
+           code = reverse_condition_maybe_unordered (code);
+         if (can_invert_p)
+           {
+             aarch64_emit_sve_predicated_cond (target, code,
+                                               ordered, op0, op1);
+             return true;
+           }
+         rtx tmp = gen_reg_rtx (pred_mode);
+         aarch64_emit_sve_predicated_cond (tmp, code, ordered, op0, op1);
+         aarch64_emit_unop (target, one_cmpl_optab, tmp);
+         return false;
+       }
+      break;
+
+    case ORDERED:
+      /* ORDERED has no immediate form.  */
+      op1 = force_reg (data_mode, op1);
+      break;
 
     default:
       gcc_unreachable ();
     }
+
+  /* There is native support for the inverse comparison.  */
+  code = reverse_condition_maybe_unordered (code);
+  if (can_invert_p)
+    {
+      rtx cond = gen_rtx_fmt_ee (code, pred_mode, op0, op1);
+      aarch64_emit_sve_ptrue_op (target, ptrue, cond);
+      return true;
+    }
+  aarch64_emit_sve_inverted_cond (target, ptrue, code, op0, op1);
+  return false;
 }
 
 /* Expand an SVE vcond pattern with operands OPS.  DATA_MODE is the mode
index 25991d97836498f48ca30b8757ed7963217da417..bcedb86291fae367abd50f98c8b76c304d195051 100644 (file)
     UNSPEC_COND_NE     ; Used in aarch64-sve.md.
     UNSPEC_COND_GE     ; Used in aarch64-sve.md.
     UNSPEC_COND_GT     ; Used in aarch64-sve.md.
-    UNSPEC_COND_LO     ; Used in aarch64-sve.md.
-    UNSPEC_COND_LS     ; Used in aarch64-sve.md.
-    UNSPEC_COND_HS     ; Used in aarch64-sve.md.
-    UNSPEC_COND_HI     ; Used in aarch64-sve.md.
-    UNSPEC_COND_UO     ; Used in aarch64-sve.md.
     UNSPEC_LASTB       ; Used in aarch64-sve.md.
 ])
 
 ;; SVE floating-point unary operations.
 (define_code_iterator SVE_FP_UNARY [neg abs sqrt])
 
+;; SVE integer comparisons.
+(define_code_iterator SVE_INT_CMP [lt le eq ne ge gt ltu leu geu gtu])
+
+;; SVE floating-point comparisons.
+(define_code_iterator SVE_FP_CMP [lt le eq ne ge gt])
+
 ;; -------------------------------------------------------------------
 ;; Code Attributes
 ;; -------------------------------------------------------------------
                        (ltu "LTU") (leu "LEU") (ne "NE") (geu "GEU")
                        (gtu "GTU")])
 
+;; The AArch64 condition associated with an rtl comparison code.
+(define_code_attr cmp_op [(lt "lt")
+                         (le "le")
+                         (eq "eq")
+                         (ne "ne")
+                         (ge "ge")
+                         (gt "gt")
+                         (ltu "lo")
+                         (leu "ls")
+                         (geu "hs")
+                         (gtu "hi")])
+
 (define_code_attr fix_trunc_optab [(fix "fix_trunc")
                                   (unsigned_fix "fixuns_trunc")])
 
                             (abs "fabs")
                             (sqrt "fsqrt")])
 
+;; The SVE immediate constraint to use for an rtl code.
+(define_code_attr sve_imm_con [(eq "vsc")
+                              (ne "vsc")
+                              (lt "vsc")
+                              (ge "vsc")
+                              (le "vsc")
+                              (gt "vsc")
+                              (ltu "vsd")
+                              (leu "vsd")
+                              (geu "vsd")
+                              (gtu "vsd")])
+
 ;; -------------------------------------------------------------------
 ;; Int Iterators.
 ;; -------------------------------------------------------------------
 
 (define_int_iterator SVE_COND_FP_OP [UNSPEC_COND_ADD UNSPEC_COND_SUB])
 
-(define_int_iterator SVE_COND_INT_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
-                                      UNSPEC_COND_EQ UNSPEC_COND_NE
-                                      UNSPEC_COND_GE UNSPEC_COND_GT
-                                      UNSPEC_COND_LO UNSPEC_COND_LS
-                                      UNSPEC_COND_HS UNSPEC_COND_HI])
-
 (define_int_iterator SVE_COND_FP_CMP [UNSPEC_COND_LT UNSPEC_COND_LE
                                      UNSPEC_COND_EQ UNSPEC_COND_NE
                                      UNSPEC_COND_GE UNSPEC_COND_GT])
                         (UNSPEC_COND_EQ "eq")
                         (UNSPEC_COND_NE "ne")
                         (UNSPEC_COND_GE "ge")
-                        (UNSPEC_COND_GT "gt")
-                        (UNSPEC_COND_LO "lo")
-                        (UNSPEC_COND_LS "ls")
-                        (UNSPEC_COND_HS "hs")
-                        (UNSPEC_COND_HI "hi")])
-
-;; The constraint to use for an UNSPEC_COND_<xx>.
-(define_int_attr imm_con [(UNSPEC_COND_EQ "vsc")
-                         (UNSPEC_COND_NE "vsc")
-                         (UNSPEC_COND_LT "vsc")
-                         (UNSPEC_COND_GE "vsc")
-                         (UNSPEC_COND_LE "vsc")
-                         (UNSPEC_COND_GT "vsc")
-                         (UNSPEC_COND_LO "vsd")
-                         (UNSPEC_COND_LS "vsd")
-                         (UNSPEC_COND_HS "vsd")
-                         (UNSPEC_COND_HI "vsd")])
+                        (UNSPEC_COND_GT "gt")])
 
 (define_int_attr sve_int_op [(UNSPEC_COND_ADD "add")
                             (UNSPEC_COND_SUB "sub")