visium-modes.def (CC_NOOV): Rename into...
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 11 Oct 2016 08:19:17 +0000 (08:19 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 11 Oct 2016 08:19:17 +0000 (08:19 +0000)
* config/visium/visium-modes.def (CC_NOOV): Rename into...
(CCNZ): ...this.
(CC_BTST): Rename into...
(CCC): ...this.
* config/visium/predicates.md (real_add_operand): New.
(visium_btst_operator): Rename into...
(visium_equality_comparison_operator): ...this.
(visium_noov_operator): Rename into...
(visium_nz_comparison_operator): ...this.
(visium_c_comparison_operator): New.
(visium_branch_operator): Adjust and deal with all CC modes.
* config/visium/visium.c (visium_adjust_cost): Adjust.
(visium_split_double_add): Use the *_set_carry patterns.
(visium_select_cc_mode): Add support for CCC mode and adjust.
(output_cbranch): Adjust and use the carry-based operators for
floating-point comparisons.
* config/visium/visium.md (flags_subst_arith): Adjust.
(addsi3_insn_set_carry): New instruction.
(subsi3_insn_set_carry): Likewise.
(negsi2_insn_set_carry): Likewise.
(btst): Adjust.
(cmp<mode>_sne): Likewise.
(cbranch<mode>4): Use ordered_comparison_operator.
(cbranch<mode>4_insn): Likewise.
(cbranchsi4_btst_insn): Adjust.

From-SVN: r240969

gcc/ChangeLog
gcc/config/visium/predicates.md
gcc/config/visium/visium-modes.def
gcc/config/visium/visium.c
gcc/config/visium/visium.md

index 06d2c23583ee5ed5b7bbd568843390bfb2c84f4a..e2cc1bb7a392572a1a26797cf2f1e466f51d9a05 100644 (file)
@@ -1,3 +1,31 @@
+2016-10-11  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * config/visium/visium-modes.def (CC_NOOV): Rename into...
+       (CCNZ): ...this.
+       (CC_BTST): Rename into...
+       (CCC): ...this.
+       * config/visium/predicates.md (real_add_operand): New.
+       (visium_btst_operator): Rename into...
+       (visium_equality_comparison_operator): ...this.
+       (visium_noov_operator): Rename into...
+       (visium_nz_comparison_operator): ...this.
+       (visium_c_comparison_operator): New.
+       (visium_branch_operator): Adjust and deal with all CC modes.
+       * config/visium/visium.c (visium_adjust_cost): Adjust.
+       (visium_split_double_add): Use the *_set_carry patterns.
+       (visium_select_cc_mode): Add support for CCC mode and adjust.
+       (output_cbranch): Adjust and use the carry-based operators for
+       floating-point comparisons.
+       * config/visium/visium.md (flags_subst_arith): Adjust.
+       (addsi3_insn_set_carry): New instruction.
+       (subsi3_insn_set_carry): Likewise.
+       (negsi2_insn_set_carry): Likewise.
+       (btst): Adjust.
+       (cmp<mode>_sne): Likewise.
+       (cbranch<mode>4): Use ordered_comparison_operator.
+       (cbranch<mode>4_insn): Likewise.
+       (cbranchsi4_btst_insn): Adjust.
+
 2016-10-11  Tom de Vries  <tom@codesourcery.com>
 
        PR middle-end/77558
index b08b06ef06a7bdd769dd3a27366d25ba1bb2796d..5e08768666a38c5c76c6f45d06e4c4b8d571e5d0 100644 (file)
        (and (match_code "const_int")
             (match_test ("INTVAL (op) >= -65535 && INTVAL (op) <= 65535")))))
 
+;; Return true if OP can be used as the second operand in a 32-bit or 64-bit
+;; add or subtract instruction directly, i.e. without the reverse trick.
+(define_predicate "real_add_operand"
+  (ior (match_operand 0 "gpc_reg_operand")
+       (and (match_code "const_int")
+            (match_test ("INTVAL (op) >= 0 && INTVAL (op) <= 65535")))))
+
 ;; Return true if OP is (or could be) outside the range 0 .. 65535, which is
 ;; the range of the immediate operands, but accept -1 for NOT.
 (define_predicate "large_immediate_operand"
        (and (match_code "const_int")
             (match_test ("INTVAL (op) < -1 || INTVAL (op) > 65535")))))
 
