From: Roger Sayle Date: Wed, 26 Aug 2020 06:21:08 +0000 (+0100) Subject: hppa: PR middle-end/87256: Improved hppa_rtx_costs avoids synth_mult madness. X-Git-Tag: releases/gcc-10.3.0~990 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed1e7a6a8ad6903ee952e82ac9ddac01efb286dd;p=thirdparty%2Fgcc.git hppa: PR middle-end/87256: Improved hppa_rtx_costs avoids synth_mult madness. Backport from master: 2020-08-26 Roger Sayle gcc/ChangeLog PR middle-end/87256 * config/pa/pa.c (hppa_rtx_costs_shadd_p): New helper function to check for coefficients supported by shNadd and shladd,l. (hppa_rtx_costs): Rewrite to avoid using estimates based upon FACTOR and enable recursing deeper into RTL expressions. * config/pa/pa.md (shd_internal): Fix define_expand to provide gen_shd_internal. --- diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 711234e597a5..55185aab6504 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -1492,6 +1492,33 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIBUTE_UNUSED, } } +/* Return true if X represents a (possibly non-canonical) shNadd pattern. + The machine mode of X is known to be SImode or DImode. */ + +static bool +hppa_rtx_costs_shadd_p (rtx x) +{ + if (GET_CODE (x) != PLUS + || !REG_P (XEXP (x, 1))) + return false; + rtx op0 = XEXP (x, 0); + if (GET_CODE (op0) == ASHIFT + && CONST_INT_P (XEXP (op0, 1)) + && REG_P (XEXP (op0, 0))) + { + unsigned HOST_WIDE_INT x = UINTVAL (XEXP (op0, 1)); + return x == 1 || x == 2 || x == 3; + } + if (GET_CODE (op0) == MULT + && CONST_INT_P (XEXP (op0, 1)) + && REG_P (XEXP (op0, 0))) + { + unsigned HOST_WIDE_INT x = UINTVAL (XEXP (op0, 1)); + return x == 2 || x == 4 || x == 8; + } + return false; +} + /* Compute a (partial) cost for rtx X. Return true if the complete cost has been computed, and false if subexpressions should be scanned. In either case, *TOTAL contains the cost result. */ @@ -1499,15 +1526,16 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIBUTE_UNUSED, static bool hppa_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, - int *total, bool speed ATTRIBUTE_UNUSED) + int *total, bool speed) { - int factor; int code = GET_CODE (x); switch (code) { case CONST_INT: - if (INTVAL (x) == 0) + if (outer_code == SET) + *total = COSTS_N_INSNS (1); + else if (INTVAL (x) == 0) *total = 0; else if (INT_14_BITS (x)) *total = 1; @@ -1530,32 +1558,35 @@ hppa_rtx_costs (rtx x, machine_mode mode, int outer_code, && outer_code != SET) *total = 0; else - *total = 8; + *total = 8; return true; case MULT: if (GET_MODE_CLASS (mode) == MODE_FLOAT) { *total = COSTS_N_INSNS (3); - return true; } - - /* A mode size N times larger than SImode needs O(N*N) more insns. */ - factor = GET_MODE_SIZE (mode) / 4; - if (factor == 0) - factor = 1; - - if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT) - *total = factor * factor * COSTS_N_INSNS (8); + else if (mode == DImode) + { + if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT) + *total = COSTS_N_INSNS (32); + else + *total = COSTS_N_INSNS (80); + } else - *total = factor * factor * COSTS_N_INSNS (20); - return true; + { + if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT) + *total = COSTS_N_INSNS (8); + else + *total = COSTS_N_INSNS (20); + } + return REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)); case DIV: if (GET_MODE_CLASS (mode) == MODE_FLOAT) { *total = COSTS_N_INSNS (14); - return true; + return false; } /* FALLTHRU */ @@ -1563,34 +1594,107 @@ hppa_rtx_costs (rtx x, machine_mode mode, int outer_code, case MOD: case UMOD: /* A mode size N times larger than SImode needs O(N*N) more insns. */ - factor = GET_MODE_SIZE (mode) / 4; - if (factor == 0) - factor = 1; - - *total = factor * factor * COSTS_N_INSNS (60); - return true; + if (mode == DImode) + *total = COSTS_N_INSNS (240); + else + *total = COSTS_N_INSNS (60); + return REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)); case PLUS: /* this includes shNadd insns */ case MINUS: if (GET_MODE_CLASS (mode) == MODE_FLOAT) + *total = COSTS_N_INSNS (3); + else if (mode == DImode) { - *total = COSTS_N_INSNS (3); - return true; + if (TARGET_64BIT) + { + *total = COSTS_N_INSNS (1); + /* Handle shladd,l instructions. */ + if (hppa_rtx_costs_shadd_p (x)) + return true; + } + else + *total = COSTS_N_INSNS (2); } - - /* A size N times larger than UNITS_PER_WORD needs N times as - many insns, taking N times as long. */ - factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD; - if (factor == 0) - factor = 1; - *total = factor * COSTS_N_INSNS (1); - return true; + else + { + *total = COSTS_N_INSNS (1); + /* Handle shNadd instructions. */ + if (hppa_rtx_costs_shadd_p (x)) + return true; + } + return REG_P (XEXP (x, 0)) + && (REG_P (XEXP (x, 1)) + || CONST_INT_P (XEXP (x, 1))); case ASHIFT: + if (mode == DImode) + { + if (TARGET_64BIT) + *total = COSTS_N_INSNS (3); + else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) + { + *total = COSTS_N_INSNS (2); + return true; + } + else if (speed) + *total = COSTS_N_INSNS (13); + else + *total = COSTS_N_INSNS (18); + } + else if (TARGET_64BIT) + *total = COSTS_N_INSNS (4); + else + *total = COSTS_N_INSNS (2); + return REG_P (XEXP (x, 0)) + && (REG_P (XEXP (x, 1)) + || CONST_INT_P (XEXP (x, 1))); + case ASHIFTRT: + if (mode == DImode) + { + if (TARGET_64BIT) + *total = COSTS_N_INSNS (3); + else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) + { + *total = COSTS_N_INSNS (2); + return true; + } + else if (speed) + *total = COSTS_N_INSNS (14); + else + *total = COSTS_N_INSNS (19); + } + else if (TARGET_64BIT) + *total = COSTS_N_INSNS (4); + else + *total = COSTS_N_INSNS (2); + return REG_P (XEXP (x, 0)) + && (REG_P (XEXP (x, 1)) + || CONST_INT_P (XEXP (x, 1))); + case LSHIFTRT: - *total = COSTS_N_INSNS (1); - return true; + if (mode == DImode) + { + if (TARGET_64BIT) + *total = COSTS_N_INSNS (2); + else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) + { + *total = COSTS_N_INSNS (2); + return true; + } + else if (speed) + *total = COSTS_N_INSNS (12); + else + *total = COSTS_N_INSNS (15); + } + else if (TARGET_64BIT) + *total = COSTS_N_INSNS (3); + else + *total = COSTS_N_INSNS (2); + return REG_P (XEXP (x, 0)) + && (REG_P (XEXP (x, 1)) + || CONST_INT_P (XEXP (x, 1))); default: return false; diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index e7b763555271..713ff175445c 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -6423,15 +6423,15 @@ { if (REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT) { - unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]); + unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]); if (shift >= 1 && shift <= 31) { rtx dst = operands[0]; rtx src = force_reg (DImode, operands[1]); emit_insn (gen_shd_internal (gen_highpart (SImode, dst), - gen_highpart (SImode, src), - GEN_INT (32-shift), gen_lowpart (SImode, src), + GEN_INT (32-shift), + gen_highpart (SImode, src), GEN_INT (shift))); emit_insn (gen_ashlsi3 (gen_lowpart (SImode, dst), gen_lowpart (SImode, src),