]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Improve cost computation for single-bit bit insertions.
authorGeorg-Johann Lay <avr@gjlay.de>
Tue, 23 May 2023 16:49:19 +0000 (18:49 +0200)
committerGeorg-Johann Lay <avr@gjlay.de>
Tue, 23 May 2023 16:51:58 +0000 (18:51 +0200)
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 partictlar 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

index 9fa50ca230da7baf771bed3b9b40dee600243e9d..4fa6f5309b29c6666f1146106e7dea0b5b1c96db 100644 (file)
@@ -11514,6 +11514,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
@@ -14574,6 +14620,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