aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2011-03-24 17:23:18 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-03-24 17:23:18 +0000
commit2b99b2b8d2300ae0f11c53920ae854873acdcf16 (patch)
tree1b8f59638c3b837c02c39ef781ff7d28edb5799c /gcc/optabs.c
parent1e2c3ec4411f7f51cafcafedad83e32049fb9686 (diff)
downloadgcc-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.c80
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;