diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2011-04-15 09:35:03 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2011-04-15 09:35:03 +0000 |
commit | 4fd3a105984e477c629b22c68ab57b169ee2e337 (patch) | |
tree | eb9aba60245750798ddf9fd86d5946bc2c46db01 /gcc/optabs.c | |
parent | b98b952feb6aea1e33371d0b64a9622603ac146e (diff) | |
download | gcc-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.c | 66 |
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 |