diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/genextract.c | 17 | ||||
-rw-r--r-- | gcc/reload.c | 40 | ||||
-rw-r--r-- | gcc/reload.h | 1 | ||||
-rw-r--r-- | gcc/reload1.c | 29 | ||||
-rw-r--r-- | gcc/tree.c | 11 |
5 files changed, 76 insertions, 22 deletions
diff --git a/gcc/genextract.c b/gcc/genextract.c index 74899a33a24..121fa302f42 100644 --- a/gcc/genextract.c +++ b/gcc/genextract.c @@ -110,8 +110,8 @@ gen_insn (insn) for (; i >= 0; i--) if (!operand_seen[i]) { - printf (" recog_operand[%d] = const0_rtx;\n", i); - printf (" recog_operand_loc[%d] = &junk;\n", i); + printf (" ro[%d] = const0_rtx;\n", i); + printf (" ro_loc[%d] = &junk;\n", i); } printf (" break;\n"); } @@ -158,7 +158,7 @@ walk_rtx (x, path) case MATCH_OPERAND: case MATCH_SCRATCH: mark_operand_seen (XINT (x, 0)); - printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", + printf (" ro[%d] = *(ro_loc[%d] = &", XINT (x, 0), XINT (x, 0)); print_path (path); printf (");\n"); @@ -175,7 +175,7 @@ walk_rtx (x, path) case MATCH_OPERATOR: mark_operand_seen (XINT (x, 0)); - printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", + printf (" ro[%d] = *(ro_loc[%d]\n = &", XINT (x, 0), XINT (x, 0)); print_path (path); printf (");\n"); @@ -190,7 +190,7 @@ walk_rtx (x, path) case MATCH_PARALLEL: mark_operand_seen (XINT (x, 0)); - printf (" recog_operand[%d] = *(recog_operand_loc[%d]\n = &", + printf (" ro[%d] = *(ro_loc[%d]\n = &", XINT (x, 0), XINT (x, 0)); print_path (path); printf (");\n"); @@ -350,11 +350,14 @@ from the machine description file `md'. */\n\n"); printf ("extern rtx *recog_operand_loc[];\n"); printf ("extern rtx *recog_dup_loc[];\n"); printf ("extern char recog_dup_num[];\n"); - printf ("extern void fatal_insn_not_found ();\n\n"); + printf ("extern\n#ifdef __GNUC__\nvolatile\n#endif\n"); + printf ("void fatal_insn_not_found ();\n\n"); printf ("void\ninsn_extract (insn)\n"); printf (" rtx insn;\n"); printf ("{\n"); + printf (" register rtx *ro = recog_operand;\n"); + printf (" register rtx **ro_loc = recog_operand_loc;\n"); printf (" int insn_code = INSN_CODE (insn);\n"); printf (" if (insn_code == -1) fatal_insn_not_found (insn);\n"); printf (" insn = PATTERN (insn);\n"); @@ -401,7 +404,7 @@ from the machine description file `md'. */\n\n"); printf ("#if __GNUC__ > 1 && !defined (bcopy)\n"); printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n"); printf ("#endif\n"); - printf (" bcopy (&XVECEXP (insn, 0, 0), recog_operand,\n"); + printf (" bcopy (&XVECEXP (insn, 0, 0), ro,\n"); printf (" sizeof (rtx) * XVECLEN (insn, 0));\n"); printf (" break;\n"); } diff --git a/gcc/reload.c b/gcc/reload.c index f7f1fc33518..05c1a2737dc 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4179,6 +4179,46 @@ copy_replacements (x, y) } } +/* If LOC was scheduled to be replaced by something, return the replacement. + Otherwise, return *LOC. */ + +rtx +find_replacement (loc) + rtx *loc; +{ + struct replacement *r; + + for (r = &replacements[0]; r < &replacements[n_replacements]; r++) + { + rtx reloadreg = reload_reg_rtx[r->what]; + + if (reloadreg && r->where == loc) + { + if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode) + reloadreg = gen_rtx (REG, r->mode, REGNO (reloadreg)); + + return reloadreg; + } + else if (reloadreg && r->subreg_loc == loc) + { + /* RELOADREG must be either a REG or a SUBREG. + + ??? Is it actually still ever a SUBREG? If so, why? */ + + if (GET_CODE (reloadreg) == REG) + return gen_rtx (REG, GET_MODE (*loc), + REGNO (reloadreg) + SUBREG_WORD (*loc)); + else if (GET_MODE (reloadreg) == GET_MODE (*loc)) + return reloadreg; + else + return gen_rtx (SUBREG, GET_MODE (*loc), SUBREG_REG (reloadreg), + SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc)); + } + } + + return *loc; +} + /* Return nonzero if register in range [REGNO, ENDREGNO) appears either explicitly or implicitly in X other than being stored into. diff --git a/gcc/reload.h b/gcc/reload.h index 1f1fed7cfa4..e7b21446c46 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -110,3 +110,4 @@ extern void find_reloads (); extern void subst_reloads (); extern rtx eliminate_regs (); extern rtx gen_input_reload (); +extern rtx find_replacement (); diff --git a/gcc/reload1.c b/gcc/reload1.c index fea5758eacb..bac9c2f29e1 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -5428,9 +5428,12 @@ gen_input_reload (reloadreg, in, before_insn) `insn_extract'and it is simpler to emit and then delete the insn if not valid than to dummy things up. */ - rtx move_operand, other_operand, insn; + rtx op0, op1, tem, insn; int code; + op0 = find_replacement (&XEXP (in, 0)); + op1 = find_replacement (&XEXP (in, 1)); + /* Since constraint checking is strict, commutativity won't be checked, so we need to do that here to avoid spurious failure if the add instruction is two-address and the second operand @@ -5440,7 +5443,10 @@ gen_input_reload (reloadreg, in, before_insn) if (GET_CODE (XEXP (in, 1)) == REG && REGNO (reloadreg) == REGNO (XEXP (in, 1))) - in = gen_rtx (PLUS, GET_MODE (in), XEXP (in, 1), XEXP (in, 0)); + tem = op0, op0 = op1, op1 = tem; + + if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1)) + in = gen_rtx (PLUS, GET_MODE (in), op0, op1); insn = emit_insn_before (gen_rtx (SET, VOIDmode, reloadreg, in), before_insn); @@ -5463,23 +5469,20 @@ gen_input_reload (reloadreg, in, before_insn) /* If that failed, we must use a conservative two-insn sequence. use move to copy constant, MEM, or pseudo register to the reload - register since "move" will be able to handle arbitrary operand, unlike - add which can't, in general. Then add the registers. + register since "move" will be able to handle an arbitrary operand, + unlike add which can't, in general. Then add the registers. If there is another way to do this for a specific machine, a DEFINE_PEEPHOLE should be specified that recognizes the sequence we emit below. */ - if (CONSTANT_P (XEXP (in, 1)) - || GET_CODE (XEXP (in, 1)) == MEM - || (GET_CODE (XEXP (in, 1)) == REG - && REGNO (XEXP (in, 1)) >= FIRST_PSEUDO_REGISTER)) - move_operand = XEXP (in, 1), other_operand = XEXP (in, 0); - else - move_operand = XEXP (in, 0), other_operand = XEXP (in, 1); + if (CONSTANT_P (op1) || GET_CODE (op1) == MEM + || (GET_CODE (op1) == REG + && REGNO (op1) >= FIRST_PSEUDO_REGISTER)) + tem = op0, op0 = op1, op1 = tem; - emit_insn_before (gen_move_insn (reloadreg, move_operand), before_insn); - emit_insn_before (gen_add2_insn (reloadreg, other_operand), before_insn); + emit_insn_before (gen_move_insn (reloadreg, op0), before_insn); + emit_insn_before (gen_add2_insn (reloadreg, op1), before_insn); } /* If IN is a simple operand, use gen_move_insn. */ diff --git a/gcc/tree.c b/gcc/tree.c index c6a74a11c6d..2b914a66d73 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1742,10 +1742,12 @@ save_expr (expr) /* If the tree evaluates to a constant, then we don't want to hide that fact (i.e. this allows further folding, and direct checks for constants). + However, a read-only object that has side effects cannot be bypassed. Since it is no problem to reevaluate literals, we just return the literal node. */ - if (TREE_CONSTANT (t) || TREE_READONLY (t) || TREE_CODE (t) == SAVE_EXPR) + if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t)) + || TREE_CODE (t) == SAVE_EXPR) return t; t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL); @@ -1852,7 +1854,12 @@ stabilize_reference_1 (e) register int length; register enum tree_code code = TREE_CODE (e); - if (TREE_CONSTANT (e) || TREE_READONLY (e) || code == SAVE_EXPR) + /* We cannot ignore const expressions because it might be a reference + to a const array but whose index contains side-effects. But we can + ignore things that are actual constant or that already have been + handled by this function. */ + + if (TREE_CONSTANT (e) || code == SAVE_EXPR) return e; switch (TREE_CODE_CLASS (code)) |