Canonicalize sparc movcc patterns such that operand 0 always appears in operand 4.
authorDavid S. Miller <davem@davemloft.net>
Wed, 26 Oct 2011 21:14:56 +0000 (21:14 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Wed, 26 Oct 2011 21:14:56 +0000 (14:14 -0700)
* config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
* config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
(*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
(*mov<I:mode>_cc_reg_sp64): Likewise.
(*movsf_cc_v9): Likewise.
(*movsf_cc_reg_sp64): Likewise.
(*movdf_cc_v9): Likewise.
(*movdf_cc_reg_sp64): Likewise.
(*movtf_cc_hq_v9): Likewise.
(*movtf_cc_reg_hq_sp64): Likewise.
(*movtf_cc_v9): Likewise.
(*movtf_cc_reg_sp64): Likewise.
* config/sparc/sparc.c (sparc_expand_conditional_move): New function.
(sparc_print_operand): Delete 'c' and 'd' handling, no longer used.

From-SVN: r180542

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md

index cd1a2365d561e8a5d4c990ac242c6aeb1af28358..d6d1382028b01be40d1be9a50e1eb27a6b655904 100644 (file)
@@ -1,3 +1,20 @@
+2011-10-26  David S. Miller  <davem@davemloft.net>
+
+       * config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
+       * config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
+       (*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
+       (*mov<I:mode>_cc_reg_sp64): Likewise.
+       (*movsf_cc_v9): Likewise.
+       (*movsf_cc_reg_sp64): Likewise.
+       (*movdf_cc_v9): Likewise.
+       (*movdf_cc_reg_sp64): Likewise.
+       (*movtf_cc_hq_v9): Likewise.
+       (*movtf_cc_reg_hq_sp64): Likewise.
+       (*movtf_cc_v9): Likewise.
+       (*movtf_cc_reg_sp64): Likewise.
+       * config/sparc/sparc.c (sparc_expand_conditional_move): New function.
+       (sparc_print_operand): Delete 'c' and 'd' handling, no longer used.
+
 2011-10-26  Eric Botcazou  <ebotcazou@adacore.com>
 
        * reload.c (reload_inner_reg_of_subreg): Change type of return value
index bb6fb07c4a366860a0e650bba65cd156bd35d39d..108e105cbeacbc3019e426f788e38d4e75f86530 100644 (file)
@@ -107,6 +107,7 @@ extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
 extern const char *output_v8plus_mult (rtx, rtx *, const char *);
 extern void sparc_expand_vector_init (rtx, rtx);
 extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
+extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
 #endif /* RTX_CODE */
 
 #endif /* __SPARC_PROTOS_H__ */
index f806c6c822105ec234cae3dc0fbca0055554069e..964bcaf15d6b75f4516e29cbaa33c9daf8e99c32 100644 (file)
@@ -8162,20 +8162,11 @@ sparc_print_operand (FILE *file, rtx x, int code)
        }
       return;
 
-      /* These are used by the conditional move instructions.  */
-    case 'c' :
+      /* This is used by the conditional move instructions.  */
     case 'C':
       {
        enum rtx_code rc = GET_CODE (x);
        
-       if (code == 'c')
-         {
-           enum machine_mode mode = GET_MODE (XEXP (x, 0));
-           if (mode == CCFPmode || mode == CCFPEmode)
-             rc = reverse_condition_maybe_unordered (GET_CODE (x));
-           else
-             rc = reverse_condition (GET_CODE (x));
-         }
        switch (rc)
          {
          case NE: fputs ("ne", file); break;
@@ -8196,20 +8187,15 @@ sparc_print_operand (FILE *file, rtx x, int code)
          case UNGT: fputs ("ug", file); break;
          case UNGE: fputs ("uge", file); break;
          case UNEQ: fputs ("ue", file); break;
-         default: output_operand_lossage (code == 'c'
-                                          ? "invalid %%c operand"
-                                          : "invalid %%C operand");
+         default: output_operand_lossage ("invalid %%C operand");
          }
        return;
       }
 
-      /* These are used by the movr instruction pattern.  */
-    case 'd':
+      /* This are used by the movr instruction pattern.  */
     case 'D':
       {
-       enum rtx_code rc = (code == 'd'
-                           ? reverse_condition (GET_CODE (x))
-                           : GET_CODE (x));
+       enum rtx_code rc = GET_CODE (x);
        switch (rc)
          {
          case NE: fputs ("ne", file); break;
@@ -8218,9 +8204,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
          case LT: fputs ("lz", file); break;
          case LE: fputs ("lez", file); break;
          case GT: fputs ("gz", file); break;
-         default: output_operand_lossage (code == 'd'
-                                          ? "invalid %%d operand"
-                                          : "invalid %%D operand");
+         default: output_operand_lossage ("invalid %%D operand");
          }
        return;
       }
@@ -11377,4 +11361,58 @@ sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   return NO_REGS;
 }
 
+bool
+sparc_expand_conditional_move (enum machine_mode mode, rtx *operands)
+{
+  enum rtx_code rc = GET_CODE (operands[1]);
+  enum machine_mode cmp_mode;
+  rtx cc_reg, dst, cmp;
+
+  cmp = operands[1];
+  cmp_mode = GET_MODE (XEXP (cmp, 0));
+  if (cmp_mode == DImode && !TARGET_ARCH64)
+    return false;
+
+  dst = operands[0];
+
+  if (! rtx_equal_p (operands[2], dst)
+      && ! rtx_equal_p (operands[3], dst))
+    {
+      if (reg_overlap_mentioned_p (dst, cmp))
+       dst = gen_reg_rtx (mode);
+
+      emit_move_insn (dst, operands[3]);
+    }
+  else if (operands[2] == dst)
+    {
+      operands[2] = operands[3];
+
+      if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
+        rc = reverse_condition_maybe_unordered (rc);
+      else
+        rc = reverse_condition (rc);
+    }
+
+  if (cmp_mode == TFmode && !TARGET_HARD_QUAD)
+    cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);
+
+  if (XEXP (cmp, 1) == const0_rtx
+      && GET_CODE (XEXP (cmp, 0)) == REG
+      && cmp_mode == DImode
+      && v9_regcmp_p (rc))
+    cc_reg = XEXP (cmp, 0);
+  else
+    cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
+
+  cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);
+
+  emit_insn (gen_rtx_SET (VOIDmode, dst,
+                         gen_rtx_IF_THEN_ELSE (mode, cmp, operands[2], dst)));
+
+  if (dst != operands[0])
+    emit_move_insn (operands[0], dst);
+
+  return true;
+}
+
 #include "gt-sparc.h"
