This small patch to rs6000_rtx_costs considerably improves code generated for large constants in 64-bit code, teaching gcc that it is better to load a constant from memory than to generate a sequence of up to five dependent instructions. Note that the rs6000 backend does generate large constants as loads from memory at expand time but optimisation passes replace them with SETs of the value due to not having correct costs.
PR 94393 * config/rs6000/rs6000.c (rs6000_rtx_costs): Cost multi-insn constants. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 15a806fe307..76aedbfae6f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21343,7 +21343,9 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code, switch (code) { - /* On the RS/6000, if it is valid in the insn, it is free. */ + /* (reg) is costed at zero by rtlanal.c:rtx_cost. That sets a + baseline for rtx costs: If a constant is valid in an insn, + it is free. */ case CONST_INT: if (((outer_code == SET || outer_code == PLUS @@ -21404,6 +21406,17 @@ rs6000_rtx_costs (rtx x, machine_mode mode, int outer_code, case CONST_DOUBLE: case CONST_WIDE_INT: + /* Subtract one insn here for consistency with the above code + that returns one less than the actual number of insns for + SETs. Don't subtract one for other than SETs, because other + operations will require the constant to be loaded to a + register before performing the operation. All special cases + for codes other than SET must be handled before we get + here. */ + *total = COSTS_N_INSNS (num_insns_constant (x, mode) + - (outer_code == SET ? 1 : 0)); + return true; + case CONST: case HIGH: case SYMBOL_REF: