From: Richard Kenner Date: Tue, 23 Jun 1992 21:36:55 +0000 (-0400) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9a856ec7dba14be85dab4690cc4c3da9c28a6e23;p=gcc.git *** empty log message *** From-SVN: r1245 --- diff --git a/gcc/optabs.c b/gcc/optabs.c index a4da38643a9..756d7dd9718 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -413,6 +413,66 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) delete_insns_since (last); } + /* Look for a wider mode of the same class for which we think we + can open-code the operation. */ + + if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) + && mode != OPTAB_DIRECT && mode != OPTAB_LIB) + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) + { + rtx xop0 = op0, xop1 = op1; + int no_extend = 0; + + /* For certain integer operations, we need not actually extend + the narrow operands, as long as we will truncate + the results to the same narrowness. */ + + if ((binoptab == ior_optab || binoptab == and_optab + || binoptab == xor_optab + || binoptab == add_optab || binoptab == sub_optab + || binoptab == smul_optab + || binoptab == ashl_optab || binoptab == lshl_optab) + && class == MODE_INT) + no_extend = 1; + + /* If an operand is a constant integer, we might as well + convert it since that is more efficient than using a SUBREG, + unlike the case for other operands. */ + + if (no_extend && GET_MODE (xop0) != VOIDmode) + xop0 = gen_rtx (SUBREG, wider_mode, + force_reg (GET_MODE (xop0), xop0), 0); + else + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + + if (no_extend && GET_MODE (xop1) != VOIDmode) + xop1 = gen_rtx (SUBREG, wider_mode, + force_reg (GET_MODE (xop1), xop1), 0); + else + xop1 = convert_to_mode (wider_mode, xop1, unsignedp); + + temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0, + unsignedp, OPTAB_DIRECT); + if (temp) + { + if (class != MODE_INT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, temp); + } + else + delete_insns_since (last); + } + } + /* These can be done a word at a time. */ if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) && class == MODE_INT @@ -1106,6 +1166,45 @@ expand_unop (mode, unoptab, op0, target, unsignedp) delete_insns_since (last); } + /* It can't be done in this mode. Can we open-code it in a wider mode? */ + + if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) + { + rtx xop0 = op0; + + /* For certain operations, we need not actually extend + the narrow operand, as long as we will truncate the + results to the same narrowness. */ + + if ((unoptab == neg_optab || unoptab == one_cmpl_optab) + && class == MODE_INT) + xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0); + else + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + + temp = expand_unop (wider_mode, unoptab, xop0, 0, unsignedp); + + if (temp) + { + if (class != MODE_INT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, temp); + } + else + delete_insns_since (last); + } + } + /* These can be done a word at a time. */ if (unoptab == one_cmpl_optab && class == MODE_INT