sparc.c (fp_sethi_p, [...]): New functions.
authorDavid S. Miller <davem@redhat.com>
Fri, 10 Dec 1999 12:08:51 +0000 (04:08 -0800)
committerDavid S. Miller <davem@gcc.gnu.org>
Fri, 10 Dec 1999 12:08:51 +0000 (04:08 -0800)
* config/sparc/sparc.c (fp_sethi_p, fp_mov_p, fp_high_losum_p):
New functions.
* config/sparc/sparc-protos.h: Add them.
* config/sparc/sparc.h: Add them to PREDICATE_CODES.
(EXTRA_CONSTRAINT_BASE): New macro, handling Q, R, and S
constraints which use those helpers.
(EXTRA_CONSTRAINT): Use this new macro.
* md.texi: Update sparc target constraints documentation.
* config/sparc/sparc.md (clear_sf, clear_sfp, movsf_const_intreg,
movsf_const_high, movsf_const_lo, movsf_insn): Delete.
(movsf_insn_novis_liveg0, movsf_insn_novis_noliveg0,
movsf_insn_vis, movsf_lo_sum, movsf_high): New patterns.
(movsf high/lo_sum split): Rework for new patterns.
(movsf expander): Allow storing fp_zero to memory if ! live_g0.

From-SVN: r30857

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

index d595ca9..42204f4 100644 (file)
@@ -1,3 +1,20 @@
+1999-12-10  David S. Miller  <davem@redhat.com>
+
+       * config/sparc/sparc.c (fp_sethi_p, fp_mov_p, fp_high_losum_p):
+       New functions.
+       * config/sparc/sparc-protos.h: Add them.
+       * config/sparc/sparc.h: Add them to PREDICATE_CODES.
+       (EXTRA_CONSTRAINT_BASE): New macro, handling Q, R, and S
+       constraints which use those helpers.
+       (EXTRA_CONSTRAINT): Use this new macro.
+       * md.texi: Update sparc target constraints documentation.
+       * config/sparc/sparc.md (clear_sf, clear_sfp, movsf_const_intreg,
+       movsf_const_high, movsf_const_lo, movsf_insn): Delete.
+       (movsf_insn_novis_liveg0, movsf_insn_novis_noliveg0,
+       movsf_insn_vis, movsf_lo_sum, movsf_high): New patterns.
+       (movsf high/lo_sum split): Rework for new patterns.
+       (movsf expander): Allow storing fp_zero to memory if ! live_g0.
+
 1999-12-09  Gavin Romig-Koch  <gavin@cetus.cygnus.com>
 
        * c-common.c (c_common_nodes_and_builtins): 
index c761669..8c5b1b1 100644 (file)
@@ -124,6 +124,9 @@ extern int emit_move_sequence PARAMS ((rtx, enum machine_mode));
 extern int extend_op PARAMS ((rtx, enum machine_mode));
 extern int fcc_reg_operand PARAMS ((rtx, enum machine_mode));
 extern int fp_zero_operand PARAMS ((rtx));
+extern int fp_sethi_p PARAMS ((rtx));
+extern int fp_mov_p PARAMS ((rtx));
+extern int fp_high_losum_p PARAMS ((rtx));
 extern int icc_or_fcc_reg_operand PARAMS ((rtx, enum machine_mode));
 extern int label_ref_operand PARAMS ((rtx, enum machine_mode));
 extern int mem_min_alignment PARAMS ((rtx, int));
index 072e7e6..9c5380d 100644 (file)
@@ -406,6 +406,85 @@ fp_zero_operand (op)
   return (REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r));
 }
 
