]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
S/390: Fix vector all/any cc modes.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 2 Dec 2016 08:51:58 +0000 (08:51 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 2 Dec 2016 08:51:58 +0000 (08:51 +0000)
This fixes a problem with the vector compares producing CC mode
results.

The instructions produce condition code modes which can be either
interpreted to check an ALL elements or an ANY element result.  As the
modes where used before they could not be inverted by the middle-end
by inverting the comparison code (e.g. eq to ne).  The result usually
was just wrong.

In fact inverting a comparison code on an CCVALL mode would require to
also change the mode to CCVANY but this cannot be done easily in the
middle-end.  With this patch the meaning of an ALL cc mode only refers
to the not-inverted comparison code (e.g. eq, gt, ge).  With that
change inverting the comparison code matches a not operation on the
condition code mask again.

Bootstrapped and regression tested on s390 and s390x.

Bye,

-Andreas-

gcc/testsuite/ChangeLog:

2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

Backport from mainline
2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* gcc.target/s390/vector/vec-scalar-cmp-1.c: Fix and harden the
pattern checks.
* gcc.target/s390/zvector/vec-cmp-1.c: New test.

gcc/ChangeLog:

2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

Backport from mainline
2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* config/s390/s390-modes.def (CCVEQANY, CCVH, CCVHANY, CCVHU)
(CCVHUANY): Remove modes.
(CCVIH, CCVIHU, CCVIALL, CCVIANY, CCVFALL, CCVFANY): Add modes and
documentation.
* config/s390/s390.c (s390_match_ccmode_set): Rename cc modes.
(s390_expand_vec_compare_scalar): Pick one of the cc consumer
modes.
(s390_branch_condition_mask): Adjust to use the new cc consumer
modes.  The new modes allow for proper reversal in the middle-end.
(s390_expand_vec_compare_cc): Determine the proper cc producer and
consumer modes for a comparison.
* config/s390/s390.md: Rename CCVH to CCVIH and CCVHU to CCVIHU
throughout the file.
* config/s390/vx-builtins.md: Likewise.

From-SVN: r243169

gcc/ChangeLog
gcc/config/s390/s390-modes.def
gcc/config/s390/s390.c
gcc/config/s390/s390.md
gcc/config/s390/vx-builtins.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
gcc/testsuite/gcc.target/s390/zvector/vec-cmp-1.c [new file with mode: 0644]

index 7e5d4ebe403a792f367376fc60db2fdc163f7b63..3e86e38aadc9378d54bae52ff7076bb7a0769d88 100644 (file)
@@ -1,3 +1,23 @@
+2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       Backport from mainline
+       2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * config/s390/s390-modes.def (CCVEQANY, CCVH, CCVHANY, CCVHU)
+       (CCVHUANY): Remove modes.
+       (CCVIH, CCVIHU, CCVIALL, CCVIANY, CCVFALL, CCVFANY): Add modes and
+       documentation.
+       * config/s390/s390.c (s390_match_ccmode_set): Rename cc modes.
+       (s390_expand_vec_compare_scalar): Pick one of the cc consumer
+       modes.
+       (s390_branch_condition_mask): Adjust to use the new cc consumer
+       modes.  The new modes allow for proper reversal in the middle-end.
+       (s390_expand_vec_compare_cc): Determine the proper cc producer and
+       consumer modes for a comparison.
+       * config/s390/s390.md: Rename CCVH to CCVIH and CCVHU to CCVIHU
+       throughout the file.
+       * config/s390/vx-builtins.md: Likewise.
+
 2016-12-01  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        Backport from mainline
index f4c53f82552865b7dfde053671c2baaaa2c24d6b..7385c68f362bba6020eeb350c7c492fd8db699b7 100644 (file)
@@ -84,22 +84,6 @@ Requested mode            -> Destination CC register mode
 CCS, CCU, CCT, CCSR, CCUR -> CCZ
 CCA                       -> CCAP, CCAN
 
-Vector comparison modes
-
-CCVEQ            EQ      -            -           NE         (VCEQ)
-CCVEQANY  EQ     EQ           -           NE         (VCEQ)
-
-CCVH     GT      -            -           LE         (VCH)
-CCVHANY          GT      GT           -           LE         (VCH)
-CCVHU    GTU     -            -           LEU        (VCHL)
-CCVHUANY  GTU    GTU          -           LEU        (VCHL)
-
-CCVFH    GT      -            -           UNLE       (VFCH)
-CCVFHANY  GT     GT           -           UNLE       (VFCH)
-CCVFHE   GE      -            -           UNLT       (VFCHE)
-CCVFHEANY GE     GE           -           UNLT       (VFCHE)
-
-
 
 
 *** Comments ***
@@ -169,14 +153,40 @@ The compare and swap instructions sets the condition code to 0/1 if the
 operands were equal/unequal. The CCZ1 mode ensures the result can be
 effectively placed into a register.
 
-
-CCV*
-
-The variants with and without ANY are generated by the same
-instructions and therefore are holding the same information.  However,
-when generating a condition code mask they require checking different
-bits of CC.  In that case the variants without ANY represent the
-results for *all* elements.
+CCVIH, CCVIHU, CCVFH, CCVFHE
+
+These are condition code modes used in instructions setting the
+condition code.  The mode determines which comparison to perform (H -
+high, HU - high unsigned, HE - high or equal) and whether it is a
+floating point comparison or not (I - int, F - float).
+
+The comparison operation to be performed needs to be encoded into the
+condition code mode since the comparison operator is not available in
+compare style patterns (set cc (compare (op0) (op1))).  So the
+condition code mode is the only information to determine the
+instruction to be used.
+
+CCVIALL, CCVIANY, CCVFALL, CCVFANY
+
+These modes are used in instructions reading the condition code.
+Opposed to the CC producer patterns the comparison operator is
+available.  Hence the comparison operation does not need to be part of
+the CC mode.  However, we still need to know whether CC has been
+generated by a float or an integer comparison in order to be able to
+invert the condition correctly (int: GT -> LE, float: GT -> UNLE).
+
+The ALL and ANY variants differ only in the usage of CC1 which
+indicates a mixed result across the vector elements.  Be aware that
+depending on the comparison code the ALL and ANY variants might
+actually refer to their opposite meaning.  I.e. while inverting the
+comparison in (EQ (reg:CCVIALL 33) (const_int 0)) results in (NE
+(reg:CCVIALL 33) (const_int 0)) it in fact describes an ANY comparison
+(inverting "all equal" should be "any not equal") However, the
+middle-end does invert only the comparison operator without touching
+the mode.
+Hence, the ALL/ANY in the mode names refer to the meaning in the
+context of EQ, GT, GE while for the inverted codes it actually means
+ANY/ALL.
 
 CCRAW
 
@@ -209,18 +219,18 @@ CC_MODE (CCT3);
 CC_MODE (CCRAW);
 
 CC_MODE (CCVEQ);
-CC_MODE (CCVEQANY);
 
-CC_MODE (CCVH);
-CC_MODE (CCVHANY);
-CC_MODE (CCVHU);
-CC_MODE (CCVHUANY);
+CC_MODE (CCVIH);
+CC_MODE (CCVIHU);
 
 CC_MODE (CCVFH);
-CC_MODE (CCVFHANY);
 CC_MODE (CCVFHE);
-CC_MODE (CCVFHEANY);
 
+CC_MODE (CCVIALL);
+CC_MODE (CCVIANY);
+
+CC_MODE (CCVFALL);
+CC_MODE (CCVFANY);
 
 /* Vector modes.  */
 
index 8d04704f74b469c703ff5a02cb118f0cb81dd2f1..9629525e5c41fcf27f392949c6690b3e01f6cab7 100644 (file)
@@ -1242,6 +1242,11 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode)
 
   gcc_assert (GET_CODE (set) == SET);
 
+  /* These modes are supposed to be used only in CC consumer
+     patterns.  */
+  gcc_assert (req_mode != CCVIALLmode && req_mode != CCVIANYmode
+             && req_mode != CCVFALLmode && req_mode != CCVFANYmode);
+
   if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set))))
     return 1;
 
@@ -1260,8 +1265,8 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode)
     case CCT2mode:
     case CCT3mode:
     case CCVEQmode:
-    case CCVHmode:
-    case CCVHUmode:
+    case CCVIHmode:
+    case CCVIHUmode:
     case CCVFHmode:
     case CCVFHEmode:
       if (req_mode != set_mode)
@@ -1719,14 +1724,21 @@ s390_expand_vec_compare_scalar (enum rtx_code *code, rtx cmp1, rtx cmp2,
       cmp2 = cmp1;
       cmp1 = tmp;
     }
-  *cc = gen_rtx_REG (cmp_mode, CC_REGNUM);
+
   emit_insn (gen_rtx_PARALLEL (VOIDmode,
               gen_rtvec (2,
-                         gen_rtx_SET (VOIDmode, *cc,
+                         gen_rtx_SET (VOIDmode,
+                                      gen_rtx_REG (cmp_mode, CC_REGNUM),
                                       gen_rtx_COMPARE (cmp_mode, cmp1,
                                                        cmp2)),
                          gen_rtx_CLOBBER (VOIDmode,
                                           gen_rtx_SCRATCH (V2DImode)))));
+
+  /* This is the cc reg how it will be used in the cc mode consumer.
+     It either needs to be CCVFALL or CCVFANY.  However, CC1 will
+     never be set by the scalar variants.  So it actually doesn't
+     matter which one we choose here.  */
+  *cc = gen_rtx_REG (CCVFALLmode, CC_REGNUM);
   return true;
 }
 