+;; Return true if OP is an equality comparison operator.
+(define_predicate "visium_equality_comparison_operator"
+  (match_code "eq,ne"))
+
+;; Return true if OP is a valid comparison operator for CCNZmode.
+(define_special_predicate "visium_nz_comparison_operator"
+  (match_code "eq,ne,lt,ge"))
+
+;; Return true if OP is a valid comparison operator for CCCmode.
+(define_special_predicate "visium_c_comparison_operator"
+  (match_code "eq,ne,ltu,geu"))
+
 ;; Return true if OP is a valid FP comparison operator.
 (define_predicate "visium_fp_comparison_operator"
   (match_code "eq,ne,ordered,unordered,unlt,unle,ungt,unge,lt,le,gt,ge"))
 
-;; Return true if OP is a valid comparison operator for CC_BTSTmode.
-(define_special_predicate "visium_btst_operator"
-  (match_code "eq,ne"))
-
-;; Return true if OP is a valid comparison operator for CC_NOOVmode.
-(define_special_predicate "visium_noov_operator"
-  (match_code "eq,ne,ge,lt"))
-
 ;; Return true if OP is a valid comparison operator for a branch.  This allows
 ;; the use of MATCH_OPERATOR to recognize all the branch insns.
 (define_predicate "visium_branch_operator"
   (match_operand 0 "comparison_operator")
 {
-  enum rtx_code code = GET_CODE (op);
-  /* These 2 comparison codes are not supported.  */
-  if (code == UNEQ || code == LTGT)
-    return false;
-  enum machine_mode cc_mode = GET_MODE (XEXP (op, 0));
-  if (cc_mode == CC_NOOVmode)
-    return visium_noov_operator (op, mode);
-  if (cc_mode == CC_BTSTmode)
-    return visium_btst_operator (op, mode);
-  return true;
+  switch (GET_MODE (XEXP (op, 0)))
+    {
+    case CCmode:
+      return ordered_comparison_operator (op, mode);
+    case CCNZmode:
+      return visium_nz_comparison_operator (op, mode);
+    case CCCmode:
+      return visium_c_comparison_operator (op, mode);
+    case CCFPmode:
+    case CCFPEmode:
+      return visium_fp_comparison_operator (op, mode);
+    default:
+      return false;
+    }
 })
 
 ;; Return true if OP is a valid comparison operator for an integer cstore.
index 5af2db9737eae019590904b8bde49899fa24c204..980745ebfe75fc76bfc2bb82e72186a408884b72 100644 (file)
@@ -19,19 +19,22 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Add any extra modes needed to represent the condition code.
 
-   On the Visium, we have a "no-overflow" mode which is used when arithmetic
-   instructions set the condition code.  Different branches are used in this
-   case for some operations.
+   We have a CCNZ mode which is used for implicit comparisons with zero when
+   arithmetic instructions set the condition code.  Only the N and Z flags
+   are valid in this mode, which means that only the =,!= and <,>= operators
+   can be used in conjunction with it.
 
-   We also have a "bit-test" mode which is used when the bit-test instruction
-   sets the condition code.
+   We also have a CCCmode which is used by the arithmetic instructions when
+   they explicitly set the C flag (unsigned overflow) and by the bit-test
+   instruction.  Only the =,!= and unsigned <,>= operators can be used in
+   conjunction with it.
 
    We also have two modes to indicate that the condition code is set by the
    the floating-point unit.  One for comparisons which generate an exception
    if the result is unordered (CCFPEmode) and one for comparisons which never
    generate such an exception (CCFPmode).  */
 
-CC_MODE (CC_NOOV);
-CC_MODE (CC_BTST);
+CC_MODE (CCNZ);
+CC_MODE (CCC);
 CC_MODE (CCFP);
 CC_MODE (CCFPE);
index af58f99aef1ea60710ef5e0527ac3417d1921dc5..4585af578949990c7f5dff163bdd7c0b671dfd00 100644 (file)
@@ -561,11 +561,12 @@ visium_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
 
              /* The logical instructions use CCmode and thus work with any
                 comparison operator, whereas the arithmetic instructions use
-                CC_NOOVmode and thus work with only a small subset.  */
+                CCNZmode and thus work with only a small subset.  */
              if (dep_attr_type == TYPE_LOGIC
                  || (dep_attr_type == TYPE_ARITH
-                     && visium_noov_operator (XEXP (src, 0),
-                                              GET_MODE (XEXP (src, 0)))))
+                     && visium_nz_comparison_operator (XEXP (src, 0),
+                                                       GET_MODE
+                                                       (XEXP (src, 0)))))
                return 0;
            }
        }
@@ -2113,16 +2114,12 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
       op8 = gen_highpart (SImode, op2);
     }
 
-  /* This is the {add,sub,neg}si3_insn_set_flags pattern.  */
   if (op4 == const0_rtx)
