Hello, This adjusts the cost calculations for shifts on SH. I tried out Richard's advice ( http://gcc.gnu.org/ml/gcc-patches/2012-07/msg01206.html ) and it seems to work OK to just leave out the mentioned CONST_INT_P case. Tested on rev 189870 with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m2a-single/-mb,-m4/-ml,-m4/-mb,-m4-single/-ml, -m4-single/-mb,-m4a-single/-ml,-m4a-single/-mb}"
and no new failures. I've also confirmed that the example function in tree-switch-conversion.c:184 now is transformed as expected. The CSiBE set shows a few improvements here and there, where these kind of transformations can be applied for when dynamic shifts are available (SH3+). For SH2 (no dynamic shifts) there also seem to be some minor improvements. OK? Cheers, Oleg ChangeLog PR target/54089 * config/sh/sh.c (shiftcosts): Remove case where first operand is a const_int. Move COSTS_N_INSNS usage into caller ... (sh_rtx_costs) ... here. Return false when shiftcosts cannot be calculated instead of MAX_COST.
Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 189877) +++ gcc/config/sh/sh.c (working copy) @@ -2859,26 +2859,22 @@ { int value; - /* There is no pattern for constant first operand. */ - if (CONST_INT_P (XEXP (x, 0))) - return MAX_COST; - if (TARGET_SHMEDIA) - return COSTS_N_INSNS (1); + return 1; if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) { if (GET_MODE (x) == DImode && CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 1) - return COSTS_N_INSNS (2); + return 2; /* Everything else is invalid, because there is no pattern for it. */ - return MAX_COST; + return -1; } /* If shift by a non constant, then this will be expensive. */ if (!CONST_INT_P (XEXP (x, 1))) - return COSTS_N_INSNS (SH_DYNAMIC_SHIFT_COST); + return SH_DYNAMIC_SHIFT_COST; /* Otherwise, return the true cost in instructions. Cope with out of range shift counts more or less arbitrarily. */ @@ -2887,13 +2883,14 @@ if (GET_CODE (x) == ASHIFTRT) { int cost = ashiftrt_insns[value]; - /* If SH3, then we put the constant in a reg and use shad. */ + /* If dynamic shifts are available and profitable in this case, then we + put the constant in a reg and use shad. */ if (cost > 1 + SH_DYNAMIC_SHIFT_COST) cost = 1 + SH_DYNAMIC_SHIFT_COST; - return COSTS_N_INSNS (cost); + return cost; } else - return COSTS_N_INSNS (shift_insns[value]); + return shift_insns[value]; } /* Return the cost of an AND/XOR/IOR operation. */ @@ -3147,8 +3144,13 @@ case ASHIFT: case ASHIFTRT: case LSHIFTRT: - *total = shiftcosts (x); - return true; + { + int cost = shiftcosts (x); + if (cost < 0) + return false; + *total = COSTS_N_INSNS (cost); + return true; + } case DIV: case UDIV: