summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/genextract.c17
-rw-r--r--gcc/reload.c40
-rw-r--r--gcc/reload.h1
-rw-r--r--gcc/reload1.c29
-rw-r--r--gcc/tree.c11
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))