-    x = gen_rtx_NEG (SImode, op5);
+    pat = gen_negsi2_insn_set_carry (op3, op5);
+  else if (code == MINUS)
+    pat = gen_subsi3_insn_set_carry (op3, op4, op5);
   else
-    x = gen_rtx_fmt_ee (code, SImode, op4, op5);
-  pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
-  XVECEXP (pat, 0, 0) = gen_rtx_SET (op3, x);
-  flags = gen_rtx_REG (CC_NOOVmode, FLAGS_REGNUM);
-  x = gen_rtx_COMPARE (CC_NOOVmode, shallow_copy_rtx (x), const0_rtx);
-  XVECEXP (pat, 0, 1) = gen_rtx_SET (flags, x);
+    pat = gen_addsi3_insn_set_carry (op3, op4, op5);
   emit_insn (pat);
 
   /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern.  */
@@ -2130,6 +2127,7 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
     x = op7;
   else
     x = gen_rtx_fmt_ee (code, SImode, op7, op8);
+  flags = gen_rtx_REG (CCCmode, FLAGS_REGNUM);
   x = gen_rtx_fmt_ee (code, SImode, x, gen_rtx_LTU (SImode, flags, const0_rtx));
   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
   XVECEXP (pat, 0, 0) = gen_rtx_SET (op6, x);
@@ -2814,6 +2812,16 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
        }
     }
 
+  /* This is for the cmp<mode>_sne pattern.  */
+  if (op1 == constm1_rtx)
+    return CCCmode;
+
+  /* This is for the add<mode>3_insn_set_carry pattern.  */
+  if ((code == LTU || code == GEU)
+      && GET_CODE (op0) == PLUS
+      && rtx_equal_p (XEXP (op0, 0), op1))
+    return CCCmode;
+
   if (op1 != const0_rtx)
     return CCmode;
 
@@ -2825,17 +2833,17 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
     case ASHIFT:
     case LTU:
     case LT:
-      /* The V flag may be set differently from a COMPARE with zero.
-        The consequence is that a comparison operator testing V must
-        be turned into another operator not testing V and yielding
-        the same result for a comparison with zero.  That's possible
-        for GE/LT which become NC/NS respectively, but not for GT/LE
-        for which the altered operator doesn't exist on the Visium.  */
-      return CC_NOOVmode;
+      /* The C and V flags may be set differently from a COMPARE with zero.
+        The consequence is that a comparison operator testing C or V must
+        be turned into another operator not testing C or V and yielding
+        the same result for a comparison with zero.  That's possible for
+        GE/LT which become NC/NS respectively, but not for GT/LE for which
+        the altered operator doesn't exist on the Visium.  */
+      return CCNZmode;
 
     case ZERO_EXTRACT:
       /* This is a btst, the result is in C instead of Z.  */
-      return CC_BTSTmode;
+      return CCCmode;
 
     case CONST_INT:
       /* This is a degenerate case, typically an uninitialized variable.  */
@@ -3077,21 +3085,21 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
   switch (code)
     {
     case NE:
-      if (cc_mode == CC_BTSTmode)
+      if (cc_mode == CCCmode)
        cond = "cs";
       else
        cond = "ne";
       break;
 
     case EQ:
-      if (cc_mode == CC_BTSTmode)
+      if (cc_mode == CCCmode)
        cond = "cc";
       else
        cond = "eq";
       break;
 
     case GE:
-      if (cc_mode == CC_NOOVmode)
+      if (cc_mode == CCNZmode)
        cond = "nc";
       else
        cond = "ge";
@@ -3110,8 +3118,8 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
 
     case LT:
       if (cc_mode == CCFPmode || cc_mode == CCFPEmode)
-       cond = "ns";
-      else if (cc_mode == CC_NOOVmode)
+       cond = "cs"; /* or "ns" */
+      else if (cc_mode == CCNZmode)
        cond = "ns";
       else
        cond = "lt";
@@ -3142,7 +3150,7 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
       break;
 
     case UNGE:
-      cond = "nc";
+      cond = "cc"; /* or "nc" */
       break;
 
     case UNGT:
index 41e3e5c57198596366c6fd9d8d06f23981709c20..de1c710f44121486fe8f7f3c365c447e0e1dbb09 100644 (file)
    (clobber (reg:CC R_FLAGS))]
   ""
   [(set (match_dup 0) (match_dup 1))
-   (set (reg:CC_NOOV R_FLAGS)
-       (compare:CC_NOOV (match_dup 1) (const_int 0)))])
+   (set (reg:CCNZ R_FLAGS)
+       (compare:CCNZ (match_dup 1) (const_int 0)))])
 
 (define_subst_attr "subst_arith" "flags_subst_arith" "_flags" "_set_flags")
 
     addi    %0,%2"
   [(set_attr "type" "arith")])
 
