diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1992-04-18 22:12:25 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1992-04-18 22:12:25 -0400 |
commit | e5f6a288fb94fa9ca3bf7408fc03146fbd292003 (patch) | |
tree | 8401d620c8eacb58c37ae5edd4ff87330b5098ed /gcc | |
parent | c8332879d817e0d98faafef982099d9c963789df (diff) | |
download | gcc-e5f6a288fb94fa9ca3bf7408fc03146fbd292003.zip gcc-e5f6a288fb94fa9ca3bf7408fc03146fbd292003.tar.gz gcc-e5f6a288fb94fa9ca3bf7408fc03146fbd292003.tar.bz2 |
*** empty log message ***
From-SVN: r790
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cse.c | 100 | ||||
-rw-r--r-- | gcc/genemit.c | 70 |
2 files changed, 153 insertions, 17 deletions
@@ -453,7 +453,7 @@ struct table_elt : (FIXED_REGNO_P (REGNO (X)) \ && REGNO_REG_CLASS (REGNO (X)) != NO_REGS) ? 0 \ : 2) \ - : rtx_cost (X) * 2) \ + : rtx_cost (X, SET) * 2) /* Determine if the quantity number for register X represents a valid index into the `qty_...' variables. */ @@ -569,8 +569,9 @@ static void cse_set_around_loop (); #define COSTS_N_INSNS(N) ((N) * 4 - 2) int -rtx_cost (x) +rtx_cost (x, outer_code) rtx x; + enum rtx_code outer_code; { register int i, j; register enum rtx_code code; @@ -627,9 +628,9 @@ rtx_cost (x) + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD); return 2; #ifdef RTX_COSTS - RTX_COSTS (x, code); + RTX_COSTS (x, code, outer_code); #endif - CONST_COSTS (x, code); + CONST_COSTS (x, code, outer_code); } /* Sum the costs of the sub-rtx's, plus cost of this operation, @@ -638,10 +639,10 @@ rtx_cost (x) fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') - total += rtx_cost (XEXP (x, i)); + total += rtx_cost (XEXP (x, i), code); else if (fmt[i] == 'E') for (j = 0; j < XVECLEN (x, i); j++) - total += rtx_cost (XVECEXP (x, i, j)); + total += rtx_cost (XVECEXP (x, i, j), code); return total; } @@ -815,7 +816,7 @@ mention_regs (x) register int changed = 0; if (x == 0) - return; + return 0; code = GET_CODE (x); if (code == REG) @@ -4157,6 +4158,11 @@ fold_rtx (x, insn) && (new = lookup_as_function (x, CONST_INT)) != 0) return new; + /* If this is a paradoxical SUBREG, we can't do anything with + it because we have no idea what value the extra bits would have. */ + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + return x; + /* Fold SUBREG_REG. If it changed, see if we can simplify the SUBREG. We might be able to if the SUBREG is extracting a single word in an integral mode or extracting the low part. */ @@ -4180,6 +4186,86 @@ fold_rtx (x, insn) if (new) return new; } + + /* If this is a narrowing SUBREG and our operand is a REG, see if + we can find an equivalence for REG that is a arithmetic operation + in a wider mode where both operands are paradoxical SUBREGs + from objects of our result mode. In that case, we couldn't report + an equivalent value for that operation, since we don't know what the + extra bits will be. But we can find an equivalence for this SUBREG + by folding that operation is the narrow mode. This allows us to + fold arithmetic in narrow modes when the machine only supports + word-sized arithmetic. */ + + if (GET_CODE (folded_arg0) == REG + && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0))) + { + struct table_elt *elt; + + /* We can use HASH here since we know that canon_hash won't be + called. */ + elt = lookup (folded_arg0, + HASH (folded_arg0, GET_MODE (folded_arg0)), + GET_MODE (folded_arg0)); + + if (elt) + elt = elt->first_same_value; + + for (; elt; elt = elt->next_same_value) + { + /* Just check for unary and binary operations. */ + if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1' + && GET_CODE (elt->exp) != SIGN_EXTEND + && GET_CODE (elt->exp) != ZERO_EXTEND + && GET_CODE (XEXP (elt->exp, 0)) == SUBREG + && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode) + { + rtx op0 = SUBREG_REG (XEXP (elt->exp, 0)); + + if (GET_CODE (op0) != REG && ! CONSTANT_P (op0)) + op0 = fold_rtx (op0, 0); + + op0 = equiv_constant (op0); + if (op0) + new = simplify_unary_operation (GET_CODE (elt->exp), mode, + op0, mode); + } + else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2' + || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c') + && ((GET_CODE (XEXP (elt->exp, 0)) == SUBREG + && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) + == mode)) + || CONSTANT_P (XEXP (elt->exp, 0))) + && ((GET_CODE (XEXP (elt->exp, 1)) == SUBREG + && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 1))) + == mode)) + || CONSTANT_P (XEXP (elt->exp, 1)))) + { + rtx op0 = gen_lowpart_common (mode, XEXP (elt->exp, 0)); + rtx op1 = gen_lowpart_common (mode, XEXP (elt->exp, 1)); + + if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0)) + op0 = fold_rtx (op0, 0); + + if (op0) + op0 = equiv_constant (op0); + + if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1)) + op1 = fold_rtx (op1, 0); + + if (op1) + op1 = equiv_constant (op1); + + if (op0 && op1) + new = simplify_binary_operation (GET_CODE (elt->exp), mode, + op0, op1); + } + + if (new) + return new; + } + } + return x; case NOT: diff --git a/gcc/genemit.c b/gcc/genemit.c index b8dbe43..f85444d 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -47,12 +47,20 @@ static int insn_index_number; struct clobber_pat { - int code_number; /* Counts only insns. */ + struct clobber_ent *insns; rtx pattern; int first_clobber; struct clobber_pat *next; } *clobber_list; +/* Records one insn that uses the clobber list. */ + +struct clobber_ent +{ + int code_number; /* Counts only insns. */ + struct clobber_ent *next; +}; + static void max_operand_1 (x) rtx x; @@ -271,14 +279,54 @@ gen_insn (insn) if (i != XVECLEN (insn, 1) - 1) { - register struct clobber_pat *new - = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat)); + register struct clobber_pat *p; + register struct clobber_ent *link + = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent)); + register int j; + + link->code_number = insn_code_number; + + /* See if any previous CLOBBER_LIST entry is the same as this + one. */ + + for (p = clobber_list; p; p = p->next) + { + if (p->first_clobber != i + 1 + || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) + continue; + + for (j = i + 1; j < XVECLEN (insn, 1); j++) + { + rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0); + rtx new = XEXP (XVECEXP (insn, 1, j), 0); + + /* OLD and NEW are the same if both are to be a SCRATCH + or if both are registers of the same mode and number. */ + if (! ((GET_CODE (old) == MATCH_SCRATCH + && GET_CODE (new) == MATCH_SCRATCH) + || (GET_CODE (old) == REG && GET_CODE (new) == REG + && GET_MODE (old) == GET_MODE (new) + && REGNO (old) == REGNO (new)))) + break; + } + + if (j == XVECLEN (insn, 1)) + break; + } + + if (p == 0) + { + p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat)); - new->code_number = insn_code_number; - new->pattern = insn; - new->first_clobber = i + 1; - new->next = clobber_list; - clobber_list = new; + p->insns = 0; + p->pattern = insn; + p->first_clobber = i + 1; + p->next = clobber_list; + clobber_list = p; + } + + link->next = p->insns; + p->insns = link; } } @@ -547,6 +595,7 @@ static void output_add_clobbers () { struct clobber_pat *clobber; + struct clobber_ent *ent; int i; printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n"); @@ -558,7 +607,8 @@ output_add_clobbers () for (clobber = clobber_list; clobber; clobber = clobber->next) { - printf (" case %d:\n", clobber->code_number); + for (ent = clobber->insns; ent; ent = ent->next) + printf (" case %d:\n", ent->code_number); for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) { @@ -567,7 +617,7 @@ output_add_clobbers () printf (";\n"); } - printf (" break;\n"); + printf (" break;\n\n"); } printf (" default:\n"); |