+/* Nonzero if OP is a floating point constant which can
+   be loaded into an integer register using a single
+   sethi instruction.  */
+
+int
+fp_sethi_p (op)
+     rtx op;
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    {
+      REAL_VALUE_TYPE r;
+      long i;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      if (REAL_VALUES_EQUAL (r, dconst0) &&
+         ! REAL_VALUE_MINUS_ZERO (r))
+       return 0;
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
+      if (SPARC_SETHI_P (i))
+       return 1;
+    }
+
+  return 0;
+}
+
+/* Nonzero if OP is a floating point constant which can
+   be loaded into an integer register using a single
+   mov instruction.  */
+
+int
+fp_mov_p (op)
+     rtx op;
+{
+  if (GET_CODE (op) == CONST_DOUBLE)
+    {
+      REAL_VALUE_TYPE r;
+      long i;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      if (REAL_VALUES_EQUAL (r, dconst0) &&
+         ! REAL_VALUE_MINUS_ZERO (r))
+       return 0;
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
+      if (SPARC_SIMM13_P (i))
+       return 1;
+    }
+
+  return 0;
+}
+
+/* Nonzero if OP is a floating point constant which can
+   be loaded into an integer register using a high/losum
+   instruction sequence.  */
+
+int
+fp_high_losum_p (op)
+     rtx op;
+{
+  /* The constraints calling this should only be in
+     SFmode move insns, so any constant which cannot
+     be moved using a single insn will do.  */
+  if (GET_CODE (op) == CONST_DOUBLE)
+    {
+      REAL_VALUE_TYPE r;
+      long i;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+      if (REAL_VALUES_EQUAL (r, dconst0) &&
+         ! REAL_VALUE_MINUS_ZERO (r))
+       return 0;
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
+      if (! SPARC_SETHI_P (i)
+          && ! SPARC_SIMM13_P (i))
+       return 1;
+    }
+
+  return 0;
+}
+
 /* Nonzero if OP is an integer register.  */
 
 int
@@ -1112,6 +1191,10 @@ input_operand (op, mode)
   if (register_operand (op, mode))
     return 1;
 
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT
+      && GET_CODE (op) == CONST_DOUBLE)
+    return 1;
+
   /* If this is a SUBREG, look inside so that we handle
      paradoxical ones.  */
   if (GET_CODE (op) == SUBREG)
index 4387fc8..c949c3e 100644 (file)
@@ -2283,12 +2283,27 @@ LFLGRET"ID":\n\
 
 /* Optional extra constraints for this machine.
 
+   'Q' handles floating point constants which can be moved into
+       an integer register with a single sethi instruction.
+
+   'R' handles floating point constants which can be moved into
+       an integer register with a single mov instruction.
+
+   'S' handles floating point constants which can be moved into
+       an integer register using a high/lo_sum sequence.
+
    'T' handles memory addresses where the alignment is known to
        be at least 8 bytes.
 
    `U' handles all pseudo registers or a hard even numbered
        integer register, needed for ldd/std instructions.  */
 
+#define EXTRA_CONSTRAINT_BASE(OP, C)   \
+   ((C) == 'Q' ? fp_sethi_p(OP)        \
+    : (C) == 'R' ? fp_mov_p(OP)        \
+    : (C) == 'S' ? fp_high_losum_p(OP) \
+    : 0)
+
 #ifndef REG_OK_STRICT
 
 /* Nonzero if X is a hard reg that can be used as an index
@@ -2303,12 +2318,13 @@ LFLGRET"ID":\n\
 /* 'T', 'U' are for aligned memory loads which aren't needed for v9.  */
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-   ((! TARGET_ARCH64 && (C) == 'T')                    \
-    ? (mem_min_alignment (OP, 8))                      \
-    : ((! TARGET_ARCH64 && (C) == 'U')                 \
-       ? (register_ok_for_ldd (OP))                    \
-       : 0))
+   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
+    || ((! TARGET_ARCH64 && (C) == 'T')                        \
+        ? (mem_min_alignment (OP, 8))                  \
+        : ((! TARGET_ARCH64 && (C) == 'U')             \
+            ? (register_ok_for_ldd (OP))               \
+            : 0)))
+
 #else
 
 /* Nonzero if X is a hard reg that can be used as an index.  */
@@ -2317,14 +2333,16 @@ LFLGRET"ID":\n\
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
 #define EXTRA_CONSTRAINT(OP, C)                                \
