aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/genextract.c7
-rw-r--r--gcc/genrecog.c4
-rw-r--r--gcc/local-alloc.c33
-rw-r--r--gcc/recog.c123
-rw-r--r--gcc/recog.h27
-rw-r--r--gcc/regclass.c13
-rw-r--r--gcc/reload.c158
-rw-r--r--gcc/reload.h3
10 files changed, 236 insertions, 161 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4268476..9907808 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,29 @@
+Sat Oct 17 02:26:03 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * Makefile.in (insn-extract.o): Fix dependencies.
+ * genextract.c (main): Generate includes for insn-config.h and
+ recog.h.
+ Delete generation of declarations which are now in recog.h.
+ * genrecog.c (main): Delete generation of definitions which are
+ now in recog.c.
+ * local-alloc.c (block_alloc): Use extract_insn and the variables
+ it sets up instead of looking up values by insn_code.
+ * recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
+ recog_dup_num): Define here instead of generating the definition in
+ genrecog.c.
+ (recog_n_operands, recog_n_dups, recog_n_alternatives,
+ recog_operand_mode, recog_constraints, recog_operand_address_p):
+ New variables.
+ (extract_insn): New function.
+ * recog.h (extract_insn): Declare function.
+ (which_alternative, recog_n_operands, recog_n_dups,
+ recog_n_alternatives, recog_operand_mode, recog_constraints,
+ recog_operand_address_p): Declare variables.
+ * regclass.c (n_occurrences): New static function.
+ * reload.c (n_occurrences): Delete function.
+ (find_reloads): Use extract_insn.
+ * reload.h (n_occurrences): Delete declaration.
+
Sat Oct 17 01:17:51 1998 Jeffrey A Law (law@cygnus.com)
* reload1.c (reload_as_needed): Fix test for when to call
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index fdf3ab2..7d01d8b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1627,7 +1627,8 @@ s-opinit : $(md_file) genopinit $(srcdir)/move-if-change
$(srcdir)/move-if-change tmp-opinit.c insn-opinit.c
touch s-opinit
-insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) system.h toplev.h
+insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) system.h toplev.h \
+ insn-config.h recog.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-extract.c
insn-extract.c: s-extract ; @true
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 991d1d0..a1e48ed 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -460,17 +460,14 @@ from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
printf ("#include \"rtl.h\"\n");
+ printf ("#include \"insn-config.h\"\n");
+ printf ("#include \"recog.h\"\n");
printf ("#include \"toplev.h\"\n\n");
/* This variable exists only so it can be the "location"
of any missing operand whose numbers are skipped by a given pattern. */
printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
- printf ("extern rtx recog_operand[];\n");
- printf ("extern rtx *recog_operand_loc[];\n");
- printf ("extern rtx *recog_dup_loc[];\n");
- printf ("extern char recog_dup_num[];\n");
-
printf ("void\ninsn_extract (insn)\n");
printf (" rtx insn;\n");
printf ("{\n");
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 5c1046a..ee33a0c 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -1802,10 +1802,6 @@ from the machine description file `md'. */\n\n");
printf ("*/\n\n");
- printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n");
- printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n");
- printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n");
- printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n");
printf ("#define operands recog_operand\n\n");
next_subroutine_number = 0;
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index 1e6955a..f26167f 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -955,13 +955,11 @@ block_alloc (b)
register rtx r0, r1;
int combined_regno = -1;
int i;
- int insn_code_number = recog_memoized (insn);
this_insn_number = insn_number;
this_insn = insn;
- if (insn_code_number >= 0)
- insn_extract (insn);
+ extract_insn (insn);
which_alternative = -1;
/* Is this insn suitable for tying two registers?
@@ -982,11 +980,11 @@ block_alloc (b)
If tying is done, WIN is set nonzero. */
- if (insn_code_number >= 0
+ if (1
#ifdef REGISTER_CONSTRAINTS
- && insn_n_operands[insn_code_number] > 1
- && insn_operand_constraint[insn_code_number][0][0] == '='
- && insn_operand_constraint[insn_code_number][0][1] != '&'
+ && recog_n_operands > 1
+ && recog_constraints[0][0] == '='
+ && recog_constraints[0][1] != '&'
#else
&& GET_CODE (PATTERN (insn)) == SET
&& rtx_equal_p (SET_DEST (PATTERN (insn)), recog_operand[0])
@@ -1000,19 +998,19 @@ block_alloc (b)
operand 0. */
int n_matching_alts = 0;
- for (i = 1; i < insn_n_operands[insn_code_number]; i++)
+ for (i = 1; i < recog_n_operands; i++)
{
- char *p = insn_operand_constraint[insn_code_number][i];
+ char *p = recog_constraints[i];
int this_match = (requires_inout (p));
n_matching_alts += this_match;
- if (this_match == insn_n_alternatives[insn_code_number])
+ if (this_match == recog_n_alternatives)
must_match_0 = i;
}
#endif
r0 = recog_operand[0];
- for (i = 1; i < insn_n_operands[insn_code_number]; i++)
+ for (i = 1; i < recog_n_operands; i++)
{
#ifdef REGISTER_CONSTRAINTS
/* Skip this operand if we found an operand that
@@ -1021,9 +1019,9 @@ block_alloc (b)
if (must_match_0 >= 0 && i != must_match_0
&& ! (i == must_match_0 + 1
- && insn_operand_constraint[insn_code_number][i-1][0] == '%')
+ && recog_constraints[i-1][0] == '%')
&& ! (i == must_match_0 - 1
- && insn_operand_constraint[insn_code_number][i][0] == '%'))
+ && recog_constraints[i][0] == '%'))
continue;
/* Likewise if each alternative has some operand that
@@ -1031,9 +1029,8 @@ block_alloc (b)
operand that doesn't list operand 0 since we know that
the operand always conflicts with operand 0. We
ignore commutatity in this case to keep things simple. */
- if (n_matching_alts == insn_n_alternatives[insn_code_number]
- && (0 == requires_inout
- (insn_operand_constraint[insn_code_number][i])))
+ if (n_matching_alts == recog_n_alternatives
+ && 0 == requires_inout (recog_constraints[i]))
continue;
#endif
@@ -1044,9 +1041,9 @@ block_alloc (b)
of them. */
if (
#ifdef REGISTER_CONSTRAINTS
- insn_operand_constraint[insn_code_number][i][0] == 'p'
+ recog_constraints[i][0] == 'p'
#else
- insn_operand_address_p[insn_code_number][i]
+ recog_operand_address_p[i]
#endif
)
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
diff --git a/gcc/recog.c b/gcc/recog.c
index 97eccbc..261bb4d 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -54,6 +54,45 @@ static rtx *find_constant_term_loc PROTO((rtx *));
int volatile_ok;
+/* The following vectors hold the results from insn_extract. */
+
+/* Indexed by N, gives value of operand N. */
+rtx recog_operand[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives location where operand N was found. */
+rtx *recog_operand_loc[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives location where the Nth duplicate-appearance of
+ an operand was found. This is something that matched MATCH_DUP. */
+rtx *recog_dup_loc[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives the operand number that was duplicated in the
+ Nth duplicate-appearance of an operand. */
+char recog_dup_num[MAX_RECOG_OPERANDS];
+
+
+/* The next variables are set up by extract_insn. */
+
+/* The number of operands of the insn. */
+int recog_n_operands;
+
+/* The number of MATCH_DUPs in the insn. */
+int recog_n_dups;
+
+/* The number of alternatives in the constraints for the insn. */
+int recog_n_alternatives;
+
+/* Indexed by N, gives the mode of operand N. */
+enum machine_mode recog_operand_mode[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives the constraint string for operand N. */
+char *recog_constraints[MAX_RECOG_OPERANDS];
+
+#ifndef REGISTER_CONSTRAINTS
+/* Indexed by N, nonzero if operand N should be an address. */
+char recog_operand_address_p[MAX_RECOG_OPERANDS];
+#endif
+
/* On return from `constrain_operands', indicate which alternative
was satisfied. */
@@ -1656,6 +1695,90 @@ adj_offsettable_operand (op, offset)
abort ();
}
+/* Analyze INSN and compute the variables recog_n_operands, recog_n_dups,
+ recog_n_alternatives, recog_operand, recog_operand_loc, recog_constraints,
+ recog_operand_mode, recog_dup_loc and recog_dup_num.
+ If REGISTER_CONSTRAINTS is not defined, also compute
+ recog_operand_address_p. */
+void
+extract_insn (insn)
+ rtx insn;
+{
+ int i;
+ int icode;
+ int noperands;
+ rtx body = PATTERN (insn);
+
+ recog_n_operands = 0;
+ recog_n_alternatives = 0;
+ recog_n_dups = 0;
+
+ switch (GET_CODE (body))
+ {
+ case USE:
+ case CLOBBER:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ return;
+
+ case SET:
+ case PARALLEL:
+ case ASM_OPERANDS:
+ recog_n_operands = noperands = asm_noperands (body);
+ if (noperands >= 0)
+ {
+ char *p;
+ /* This insn is an `asm' with operands. */
+
+ /* expand_asm_operands makes sure there aren't too many operands. */
+ if (noperands > MAX_RECOG_OPERANDS)
+ abort ();
+
+ /* Now get the operand values and constraints out of the insn. */
+ decode_asm_operands (body, recog_operand, recog_operand_loc,
+ recog_constraints, recog_operand_mode);
+ if (noperands > 0)
+ {
+ char *p = recog_constraints[0];
+ recog_n_alternatives = 1;
+ while (*p)
+ recog_n_alternatives += (*p++ == ',');
+ }
+#ifndef REGISTER_CONSTRAINTS
+ bzero (recog_operand_address_p, sizeof recog_operand_address_p);
+#endif
+ break;
+ }
+
+ /* FALLTHROUGH */
+
+ default:
+ /* Ordinary insn: recognize it, get the operands via insn_extract
+ and get the constraints. */
+
+ icode = recog_memoized (insn);
+ if (icode < 0)
+ fatal_insn_not_found (insn);
+
+ recog_n_operands = noperands = insn_n_operands[icode];
+ recog_n_alternatives = insn_n_alternatives[icode];
+ recog_n_dups = insn_n_dups[icode];
+
+ insn_extract (insn);
+
+ for (i = 0; i < noperands; i++)
+ {
+#ifdef REGISTER_CONSTRAINTS
+ recog_constraints[i] = insn_operand_constraint[icode][i];
+#else
+ recog_operand_address_p[i] = insn_operand_address_p[icode][i];
+#endif
+ recog_operand_mode[i] = insn_operand_mode[icode][i];
+ }
+ }
+}
+
#ifdef REGISTER_CONSTRAINTS
/* Check the operands of an insn (found in recog_operands)
diff --git a/gcc/recog.h b/gcc/recog.h
index 980b76f..195efe3 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -61,10 +61,15 @@ extern int mode_dependent_address_p PROTO((rtx));
extern int recog PROTO((rtx, rtx, int *));
extern void add_clobbers PROTO((rtx, int));
extern void insn_extract PROTO((rtx));
+extern void extract_insn PROTO((rtx));
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
+/* Set by constrain_operands to the number of the alternative that
+ matched. */
+extern int which_alternative;
+
/* The following vectors hold the results from insn_extract. */
/* Indexed by N, gives value of operand N. */
@@ -81,6 +86,28 @@ extern rtx *recog_dup_loc[];
Nth duplicate-appearance of an operand. */
extern char recog_dup_num[];
+/* The next variables are set up by extract_insn. */
+
+/* The number of operands of the insn. */
+extern int recog_n_operands;
+
+/* The number of MATCH_DUPs in the insn. */
+extern int recog_n_dups;
+
+/* The number of alternatives in the constraints for the insn. */
+extern int recog_n_alternatives;
+
+/* Indexed by N, gives the mode of operand N. */
+extern enum machine_mode recog_operand_mode[];
+
+/* Indexed by N, gives the constraint string for operand N. */
+extern char *recog_constraints[];
+
+#ifndef REGISTER_CONSTRAINTS
+/* Indexed by N, nonzero if operand N should be an address. */
+extern char recog_operand_address_p[];
+#endif
+
/* Access the output function for CODE. */
#define OUT_FCN(CODE) (*insn_outfun[(int) (CODE)])
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 601b2f7..bfb5fe6 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -665,6 +665,7 @@ static int loop_depth;
static int loop_cost;
+static int n_occurrences PROTO((int, char *));
static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
char **, rtx));
static int copy_cost PROTO((rtx, enum machine_mode,
@@ -707,6 +708,18 @@ regclass_init ()
prefclass = 0;
}
+/* Return the number of times character C occurs in string S. */
+static int
+n_occurrences (c, s)
+ int c;
+ char *s;
+{
+ int n = 0;
+ while (*s)
+ n += (*s++ == c);
+ return n;
+}
+
/* This is a pass of the compiler that scans all instructions
and calculates the preferred class for each pseudo-register.
This information can be accessed later by calling `reg_preferred_class'.
diff --git a/gcc/reload.c b/gcc/reload.c
index 6f3ba43..a60841f 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -2156,19 +2156,6 @@ operands_match_p (x, y)
return 1 + success_2;
}
-/* Return the number of times character C occurs in string S. */
-
-int
-n_occurrences (c, s)
- int c;
- char *s;
-{
- int n = 0;
- while (*s)
- n += (*s++ == c);
- return n;
-}
-
/* Describe the range of registers or memory referenced by X.
If X is a register, set REG_FLAG and put the first register
number into START and the last plus one into END.
@@ -2442,7 +2429,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
static int last_output_reload_regno = -1;
this_insn = insn;
- this_insn_is_asm = 0; /* Tentative. */
n_reloads = 0;
n_replacements = 0;
n_earlyclobbers = 0;
@@ -2470,85 +2456,36 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
bzero ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
#endif
- /* Find what kind of insn this is. NOPERANDS gets number of operands.
- Make OPERANDS point to a vector of operand values.
- Make OPERAND_LOCS point to a vector of pointers to
- where the operands were found.
- Fill CONSTRAINTS and CONSTRAINTS1 with pointers to the
- constraint-strings for this insn.
- Return if the insn needs no reload processing. */
-
- switch (GET_CODE (body))
- {
- case USE:
- case CLOBBER:
- case ASM_INPUT:
- case ADDR_VEC:
- case ADDR_DIFF_VEC:
- return 0;
-
- case SET:
- /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
- is cheap to move between them. If it is not, there may not be an insn
- to do the copy, so we may need a reload. */
- if (GET_CODE (SET_DEST (body)) == REG
- && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (SET_SRC (body)) == REG
- && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
- && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
- REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
- return 0;
- case PARALLEL:
- case ASM_OPERANDS:
- reload_n_operands = noperands = asm_noperands (body);
- if (noperands >= 0)
- {
- /* This insn is an `asm' with operands. */
-
- insn_code_number = -1;
- this_insn_is_asm = 1;
+ /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
+ is cheap to move between them. If it is not, there may not be an insn
+ to do the copy, so we may need a reload. */
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_DEST (body)) == REG
+ && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
+ && GET_CODE (SET_SRC (body)) == REG
+ && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
+ && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
+ REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
+ return 0;
- /* expand_asm_operands makes sure there aren't too many operands. */
- if (noperands > MAX_RECOG_OPERANDS)
- abort ();
+ extract_insn (insn);
- /* Now get the operand values and constraints out of the insn. */
+ noperands = reload_n_operands = recog_n_operands;
+ n_alternatives = recog_n_alternatives;
- decode_asm_operands (body, recog_operand, recog_operand_loc,
- constraints, operand_mode);
- if (noperands > 0)
- {
- bcopy ((char *) constraints, (char *) constraints1,
- noperands * sizeof (char *));
- n_alternatives = n_occurrences (',', constraints[0]) + 1;
- }
- break;
- }
+ /* Just return "no reloads" if insn has no operands with constraints. */
+ if (noperands == 0 || n_alternatives == 0)
+ return 0;
- default:
- /* Ordinary insn: recognize it, get the operands via insn_extract
- and get the constraints. */
+ insn_code_number = INSN_CODE (insn);
+ this_insn_is_asm = insn_code_number < 0;
- insn_code_number = recog_memoized (insn);
- if (insn_code_number < 0)
- fatal_insn_not_found (insn);
-
- reload_n_operands = noperands = insn_n_operands[insn_code_number];
- n_alternatives = insn_n_alternatives[insn_code_number];
- /* Just return "no reloads" if insn has no operands with constraints. */
- if (n_alternatives == 0)
- return 0;
- insn_extract (insn);
- for (i = 0; i < noperands; i++)
- {
- constraints[i] = constraints1[i]
- = insn_operand_constraint[insn_code_number][i];
- operand_mode[i] = insn_operand_mode[insn_code_number][i];
- }
- }
-
- if (noperands == 0)
- return 0;
+ bcopy ((char *) recog_operand_mode, (char *) operand_mode,
+ noperands * sizeof (enum machine_mode));
+ bcopy ((char *) recog_constraints, (char *) constraints,
+ noperands * sizeof (char *));
+ bcopy ((char *) constraints, (char *) constraints1,
+ noperands * sizeof (char *));
commutative = -1;
@@ -4272,50 +4209,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
replace_reloads = replace;
this_insn = insn;
- /* Find what kind of insn this is. NOPERANDS gets number of operands.
- Store the operand values in RECOG_OPERAND and the locations
- of the words in the insn that point to them in RECOG_OPERAND_LOC.
- Return if the insn needs no reload processing. */
-
- switch (GET_CODE (body))
- {
- case USE:
- case CLOBBER:
- case ASM_INPUT:
- case ADDR_VEC:
- case ADDR_DIFF_VEC:
- return;
+ extract_insn (insn);
- case PARALLEL:
- case SET:
- noperands = asm_noperands (body);
- if (noperands >= 0)
- {
- /* This insn is an `asm' with operands.
- First, find out how many operands, and allocate space. */
-
- insn_code_number = -1;
- /* ??? This is a bug! ???
- Give up and delete this insn if it has too many operands. */
- if (noperands > MAX_RECOG_OPERANDS)
- abort ();
-
- /* Now get the operand values out of the insn. */
-
- decode_asm_operands (body, recog_operand, recog_operand_loc,
- NULL_PTR, NULL_PTR);
- break;
- }
-
- default:
- /* Ordinary insn: recognize it, allocate space for operands and
- constraints, and get them out via insn_extract. */
-
- insn_code_number = recog_memoized (insn);
- noperands = insn_n_operands[insn_code_number];
- insn_extract (insn);
- }
+ noperands = reload_n_operands = recog_n_operands;
+ /* Return if the insn needs no reload processing. */
if (noperands == 0)
return;
diff --git a/gcc/reload.h b/gcc/reload.h
index e49da9a..24e6aa8 100644
--- a/gcc/reload.h
+++ b/gcc/reload.h
@@ -247,9 +247,6 @@ extern int remove_address_replacements PROTO((rtx in_rtx));
autoincrement and autodecrement. */
extern int operands_match_p PROTO((rtx, rtx));
-/* Return the number of times character C occurs in string S. */
-extern int n_occurrences PROTO((int, char *));
-
/* Return 1 if altering OP will not modify the value of CLOBBER. */
extern int safe_from_earlyclobber PROTO((rtx, rtx));