[PATCH] bpf: Handle constants in TARGET_RTX_COSTS

Jose E. Marchesi jemarch@gnu.org
Tue Jul 7 10:23:55 GMT 2026


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.


More information about the bpf mailing list