-   ((! TARGET_ARCH64 && (C) == 'T')                    \
-    ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
-    : ((! TARGET_ARCH64 && (C) == 'U')                 \
-       ? (GET_CODE (OP) == REG                         \
-          && (REGNO (OP) < FIRST_PSEUDO_REGISTER       \
-             || reg_renumber[REGNO (OP)] >= 0)         \
-          && register_ok_for_ldd (OP))                 \
-       : 0))
+   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
+    || ((! TARGET_ARCH64 && (C) == 'T')                        \
+        ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
+        : ((! TARGET_ARCH64 && (C) == 'U')             \
+           ? (GET_CODE (OP) == REG                     \
+              && (REGNO (OP) < FIRST_PSEUDO_REGISTER   \
+                 || reg_renumber[REGNO (OP)] >= 0)     \
+              && register_ok_for_ldd (OP))             \
+           : 0)))
+
 #endif
 \f
 /* Should gcc use [%reg+%lo(xx)+offset] addresses?  */
@@ -3309,6 +3327,9 @@ do {                                                                      \
 #define PREDICATE_CODES                                                        \
 {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},          \
 {"fp_zero_operand", {CONST_DOUBLE}},                                   \
+{"fp_sethi_p", {CONST_DOUBLE}},                                                \
+{"fp_mov_p", {CONST_DOUBLE}},                                          \
+{"fp_high_losum_p", {CONST_DOUBLE}},                                   \
 {"intreg_operand", {SUBREG, REG}},                                     \
 {"fcc_reg_operand", {REG}},                                            \
 {"icc_or_fcc_reg_operand", {REG}},                                     \
index 25951f0..b7025a8 100644 (file)
 ;;                     9       sethh
 ;;                     10      setlm
 ;;                     11      embmedany_sethi, embmedany_brsum
-;;                      12     movsf_const_high
 ;;                     13      embmedany_textuhi
 ;;                     14      embmedany_texthi
 ;;                     15      embmedany_textulo
 ;;                     16      embmedany_textlo
-;;                      17     movsf_const_lo
 ;;                     18      sethm
 ;;                     19      setlo
 ;;
 \f
 ;; Floating point move insns
 
-(define_insn "*clear_sf"
-  [(set (match_operand:SF 0 "register_operand" "=f")
-        (match_operand:SF 1 "const_double_operand" ""))]
-  "TARGET_VIS
-   && fp_zero_operand (operands[1])"
-  "fzeros\\t%0"
-  [(set_attr "type" "fpmove")
-   (set_attr "length" "1")])
+(define_insn "*movsf_insn_novis_liveg0"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
+       (match_operand:SF 1 "input_operand"         "f,G,Q,*rR,S,m,m,f,*r"))]
+  "(TARGET_FPU && ! TARGET_VIS && TARGET_LIVE_G0)
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode))"
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && (which_alternative == 2
+          || which_alternative == 3
+          || which_alternative == 4))
+    {
+      REAL_VALUE_TYPE r;
+      long i;
 
-(define_insn "*clear_sfp"
-  [(set (match_operand:SF 0 "memory_operand" "=m")
-        (match_operand:SF 1 "const_double_operand" ""))]
-  "! TARGET_LIVE_G0
-   && fp_zero_operand (operands[1])"
-  "st\\t%%g0, %0"
-  [(set_attr "type" "store")
+      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
+      operands[1] = GEN_INT (i);
+    }
+
+  switch (which_alternative)
+    {
+    case 0:
+      return \"fmovs\\t%1, %0\";
+    case 1:
+      return \"and\\t%0, 0, %0\";
+    case 2:
+      return \"sethi\\t%%hi(%a1), %0\";
+    case 3:
+      return \"mov\\t%1, %0\";
+    case 4:
+      return \"#\";
+    case 5:
+    case 6:
+      return \"ld\\t%1, %0\";
+    case 7:
+    case 8:
+      return \"st\\t%1, %0\";
+    }
+}"
+  [(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
    (set_attr "length" "1")])
 
-(define_insn "*movsf_const_intreg"
-  [(set (match_operand:SF 0 "register_operand" "=f,r")
-        (match_operand:SF 1 "const_double_operand" "m#F,F"))]
-  "TARGET_FPU"
+(define_insn "*movsf_insn_novis_noliveg0"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
+       (match_operand:SF 1 "input_operand"         "f,G,Q,*rR,S,m,m,f,*rG"))]
+  "(TARGET_FPU && ! TARGET_VIS && ! TARGET_LIVE_G0)
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode)
+       || fp_zero_operand (operands[1]))"
   "*
 {
-  REAL_VALUE_TYPE r;
-  long i;
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && (which_alternative == 2
+          || which_alternative == 3
+          || which_alternative == 4))
+    {
+      REAL_VALUE_TYPE r;
+      long i;
 
-  if (which_alternative == 0)
-    return \"ld\\t%1, %0\";
+      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
+      operands[1] = GEN_INT (i);
+    }
 