@@ -1988,92 +2000,63 @@ s390_branch_condition_mask (rtx code)
       break;
 
       /* Vector comparison modes.  */
-
-    case CCVEQmode:
-      switch (GET_CODE (code))
-       {
-       case EQ:        return CC0;
-       case NE:        return CC3;
-       default:        return -1;
-       }
-
-    case CCVEQANYmode:
-      switch (GET_CODE (code))
-       {
-       case EQ:        return CC0 | CC1;
-       case NE:        return CC3 | CC1;
-       default:        return -1;
-       }
-
-      /* Integer vector compare modes.  */
-
-    case CCVHmode:
-      switch (GET_CODE (code))
-       {
-       case GT:        return CC0;
-       case LE:        return CC3;
-       default:        return -1;
-       }
-
-    case CCVHANYmode:
-      switch (GET_CODE (code))
-       {
-       case GT:        return CC0 | CC1;
-       case LE:        return CC3 | CC1;
-       default:        return -1;
-       }
-
-    case CCVHUmode:
-      switch (GET_CODE (code))
-       {
-       case GTU:       return CC0;
-       case LEU:       return CC3;
-       default:        return -1;
-       }
-
-    case CCVHUANYmode:
-      switch (GET_CODE (code))
-       {
-       case GTU:       return CC0 | CC1;
-       case LEU:       return CC3 | CC1;
-       default:        return -1;
-       }
-
-      /* FP vector compare modes.  */
-
-    case CCVFHmode:
+      /* CC2 will never be set.  It however is part of the negated
+        masks.  */
+    case CCVIALLmode:
       switch (GET_CODE (code))
        {
-       case GT:        return CC0;
-       case UNLE:      return CC3;
+       case EQ:
+       case GTU:
+       case GT:
+       case GE:        return CC0;
+         /* The inverted modes are in fact *any* modes.  */
+       case NE:
+       case LEU:
+       case LE:
+       case LT:        return CC3 | CC1 | CC2;
        default:        return -1;
        }
 
-    case CCVFHANYmode:
+    case CCVIANYmode:
       switch (GET_CODE (code))
        {
-       case GT:        return CC0 | CC1;
-       case UNLE:      return CC3 | CC1;
+       case EQ:
+       case GTU:
+       case GT:
+       case GE:        return CC0 | CC1;
+         /* The inverted modes are in fact *all* modes.  */
+       case NE:
+       case LEU:
+       case LE:
+       case LT:        return CC3 | CC2;
        default:        return -1;
        }
-
-    case CCVFHEmode:
+    case CCVFALLmode:
       switch (GET_CODE (code))
        {
+       case EQ:
+       case GT:
        case GE:        return CC0;
-       case UNLT:      return CC3;
+         /* The inverted modes are in fact *any* modes.  */
+       case NE:
+       case UNLE:
+       case UNLT:      return CC3 | CC1 | CC2;
        default:        return -1;
        }
 
-    case CCVFHEANYmode:
+    case CCVFANYmode:
       switch (GET_CODE (code))
        {
+       case EQ:
+       case GT:
        case GE:        return CC0 | CC1;
-       case UNLT:      return CC3 | CC1;
+         /* The inverted modes are in fact *all* modes.  */
+       case NE:
+       case UNLE:
+       case UNLT:      return CC3 | CC2;
        default:        return -1;
        }
 
