From 62442ab9cb306b379718f9ed797b7c60c40df6c8 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 31 Aug 2007 14:10:35 +0000 Subject: [PATCH] optabs.c (shift_optab_p, [...]): New functions, split out from expand_binop. gcc/ * optabs.c (shift_optab_p, commutative_optab_p): New functions, split out from expand_binop. (avoid_expensive_constant): New function. (expand_binop_directly): Remove commutative_op argument and call cummutative_optab_p instead. Do not change op0 or op1 when swapping xop0 and xop1. Apply avoid_expensive_constant to each argument after potential swapping. Enforce the canonical order of commutative operands. (expand_binop): Use shift_optab_p and commutative_optab_p. Update the calls to expand_binop_directly. Only force constants into registers when widening an operation. Only swap operands once a direct expansion has been rejected. (expand_twoval_binop): Only force constants into registers when using a direct expansion. From-SVN: r127991 --- gcc/ChangeLog | 17 ++++++ gcc/optabs.c | 187 ++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 128 insertions(+), 76 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8e54cb943b2..efbaba08c57 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2007-08-31 Richard Sandiford + + * optabs.c (shift_optab_p, commutative_optab_p): New functions, + split out from expand_binop. + (avoid_expensive_constant): New function. + (expand_binop_directly): Remove commutative_op argument and + call cummutative_optab_p instead. Do not change op0 or op1 + when swapping xop0 and xop1. Apply avoid_expensive_constant + to each argument after potential swapping. Enforce the + canonical order of commutative operands. + (expand_binop): Use shift_optab_p and commutative_optab_p. + Update the calls to expand_binop_directly. Only force constants + into registers when widening an operation. Only swap operands + once a direct expansion has been rejected. + (expand_twoval_binop): Only force constants into registers when + using a direct expansion. + 2007-08-31 Maxim Kuvyrkov * sched-deps.c (update_dep): Mark arguments with ATTRIBUTE_UNUSED. diff --git a/gcc/optabs.c b/gcc/optabs.c index f2b47fc4f68..6b292638c89 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1246,6 +1246,56 @@ swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1) return rtx_equal_p (op1, target); } +/* Return true if BINOPTAB implements a shift operation. */ + +static bool +shift_optab_p (optab binoptab) +{ + switch (binoptab->code) + { + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + case ROTATE: + case ROTATERT: + return true; + + default: + return false; + } +} + +/* Return true if BINOPTAB implements a commutatative binary operation. */ + +static bool +commutative_optab_p (optab binoptab) +{ + return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH + || binoptab == smul_widen_optab + || binoptab == umul_widen_optab + || binoptab == smul_highpart_optab + || binoptab == umul_highpart_optab); +} + +/* X is to be used in mode MODE as an operand to BINOPTAB. If we're + optimizing, and if the operand is a constant that costs more than + 1 instruction, force the constant into a register and return that + register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */ + +static rtx +avoid_expensive_constant (enum machine_mode mode, optab binoptab, + rtx x, bool unsignedp) +{ + if (optimize + && CONSTANT_P (x) + && rtx_cost (x, binoptab->code) > COSTS_N_INSNS (1)) + { + if (GET_MODE (x) != VOIDmode) + x = convert_modes (mode, VOIDmode, x, unsignedp); + x = force_reg (mode, x); + } + return x; +} /* Helper function for expand_binop: handle the case where there is an insn that directly implements the indicated operation. @@ -1254,55 +1304,72 @@ static rtx expand_binop_directly (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods, - int commutative_op, rtx last) + rtx last) { int icode = (int) optab_handler (binoptab, mode)->insn_code; enum machine_mode mode0 = insn_data[icode].operand[1].mode; enum machine_mode mode1 = insn_data[icode].operand[2].mode; enum machine_mode tmp_mode; + bool commutative_p; rtx pat; rtx xop0 = op0, xop1 = op1; rtx temp; + rtx swap; if (target) temp = target; else temp = gen_reg_rtx (mode); - + /* If it is a commutative operator and the modes would match if we would swap the operands, we can save the conversions. */ - if (commutative_op) + commutative_p = commutative_optab_p (binoptab); + if (commutative_p + && GET_MODE (xop0) != mode0 && GET_MODE (xop1) != mode1 + && GET_MODE (xop0) == mode1 && GET_MODE (xop1) == mode1) { - if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1 - && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0) - { - rtx tmp; - - tmp = op0; op0 = op1; op1 = tmp; - tmp = xop0; xop0 = xop1; xop1 = tmp; - } + swap = xop0; + xop0 = xop1; + xop1 = swap; } + /* If we are optimizing, force expensive constants into a register. */ + xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp); + 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 (op0) != mode0 && mode0 != VOIDmode) + if (GET_MODE (xop0) != mode0 && mode0 != VOIDmode) xop0 = convert_modes (mode0, - GET_MODE (op0) != VOIDmode - ? GET_MODE (op0) + GET_MODE (xop0) != VOIDmode + ? GET_MODE (xop0) : mode, xop0, unsignedp); - if (GET_MODE (op1) != mode1 && mode1 != VOIDmode) + if (GET_MODE (xop1) != mode1 && mode1 != VOIDmode) xop1 = convert_modes (mode1, - GET_MODE (op1) != VOIDmode - ? GET_MODE (op1) + 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. */ @@ -1375,12 +1442,6 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, enum mode_class class; enum machine_mode wider_mode; rtx temp; - int commutative_op = 0; - int shift_op = (binoptab->code == ASHIFT - || binoptab->code == ASHIFTRT - || binoptab->code == LSHIFTRT - || binoptab->code == ROTATE - || binoptab->code == ROTATERT); rtx entry_last = get_last_insn (); rtx last; @@ -1395,54 +1456,16 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, binoptab = add_optab; } - /* If we are inside an appropriately-short loop and we are optimizing, - force expensive constants into a register. */ - if (CONSTANT_P (op0) && optimize - && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1)) - { - if (GET_MODE (op0) != VOIDmode) - op0 = convert_modes (mode, VOIDmode, op0, unsignedp); - op0 = force_reg (mode, op0); - } - - if (CONSTANT_P (op1) && optimize - && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1)) - { - if (GET_MODE (op1) != VOIDmode) - op1 = convert_modes (mode, VOIDmode, op1, unsignedp); - op1 = force_reg (mode, op1); - } - /* Record where to delete back to if we backtrack. */ last = get_last_insn (); - /* 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 (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH - || binoptab == smul_widen_optab - || binoptab == umul_widen_optab - || binoptab == smul_highpart_optab - || binoptab == umul_highpart_optab) - { - commutative_op = 1; - - if (swap_commutative_operands_with_target (target, op0, op1)) - { - temp = op1; - op1 = op0; - op0 = temp; - } - } - /* If we can do it with a three-operand insn, do so. */ if (methods != OPTAB_MUST_WIDEN && optab_handler (binoptab, mode)->insn_code != CODE_FOR_nothing) { temp = expand_binop_directly (mode, binoptab, op0, op1, target, - unsignedp, methods, commutative_op, last); + unsignedp, methods, last); if (temp) return temp; } @@ -1469,8 +1492,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, NULL_RTX, unsignedp, OPTAB_DIRECT); temp = expand_binop_directly (mode, otheroptab, op0, newop1, - target, unsignedp, methods, - commutative_op, last); + target, unsignedp, methods, last); if (temp) return temp; } @@ -1529,7 +1551,14 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, || binoptab == add_optab || binoptab == sub_optab || binoptab == smul_optab || binoptab == ashl_optab) && class == MODE_INT) - no_extend = 1; + { + no_extend = 1; + xop0 = avoid_expensive_constant (mode, binoptab, + xop0, unsignedp); + if (binoptab != ashl_optab) + xop1 = avoid_expensive_constant (mode, binoptab, + xop1, unsignedp); + } xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend); @@ -1558,6 +1587,18 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, } } + /* 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_optab_p (binoptab) + && swap_commutative_operands_with_target (target, op0, op1)) + { + temp = op1; + op1 = op0; + op0 = temp; + } + /* These can be done a word at a time. */ if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) && class == MODE_INT @@ -1980,7 +2021,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, start_sequence (); - if (shift_op) + if (shift_optab_p (binoptab)) { op1_mode = targetm.libgcc_shift_count_mode (); /* Specify unsigned here, @@ -2256,16 +2297,6 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, class = GET_MODE_CLASS (mode); - /* If we are inside an appropriately-short loop and we are optimizing, - force expensive constants into a register. */ - if (CONSTANT_P (op0) && optimize - && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1)) - op0 = force_reg (mode, op0); - - if (CONSTANT_P (op1) && optimize - && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1)) - op1 = force_reg (mode, op1); - if (!targ0) targ0 = gen_reg_rtx (mode); if (!targ1) @@ -2282,6 +2313,10 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, rtx pat; rtx xop0 = op0, xop1 = op1; + /* If we are optimizing, force expensive constants into a register. */ + xop0 = avoid_expensive_constant (mode0, binoptab, xop0, unsignedp); + 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 -- 2.11.4.GIT