OSDN Git Service

*** empty log message ***
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 27 May 1992 22:10:02 +0000 (22:10 +0000)
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 27 May 1992 22:10:02 +0000 (22:10 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@1107 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md
gcc/unroll.c

index 7652793..9639dd6 100644 (file)
@@ -938,10 +938,33 @@ singlemove_string (operands)
       else
        abort ();
     }
-  if (GET_CODE (operands[1]) == MEM)
+  else if (GET_CODE (operands[1]) == MEM)
     return "ld %1,%0";
-  if (GET_CODE (operands[1]) == CONST_INT
-      && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
+  else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    {
+      int i;
+      union real_extract u;
+      union float_extract { float f; int i; } v;
+
+      /* Must be SFmode, otherwise this doesn't make sense.  */
+      if (GET_MODE (operands[1]) != SFmode)
+       abort ();
+
+      bcopy (&CONST_DOUBLE_LOW (operands[1]), &u, sizeof u);
+      v.f = REAL_VALUE_TRUNCATE (SFmode, u.d);
+      i = v.i;
+
+      operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
+
+      if (CONST_OK_FOR_LETTER_P (i, 'I'))
+       return "mov %1,%0";
+      else if ((i & 0x000003FF) != 0)
+       return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
+      else
+       return "sethi %%hi(%a1),%0";
+    }
+  else if (GET_CODE (operands[1]) == CONST_INT
+          && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
     {
       int i = INTVAL (operands[1]);
 
@@ -952,7 +975,7 @@ singlemove_string (operands)
       else
        return "sethi %%hi(%a1),%0";
     }
-  /* ??? Wrong if target is DImode?  */
+  /* Operand 1 must be a register, or a 'I' type CONST_INT.  */
   return "mov %1,%0";
 }
 \f
index 3e69891..4eaa1c3 100644 (file)
@@ -528,7 +528,15 @@ extern char leaf_reg_backmap[];
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
    in some cases it is preferable to use a more restrictive class.  */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
+/* We can't load constants into FP registers.  We can't load any FP constant
+   if an 'E' constraint fails to match it.  */
+#define PREFERRED_RELOAD_CLASS(X,CLASS)                        \
+  (CONSTANT_P (X)                                      \
+   && ((CLASS) == FP_REGS                              \
+       || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+          && (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT   \
+              || HOST_BITS_PER_INT != BITS_PER_WORD))) \
+   ? NO_REGS : (CLASS))
 
 /* Return the register class of a scratch register needed to load IN into
    a register of class CLASS in MODE.
index 95c5086..cfc13bd 100644 (file)
 ;; This pattern forces (set (reg:DF ...) (const_double ...))
 ;; to be reloaded by putting the constant into memory.
 ;; It must come before the more general movdf pattern.
-;; ??? A similar pattern for SF mode values would also be useful, but it
-;; is not as easy to write.
 (define_insn ""
   [(set (match_operand:DF 0 "general_operand" "=?r,f,o")
        (match_operand:DF 1 "" "?E,m,G"))]
 
 ;; Floating-point move insns.
 
+;; This pattern forces (set (reg:SF ...) (const_double ...))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general movsf pattern.
+(define_insn ""
+  [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
+       (match_operand:SF 1 "" "?E,m,G"))]
+  "GET_CODE (operands[1]) == CONST_DOUBLE"
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return singlemove_string (operands);
+    case 1:
+      return \"ld %1,%0\";
+    case 2:
+      return \"st %%g0,%0\";
+    }
+}"
+  [(set_attr "type" "load,fpload,store")
+   (set_attr "length" "2,1,1")])
+
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
        (match_operand:SF 1 "general_operand" ""))]
index 0502eb8..f285e24 100644 (file)
@@ -2454,7 +2454,28 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
          /* If the giv is an address destination, it could be something other
             than a simple register, these have to be treated differently.  */
          else if (v->giv_type == DEST_REG)
-           splittable_regs[REGNO (v->new_reg)] = value;
+           {
+             /* If value is not a constant, register, or register plus
+                constant, then compute its value into a register before
+                loop start.  This prevents illegal rtx sharing, and should
+                generate better code.  We can use bl->initial_value here
+                instead of splittable_regs[bl->regno] because this code
+                is going before the loop start.  */
+             if (unroll_type == UNROLL_COMPLETELY
+                 && GET_CODE (value) != CONST_INT
+                 && GET_CODE (value) != REG
+                 && (GET_CODE (value) != PLUS
+                     || GET_CODE (XEXP (value, 0)) != REG
+                     || GET_CODE (XEXP (value, 1)) != CONST_INT))
+               {
+                 rtx tem = gen_reg_rtx (v->mode);
+                 emit_iv_add_mult (bl->initial_value, v->mult_val,
+                                   v->add_val, tem, loop_start);
+                 value = tem;
+               }
+               
+             splittable_regs[REGNO (v->new_reg)] = value;
+           }
          else
            {
              /* Splitting address givs is useful since it will often allow us