From 0d2ab259bc519429c521804f6734a2a294a5269d Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Tue, 23 May 2023 18:49:19 +0200 Subject: [PATCH] Improve cost computation for single-bit bit insertions. Some miscomputation of rtx_costs lead to sub-optimal code for single-bit bit insertions. This patch implements TARGET_INSN_COST, which has a chance to see the whole insn during insn combination; in particular the SET_DEST of (set (zero_extract (...) ...)). gcc/ * config/avr/avr.cc (avr_insn_cost): New static function. (TARGET_INSN_COST): Define to that function. --- gcc/config/avr/avr.cc | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index c193430cf07..5410c194953 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -11515,6 +11515,52 @@ avr_rtx_costs (rtx x, machine_mode mode, int outer_code, } +/* Implement `TARGET_INSN_COST'. */ +/* For some insns, it is not enough to look at the cost of the SET_SRC. + In that case, have a look at the entire insn, e.g. during insn combine. */ + +static int +avr_insn_cost (rtx_insn *insn, bool speed) +{ + const int unknown_cost = -1; + int cost = unknown_cost; + + rtx set = single_set (insn); + + if (set + && ZERO_EXTRACT == GET_CODE (SET_DEST (set))) + { + // Try find anything that would flip the extracted bit. + bool not_bit_p = false; + + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, SET_SRC (set), NONCONST) + { + enum rtx_code code = GET_CODE (*iter); + not_bit_p |= code == NOT || code == XOR || code == GE; + } + + // Don't go too deep into the analysis. In almost all cases, + // using BLD/BST is the best we can do for single-bit moves, + // even considering CSE. + cost = COSTS_N_INSNS (2 + not_bit_p); + } + + if (cost != unknown_cost) + { + if (avr_log.rtx_costs) + avr_edump ("\n%? (%s) insn_cost=%d\n%r\n", + speed ? "speed" : "size", cost, insn); + return cost; + } + + // Resort to what rtlanal.cc::insn_cost() implements as a default + // when targetm.insn_cost() is not implemented. + + return pattern_cost (PATTERN (insn), speed); +} + + /* Implement `TARGET_ADDRESS_COST'. */ static int @@ -14572,6 +14618,8 @@ avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code) #undef TARGET_ASM_FINAL_POSTSCAN_INSN #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn +#undef TARGET_INSN_COST +#define TARGET_INSN_COST avr_insn_cost #undef TARGET_REGISTER_MOVE_COST #define TARGET_REGISTER_MOVE_COST avr_register_move_cost #undef TARGET_MEMORY_MOVE_COST