From 9ee2b2fff8e9805c42c97eb1de02dc84e7daf3d9 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Tue, 12 Apr 2011 12:51:28 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@172316 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 ++++++++ gcc/genoutput.c | 11 ++++++++++- gcc/optabs.c | 61 +++++++++++++++++++++++++++++++++++++++++++-------------- gcc/recog.h | 2 ++ 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c95d893..4a1ec50 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2011-04-12 Richard Sandiford + * 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. + +2011-04-12 Richard Sandiford + * genpreds.c (process_define_predicate): Move most processing to gensupport.c. Continue to validate the expression. * genrecog.c (did_you_mean_codes, compute_predicate_codes) diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 3e89cfd..621439f 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -66,6 +66,8 @@ along with GCC; see the file COPYING3. If not see MATCH_OPERAND; it is zero for operands that should not be changed during register elimination such as MATCH_OPERATORs. + g. `allows_mem', is true for operands that accept MEM rtxes. + The code number of an insn is simply its position in the machine description; code numbers are assigned sequentially to entries in the description, starting with code number 0. @@ -256,6 +258,8 @@ output_operand_data (void) for (d = odata; d; d = d->next) { + struct pred_data *pred; + printf (" {\n"); printf (" %s,\n", @@ -269,7 +273,12 @@ output_operand_data (void) printf (" %d,\n", d->constraint == NULL ? 1 : 0); - printf (" %d\n", d->eliminable); + printf (" %d,\n", d->eliminable); + + pred = NULL; + if (d->predicate) + pred = lookup_predicate (d->predicate); + printf (" %d\n", pred && pred->codes[MEM]); printf(" },\n"); } diff --git a/gcc/optabs.c b/gcc/optabs.c index 682b8e4..15f50f7 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7001,6 +7001,36 @@ 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, try forcing the address into a register. */ + if (MEM_P (op->value) && insn_data[(int) icode].operand[opno].allows_mem) + { + 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 +7041,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 +7067,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 +7104,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 diff --git a/gcc/recog.h b/gcc/recog.h index 0261bc6..cce1321 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -272,6 +272,8 @@ struct insn_operand_data const char is_operator; const char eliminable; + + const char allows_mem; }; /* Legal values for insn_data.output_format. Indicate what type of data -- 2.7.4