From 2b9a9aea2f9414a4abe0450d0c660deb8532bd83 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Wed, 27 May 1992 15:10:02 -0700 Subject: [PATCH] *** empty log message *** From-SVN: r1107 --- gcc/config/sparc/sparc.c | 31 +++++++++++++++++++++++++++---- gcc/config/sparc/sparc.h | 10 +++++++++- gcc/config/sparc/sparc.md | 24 ++++++++++++++++++++++-- gcc/unroll.c | 23 ++++++++++++++++++++++- 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 76527931f5e..9639dd6d915 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 3e69891f288..4eaa1c3d547 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 95c50861754..cfc13bd0d61 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 0502eb8341a..f285e244d13 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 -- 2.30.2