-
     case CCRAWmode:
       switch (GET_CODE (code))
        {
@@ -6128,13 +6111,15 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
 
 /* Expand the comparison CODE of CMP1 and CMP2 and copy 1 or 0 into
    TARGET if either all (ALL_P is true) or any (ALL_P is false) of the
-   elements in CMP1 and CMP2 fulfill the comparison.  */
+   elements in CMP1 and CMP2 fulfill the comparison.
+   This function is only used to emit patterns for the vx builtins and
+   therefore only handles comparison codes required by the
+   builtins.  */
 void
 s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
                            rtx cmp1, rtx cmp2, bool all_p)
 {
-  enum rtx_code new_code = code;
-  machine_mode cmp_mode, full_cmp_mode, scratch_mode;
+  machine_mode cc_producer_mode, cc_consumer_mode, scratch_mode;
   rtx tmp_reg = gen_reg_rtx (SImode);
   bool swap_p = false;
 
@@ -6142,53 +6127,71 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
     {
       switch (code)
        {
-       case EQ:  cmp_mode = CCVEQmode; break;
-       case NE:  cmp_mode = CCVEQmode; break;
-       case GT:  cmp_mode = CCVHmode;  break;
-       case GE:  cmp_mode = CCVHmode;  new_code = LE; swap_p = true; break;
-       case LT:  cmp_mode = CCVHmode;  new_code = GT; swap_p = true; break;
-       case LE:  cmp_mode = CCVHmode;  new_code = LE; break;
-       case GTU: cmp_mode = CCVHUmode; break;
-       case GEU: cmp_mode = CCVHUmode; new_code = LEU; swap_p = true; break;
-       case LTU: cmp_mode = CCVHUmode; new_code = GTU; swap_p = true; break;
-       case LEU: cmp_mode = CCVHUmode; new_code = LEU; break;
-       default: gcc_unreachable ();
+       case EQ:
+       case NE:
+         cc_producer_mode = CCVEQmode;
+         break;
+       case GE:
+       case LT:
+         code = swap_condition (code);
+         swap_p = true;
+         /* fallthrough */
+       case GT:
+       case LE:
+         cc_producer_mode = CCVIHmode;
+         break;
+       case GEU:
+       case LTU:
+         code = swap_condition (code);
+         swap_p = true;
+         /* fallthrough */
+       case GTU:
+       case LEU:
+         cc_producer_mode = CCVIHUmode;
+         break;
+       default:
+         gcc_unreachable ();
        }
+
       scratch_mode = GET_MODE (cmp1);
+      /* These codes represent inverted CC interpretations.  Inverting
+        an ALL CC mode results in an ANY CC mode and the other way
+        around.  Invert the all_p flag here to compensate for
+        that.  */
+      if (code == NE || code == LE || code == LEU)
+       all_p = !all_p;
+
+      cc_consumer_mode = all_p ? CCVIALLmode : CCVIANYmode;
     }
-  else if (GET_MODE (cmp1) == V2DFmode)
+  else if (GET_MODE_CLASS (GET_MODE (cmp1)) == MODE_VECTOR_FLOAT)
     {
+      bool inv_p = false;
+
       switch (code)
        {
-       case EQ:   cmp_mode = CCVEQmode;  break;
-       case NE:   cmp_mode = CCVEQmode;  break;
-       case GT:   cmp_mode = CCVFHmode;  break;
-       case GE:   cmp_mode = CCVFHEmode; break;
-       case UNLE: cmp_mode = CCVFHmode;  break;
-       case UNLT: cmp_mode = CCVFHEmode; break;
-       case LT:   cmp_mode = CCVFHmode;  new_code = GT; swap_p = true; break;
-       case LE:   cmp_mode = CCVFHEmode; new_code = GE; swap_p = true; break;
+       case EQ:   cc_producer_mode = CCVEQmode;  break;
+       case NE:   cc_producer_mode = CCVEQmode;  inv_p = true; break;
+       case GT:   cc_producer_mode = CCVFHmode;  break;
+       case GE:   cc_producer_mode = CCVFHEmode; break;
+       case UNLE: cc_producer_mode = CCVFHmode;  inv_p = true; break;
+       case UNLT: cc_producer_mode = CCVFHEmode; inv_p = true; break;
+       case LT:   cc_producer_mode = CCVFHmode;  code = GT; swap_p = true; break;
+       case LE:   cc_producer_mode = CCVFHEmode; code = GE; swap_p = true; break;
        default: gcc_unreachable ();
        }
-      scratch_mode = V2DImode;
+      scratch_mode = mode_for_vector (
+                      int_mode_for_mode (GET_MODE_INNER (GET_MODE (cmp1))),
+                      GET_MODE_NUNITS (GET_MODE (cmp1)));
+      gcc_assert (scratch_mode != BLKmode);
+
+      if (inv_p)
+       all_p = !all_p;
+
+      cc_consumer_mode = all_p ? CCVFALLmode : CCVFANYmode;
     }
   else
     gcc_unreachable ();
 
-  if (!all_p)
-    switch (cmp_mode)
-      {
-      case CCVEQmode:  full_cmp_mode = CCVEQANYmode;  break;
-      case CCVHmode:   full_cmp_mode = CCVHANYmode;   break;
-      case CCVHUmode:  full_cmp_mode = CCVHUANYmode;  break;
-      case CCVFHmode:  full_cmp_mode = CCVFHANYmode;  break;
-      case CCVFHEmode: full_cmp_mode = CCVFHEANYmode; break;
-      default: gcc_unreachable ();
-      }
-  else
-    /* The modes without ANY match the ALL modes.  */
-    full_cmp_mode = cmp_mode;
-
   if (swap_p)
     {
       rtx tmp = cmp2;
@@ -6197,9 +6200,9 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
     }
 
   emit_insn (gen_rtx_PARALLEL (VOIDmode,
-              gen_rtvec (2, gen_rtx_SET (VOIDmode,
-                              gen_rtx_REG (cmp_mode, CC_REGNUM),
-                              gen_rtx_COMPARE (cmp_mode, cmp1, cmp2)),
+                         gen_rtvec (2, gen_rtx_SET (VOIDmode,
+                              gen_rtx_REG (cc_producer_mode, CC_REGNUM),
+                              gen_rtx_COMPARE (cc_producer_mode, cmp1, cmp2)),
                          gen_rtx_CLOBBER (VOIDmode,
                                           gen_rtx_SCRATCH (scratch_mode)))));
   emit_move_insn (target, const0_rtx);
@@ -6207,10 +6210,10 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
 
   emit_move_insn (target,
                  gen_rtx_IF_THEN_ELSE (SImode,
-                   gen_rtx_fmt_ee (new_code, VOIDmode,
-                                   gen_rtx_REG (full_cmp_mode, CC_REGNUM),
+                   gen_rtx_fmt_ee (code, VOIDmode,
+                                   gen_rtx_REG (cc_consumer_mode, CC_REGNUM),
                                    const0_rtx),
-                     target, tmp_reg));
+                                       tmp_reg, target));
 }
 
 /* Generate a vector comparison expression loading either elements of
index e7d9b55020f8b4f77d514fd13e4b27bf56995a5d..34106e4202ba44e6693a8946df11cec8a8cecc0f 100644 (file)
 ; Used with VFCMP to expand part of the mnemonic
 ; For fp we have a mismatch: eq in the insn name - e in asm
 (define_mode_attr asm_fcmp [(CCVEQ "e") (CCVFH "h") (CCVFHE "he")])
-(define_mode_attr insn_cmp [(CCVEQ "eq") (CCVH "h") (CCVHU "hl") (CCVFH "h") (CCVFHE "he")])
+(define_mode_attr insn_cmp [(CCVEQ "eq") (CCVIH "h") (CCVIHU "hl") (CCVFH "h") (CCVFHE "he")])
 
 
 (include "vector.md")
index 9cc13ce73de59218dee6edb5155a5af69998e299..d1481fdb70575c6c7cd4de8f3dbe1fe564a0d609 100644 (file)
@@ -36,7 +36,7 @@
                              (V1DF "DI") (V2DF "DI")])
 
 ; Condition code modes generated by int comparisons
-(define_mode_iterator VICMP [CCVEQ CCVH CCVHU])
+(define_mode_iterator VICMP [CCVEQ CCVIH CCVIHU])
 
 ; Comparisons supported by the vec_cmp* builtins
 (define_code_iterator intcmp [eq gt gtu ge geu lt ltu le leu])
 
 (define_expand "vec_cmph<VI_HW:mode>_cc"
   [(parallel
-    [(set (reg:CCVH CC_REGNUM)
-         (compare:CCVH (match_operand:VI_HW 1 "register_operand" "v")
-                       (match_operand:VI_HW 2 "register_operand" "v")))
+    [(set (reg:CCVIH CC_REGNUM)
+         (compare:CCVIH (match_operand:VI_HW 1 "register_operand" "v")
+                        (match_operand:VI_HW 2 "register_operand" "v")))
      (set (match_operand:VI_HW 0 "register_operand" "=v")
          (gt:VI_HW (match_dup 1) (match_dup 2)))])
    (set (match_operand:SI 3 "memory_operand" "")
-       (unspec:SI [(reg:CCVH CC_REGNUM)] UNSPEC_CC_TO_INT))]
+       (unspec:SI [(reg:CCVIH CC_REGNUM)] UNSPEC_CC_TO_INT))]
   "TARGET_VX")
 
 (define_expand "vec_cmphl<VI_HW:mode>_cc"
   [(parallel
-    [(set (reg:CCVHU CC_REGNUM)
-         (compare:CCVHU (match_operand:VI_HW 1 "register_operand" "v")
-                        (match_operand:VI_HW 2 "register_operand" "v")))
+    [(set (reg:CCVIHU CC_REGNUM)
+         (compare:CCVIHU (match_operand:VI_HW 1 "register_operand" "v")
+                         (match_operand:VI_HW 2 "register_operand" "v")))
      (set (match_operand:VI_HW 0 "register_operand" "=v")
          (gtu:VI_HW (match_dup 1) (match_dup 2)))])
    (set (match_operand:SI 3 "memory_operand" "")
-       (unspec:SI [(reg:CCVHU CC_REGNUM)] UNSPEC_CC_TO_INT))]
+       (unspec:SI [(reg:CCVIHU CC_REGNUM)] UNSPEC_CC_TO_INT))]
   "TARGET_VX")
 
 
   [(set_attr "op_type" "VRR")])
 
 (define_insn "*vec_cmph<VI_HW:mode>_cc"
-  [(set (reg:CCVH CC_REGNUM)
-       (compare:CCVH (match_operand:VI_HW 0 "register_operand"  "v")
-                     (match_operand:VI_HW 1 "register_operand"  "v")))
+  [(set (reg:CCVIH CC_REGNUM)
+       (compare:CCVIH (match_operand:VI_HW 0 "register_operand"  "v")
+                      (match_operand:VI_HW 1 "register_operand"  "v")))
    (set (match_operand:VI_HW               2 "register_operand" "=v")
        (gt:VI_HW (match_dup 0) (match_dup 1)))]
   "TARGET_VX"
   [(set_attr "op_type" "VRR")])
 
 (define_insn "*vec_cmphl<VI_HW:mode>_cc"
-  [(set (reg:CCVHU CC_REGNUM)
-       (compare:CCVHU (match_operand:VI_HW 0 "register_operand"  "v")
-                      (match_operand:VI_HW 1 "register_operand"  "v")))
+  [(set (reg:CCVIHU CC_REGNUM)
+       (compare:CCVIHU (match_operand:VI_HW 0 "register_operand"  "v")
+                       (match_operand:VI_HW 1 "register_operand"  "v")))
    (set (match_operand:VI_HW                2 "register_operand" "=v")
        (gtu:VI_HW (match_dup 0) (match_dup 1)))]
   "TARGET_VX"
 
 (define_expand "vec_cmphv2df_cc"
   [(parallel
-    [(set (reg:CCVH CC_REGNUM)
-         (compare:CCVH (match_operand:V2DF 1 "register_operand"  "v")
-                       (match_operand:V2DF 2 "register_operand"  "v")))
+    [(set (reg:CCVIH CC_REGNUM)
+         (compare:CCVIH (match_operand:V2DF 1 "register_operand"  "v")
+                        (match_operand:V2DF 2 "register_operand"  "v")))
      (set (match_operand:V2DI 0 "register_operand" "=v")
          (gt:V2DI (match_dup 1) (match_dup 2)))])
    (set (match_operand:SI 3 "memory_operand" "")
-       (unspec:SI [(reg:CCVH CC_REGNUM)] UNSPEC_CC_TO_INT))]
+       (unspec:SI [(reg:CCVIH CC_REGNUM)] UNSPEC_CC_TO_INT))]
   "TARGET_VX")
 
 (define_expand "vec_cmphev2df_cc"
   [(set_attr "op_type" "VRR")])
 
 (define_insn "*vec_cmphv2df_cc"
-  [(set (reg:CCVH CC_REGNUM)
-       (compare:CCVH (match_operand:V2DF 0 "register_operand"  "v")
-                     (match_operand:V2DF 1 "register_operand"  "v")))
+  [(set (reg:CCVIH CC_REGNUM)
+       (compare:CCVIH (match_operand:V2DF 0 "register_operand"  "v")
+                      (match_operand:V2DF 1 "register_operand"  "v")))
    (set (match_operand:V2DI               2 "register_operand" "=v")
        (gt:V2DI (match_dup 0) (match_dup 1)))]
   "TARGET_VX"
index 97fd34c713bd467e9e4dd41275417acabf92d45f..cb846e6d9b93c788b1a005cf3aeab10beb702f28 100644 (file)
@@ -1,3 +1,12 @@
+2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       Backport from mainline
+       2016-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       * gcc.target/s390/vector/vec-scalar-cmp-1.c: Fix and harden the
+       pattern checks.
+       * gcc.target/s390/zvector/vec-cmp-1.c: New test.
+
 2016-12-01  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/78279
index b79120f20f0f7c435a010b1549812f1a1de3cf36..5e61abfcbfe5dd19c476bfc17cabaa3b467619d7 100644 (file)
@@ -1,16 +1,7 @@
 /* Check that we use the scalar variants of vector compares.  */
 
 /* { dg-do compile { target { s390*-*-* } } } */
