summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2011-04-15 09:35:03 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-04-15 09:35:03 +0000
commit4fd3a105984e477c629b22c68ab57b169ee2e337 (patch)
treeeb9aba60245750798ddf9fd86d5946bc2c46db01 /gcc/optabs.c
parentb98b952feb6aea1e33371d0b64a9622603ac146e (diff)
downloadgcc-4fd3a105984e477c629b22c68ab57b169ee2e337.tar.gz
recog.h (insn_operand_data): Add an "allows_mem" field.
gcc/ * recog.h (insn_operand_data): Add an "allows_mem" field. * genoutput.c (output_operand_data): Initialize it. * optabs.c (maybe_legitimize_operand_same_code): New function. (maybe_legitimize_operand): Use it when matching the original op->value. From-SVN: r172478
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 682b8e40f7c..34bd731c3b3 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -7001,6 +7001,41 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
(operand, insn_data[(int) icode].operand[opno].mode)));
}
+/* Like maybe_legitimize_operand, but do not change the code of the
+ current rtx value. */
+
+static bool
+maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno,
+ struct expand_operand *op)
+{
+ /* See if the operand matches in its current form. */
+ if (insn_operand_matches (icode, opno, op->value))
+ return true;
+
+ /* If the operand is a memory whose address has no side effects,
+ try forcing the address into a register. The check for side
+ effects is important because force_reg cannot handle things
+ like auto-modified addresses. */
+ if (insn_data[(int) icode].operand[opno].allows_mem
+ && MEM_P (op->value)
+ && !side_effects_p (XEXP (op->value, 0)))
+ {
+ rtx addr, mem, last;
+
+ last = get_last_insn ();
+ addr = force_reg (Pmode, XEXP (op->value, 0));
+ mem = replace_equiv_address (op->value, addr);
+ if (insn_operand_matches (icode, opno, mem))
+ {
+ op->value = mem;
+ return true;
+ }
+ delete_insns_since (last);
+ }
+
+ return false;
+}
+
/* Try to make OP match operand OPNO of instruction ICODE. Return true
on success, storing the new operand value back in OP. */
@@ -7011,22 +7046,25 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
enum machine_mode mode, imode;
bool old_volatile_ok, result;
- old_volatile_ok = volatile_ok;
mode = op->mode;
- result = false;
switch (op->type)
{
case EXPAND_FIXED:
+ old_volatile_ok = volatile_ok;
volatile_ok = true;
- break;
+ result = maybe_legitimize_operand_same_code (icode, opno, op);
+ volatile_ok = old_volatile_ok;
+ return result;
case EXPAND_OUTPUT:
gcc_assert (mode != VOIDmode);
- if (!op->value
- || op->value == const0_rtx
- || GET_MODE (op->value) != mode
- || !insn_operand_matches (icode, opno, op->value))
- op->value = gen_reg_rtx (mode);
+ if (op->value
+ && op->value != const0_rtx
+ && GET_MODE (op->value) == mode
+ && maybe_legitimize_operand_same_code (icode, opno, op))
+ return true;
+
+ op->value = gen_reg_rtx (mode);
break;
case EXPAND_INPUT:
@@ -7034,9 +7072,10 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
gcc_assert (mode != VOIDmode);
gcc_assert (GET_MODE (op->value) == VOIDmode
|| GET_MODE (op->value) == mode);
- result = insn_operand_matches (icode, opno, op->value);
- if (!result)
- op->value = copy_to_mode_reg (mode, op->value);
+ if (maybe_legitimize_operand_same_code (icode, opno, op))
+ return true;
+
+ op->value = copy_to_mode_reg (mode, op->value);
break;
case EXPAND_CONVERT_TO:
@@ -7070,10 +7109,7 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
goto input;
break;
}
- if (!result)
- result = insn_operand_matches (icode, opno, op->value);
- volatile_ok = old_volatile_ok;
- return result;
+ return insn_operand_matches (icode, opno, op->value);
}
/* Make OP describe an input operand that should have the same value