+(define_insn "addsi3_insn_set_carry"
+  [(set (match_operand:SI 0 "register_operand"          "=r,r")
+       (plus:SI (match_operand:SI 1 "register_operand" "%r,0")
+                (match_operand:SI 2 "real_add_operand" " r,J")))
+   (set (reg:CCC R_FLAGS)
+       (compare:CCC (plus:SI (match_dup 1) (match_dup 2))
+                    (match_dup 1)))]
+  "reload_completed"
+  "@
+    add.l   %0,%1,%2
+    addi    %0,%2"
+  [(set_attr "type" "arith")])
+
 (define_expand "adddi3"
   [(set (match_operand:DI 0 "register_operand" "")
        (plus:DI (match_operand:DI 1 "register_operand" "")
     subi    %0,%2"
   [(set_attr "type" "arith")])
 
+(define_insn "subsi3_insn_set_carry"
+  [(set (match_operand:SI 0 "register_operand"           "=r,r")
+       (minus:SI (match_operand:SI 1 "register_operand" " r,0")
+                 (match_operand:SI 2 "real_add_operand" " r,J")))
+   (set (reg:CC R_FLAGS)
+       (compare:CC (match_dup 1) (match_dup 2)))]
+  "reload_completed"
+  "@
+    sub.l   %0,%r1,%2
+    subi    %0,%2"
+  [(set_attr "type" "arith")])
+
 (define_expand "subdi3"
   [(set (match_operand:DI 0 "register_operand" "")
        (minus:DI (match_operand:DI 1 "register_operand" "")
   "sub<s>   %0,r0,%1"
   [(set_attr "type" "arith")])
 
+(define_insn "negsi2_insn_set_carry"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (neg:SI (match_operand:SI 1 "register_operand" "r")))
+   (set (reg:CCC R_FLAGS)
+       (compare:CCC (not:SI (match_dup 1)) (const_int -1)))]
+  "reload_completed"
+  "sub.l   %0,r0,%1"
+  [(set_attr "type" "arith")])
+
 (define_expand "negdi2"
   [(set (match_operand:DI 0 "register_operand" "")
        (neg:DI (match_operand:DI 1 "register_operand" "")))]
 ; BITS_BIG_ENDIAN is defined to 1 so operand #1 counts from the MSB.
 
 (define_insn "*btst"
-  [(set (reg:CC_BTST R_FLAGS)
-       (compare:CC_BTST (zero_extract:SI
-                          (match_operand:SI 0 "register_operand" "r")
-                          (const_int 1)
-                          (match_operand:QI 1 "const_shift_operand" "K"))
-                        (const_int 0)))]
+  [(set (reg:CCC R_FLAGS)
+       (compare:CCC (zero_extract:SI
+                      (match_operand:SI 0 "register_operand" "r")
+                      (const_int 1)
+                      (match_operand:QI 1 "const_shift_operand" "K"))
+                    (const_int 0)))]
   "reload_completed"
   "lsr.l   r0,%0,32-%1"
   [(set_attr "type" "logic")])
   [(set_attr "type" "cmp")])
 
 (define_insn "*cmp<mode>_sne"
-  [(set (reg:CC R_FLAGS)
-       (compare:CC (not:I (match_operand:I 0 "register_operand" "r"))
-                   (const_int -1)))]
+  [(set (reg:CCC R_FLAGS)
+       (compare:CCC (not:I (match_operand:I 0 "register_operand" "r"))
+                    (const_int -1)))]
   "reload_completed"
   "cmp<s>   r0,%0"
   [(set_attr "type" "cmp")])
 
 (define_expand "cbranch<mode>4"
   [(set (pc)
-       (if_then_else (match_operator 0 "comparison_operator"
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
                       [(match_operand:I 1 "register_operand")
                        (match_operand:I 2 "reg_or_0_operand")])
                      (label_ref (match_operand 3 ""))
 
 (define_insn_and_split "*cbranch<mode>4_insn"
   [(set (pc)
-       (if_then_else (match_operator 0 "comparison_operator"
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
                       [(match_operand:I 1 "register_operand" "r")
                        (match_operand:I 2 "reg_or_0_operand" "rO")])
                      (label_ref (match_operand 3 ""))
 
 (define_insn_and_split "*cbranchsi4_btst_insn"
   [(set (pc)
-       (if_then_else (match_operator 0 "visium_btst_operator"
+       (if_then_else (match_operator 0 "visium_equality_comparison_operator"
                       [(zero_extract:SI
                           (match_operand:SI 1 "register_operand" "r")
                           (const_int 1)