-/* { dg-options "-O3 -mzarch -march=z13" } */
-
-/* { dg-final { scan-assembler-times "wfcedbs\t%v\[0-9\]*,%v0,%v2" 2 } } */
-/* { dg-final { scan-assembler-times "wfchdbs\t%v\[0-9\]*,%v0,%v2" 1 } } */
-/* { dg-final { scan-assembler-times "wfchedbs\t%v\[0-9\]*,%v2,%v0" 1 } } */
-/* { dg-final { scan-assembler-times "wfchdbs\t%v\[0-9\]*,%v2,%v0" 1 } } */
-/* { dg-final { scan-assembler-times "wfchedbs\t%v\[0-9\]*,%v2,%v0" 1 } } */
-/* { dg-final { scan-assembler-times "locrne" 5 } } */
-/* { dg-final { scan-assembler-times "locrno" 1 } } */
-
+/* { dg-options "-O3 -mzarch -march=z13 -fno-asynchronous-unwind-tables" } */
 
 int
 eq (double a, double b)
@@ -18,32 +9,44 @@ eq (double a, double b)
   return a == b;
 }
 
+/* { dg-final { scan-assembler "eq:\n\twfcedbs\t%v\[0-9\]*,%v0,%v2\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocrne\t%r2,%r1" } } */
+
 int
 ne (double a, double b)
 {
   return a != b;
 }
 