-  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-  REAL_VALUE_TO_TARGET_SINGLE (r, i);
-  if (SPARC_SIMM13_P (i) || SPARC_SETHI_P (i))
+  switch (which_alternative)
     {
+    case 0:
+      return \"fmovs\\t%1, %0\";
+    case 1:
+      return \"clr\\t%0\";
+    case 2:
+      return \"sethi\\t%%hi(%a1), %0\";
+    case 3:
+      return \"mov\\t%1, %0\";
+    case 4:
+      return \"#\";
+    case 5:
+    case 6:
+      return \"ld\\t%1, %0\";
+    case 7:
+    case 8:
+      return \"st\\t%r1, %0\";
+    }
+}"
+  [(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
+   (set_attr "length" "1")])
+
+(define_insn "*movsf_insn_vis"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
+       (match_operand:SF 1 "input_operand"         "f,G,G,Q,*rR,S,m,m,f,*rG"))]
+  "(TARGET_FPU && TARGET_VIS)
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode)
+       || fp_zero_operand (operands[1]))"
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_DOUBLE
+      && (which_alternative == 3
+          || which_alternative == 4
+          || which_alternative == 5))
+    {
+      REAL_VALUE_TYPE r;
+      long i;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+      REAL_VALUE_TO_TARGET_SINGLE (r, i);
       operands[1] = GEN_INT (i);
-      if (SPARC_SIMM13_P (INTVAL (operands[1])))
-        return \"mov\\t%1, %0\";
-      else if (SPARC_SETHI_P (INTVAL (operands[1])))
-        return \"sethi\\t%%hi(%a1), %0\";
-      else
-        abort ();
     }
-  else
-    return \"#\";
+
+  switch (which_alternative)
+    {
+    case 0:
+      return \"fmovs\\t%1, %0\";
+    case 1:
+      return \"fzeros\\t%0\";
+    case 2:
+      return \"clr\\t%0\";
+    case 3:
+      return \"sethi\\t%%hi(%a1), %0\";
+    case 4:
+      return \"mov\\t%1, %0\";
+    case 5:
+      return \"#\";
+    case 6:
+    case 7:
+      return \"ld\\t%1, %0\";
+    case 8:
+    case 9:
+      return \"st\\t%r1, %0\";
+    }
 }"
-  [(set_attr "type" "move")
-   (set_attr "length" "1,2")])
+  [(set_attr "type" "fpmove,fpmove,move,move,move,*,load,fpload,fpstore,store")
+   (set_attr "length" "1")])
 
-;; There isn't much I can do about this, if I change the
-;; mode then flow info gets really confused because the
-;; destination no longer looks the same.  Ho hum...
-(define_insn "*movsf_const_high"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-        (unspec:SF [(match_operand 1 "const_int_operand" "")] 12))]
-  ""
-  "sethi\\t%%hi(%a1), %0"
-  [(set_attr "type" "move")
+(define_insn "*movsf_lo_sum"
+  [(set (match_operand:SF 0 "register_operand" "")
+        (lo_sum:SF (match_operand:SF 1 "register_operand" "")
+                   (match_operand:SF 2 "const_double_operand" "")))]
+  "TARGET_FPU && fp_high_losum_p (operands[2])"
+  "*
+{
+  REAL_VALUE_TYPE r;
+  long i;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
+  REAL_VALUE_TO_TARGET_SINGLE (r, i);
+  operands[2] = GEN_INT (i);
+  return \"or\\t%1, %%lo(%a2), %0\";
+}"
+  [(set_attr "type" "ialu")
    (set_attr "length" "1")])
 
-(define_insn "*movsf_const_lo"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-        (unspec:SF [(match_operand:SF 1 "register_operand" "r")
-                    (match_operand 2 "const_int_operand" "")] 17))]
-  ""
-  "or\\t%1, %%lo(%a2), %0"
+(define_insn "*movsf_high"
+  [(set (match_operand:SF 0 "register_operand" "")
+        (high:SF (match_operand:SF 1 "const_double_operand" "")))]
+  "TARGET_FPU && fp_high_losum_p (operands[1])"
+  "*
+{
+  REAL_VALUE_TYPE r;
+  long i;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+  REAL_VALUE_TO_TARGET_SINGLE (r, i);
+  operands[1] = GEN_INT (i);
+  return \"sethi\\t%%hi(%1), %0\";
+}"
   [(set_attr "type" "move")
    (set_attr "length" "1")])
 
   [(set (match_operand:SF 0 "register_operand" "")
         (match_operand:SF 1 "const_double_operand" ""))]
   "TARGET_FPU
