diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 28 |
2 files changed, 23 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3e89d0b999e..66406b3d183 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-07-27 Oleg Endo <olegendo@gcc.gnu.org> + + 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. + 2012-07-27 Richard Guenther <rguenther@suse.de> * tree-cfg.c (gimple_can_merge_blocks_p): Do more fine-grained diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 477d59c8de1..8edbb34e059 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -2859,26 +2859,22 @@ shiftcosts (rtx x) { 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 @@ shiftcosts (rtx x) 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 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, 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: |