diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9997eddd0e3..d159770e946 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ Sun Feb 18 15:45:17 2001 Richard Kenner + * Makefile.in (gcse.o): Now includes ggc.h. + * gcse.c: Include ggc.h. + (want_to_gcse_p): Verify expression can be in SET as valid insn. + (try_replace_reg): Remove warning of uninitialize variable. + (process_insert_insn): Call invalid_insn_p to validate insn. + * recog.c (insn_invalid_p): Now global. + See if can make valid by adding CLOBBERs of SCRATCH only and do if so. + * recog.h (insn_invalid_p): New declaration. + * jump.c (jump_optimize_1): Only define reversed_code #ifdef HAVE_trap. * config/sparc/sparc.c (eligible_for_epilogue_delay): Don't put diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 304fbd13bf5..671107bc912 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1423,7 +1423,7 @@ cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \ real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \ $(BASIC_BLOCK_H) $(GGC_H) gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \ - flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \ + flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \ function.h output.h toplev.h sibcall.o : sibcall.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) function.h \ hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) diff --git a/gcc/gcse.c b/gcc/gcse.c index 5bb86809bad..a5c552c376e 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -159,6 +159,7 @@ Boston, MA 02111-1307, USA. */ #include "output.h" #include "function.h" #include "expr.h" +#include "ggc.h" #include "obstack.h" #define obstack_chunk_alloc gmalloc @@ -1187,13 +1188,17 @@ static int *reg_last_set; static int mem_first_set; static int mem_last_set; -/* Perform a quick check whether X, the source of a set, is something - we want to consider for GCSE. */ +/* See whether X, the source of a set, is something we want to consider for + GCSE. */ static int want_to_gcse_p (x) rtx x; { + static rtx test_insn = 0; + int num_clobbers = 0; + int icode; + switch (GET_CODE (x)) { case REG: @@ -1207,7 +1212,31 @@ want_to_gcse_p (x) break; } - return 1; + /* If this is a valid operand, we are OK. If it's VOIDmode, we aren't. */ + if (general_operand (x, GET_MODE (x))) + return 1; + else if (GET_MODE (x) == VOIDmode) + return 0; + + /* Otherwise, check if we can make a valid insn from it. First initialize + our test insn if we haven't already. */ + if (test_insn == 0) + { + test_insn + = make_insn_raw (gen_rtx_SET (VOIDmode, + gen_rtx_REG (word_mode, + FIRST_PSEUDO_REGISTER * 2), + const0_rtx)); + NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0; + ggc_add_rtx_root (&test_insn, 1); + } + + /* Now make an insn like the one we would make when GCSE'ing and see if + valid. */ + PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x)); + SET_SRC (PATTERN (test_insn)) = x; + return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0 + && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode))); } /* Return non-zero if the operands of expression X are unchanged from the @@ -3612,7 +3641,7 @@ try_replace_reg (from, to, insn) rtx from, to, insn; { rtx note = find_reg_equal_equiv_note (insn); - rtx src; + rtx src = 0; int success = 0; rtx set = single_set (insn); @@ -3640,10 +3669,10 @@ try_replace_reg (from, to, insn) if (!success) success = validate_replace_src (from, to, insn); - /* We've failed to do replacement, have a single SET, and don't already - have a note, two to add a REG_EQUAL note to not lose information. */ + /* If we've failed to do replacement, have a single SET, and don't already + have a note, add a REG_EQUAL note to not lose information. */ if (!success && note == 0 && set != 0) - note= REG_NOTES (insn) + note = REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn)); /* If there is already a NOTE, update the expression in it with our @@ -4265,13 +4294,22 @@ process_insert_insn (expr) struct expr *expr; { rtx reg = expr->reaching_reg; - rtx pat, copied_expr; - rtx first_new_insn; + rtx exp = copy_rtx (expr->expr); + rtx pat; start_sequence (); - copied_expr = copy_rtx (expr->expr); - emit_move_insn (reg, copied_expr); - first_new_insn = get_insns (); + + /* If the expression is something that's an operand, like a constant, + just copy it to a register. */ + if (general_operand (exp, GET_MODE (reg))) + emit_move_insn (reg, exp); + + /* Otherwise, make a new insn to compute this expression and make sure the + insn will be recognized (this also adds any needed CLOBBERs). Copy the + expression to make sure we don't have any sharing issues. */ + if (insn_invalid_p (emit_insn (gen_rtx_SET (VOIDmode, reg, exp)))) + abort (); + pat = gen_sequence (); end_sequence (); diff --git a/gcc/recog.c b/gcc/recog.c index d6cdf5450e4..bf8a3e37087 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -58,7 +58,6 @@ Boston, MA 02111-1307, USA. */ static void validate_replace_rtx_1 PARAMS ((rtx *, rtx, rtx, rtx)); static rtx *find_single_use_1 PARAMS ((rtx, rtx *)); static rtx *find_constant_term_loc PARAMS ((rtx *)); -static int insn_invalid_p PARAMS ((rtx)); static void validate_replace_src_1 PARAMS ((rtx *, void *)); /* Nonzero means allow operands to be volatile. @@ -217,7 +216,7 @@ validate_change (object, loc, new, in_group) if (in_group == 0 && num_changes != 0) abort (); - *loc = new; + *loc = new; /* Save the information describing this change. */ if (num_changes >= changes_allocated) @@ -260,18 +259,43 @@ validate_change (object, loc, new, in_group) /* This subroutine of apply_change_group verifies whether the changes to INSN were valid; i.e. whether INSN can still be recognized. */ -static int +int insn_invalid_p (insn) rtx insn; { - int icode = recog_memoized (insn); + rtx pat = PATTERN (insn); + int num_clobbers = 0; + /* If we are before reload and the pattern is a SET, see if we can add + clobbers. */ + int icode = recog (pat, insn, + (GET_CODE (pat) == SET + && ! reload_completed && ! reload_in_progress) + ? &num_clobbers : NULL_PTR); int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0; - if (is_asm && ! check_asm_operands (PATTERN (insn))) - return 1; - if (! is_asm && icode < 0) + + /* If this is an asm and the operand aren't legal, then fail. Likewise if + this is not an asm and the insn wasn't recognized. */ + if ((is_asm && ! check_asm_operands (PATTERN (insn))) + || (!is_asm && icode < 0)) return 1; + /* If we have to add CLOBBERs, fail if we have to add ones that reference + hard registers since our callers can't know if they are live or not. + Otherwise, add them. */ + if (num_clobbers > 0) + { + rtx newpat; + + if (added_clobbers_hard_reg_p (icode)) + return 1; + + newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1)); + XVECEXP (newpat, 0, 0) = pat; + add_clobbers (newpat, icode); + PATTERN (insn) = pat = newpat; + } + /* After reload, verify that all constraints are satisfied. */ if (reload_completed) { @@ -281,6 +305,7 @@ insn_invalid_p (insn) return 1; } + INSN_CODE (insn) = icode; return 0; } @@ -744,9 +769,11 @@ validate_replace_rtx_group (from, to, insn) /* Function called by note_uses to replace used subexpressions. */ struct validate_replace_src_data - { - rtx from, to, insn; - }; +{ + rtx from; /* Old RTX */ + rtx to; /* New RTX */ + rtx insn; /* Insn in which substitution is occurring. */ +}; static void validate_replace_src_1 (x, data) diff --git a/gcc/recog.h b/gcc/recog.h index b59d66498f0..e15a423d4dd 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -77,6 +77,7 @@ extern int recog_memoized_1 PARAMS ((rtx)); extern int check_asm_operands PARAMS ((rtx)); extern int asm_operand_ok PARAMS ((rtx, const char *)); extern int validate_change PARAMS ((rtx, rtx *, rtx, int)); +extern int insn_invalid_p PARAMS ((rtx)); extern int apply_change_group PARAMS ((void)); extern int num_validated_changes PARAMS ((void)); extern void cancel_changes PARAMS ((int));