diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2011-03-24 17:23:18 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2011-03-24 17:23:18 +0000 |
commit | 2b99b2b8d2300ae0f11c53920ae854873acdcf16 (patch) | |
tree | 1b8f59638c3b837c02c39ef781ff7d28edb5799c /gcc/optabs.c | |
parent | 1e2c3ec4411f7f51cafcafedad83e32049fb9686 (diff) | |
download | gcc-2b99b2b8d2300ae0f11c53920ae854873acdcf16.zip gcc-2b99b2b8d2300ae0f11c53920ae854873acdcf16.tar.gz gcc-2b99b2b8d2300ae0f11c53920ae854873acdcf16.tar.bz2 |
re PR rtl-optimization/48263 (build fails for cris-elf in libgfortran)
gcc/
PR rtl-optimization/48263
* optabs.c (expand_binop_directly): Reinstate convert_modes code
and original commutative_p handling. Use maybe_gen_insn.
From-SVN: r171418
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 80 |
1 files changed, 48 insertions, 32 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index d1cfd3a..a133596b3 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1269,6 +1269,38 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, if (!shift_optab_p (binoptab)) xop1 = avoid_expensive_constant (mode1, binoptab, xop1, unsignedp); + /* In case the insn wants input operands in modes different from + those of the actual operands, convert the operands. It would + seem that we don't need to convert CONST_INTs, but we do, so + that they're properly zero-extended, sign-extended or truncated + for their mode. */ + + if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode) + xop0 = convert_modes (mode0, + GET_MODE (xop0) != VOIDmode + ? GET_MODE (xop0) + : mode, + xop0, unsignedp); + + if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode) + xop1 = convert_modes (mode1, + GET_MODE (xop1) != VOIDmode + ? GET_MODE (xop1) + : mode, + xop1, unsignedp); + + /* If operation is commutative, + try to make the first operand a register. + Even better, try to make it the same as the target. + Also try to make the last operand a constant. */ + if (commutative_p + && swap_commutative_operands_with_target (target, xop0, xop1)) + { + swap = xop1; + xop1 = xop0; + xop0 = swap; + } + /* Now, if insn's predicates don't allow our operands, put them into pseudo regs. */ @@ -1291,41 +1323,25 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, tmp_mode = mode; create_output_operand (&ops[0], target, tmp_mode); - create_convert_operand_from (&ops[1], xop0, mode, unsignedp); - create_convert_operand_from (&ops[2], xop1, mode, unsignedp); - if (maybe_legitimize_operands (icode, 0, 3, ops)) - { - /* If operation is commutative, - try to make the first operand a register. - Even better, try to make it the same as the target. - Also try to make the last operand a constant. */ - if (commutative_p - && swap_commutative_operands_with_target (ops[0].value, ops[1].value, - ops[2].value)) + create_input_operand (&ops[1], xop0, mode0); + create_input_operand (&ops[2], xop1, mode1); + pat = maybe_gen_insn (icode, 3, ops); + if (pat) + { + /* If PAT is composed of more than one insn, try to add an appropriate + REG_EQUAL note to it. If we can't because TEMP conflicts with an + operand, call expand_binop again, this time without a target. */ + if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX + && ! add_equal_note (pat, ops[0].value, binoptab->code, + ops[1].value, ops[2].value)) { - swap = ops[2].value; - ops[2].value = ops[1].value; - ops[1].value = swap; + delete_insns_since (last); + return expand_binop (mode, binoptab, op0, op1, NULL_RTX, + unsignedp, methods); } - pat = GEN_FCN (icode) (ops[0].value, ops[1].value, ops[2].value); - if (pat) - { - /* If PAT is composed of more than one insn, try to add an appropriate - REG_EQUAL note to it. If we can't because TEMP conflicts with an - operand, call expand_binop again, this time without a target. */ - if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX - && ! add_equal_note (pat, ops[0].value, binoptab->code, - ops[1].value, ops[2].value)) - { - delete_insns_since (last); - return expand_binop (mode, binoptab, op0, op1, NULL_RTX, - unsignedp, methods); - } - - emit_insn (pat); - return ops[0].value; - } + emit_insn (pat); + return ops[0].value; } delete_insns_since (last); return NULL_RTX; |