AVR: target/54378 - Reconsider the default shift costs.
This patch calculates more accurate shift costs, but makes
the costs for larger offsets no more expensive than the costs
for an unrolled shift.
gcc/
PR target/54378
* config/avr/avr.cc (avr_default_shift_costs): New static function.
(avr_rtx_costs_1) [ASHIFT, LSHIFTRT, ASHIFTRT]: Use it
to determine the default shift costs for shifts with a
constant shift offset.
@@ -12028,6 +12028,24 @@ avr_operand_rtx_cost (rtx x, machine_mode mode, rtx_code outer,
return total;
}
+
+/* Return the default shift costs for an n-byte shift with a constant
+ bit offset in terms of cycles (speed) or in terms of words (!speed). */
+
+static int
+avr_default_shift_costs (int n_bytes, int offset, bool speed)
+{
+ int c_space = 3 + n_bytes;
+ int c_speed = offset <= 4
+ ? (3 + n_bytes) * offset
+ // For larger offsets, don't make the speed costs more costly than
+ // an unrolled shift, because we cannot rollback from an unrolled shift.
+ : n_bytes * offset;
+
+ return COSTS_N_INSNS (speed ? c_speed : c_space);
+}
+
+
/* Worker function for AVR backend's rtx_cost function.
X is rtx expression whose cost is to be calculated.
Return true if the complete cost has been computed.
@@ -12038,8 +12056,11 @@ static bool
avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
int /*opno*/, int *total, bool speed)
{
- rtx_code code = GET_CODE (x);
- HOST_WIDE_INT val;
+ const rtx_code code = GET_CODE (x);
+ const int n_bytes = GET_MODE_SIZE (mode);
+ const HOST_WIDE_INT val1 = BINARY_P (x) && CONST_INT_P (XEXP (x, 1))
+ ? INTVAL (XEXP (x, 1))
+ : -1;
switch (code)
{
@@ -12054,7 +12075,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
return true;
case MEM:
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
return true;
case NEG:
@@ -12068,7 +12089,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
case E_HImode:
case E_PSImode:
case E_SImode:
- *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
+ *total = COSTS_N_INSNS (2 * n_bytes - 1);
break;
default:
@@ -12092,19 +12113,19 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
return true;
case NOT:
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
return true;
case ZERO_EXTEND:
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
+ *total = COSTS_N_INSNS (n_bytes
- GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
*total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
code, 0, speed);
return true;
case SIGN_EXTEND:
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
+ *total = COSTS_N_INSNS (n_bytes + 2
- GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
*total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
code, 0, speed);
@@ -12144,13 +12165,13 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
&& REG_P (XEXP (x, 1)))
{
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
return true;
}
if (REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
{
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
return true;
}
@@ -12159,8 +12180,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
&& REG_P (XEXP (x, 1)))
{
int size2 = GET_MODE_SIZE (GET_MODE (XEXP (XEXP (x, 0), 0)));
- *total = COSTS_N_INSNS (2 + GET_MODE_SIZE (mode)
- + (GET_MODE_SIZE (mode) > 1 + size2));
+ *total = COSTS_N_INSNS (2 + n_bytes
+ + (n_bytes > 1 + size2));
return true;
}
@@ -12249,7 +12270,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
if (REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
{
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
return true;
}
// *sub<HISI:mode>3.sign_extend.<QIPSI:mode>
@@ -12257,8 +12278,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
&& GET_CODE (XEXP (x, 1)) == SIGN_EXTEND)
{
int size2 = GET_MODE_SIZE (GET_MODE (XEXP (XEXP (x, 1), 0)));
- *total = COSTS_N_INSNS (2 + GET_MODE_SIZE (mode)
- + (GET_MODE_SIZE (mode) > 1 + size2));
+ *total = COSTS_N_INSNS (2 + n_bytes
+ + (n_bytes > 1 + size2));
return true;
}
@@ -12321,17 +12342,17 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
|| LSHIFTRT == GET_CODE (XEXP (x, 0))))
{
// "*insv.any_shift.<mode>
- *total = COSTS_N_INSNS (1 + GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (1 + n_bytes);
return true;
}
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
if (!CONST_INT_P (XEXP (x, 1)))
*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
return true;
case XOR:
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (n_bytes);
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
return true;
@@ -12445,12 +12466,12 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
if (!speed)
*total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
else
- *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
+ *total = COSTS_N_INSNS (15 * n_bytes);
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
/* For div/mod with const-int divisor we have at least the cost of
loading the divisor. */
if (CONST_INT_P (XEXP (x, 1)))
- *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ *total += COSTS_N_INSNS (n_bytes);
/* Add some overall penaly for clobbering and moving around registers */
*total += COSTS_N_INSNS (2);
return true;
@@ -12459,20 +12480,18 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
switch (mode)
{
case E_QImode:
- if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
+ if (val1 == 4)
*total = COSTS_N_INSNS (1);
-
break;
case E_HImode:
- if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
+ if (val1 == 8)
*total = COSTS_N_INSNS (3);
-
break;
case E_SImode:
if (CONST_INT_P (XEXP (x, 1)))
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 8:
case 24:
@@ -12512,11 +12531,10 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
}
else
{
- val = INTVAL (XEXP (x, 1));
- if (val == 7)
+ if (val1 == 7)
*total = COSTS_N_INSNS (3);
- else if (val >= 0 && val <= 7)
- *total = COSTS_N_INSNS (val);
+ else if (val1 >= 0 && val1 <= 7)
+ *total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);
}
@@ -12548,7 +12566,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12581,9 +12599,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 5 : 10);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;
@@ -12593,7 +12610,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 6 : 73);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12607,7 +12624,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (5);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
break;
}
break;
@@ -12620,7 +12637,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12640,9 +12657,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 7 : 8);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;
@@ -12664,13 +12680,12 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
}
else
{
- val = INTVAL (XEXP (x, 1));
- if (val == 6)
+ if (val1 == 6)
*total = COSTS_N_INSNS (4);
- else if (val == 7)
+ else if (val1 == 7)
*total = COSTS_N_INSNS (2);
- else if (val >= 0 && val <= 7)
- *total = COSTS_N_INSNS (val);
+ else if (val1 >= 0 && val1 <= 7)
+ *total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);
}
@@ -12693,7 +12708,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12725,9 +12740,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 5 : 8);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;
@@ -12737,7 +12751,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 6 : 73);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12753,7 +12767,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (4);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
break;
}
break;
@@ -12766,7 +12780,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12786,9 +12800,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;
@@ -12816,11 +12829,10 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
}
else
{
- val = INTVAL (XEXP (x, 1));
- if (val == 7)
+ if (val1 == 7)
*total = COSTS_N_INSNS (3);
- else if (val >= 0 && val <= 7)
- *total = COSTS_N_INSNS (val);
+ else if (val1 >= 0 && val1 <= 7)
+ *total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);
}
@@ -12834,7 +12846,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12869,9 +12881,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 5 : 9);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;
@@ -12881,7 +12892,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (!speed ? 6 : 73);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12895,7 +12906,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (5);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
break;
}
break;
@@ -12908,7 +12919,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
speed);
}
else
- switch (INTVAL (XEXP (x, 1)))
+ switch (val1)
{
case 0:
*total = 0;
@@ -12928,9 +12939,8 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (6);
break;
default:
- *total = COSTS_N_INSNS (!speed ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
- speed);
+ *total = avr_default_shift_costs (n_bytes, val1, speed);
+ break;
}
break;