index d1ebb24c25f5ee18620c7598cf421e8017762864..2bae28e6e1979fb8169da5b55cbb22ce108cd54b 100644 (file)
 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
 ;; 3 contains the constant if one is present, but we handle either for
 ;; generality (sparc.c puts a constant in operand 2).
+;;
+;; Our instruction patterns, on the other hand, canonicalize such that
+;; operand 3 must be the set destination.
 
 (define_expand "mov<I:mode>cc"
   [(set (match_operand:I 0 "register_operand" "")
                        (match_operand:I 3 "arith10_operand" "")))]
   "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
 {
-  rtx cc_reg;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+  if (! sparc_expand_conditional_move (<I:MODE>mode, operands))
     FAIL;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
-    operands[1]
-      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
-                                 GET_CODE (operands[1]));
-
-  if (XEXP (operands[1], 1) == const0_rtx
-      && GET_CODE (XEXP (operands[1], 0)) == REG
-      && GET_MODE (XEXP (operands[1], 0)) == DImode
-      && v9_regcmp_p (GET_CODE (operands[1])))
-    cc_reg = XEXP (operands[1], 0);
-  else
-    cc_reg = gen_compare_reg (operands[1]);
-
-  operands[1]
-    = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
-                     const0_rtx);
+  DONE;
 })
 
 (define_expand "mov<F:mode>cc"
                        (match_operand:F 3 "register_operand" "")))]
   "TARGET_V9 && TARGET_FPU"
 {
-  rtx cc_reg;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+  if (! sparc_expand_conditional_move (<F:MODE>mode, operands))
     FAIL;
-
-  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
-    operands[1]
-      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
-                                 GET_CODE (operands[1]));
-
-  if (XEXP (operands[1], 1) == const0_rtx
-      && GET_CODE (XEXP (operands[1], 0)) == REG
-      && GET_MODE (XEXP (operands[1], 0)) == DImode
-      && v9_regcmp_p (GET_CODE (operands[1])))
-    cc_reg = XEXP (operands[1], 0);
-  else
-    cc_reg = gen_compare_reg (operands[1]);
-
-  operands[1]
-    = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
-                     const0_rtx);
+  DONE;
 })
 
 ;; Conditional move define_insns
 
 (define_insn "*mov<I:mode>_cc_v9"
-  [(set (match_operand:I 0 "register_operand" "=r,r")
+  [(set (match_operand:I 0 "register_operand" "=r")
        (if_then_else:I (match_operator 1 "comparison_operator"
-                              [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+                              [(match_operand 2 "icc_or_fcc_register_operand" "X")
                                (const_int 0)])
-                       (match_operand:I 3 "arith11_operand" "rL,0")
-                       (match_operand:I 4 "arith11_operand" "0,rL")))]
+                       (match_operand:I 3 "arith11_operand" "rL")
+                       (match_operand:I 4 "register_operand" "0")))]
   "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
-  "@
-   mov%C1\t%x2, %3, %0
-   mov%c1\t%x2, %4, %0"
+  "mov%C1\t%x2, %3, %0"
   [(set_attr "type" "cmove")])
 
 (define_insn "*mov<I:mode>_cc_reg_sp64"
-  [(set (match_operand:I 0 "register_operand" "=r,r")
+  [(set (match_operand:I 0 "register_operand" "=r")
        (if_then_else:I (match_operator 1 "v9_register_compare_operator"
-                               [(match_operand:DI 2 "register_operand" "r,r")
+                               [(match_operand:DI 2 "register_operand" "r")
                                 (const_int 0)])
-                       (match_operand:I 3 "arith10_operand" "rM,0")
-                       (match_operand:I 4 "arith10_operand" "0,rM")))]
+                       (match_operand:I 3 "arith10_operand" "rM")
+                       (match_operand:I 4 "register_operand" "0")))]
   "TARGET_ARCH64"
-  "@
-   movr%D1\t%2, %r3, %0
-   movr%d1\t%2, %r4, %0"
+  "movr%D1\t%2, %r3, %0"
   [(set_attr "type" "cmove")])
 
 (define_insn "*movsf_cc_v9"
-  [(set (match_operand:SF 0 "register_operand" "=f,f")
+  [(set (match_operand:SF 0 "register_operand" "=f")
        (if_then_else:SF (match_operator 1 "comparison_operator"
-                               [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+                               [(match_operand 2 "icc_or_fcc_register_operand" "X")
                                 (const_int 0)])
-                        (match_operand:SF 3 "register_operand" "f,0")
-                        (match_operand:SF 4 "register_operand" "0,f")))]
+                        (match_operand:SF 3 "register_operand" "f")
+                        (match_operand:SF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU"
-  "@
-   fmovs%C1\t%x2, %3, %0
-   fmovs%c1\t%x2, %4, %0"
+  "fmovs%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")])
 
 (define_insn "*movsf_cc_reg_sp64"
-  [(set (match_operand:SF 0 "register_operand" "=f,f")
+  [(set (match_operand:SF 0 "register_operand" "=f")
        (if_then_else:SF (match_operator 1 "v9_register_compare_operator"
-                               [(match_operand:DI 2 "register_operand" "r,r")
+                               [(match_operand:DI 2 "register_operand" "r")
                                 (const_int 0)])
-                        (match_operand:SF 3 "register_operand" "f,0")
-                        (match_operand:SF 4 "register_operand" "0,f")))]
+                        (match_operand:SF 3 "register_operand" "f")
+                        (match_operand:SF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU"
-  "@
-   fmovrs%D1\t%2, %3, %0
-   fmovrs%d1\t%2, %4, %0"
+  "fmovrs%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")])
 
 ;; Named because invoked by movtf_cc_v9
 (define_insn "movdf_cc_v9"
-  [(set (match_operand:DF 0 "register_operand" "=e,e")
+  [(set (match_operand:DF 0 "register_operand" "=e")
        (if_then_else:DF (match_operator 1 "comparison_operator"
-                               [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+                               [(match_operand 2 "icc_or_fcc_register_operand" "X")
                                 (const_int 0)])
-                        (match_operand:DF 3 "register_operand" "e,0")
-                        (match_operand:DF 4 "register_operand" "0,e")))]
+                        (match_operand:DF 3 "register_operand" "e")
+                        (match_operand:DF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU"
-  "@
-   fmovd%C1\t%x2, %3, %0
-   fmovd%c1\t%x2, %4, %0"
+  "fmovd%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")
    (set_attr "fptype" "double")])
 
 ;; Named because invoked by movtf_cc_reg_sp64
 (define_insn "movdf_cc_reg_sp64"
-  [(set (match_operand:DF 0 "register_operand" "=e,e")
+  [(set (match_operand:DF 0 "register_operand" "=e")
        (if_then_else:DF (match_operator 1 "v9_register_compare_operator"
-                               [(match_operand:DI 2 "register_operand" "r,r")
+                               [(match_operand:DI 2 "register_operand" "r")
                                 (const_int 0)])
-                        (match_operand:DF 3 "register_operand" "e,0")
-                        (match_operand:DF 4 "register_operand" "0,e")))]
+                        (match_operand:DF 3 "register_operand" "e")
+                        (match_operand:DF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU"
-  "@
-   fmovrd%D1\t%2, %3, %0
-   fmovrd%d1\t%2, %4, %0"
+  "fmovrd%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")
    (set_attr "fptype" "double")])
 
 (define_insn "*movtf_cc_hq_v9"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
        (if_then_else:TF (match_operator 1 "comparison_operator"
-                               [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+                               [(match_operand 2 "icc_or_fcc_register_operand" "X")
                                 (const_int 0)])
-                        (match_operand:TF 3 "register_operand" "e,0")
-                        (match_operand:TF 4 "register_operand" "0,e")))]
+                        (match_operand:TF 3 "register_operand" "e")
+                        (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-  "@
-   fmovq%C1\t%x2, %3, %0
-   fmovq%c1\t%x2, %4, %0"
+  "fmovq%C1\t%x2, %3, %0"
   [(set_attr "type" "fpcmove")])
 
 (define_insn "*movtf_cc_reg_hq_sp64"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
        (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
-                               [(match_operand:DI 2 "register_operand" "r,r")
+                               [(match_operand:DI 2 "register_operand" "r")
                                 (const_int 0)])
-                        (match_operand:TF 3 "register_operand" "e,0")
-                        (match_operand:TF 4 "register_operand" "0,e")))]
+                        (match_operand:TF 3 "register_operand" "e")
+                        (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
-  "@
-   fmovrq%D1\t%2, %3, %0
-   fmovrq%d1\t%2, %4, %0"
+  "fmovrq%D1\t%2, %3, %0"
   [(set_attr "type" "fpcrmove")])
 
 (define_insn_and_split "*movtf_cc_v9"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
        (if_then_else:TF (match_operator 1 "comparison_operator"
-                           [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+                           [(match_operand 2 "icc_or_fcc_register_operand" "X")
                             (const_int 0)])
-                        (match_operand:TF 3 "register_operand" "e,0")
-                        (match_operand:TF 4 "register_operand" "0,e")))]
+                        (match_operand:TF 3 "register_operand" "e")
+                        (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
   "#"
   "&& reload_completed"
 {
   rtx set_dest = operands[0];
   rtx set_srca = operands[3];
-  rtx set_srcb = operands[4];
-  int third = rtx_equal_p (set_dest, set_srca);
   rtx dest1, dest2;
-  rtx srca1, srca2, srcb1, srcb2;
+  rtx srca1, srca2;
 
   dest1 = gen_df_reg (set_dest, 0);
   dest2 = gen_df_reg (set_dest, 1);
   srca1 = gen_df_reg (set_srca, 0);
   srca2 = gen_df_reg (set_srca, 1);
-  srcb1 = gen_df_reg (set_srcb, 0);
-  srcb2 = gen_df_reg (set_srcb, 1);
 
-  /* Now emit using the real source and destination we found, swapping
-     the order if we detect overlap.  */
-  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
-      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+  if (reg_overlap_mentioned_p (dest1, srca2))
     {
-      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
-      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
+      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
+      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
     }
   else
     {
-      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
-      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
+      emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
+      emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
     }
   DONE;
 }
   [(set_attr "length" "2")])
 
 (define_insn_and_split "*movtf_cc_reg_sp64"
-  [(set (match_operand:TF 0 "register_operand" "=e,e")
+  [(set (match_operand:TF 0 "register_operand" "=e")
        (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
-                               [(match_operand:DI 2 "register_operand" "r,r")
+                               [(match_operand:DI 2 "register_operand" "r")
                                 (const_int 0)])
-                        (match_operand:TF 3 "register_operand" "e,0")
-                        (match_operand:TF 4 "register_operand" "0,e")))]
+                        (match_operand:TF 3 "register_operand" "e")
+                        (match_operand:TF 4 "register_operand" "0")))]
   "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
   "#"
   "&& reload_completed"
 {
   rtx set_dest = operands[0];
   rtx set_srca = operands[3];
-  rtx set_srcb = operands[4];
-  int third = rtx_equal_p (set_dest, set_srca);
   rtx dest1, dest2;
-  rtx srca1, srca2, srcb1, srcb2;
+  rtx srca1, srca2;
 
   dest1 = gen_df_reg (set_dest, 0);
   dest2 = gen_df_reg (set_dest, 1);
   srca1 = gen_df_reg (set_srca, 0);
   srca2 = gen_df_reg (set_srca, 1);
-  srcb1 = gen_df_reg (set_srcb, 0);
-  srcb2 = gen_df_reg (set_srcb, 1);
 
-  /* Now emit using the real source and destination we found, swapping
-     the order if we detect overlap.  */
-  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
-      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+  if (reg_overlap_mentioned_p (dest1, srca2))
     {
-      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
-      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
     }
   else
     {
-      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
-      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
+      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
     }
   DONE;
 }