+   && fp_high_losum_p (operands[1])
    && (GET_CODE (operands[0]) == REG
        && REGNO (operands[0]) < 32)"
-  [(set (match_dup 0) (unspec:SF [(match_dup 1)] 12))
-   (set (match_dup 0) (unspec:SF [(match_dup 0) (match_dup 1)] 17))]
-  "
-{
-  REAL_VALUE_TYPE r;
-  long i;
+  [(set (match_dup 0) (high:SF (match_dup 1)))
+   (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
 
-  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
-  REAL_VALUE_TO_TARGET_SINGLE (r, i);
-  operands[1] = GEN_INT (i);
-}")
+;; Exactly the same as above, except that all `f' cases are deleted.
+;; This is necessary to prevent reload from ever trying to use a `f' reg
+;; when -mno-fpu.
+
+(define_insn "*movsf_no_f_insn"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
+       (match_operand:SF 1 "input_operand"    "r,m,r"))]
+  "! TARGET_FPU
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode))"
+  "@
+   mov\\t%1, %0
+   ld\\t%1, %0
+   st\\t%1, %0"
+  [(set_attr "type" "move,load,store")
+   (set_attr "length" "1")])
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
   /* Handle sets of MEM first.  */
   if (GET_CODE (operands[0]) == MEM)
     {
-      if (register_operand (operands[1], SFmode))
+      if (register_operand (operands[1], SFmode)
+         || (! TARGET_LIVE_G0
+             && GET_CODE (operands[1]) == CONST_DOUBLE
+              && fp_zero_operand (operands[1])))
        goto movsf_is_ok;
 
       if (! reload_in_progress)
   ;
 }")
 
-(define_insn "*movsf_insn"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,r,r,m")
-       (match_operand:SF 1 "input_operand"    "f,m,f,r,m,r"))]
-  "TARGET_FPU
-   && (register_operand (operands[0], SFmode)
-       || register_operand (operands[1], SFmode))"
-  "@
-   fmovs\\t%1, %0
-   ld\\t%1, %0
-   st\\t%1, %0
-   mov\\t%1, %0
-   ld\\t%1, %0
-   st\\t%1, %0"
-  [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")
-   (set_attr "length" "1")])
-
-;; Exactly the same as above, except that all `f' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `f' reg
-;; when -mno-fpu.
-
-(define_insn "*movsf_no_f_insn"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
-       (match_operand:SF 1 "input_operand"    "r,m,r"))]
-  "! TARGET_FPU
-   && (register_operand (operands[0], SFmode)
-       || register_operand (operands[1], SFmode))"
-  "@
-   mov\\t%1, %0
-   ld\\t%1, %0
-   st\\t%1, %0"
-  [(set_attr "type" "move,load,store")
-   (set_attr "length" "1")])
-
 (define_insn "*clear_df"
   [(set (match_operand:DF 0 "register_operand" "=e")
         (match_operand:DF 1 "const_double_operand" ""))]
index 4830167..067d464 100644 (file)
@@ -1621,11 +1621,19 @@ Floating-point zero
 Signed 13 bit constant, sign-extended to 32 or 64 bits
 
 @item Q
-Memory reference that can be loaded with one instruction  (@samp{m} is
-more appropriate for @code{asm} statements)
+Floating-point constant whose integral representation can
+be moved into an integer register using a single sethi
+instruction
+
+@item R
+Floating-point constant whose integral representation can
+be moved into an integer register using a single mov
+instruction
 
 @item S
-Constant, or memory address
+Floating-point constant whose integral representation can
+be moved into an integer register using a high/lo_sum
+instruction sequence
 
 @item T
 Memory address aligned to an 8-byte boundary