+/* { dg-final { scan-assembler "ne:\n\twfcedbs\t%v\[0-9\]*,%v0,%v2\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocre\t%r2,%r1" } } */
+
 int
 gt (double a, double b)
 {
   return a > b;
 }
 
+/* { dg-final { scan-assembler "gt:\n\twfchdbs\t%v\[0-9\]*,%v0,%v2\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocrne\t%r2,%r1" } } */
+
 int
 ge (double a, double b)
 {
   return a >= b;
 }
 
+/* { dg-final { scan-assembler "ge:\n\twfchedbs\t%v\[0-9\]*,%v0,%v2\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocrne\t%r2,%r1" } } */
+
 int
 lt (double a, double b)
 {
   return a < b;
 }
 
+/* { dg-final { scan-assembler "lt:\n\twfchdbs\t%v\[0-9\]*,%v2,%v0\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocrne\t%r2,%r1" } } */
+
 int
 le (double a, double b)
 {
   return a <= b;
 }
+
+/* { dg-final { scan-assembler "le:\n\twfchedbs\t%v\[0-9\]*,%v2,%v0\n\tlhi\t%r1,0\n\tlhi\t%r2,1\n\tlocrne\t%r2,%r1" } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-1.c b/gcc/testsuite/gcc.target/s390/zvector/vec-cmp-1.c
new file mode 100644 (file)
index 0000000..438da2a
--- /dev/null
@@ -0,0 +1,174 @@
+/* { dg-do compile { target { s390*-*-* } } } */
+/* { dg-options "-O3 -mzarch -march=z13 -mzvector -fno-asynchronous-unwind-tables" } */
+
+#include <vecintrin.h>
+
+int __attribute__((noinline,noclone))
+all_eq_double (vector double a, vector double b)
+{
+       return vec_all_eq (a, b);
+}
+/* { dg-final { scan-assembler-times all_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_ne_double (vector double a, vector double b)
+{
+       return vec_all_ne (a, b);
+}
+/* { dg-final { scan-assembler-times all_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrnle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_gt_double (vector double a, vector double b)
+{
+       return vec_all_gt (a, b);
+}
+/* { dg-final { scan-assembler-times all_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_lt_double (vector double a, vector double b)
+{
+       return vec_all_lt (a, b);
+}
+/* { dg-final { scan-assembler-times all_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_ge_double (vector double a, vector double b)
+{
+       return vec_all_ge (a, b);
+}
+/* { dg-final { scan-assembler-times all_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_le_double (vector double a, vector double b)
+{
+       return vec_all_le (a, b);
+}
+/* { dg-final { scan-assembler-times all_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_eq_double (vector double a, vector double b)
+{
+       return vec_any_eq (a, b);
+}
+/* { dg-final { scan-assembler-times any_eq_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_ne_double (vector double a, vector double b)
+{
+       return vec_any_ne (a, b);
+}
+/* { dg-final { scan-assembler-times any_ne_double:\n\tvfcedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrne\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_gt_double (vector double a, vector double b)
+{
+       return vec_any_gt (a, b);
+}
+/* { dg-final { scan-assembler-times any_gt_double:\n\tvfchdbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_lt_double (vector double a, vector double b)
+{
+       return vec_any_lt (a, b);
+}
+/* { dg-final { scan-assembler-times any_lt_double:\n\tvfchdbs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_ge_double (vector double a, vector double b)
+{
+       return vec_any_ge (a, b);
+}
+/* { dg-final { scan-assembler-times any_ge_double:\n\tvfchedbs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_le_double (vector double a, vector double b)
+{
+       return vec_any_le (a, b);
+}
+/* { dg-final { scan-assembler-times any_le_double:\n\tvfchedbs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_eq_int (vector int a, vector int b)
+{
+       return vec_all_eq (a, b);
+}
+/* { dg-final { scan-assembler-times all_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_ne_int (vector int a, vector int b)
+{
+       return vec_all_ne (a, b);
+}
+/* { dg-final { scan-assembler-times all_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrnle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_gt_int (vector int a, vector int b)
+{
+       return vec_all_gt (a, b);
+}
+/* { dg-final { scan-assembler-times all_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_lt_int (vector int a, vector int b)
+{
+       return vec_all_lt (a, b);
+}
+/* { dg-final { scan-assembler-times all_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocre\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_ge_int (vector int a, vector int b)
+{
+       return vec_all_ge (a, b);
+}
+/* { dg-final { scan-assembler-times all_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrnle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+all_le_int (vector int a, vector int b)
+{
+       return vec_all_le (a, b);
+}
+/* { dg-final { scan-assembler-times all_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrnle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_eq_int (vector int a, vector int b)
+{
+       return vec_any_eq (a, b);
+}
+/* { dg-final { scan-assembler-times any_eq_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_ne_int (vector int a, vector int b)
+{
+       return vec_any_ne (a, b);
+}
+/* { dg-final { scan-assembler-times any_ne_int:\n\tvceqfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrne\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_gt_int (vector int a, vector int b)
+{
+       return vec_any_gt (a, b);
+}
+/* { dg-final { scan-assembler-times any_gt_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_lt_int (vector int a, vector int b)
+{
+       return vec_any_lt (a, b);
+}
+/* { dg-final { scan-assembler-times any_lt_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrle\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_ge_int (vector int a, vector int b)
+{
+       return vec_any_ge (a, b);
+}
+/* { dg-final { scan-assembler-times any_ge_int:\n\tvchfs\t%v\[0-9\]*,%v26,%v24\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrne\t%r2,%r1 1 } } */
+
+int __attribute__((noinline,noclone))
+any_le_int (vector int a, vector int b)
+{
+       return vec_any_le (a, b);
+}
+/* { dg-final { scan-assembler-times any_le_int:\n\tvchfs\t%v\[0-9\]*,%v24,%v26\n\tlhi\t%r1,1\n\tlhi\t%r2,0\n\tlocrne\t%r2,%r1 1 } } */
+
+