Hi Vineet.
>> On 7/2/26 3:21 PM, Jose E. Marchesi wrote:
>>> static bool
>>> -bpf_rtx_costs (rtx x ATTRIBUTE_UNUSED,
>>> +bpf_rtx_costs (rtx x,
>>> enum machine_mode mode ATTRIBUTE_UNUSED,
>>> - int outer_code ATTRIBUTE_UNUSED,
>>> + int outer_code,
>>> int opno ATTRIBUTE_UNUSED,
>>> - int *total ATTRIBUTE_UNUSED,
>>> + int *total,
>>> bool speed ATTRIBUTE_UNUSED)
>>> {
>>> - /* To be written. */
>>> + switch (GET_CODE (x))
>>> + {
>>> + case CONST_INT:
>>> + {
>>> + HOST_WIDE_INT val = INTVAL (x);
>>> + /* BPF ALU instructions take a signed 32-bit immediate operand. */
>>> + bool imm32 = (val == (HOST_WIDE_INT) (int32_t) val);
>>> I would prefer if you would define a BPF_IMM32 macro in bpf.h and then
>>> use it as well in the imm32_operand predicate in predicates.md.
>>
>> OK.
>
> I forgot the _P in the suggested name. It shall be BPF_IMM32_P.
>
>>
>>>> + switch (outer_code)
>>>> + {
>>>> + /* Do not report a free constant when it is the operand of a
>>>> + multiply, divide or modulo. A zero-cost constant misleads
>>>> + synth_mult () and expand_divmod () into implementing the
>>>> + operation as a sequence of shifts/adds (or a magic-number
>>>> + multiply) instead of BPF's native single-instruction mul/div,
>>>> + which is cheaper here. */
>
> Been looking at expand_divmod, expmed_mult_highpart, choose_mult_variant
> and friends to see why they would get misled when the cost of
> div/udiv/mod with a constant op is COSTS_N_INSNS (1), and not when the
> cost is CONSTS_N_INSNS (2). No success yet.. Do you know what is the
> cause? Which div/mod tests are regressing?
I used the following program, which is derived from the
divmod-libcall-1.c and divmod-libcall-2.c testcases:
int
foodiv (unsigned int len)
{
return ((unsigned long)len) * 234 / 5;
}
int
foomod (unsigned int len)
{
return ((unsigned long)len) * 234 % 5;
}
long
bardiv (long x)
{
return x * 234 / 5;
}
long
barmod (long x)
{
return x * 234 % 5;
}
With your patch as-is, which assigns cost 1 to imm32 operands in
mult/div/udiv/mod/umod instructions, i.e.
case CONST_INT:
{
HOST_WIDE_INT val = INTVAL (x);
/* BPF ALU instructions take a signed 32-bit immediate operand. */
bool imm32 = (val == (HOST_WIDE_INT) (int32_t) val);
switch (outer_code)
{
/* Do not report a free constant when it is the operand of a
multiply, divide or modulo. A zero-cost constant misleads
synth_mult () and expand_divmod () into implementing the
operation as a sequence of shifts/adds (or a magic-number
multiply) instead of BPF's native single-instruction mul/div,
which is cheaper here. */
case MULT:
case DIV:
case UDIV:
case MOD:
case UMOD:
*total = COSTS_N_INSNS (1);
break;
default:
/* An immediate operand is free; a wider constant needs an
extra LD_IMM64. */
*total = imm32 ? 0 : COSTS_N_INSNS (1);
}
return true;
}
I get:
-O2 -mcpu=v3
foodiv:
w0 = w1
r0 *= 234
r0 /= 5
exit
foomod:
w0 = w1
r0 *= 234
r0 %= 5
exit
bardiv:
r2 = 5
r1 *= 234
call __divdi3
exit
barmod:
r2 = 5
r1 *= 234
call __moddi3
exit
-O2 -mcpu=v4
foodiv:
w0 = w1
r0 *= 234
r0 /= 5
exit
foomod:
w0 = w1
r0 *= 234
r0 %= 5
exit
bardiv:
r0 = r1
r0 *= 234
r0 s/= 5
exit
barmod:
r0 = r1
r0 *= 234
r0 s%= 5
exit
Which is as expected.
Then, modifying your patch so it assigns cost 0 to imm32 immediates also
in div, mod and mul instructions, i.e.
case CONST_INT:
{
HOST_WIDE_INT val = INTVAL (x);
/* BPF ALU instructions take a signed 32-bit immediate operand. */
bool imm32 = (val == (HOST_WIDE_INT) (int32_t) val);
/* An immediate operand is free; a wider constant needs an
extra LD_IMM64. */
*total = imm32 ? 0 : COSTS_N_INSNS (1);
return true;
}
I get:
-O2 -mcpu=v3
foodiv:
w0 = w1
r0 *= 234
r0 /= 5
exit
foomod:
w0 = w1
r0 *= 234
r0 %= 5
exit
bardiv:
r2 = 5
r1 *= 234
call __divdi3
exit
barmod:
r2 = 5
r1 *= 234
call __moddi3
exit
-O2 -mcpu=v4
foodiv:
w0 = w1
r0 *= 234
r0 /= 5
exit
foomod:
w0 = w1
r0 *= 234
r0 %= 5
exit
bardiv:
r0 = r1
r0 *= 234
r0 s/= 5
exit
barmod:
r0 = r1
r0 *= 234
r0 s%= 5
exit
Wich is also as expected.