aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <wilson@gcc.gnu.org>1992-05-27 15:10:02 -0700
committerJim Wilson <wilson@gcc.gnu.org>1992-05-27 15:10:02 -0700
commit2b9a9aea2f9414a4abe0450d0c660deb8532bd83 (patch)
treefc995758d89143c072b49963a64928ed40592d22
parent2f3d30bb57917a3925e2e362a74f024b25cafcc4 (diff)
downloadgcc-2b9a9aea2f9414a4abe0450d0c660deb8532bd83.zip
gcc-2b9a9aea2f9414a4abe0450d0c660deb8532bd83.tar.gz
gcc-2b9a9aea2f9414a4abe0450d0c660deb8532bd83.tar.bz2
*** empty log message ***
From-SVN: r1107
-rw-r--r--gcc/config/sparc/sparc.c31
-rw-r--r--gcc/config/sparc/sparc.h10
-rw-r--r--gcc/config/sparc/sparc.md24
-rw-r--r--gcc/unroll.c23
4 files changed, 80 insertions, 8 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 7652793..9639dd6 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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";
}
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 3e69891..4eaa1c3 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -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.
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 95c5086..cfc13bd 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1115,8 +1115,6 @@
;; 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"))]
@@ -1206,6 +1204,28 @@
;; 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" ""))]
diff --git a/gcc/unroll.c b/gcc/unroll.c
index 0502eb8..f285e24 100644
--- a/gcc/unroll.c
+++ b/gcc/unroll.c
@@ -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