aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-05-27 13:23:15 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-05-27 13:23:15 -0700
commit232801393614cd0dd2d1d9edb0821a08fe57e767 (patch)
tree2a3db5cb69837af35662b42fa3a1b95b877158ed
parent30196c1ff4ff35c7d46be079c0b6466e9203a784 (diff)
downloadgcc-232801393614cd0dd2d1d9edb0821a08fe57e767.zip
gcc-232801393614cd0dd2d1d9edb0821a08fe57e767.tar.gz
gcc-232801393614cd0dd2d1d9edb0821a08fe57e767.tar.bz2
Makefile.in (recog.o): Don't depend on resource.h.
* Makefile.in (recog.o): Don't depend on resource.h. * recog.c: Don't include resource.h. (recog_last_allowed_insn): Remove. (recog_next_insn): Remove. (struct peep2_insn_data): New. (peep2_insn_data, peep2_current): New. (peep2_next_insn): New. (peep2_regno_dead_p, peep2_reg_dead_p): New. (peep2_find_free_register): New. (peephole2_optimize): Track life information by insn as we go. * recog.h: Update declarations. * resource.c (find_free_register, reg_dead_p): Remove. * resource.h: Remove their declarations. * toplev.c: Include hard-reg-set.h before recog.h. * genconfig.c (max_insns_per_peep2): New. (gen_peephole2): New. (main): Call it. * genemit.c (output_peephole2_scratches): Generate calls to peep2_find_free_register; adjust surrounding code. (main): Have insn-emit.c include hard-reg-set.h before recog.h. * genrecog.c (change_state): Don't track last_insn. (write_action): Write into *_pmatch_len before accepting. (write_tree): Adjust peephole2_insns and subroutines to match. * config/i386/i386.md (all peepholes): Use peep2_regno_dead_p. From-SVN: r34208
-rw-r--r--gcc/ChangeLog29
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/config/i386/i386.md45
-rw-r--r--gcc/genconfig.c35
-rw-r--r--gcc/genemit.c15
-rw-r--r--gcc/genrecog.c50
-rw-r--r--gcc/recog.c325
-rw-r--r--gcc/recog.h11
-rw-r--r--gcc/resource.c106
-rw-r--r--gcc/resource.h3
-rw-r--r--gcc/toplev.c2
11 files changed, 408 insertions, 215 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6dfc954..b8c478e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,34 @@
2000-05-27 Richard Henderson <rth@cygnus.com>
+ * Makefile.in (recog.o): Don't depend on resource.h.
+ * recog.c: Don't include resource.h.
+ (recog_last_allowed_insn): Remove.
+ (recog_next_insn): Remove.
+ (struct peep2_insn_data): New.
+ (peep2_insn_data, peep2_current): New.
+ (peep2_next_insn): New.
+ (peep2_regno_dead_p, peep2_reg_dead_p): New.
+ (peep2_find_free_register): New.
+ (peephole2_optimize): Track life information by insn as we go.
+ * recog.h: Update declarations.
+ * resource.c (find_free_register, reg_dead_p): Remove.
+ * resource.h: Remove their declarations.
+ * toplev.c: Include hard-reg-set.h before recog.h.
+
+ * genconfig.c (max_insns_per_peep2): New.
+ (gen_peephole2): New.
+ (main): Call it.
+ * genemit.c (output_peephole2_scratches): Generate calls to
+ peep2_find_free_register; adjust surrounding code.
+ (main): Have insn-emit.c include hard-reg-set.h before recog.h.
+ * genrecog.c (change_state): Don't track last_insn.
+ (write_action): Write into *_pmatch_len before accepting.
+ (write_tree): Adjust peephole2_insns and subroutines to match.
+
+ * config/i386/i386.md (all peepholes): Use peep2_regno_dead_p.
+
+2000-05-27 Richard Henderson <rth@cygnus.com>
+
* function.c (thread_prologue_epilogue_insns): Don't move the
line note at the head of the chain. Only force a lineno note
before the end of block 0.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index c362db2..5456c47 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1382,7 +1382,7 @@ final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
dbxout.h $(BASIC_BLOCK_H)
recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) function.h $(BASIC_BLOCK_H) \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
- insn-flags.h insn-codes.h real.h toplev.h output.h resource.h
+ insn-flags.h insn-codes.h real.h toplev.h output.h
reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) $(RECOG_H) \
$(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h \
varray.h function.h
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 5696c26..cdadf5d 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -9591,10 +9591,11 @@
[(match_scratch:SI 1 "r")
(set (match_operand:SI 0 "memory_operand" "")
(const_int 0))]
- "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ "! optimize_size
&& ! TARGET_USE_MOV0
- && TARGET_SPLIT_LONG_MOVES"
+ && TARGET_SPLIT_LONG_MOVES
+ && get_attr_length (insn) >= ix86_cost->large_insn
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 1) (const_int 0))
(clobber (reg:CC 17))])
(set (match_dup 0) (match_dup 1))]
@@ -9604,10 +9605,11 @@
[(match_scratch:HI 1 "r")
(set (match_operand:HI 0 "memory_operand" "")
(const_int 0))]
- "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ "! optimize_size
&& ! TARGET_USE_MOV0
- && TARGET_SPLIT_LONG_MOVES"
+ && TARGET_SPLIT_LONG_MOVES
+ && get_attr_length (insn) >= ix86_cost->large_insn
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 2) (const_int 0))
(clobber (reg:CC 17))])
(set (match_dup 0) (match_dup 1))]
@@ -9617,10 +9619,11 @@
[(match_scratch:QI 1 "q")
(set (match_operand:QI 0 "memory_operand" "")
(const_int 0))]
- "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ "! optimize_size
&& ! TARGET_USE_MOV0
- && TARGET_SPLIT_LONG_MOVES"
+ && TARGET_SPLIT_LONG_MOVES
+ && get_attr_length (insn) >= ix86_cost->large_insn
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 2) (const_int 0))
(clobber (reg:CC 17))])
(set (match_dup 0) (match_dup 1))]
@@ -9630,8 +9633,9 @@
[(match_scratch:SI 2 "r")
(set (match_operand:SI 0 "memory_operand" "")
(match_operand:SI 1 "immediate_operand" ""))]
- "! optimize_size && get_attr_length (insn) >= ix86_cost->large_insn
- && TARGET_SPLIT_LONG_MOVES"
+ "! optimize_size
+ && get_attr_length (insn) >= ix86_cost->large_insn
+ && TARGET_SPLIT_LONG_MOVES"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
@@ -9675,14 +9679,14 @@
;; represented using a modRM byte. The XOR replacement is long decoded,
;; so this split helps here as well.
;;
-;; Note: Can't do this as a regular split because reg_dead_p assumes
-;; resource info is live.
+;; Note: Can't do this as a regular split because we can't get proper
+;; lifetime information then.
(define_peephole2
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
"!optimize_size
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ && peep2_regno_dead_p (0, FLAGS_REG)
&& ((TARGET_PENTIUM
&& (GET_CODE (operands[0]) != MEM
|| !memory_displacement_operand (operands[0], SImode)))
@@ -9696,7 +9700,7 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
"!optimize_size
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ && peep2_regno_dead_p (0, FLAGS_REG)
&& ((TARGET_PENTIUM
&& (GET_CODE (operands[0]) != MEM
|| !memory_displacement_operand (operands[0], HImode)))
@@ -9710,7 +9714,7 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
(not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
"!optimize_size
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))
+ && peep2_regno_dead_p (0, FLAGS_REG)
&& ((TARGET_PENTIUM
&& (GET_CODE (operands[0]) != MEM
|| !memory_displacement_operand (operands[0], QImode)))
@@ -9873,7 +9877,7 @@
|| GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == SImode)
&& (! TARGET_USE_MOV0 || optimize_size)
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (const_int 0))
(clobber (reg:CC 17))])]
"operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
@@ -9885,7 +9889,7 @@
"(GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == SImode)
&& (optimize_size || TARGET_PENTIUM)
- && reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (const_int -1))
(clobber (reg:CC 17))])]
"operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]));")
@@ -9896,7 +9900,7 @@
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_dup 0)
(match_operand:SI 1 "nonmemory_operand" "")))]
- "reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+ "peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
"")
@@ -9905,7 +9909,8 @@
[(set (match_operand:SI 0 "register_operand" "")
(mult:SI (match_dup 0)
(match_operand:SI 1 "immediate_operand" "")))]
- "reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
+ "exact_log2 (INTVAL (operands[1])) >= 0
+ && peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
(clobber (reg:CC 17))])]
"operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index 6508c39..e7964ab 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -42,6 +42,9 @@ static int have_peephole2_flag;
/* Maximum number of insns seen in a split. */
static int max_insns_per_split = 1;
+/* Maximum number of input insns for peephole2. */
+static int max_insns_per_peep2;
+
static int clobbers_seen_this_insn;
static int dup_operands_seen_this_insn;
@@ -239,6 +242,26 @@ gen_peephole (peep)
walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
}
+static void
+gen_peephole2 (peep)
+ rtx peep;
+{
+ int i, n;
+
+ /* Look through the patterns that are matched
+ to compute the maximum operand number. */
+ for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
+ walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
+
+ /* Look at the number of insns this insn can be matched from. */
+ for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
+ if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
+ && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
+ n++;
+ if (n > max_insns_per_peep2)
+ max_insns_per_peep2 = n;
+}
+
extern int main PARAMS ((int, char **));
int
@@ -289,7 +312,7 @@ from the machine description file `md'. */\n\n");
case DEFINE_PEEPHOLE2:
have_peephole2_flag = 1;
- gen_split (desc);
+ gen_peephole2 (desc);
break;
case DEFINE_PEEPHOLE:
@@ -302,9 +325,8 @@ from the machine description file `md'. */\n\n");
}
}
- printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
-
- printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
+ printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
+ printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
/* This is conditionally defined, in case the user writes code which emits
more splits than we can readily see (and knows s/he does it). */
@@ -328,7 +350,10 @@ from the machine description file `md'. */\n\n");
printf ("#define HAVE_peephole 1\n");
if (have_peephole2_flag)
- printf ("#define HAVE_peephole2 1\n");
+ {
+ printf ("#define HAVE_peephole2 1\n");
+ printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
+ }
fflush (stdout);
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
diff --git a/gcc/genemit.c b/gcc/genemit.c
index dab819b..54793d4 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -699,10 +699,7 @@ output_peephole2_scratches (split)
int i;
int insn_nr = 0;
- printf (" rtx first_insn ATTRIBUTE_UNUSED;\n");
- printf (" rtx last_insn ATTRIBUTE_UNUSED;\n");
printf (" HARD_REG_SET _regs_allocated;\n");
-
printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
for (i = 0; i < XVECLEN (split, 0); i++)
@@ -721,15 +718,11 @@ output_peephole2_scratches (split)
}
else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
cur_insn_nr++;
- printf (" first_insn = recog_next_insn (curr_insn, %d);\n", insn_nr);
- if (last_insn_nr > insn_nr)
- printf (" last_insn = recog_next_insn (curr_insn, %d);\n",
- last_insn_nr - 1);
- else
- printf (" last_insn = 0;\n");
- printf (" if ((operands[%d] = find_free_register (first_insn, last_insn, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
+
+ printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
return NULL;\n",
XINT (elt, 0),
+ insn_nr, last_insn_nr,
XSTR (elt, 1),
GET_MODE_NAME (GET_MODE (elt)));
@@ -777,8 +770,8 @@ from the machine description file `md'. */\n\n");
printf ("#include \"insn-config.h\"\n");
printf ("#include \"insn-flags.h\"\n");
printf ("#include \"insn-codes.h\"\n");
- printf ("#include \"recog.h\"\n");
printf ("#include \"hard-reg-set.h\"\n");
+ printf ("#include \"recog.h\"\n");
printf ("#include \"resource.h\"\n");
printf ("#include \"reload.h\"\n\n");
printf ("#define FAIL return (end_sequence (), _val)\n");
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 7c435a0..b955eb0 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -272,8 +272,8 @@ static struct decision *write_switch
static void write_cond
PARAMS ((struct decision_test *, int, enum routine_type));
static void write_action
- PARAMS ((struct decision_test *, int, int, struct decision *,
- enum routine_type));
+ PARAMS ((struct decision *, struct decision_test *, int, int,
+ struct decision *, enum routine_type));
static int is_unconditional
PARAMS ((struct decision_test *, enum routine_type));
static int write_node
@@ -1578,10 +1578,6 @@ change_state (oldpos, newpos, afterward, indent)
if (newpos[new_has_insn] >= 'A' && newpos[new_has_insn] <= 'Z')
break;
- /* Make sure to reset the last_insn pointer when popping back up. */
- if (old_has_insn >= 0 && new_has_insn < 0)
- printf ("%slast_insn = insn;\n", indent);
-
/* Go down to desired level. */
while (depth < ndepth)
{
@@ -1591,21 +1587,20 @@ change_state (oldpos, newpos, afterward, indent)
/* We can only fail if we're moving down the tree. */
if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
{
- printf ("%slast_insn = recog_next_insn (insn, %d);\n",
+ printf ("%stem = peep2_next_insn (%d);\n",
indent, newpos[depth] - 'A');
}
else
{
- printf ("%stem = recog_next_insn (insn, %d);\n",
+ printf ("%stem = peep2_next_insn (%d);\n",
indent, newpos[depth] - 'A');
printf ("%sif (tem == NULL_RTX)\n", indent);
if (afterward)
printf ("%s goto L%d;\n", indent, afterward->number);
else
printf ("%s goto ret0;\n", indent);
- printf ("%slast_insn = tem;\n", indent);
}
- printf ("%sx%d = PATTERN (last_insn);\n", indent, depth + 1);
+ printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
}
else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
@@ -1888,7 +1883,8 @@ write_cond (p, depth, subroutine_type)
perform a state change. For the `accept' tests we must do more work. */
static void
-write_action (test, depth, uncond, success, subroutine_type)
+write_action (p, test, depth, uncond, success, subroutine_type)
+ struct decision *p;
struct decision_test *test;
int depth, uncond;
struct decision *success;
@@ -1942,9 +1938,20 @@ write_action (test, depth, uncond, success, subroutine_type)
break;
case PEEPHOLE2:
- printf ("%stem = gen_peephole2_%d (insn, operands);\n",
- indent, test->u.insn.code_number);
- printf ("%sif (tem != 0)\n%s goto ret1;\n", indent, indent);
+ {
+ int match_len = 0, i;
+
+ for (i = strlen (p->position) - 1; i >= 0; --i)
+ if (p->position[i] >= 'A' && p->position[i] <= 'Z')
+ {
+ match_len = p->position[i] - 'A';
+ break;
+ }
+ printf ("%s*_pmatch_len = %d;\n", indent, match_len);
+ printf ("%stem = gen_peephole2_%d (insn, operands);\n",
+ indent, test->u.insn.code_number);
+ printf ("%sif (tem != 0)\n%s return tem;\n", indent, indent);
+ }
break;
default:
@@ -2027,7 +2034,7 @@ write_node (p, depth, subroutine_type)
printf (")\n");
}
- write_action (last_test, depth, uncond, p->success.first, subroutine_type);
+ write_action (p, last_test, depth, uncond, p->success.first, subroutine_type);
return uncond > 0;
}
@@ -2090,7 +2097,7 @@ write_tree (head, prevpos, type, initial)
};
static const char * const call_suffix[] = {
- ", pnum_clobbers", "", ", _plast_insn"
+ ", pnum_clobbers", "", ", _pmatch_len"
};
/* This node has been broken out into a separate subroutine.
@@ -2167,12 +2174,13 @@ split%s (x0, insn)\n\
rtx insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
break;
case PEEPHOLE2:
- printf ("%srtx peephole2%s PARAMS ((rtx, rtx, rtx *));\n", s_or_e, extension);
+ printf ("%srtx peephole2%s PARAMS ((rtx, rtx, int *));\n",
+ s_or_e, extension);
printf ("%srtx\n\
-peephole2%s (x0, insn, _plast_insn)\n\
+peephole2%s (x0, insn, _pmatch_len)\n\
register rtx x0;\n\
rtx insn ATTRIBUTE_UNUSED;\n\
- rtx *_plast_insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+ int *_pmatch_len ATTRIBUTE_UNUSED;\n", s_or_e, extension);
break;
}
@@ -2180,8 +2188,6 @@ peephole2%s (x0, insn, _plast_insn)\n\
for (i = 1; i <= max_depth; i++)
printf (" register rtx x%d ATTRIBUTE_UNUSED;\n", i);
- if (type == PEEPHOLE2)
- printf (" register rtx last_insn = insn;\n");
printf (" %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
if (head->first)
@@ -2189,8 +2195,6 @@ peephole2%s (x0, insn, _plast_insn)\n\
else
printf (" goto ret0;\n");
- if (type == PEEPHOLE2)
- printf (" ret1:\n *_plast_insn = last_insn;\n return tem;\n");
printf (" ret0:\n return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
}
diff --git a/gcc/recog.c b/gcc/recog.c
index bac7e47..8760041 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "basic-block.h"
#include "output.h"
-#include "resource.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
@@ -2682,100 +2681,340 @@ split_all_insns (upd_life)
}
#ifdef HAVE_peephole2
-/* This is the last insn we'll allow recog_next_insn to consider. */
-static rtx recog_last_allowed_insn;
+struct peep2_insn_data
+{
+ rtx insn;
+ regset live_before;
+};
+
+static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
+static int peep2_current;
+
+/* A non-insn marker indicating the last insn of the block.
+ The live_before regset for this element is correct, indicating
+ global_live_at_end for the block. */
+#define PEEP2_EOB pc_rtx
+
+/* Return the Nth non-note insn after `current', or return NULL_RTX if it
+ does not exist. Used by the recognizer to find the next insn to match
+ in a multi-insn pattern. */
-/* Return the Nth non-note insn after INSN, or return NULL_RTX if it does
- not exist. Used by the recognizer to find the next insn to match in a
- multi-insn pattern. */
rtx
-recog_next_insn (insn, n)
- rtx insn;
+peep2_next_insn (n)
int n;
{
- if (insn != NULL_RTX)
+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
+ abort ();
+
+ n += peep2_current;
+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
+ n -= MAX_INSNS_PER_PEEP2 + 1;
+
+ if (peep2_insn_data[n].insn == PEEP2_EOB)
+ return NULL_RTX;
+ return peep2_insn_data[n].insn;
+}
+
+/* Return true if REGNO is dead before the Nth non-note insn
+ after `current'. */
+
+int
+peep2_regno_dead_p (ofs, regno)
+ int ofs;
+ int regno;
+{
+ if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+ abort ();
+
+ ofs += peep2_current;
+ if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+ ofs -= MAX_INSNS_PER_PEEP2 + 1;
+
+ if (peep2_insn_data[ofs].insn == NULL_RTX)
+ abort ();
+
+ return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
+}
+
+/* Similarly for a REG. */
+
+int
+peep2_reg_dead_p (ofs, reg)
+ int ofs;
+ rtx reg;
+{
+ int regno, n;
+
+ if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+ abort ();
+
+ ofs += peep2_current;
+ if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
+ ofs -= MAX_INSNS_PER_PEEP2 + 1;
+
+ if (peep2_insn_data[ofs].insn == NULL_RTX)
+ abort ();
+
+ regno = REGNO (reg);
+ n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ while (--n >= 0)
+ if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
+ return 0;
+ return 1;
+}
+
+/* Try to find a hard register of mode MODE, matching the register class in
+ CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
+ remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
+ in which case the only condition is that the register must be available
+ before CURRENT_INSN.
+ Registers that already have bits set in REG_SET will not be considered.
+
+ If an appropriate register is available, it will be returned and the
+ corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
+ returned. */
+
+rtx
+peep2_find_free_register (from, to, class_str, mode, reg_set)
+ int from, to;
+ const char *class_str;
+ enum machine_mode mode;
+ HARD_REG_SET *reg_set;
+{
+ static int search_ofs;
+ enum reg_class class;
+ HARD_REG_SET live;
+ int i;
+
+ if (from >= MAX_INSNS_PER_PEEP2 + 1 || to >= MAX_INSNS_PER_PEEP2 + 1)
+ abort ();
+
+ from += peep2_current;
+ if (from >= MAX_INSNS_PER_PEEP2 + 1)
+ from -= MAX_INSNS_PER_PEEP2 + 1;
+ to += peep2_current;
+ if (to >= MAX_INSNS_PER_PEEP2 + 1)
+ to -= MAX_INSNS_PER_PEEP2 + 1;
+
+ if (peep2_insn_data[from].insn == NULL_RTX)
+ abort ();
+ REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
+
+ while (from != to)
{
- while (n > 0)
+ HARD_REG_SET this_live;
+
+ if (++from >= MAX_INSNS_PER_PEEP2 + 1)
+ from = 0;
+ if (peep2_insn_data[from].insn == NULL_RTX)
+ abort ();
+ REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
+ IOR_HARD_REG_SET (live, this_live);
+ }
+
+ class = (class_str[0] == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_LETTER (class_str[0]));
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int raw_regno, regno, success, j;
+
+ /* Distribute the free registers as much as possible. */
+ raw_regno = search_ofs + i;
+ if (raw_regno >= FIRST_PSEUDO_REGISTER)
+ raw_regno -= FIRST_PSEUDO_REGISTER;
+#ifdef REG_ALLOC_ORDER
+ regno = reg_alloc_order[raw_regno];
+#else
+ regno = raw_regno;
+#endif
+
+ /* Don't allocate fixed registers. */
+ if (fixed_regs[regno])
+ continue;
+ /* Make sure the register is of the right class. */
+ if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+ continue;
+ /* And can support the mode we need. */
+ if (! HARD_REGNO_MODE_OK (regno, mode))
+ continue;
+ /* And that we don't create an extra save/restore. */
+ if (! call_used_regs[regno] && ! regs_ever_live[regno])
+ continue;
+ /* And we don't clobber traceback for noreturn functions. */
+ if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
+ && (! reload_completed || frame_pointer_needed))
+ continue;
+
+ success = 1;
+ for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ {
+ if (TEST_HARD_REG_BIT (*reg_set, regno + j)
+ || TEST_HARD_REG_BIT (live, regno + j))
+ {
+ success = 0;
+ break;
+ }
+ }
+ if (success)
{
- if (insn == recog_last_allowed_insn)
- return NULL_RTX;
+ for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ SET_HARD_REG_BIT (*reg_set, regno + j);
- insn = NEXT_INSN (insn);
- if (insn == NULL_RTX)
- break;
+ /* Start the next search with the next register. */
+ if (++raw_regno >= FIRST_PSEUDO_REGISTER)
+ raw_regno = 0;
+ search_ofs = raw_regno;
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- n -= 1;
+ return gen_rtx_REG (mode, regno);
}
}
- return insn;
+ search_ofs = 0;
+ return NULL_RTX;
}
/* Perform the peephole2 optimization pass. */
+
void
peephole2_optimize (dump_file)
FILE *dump_file ATTRIBUTE_UNUSED;
{
+ regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
rtx insn, prev;
- int i, changed;
+ regset live;
+ int i, b;
+#ifdef HAVE_conditional_execution
sbitmap blocks;
+ int changed;
+#endif
- /* ??? TODO: Arrange with resource.c to start at bb->global_live_at_end
- and backtrack insn by insn as we proceed through the block. In this
- way we'll not need to keep searching forward from the beginning of
- basic blocks to find register life info. */
-
- init_resource_info (NULL);
+ /* Initialize the regsets we're going to use. */
+ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+ peep2_insn_data[i].live_before = INITIALIZE_REG_SET (rs_heads[i]);
+ live = INITIALIZE_REG_SET (rs_heads[i]);
+#ifdef HAVE_conditional_execution
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
changed = 0;
+#else
+ count_or_remove_death_notes (NULL, 1);
+#endif
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ for (b = n_basic_blocks - 1; b >= 0; --b)
{
- basic_block bb = BASIC_BLOCK (i);
+ basic_block bb = BASIC_BLOCK (b);
+ struct propagate_block_info *pbi;
+
+ /* Indicate that all slots except the last holds invalid data. */
+ for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+
+ /* Indicate that the last slot contains live_after data. */
+ peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+ peep2_current = MAX_INSNS_PER_PEEP2;
- /* Since we don't update life info until the very end, we can't
- allow matching instructions that we've replaced before. Walk
- backward through the basic block so that we don't have to
- care about subsequent life info; recog_last_allowed_insn to
- restrict how far forward we will allow the match to proceed. */
+ /* Start up propagation. */
+ COPY_REG_SET (live, bb->global_live_at_end);
+ COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+
+#ifdef HAVE_conditional_execution
+ pbi = init_propagate_block_info (bb, live, NULL, 0);
+#else
+ pbi = init_propagate_block_info (bb, live, NULL, PROP_DEATH_NOTES);
+#endif
- recog_last_allowed_insn = NEXT_INSN (bb->end);
for (insn = bb->end; ; insn = prev)
{
prev = PREV_INSN (insn);
if (INSN_P (insn))
{
- rtx try, last_insn;
-
- try = peephole2_insns (PATTERN (insn), insn, &last_insn);
+ rtx try;
+ int match_len;
+
+ /* Record this insn. */
+ if (--peep2_current < 0)
+ peep2_current = MAX_INSNS_PER_PEEP2;
+ peep2_insn_data[peep2_current].insn = insn;
+ propagate_one_insn (pbi, insn);
+ COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
+
+ /* Match the peephole. */
+ try = peephole2_insns (PATTERN (insn), insn, &match_len);
if (try != NULL)
{
- flow_delete_insn_chain (insn, last_insn);
+ i = match_len + peep2_current;
+ if (i >= MAX_INSNS_PER_PEEP2 + 1)
+ i -= MAX_INSNS_PER_PEEP2 + 1;
+
+ /* Replace the old sequence with the new. */
+ flow_delete_insn_chain (insn, peep2_insn_data[i].insn);
try = emit_insn_after (try, prev);
- if (last_insn == bb->end)
+ /* Adjust the basic block boundaries. */
+ if (peep2_insn_data[i].insn == bb->end)
bb->end = try;
if (insn == bb->head)
bb->head = NEXT_INSN (prev);
- recog_last_allowed_insn = NEXT_INSN (prev);
- SET_BIT (blocks, i);
+#ifdef HAVE_conditional_execution
+ /* With conditional execution, we cannot back up the
+ live information so easily, since the conditional
+ death data structures are not so self-contained.
+ So record that we've made a modification to this
+ block and update life information at the end. */
+ SET_BIT (blocks, b);
changed = 1;
+
+ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+ peep2_insn_data[peep2_current].insn = PEEP2_EOB;
+#else
+ /* Back up lifetime information past the end of the
+ newly created sequence. */
+ if (++i >= MAX_INSNS_PER_PEEP2 + 1)
+ i = 0;
+ COPY_REG_SET (live, peep2_insn_data[i].live_before);
+
+ /* Update life information for the new sequence. */
+ do
+ {
+ if (INSN_P (try))
+ {
+ if (--i < 0)
+ i = MAX_INSNS_PER_PEEP2;
+ peep2_insn_data[i].insn = try;
+ propagate_one_insn (pbi, try);
+ COPY_REG_SET (peep2_insn_data[i].live_before, live);
+ }
+ try = PREV_INSN (try);
+ }
+ while (try != prev);
+
+ /* ??? Should verify that LIVE now matches what we
+ had before the new sequence. */
+
+ peep2_current = i;
+#endif
}
}
if (insn == bb->head)
break;
}
+
+ free_propagate_block_info (pbi);
}
- free_resource_info ();
+ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
+ FREE_REG_SET (peep2_insn_data[i].live_before);
+ FREE_REG_SET (live);
- compute_bb_for_insn (get_max_uid ());
+#ifdef HAVE_conditional_execution
count_or_remove_death_notes (blocks, 1);
update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
-}
+ sbitmap_free (blocks);
#endif
+}
+#endif /* HAVE_peephole2 */
diff --git a/gcc/recog.h b/gcc/recog.h
index 51f6fb0..465013a 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -116,9 +116,16 @@ extern void add_clobbers PARAMS ((rtx, int));
extern void insn_extract PARAMS ((rtx));
extern void extract_insn PARAMS ((rtx));
extern void preprocess_constraints PARAMS ((void));
-extern rtx recog_next_insn PARAMS ((rtx, int));
+extern rtx peep2_next_insn PARAMS ((int));
+extern int peep2_regno_dead_p PARAMS ((int, int));
+extern int peep2_reg_dead_p PARAMS ((int, rtx));
+#ifdef CLEAR_HARD_REG_SET
+extern rtx peep2_find_free_register PARAMS ((int, int, const char *,
+ enum machine_mode,
+ HARD_REG_SET *));
+#endif
extern void peephole2_optimize PARAMS ((FILE *));
-extern rtx peephole2_insns PARAMS ((rtx, rtx, rtx *));
+extern rtx peephole2_insns PARAMS ((rtx, rtx, int *));
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
diff --git a/gcc/resource.c b/gcc/resource.c
index d84fabe..af1b4ed 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -1268,109 +1268,3 @@ mark_end_of_function_resources (trial, include_delayed_effects)
mark_referenced_resources (trial, &end_of_function_needs,
include_delayed_effects);
}
-
-/* Try to find a hard register of mode MODE, matching the register class in
- CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
- remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
- in which case the only condition is that the register must be available
- before CURRENT_INSN.
- Registers that already have bits set in REG_SET will not be considered.
-
- If an appropriate register is available, it will be returned and the
- corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
- returned. */
-
-rtx
-find_free_register (current_insn, last_insn, class_str, mode, reg_set)
- rtx current_insn, last_insn;
- const char *class_str;
- int mode;
- HARD_REG_SET *reg_set;
-{
- int i, j;
- struct resources used;
- unsigned char clet = class_str[0];
- enum reg_class class
- = (clet == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (clet));
-
- mark_target_live_regs (get_insns (), current_insn, &used);
- if (last_insn)
- while (current_insn != last_insn)
- {
- /* Exclude anything set in this insn. */
- mark_set_resources (PATTERN (current_insn), &used, 0,
- MARK_SRC_DEST_CALL);
- current_insn = next_nonnote_insn (current_insn);
- }
-
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int regno;
- int success;
-
-#ifdef REG_ALLOC_ORDER
- regno = reg_alloc_order [i];
-#else
- regno = i;
-#endif
-
- /* Don't allocate fixed registers. */
- if (fixed_regs[regno])
- continue;
- /* Make sure the register is of the right class. */
- if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
- continue;
- /* And can support the mode we need. */
- if (! HARD_REGNO_MODE_OK (regno, mode))
- continue;
- /* And that we don't create an extra save/restore. */
- if (! call_used_regs[regno] && ! regs_ever_live[regno])
- continue;
- /* And we don't clobber traceback for noreturn functions. */
- if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
- && (! reload_completed || frame_pointer_needed))
- continue;
-
- success = 1;
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
- {
- if (TEST_HARD_REG_BIT (*reg_set, regno + j)
- || TEST_HARD_REG_BIT (used.regs, regno + j))
- {
- success = 0;
- break;
- }
- }
- if (success)
- {
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
- {
- SET_HARD_REG_BIT (*reg_set, regno + j);
- }
- return gen_rtx_REG (mode, regno);
- }
- }
- return NULL_RTX;
-}
-
-/* Return true if REG is dead at CURRENT_INSN. */
-
-int
-reg_dead_p (current_insn, reg)
- rtx current_insn, reg;
-{
- struct resources used;
- int regno, j;
-
- mark_target_live_regs (get_insns (), current_insn, &used);
-
- regno = REGNO (reg);
- for (j = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; j >= 0; j--)
- {
- if (TEST_HARD_REG_BIT (used.regs, regno + j))
- return 0;
- }
-
- return 1;
-}
diff --git a/gcc/resource.h b/gcc/resource.h
index 718ec65..4f01731 100644
--- a/gcc/resource.h
+++ b/gcc/resource.h
@@ -50,6 +50,3 @@ extern void incr_ticks_for_insn PARAMS ((rtx));
extern void mark_end_of_function_resources PARAMS ((rtx, int));
extern void init_resource_info PARAMS ((rtx));
extern void free_resource_info PARAMS ((void));
-extern rtx find_free_register PARAMS ((rtx, rtx, const char *, int,
- HARD_REG_SET *));
-extern int reg_dead_p PARAMS ((rtx, rtx));
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 30ef18a..1fc72f1 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-attr.h"
#include "insn-codes.h"
#include "insn-config.h"
+#include "hard-reg-set.h"
#include "recog.h"
#include "defaults.h"
#include "output.h"
@@ -54,7 +55,6 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "toplev.h"
#include "expr.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
#include "intl.h"
#include "ggc.h"