OK, thanks.
> The default cost of MULT/DIV/MOD in rtx_cost () is high: 5,7 insns > respectively. This causes even a trivial mpy by 7 to be synthesized. > Given these have direct equivalents in BPF ISA, fix the cost to generate > native BPF insns. > > Note the existing divmod-licall-2.c test was a bit fragile as it forced > cast signed an actual unsigned int which is provably non-negative. In > the new cost model compiler would generate a native unsigned divide > not available for -mcpu=v3, tripping up the test. Fix by ensuring the > arg is actually signed. > > gcc/ChangeLog: > > * config/bpf/bpf.cc (bpf_rtx_costs): Assign MPY/DIV/MOD cost 1. > > gcc/testsuite/ChangeLog: > > * gcc.target/bpf/divmod-libcall-2.c: Change args/ret to signed. > * gcc.target/bpf/mult-large.c: New test. > * gcc.target/bpf/mult-small.c: New test. > > Signed-off-by: Vineet Gupta <[email protected]> > --- > gcc/config/bpf/bpf.cc | 24 ++++++++++++++++--- > .../gcc.target/bpf/divmod-libcall-2.c | 15 +++++++----- > gcc/testsuite/gcc.target/bpf/mult-large.c | 22 +++++++++++++++++ > gcc/testsuite/gcc.target/bpf/mult-small.c | 20 ++++++++++++++++ > 4 files changed, 72 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/bpf/mult-large.c > create mode 100644 gcc/testsuite/gcc.target/bpf/mult-small.c > > diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc > index 89a4917cd0a0..58d2318f972b 100644 > --- a/gcc/config/bpf/bpf.cc > +++ b/gcc/config/bpf/bpf.cc > @@ -602,14 +602,32 @@ bpf_legitimate_address_p (machine_mode mode, > `rtx_cost' should recurse. */ > > 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 opno ATTRIBUTE_UNUSED, > - int *total ATTRIBUTE_UNUSED, > + int *total, > bool speed ATTRIBUTE_UNUSED) > { > - /* To be written. */ > + switch (GET_CODE (x)) > + { > + case MULT: > + case DIV: > + case UDIV: > + case MOD: > + case UMOD: > + /* BPF implements these as a single instruction, so keep the native > + operation cheaper than synthesized sequence. > + Only influences choice between actually available alternatives; > + if the operation has no insn (e.g. a 64-bit signed divide before > + -mcpu=v4) expand_divmod () still falls back to a libcall. > + Return false so caller rtx_cost keeps recursing for operands. */ > + *total = COSTS_N_INSNS (1); > + return false; > + > + default: > + return false; > + } > return false; > } > > diff --git a/gcc/testsuite/gcc.target/bpf/divmod-libcall-2.c > b/gcc/testsuite/gcc.target/bpf/divmod-libcall-2.c > index 792d689395a2..7296579171d2 100644 > --- a/gcc/testsuite/gcc.target/bpf/divmod-libcall-2.c > +++ b/gcc/testsuite/gcc.target/bpf/divmod-libcall-2.c > @@ -1,16 +1,19 @@ > +/* Inverse of divmod-libcall-1.c. Ensure libcalls are generated for > + -mcpu=v3 due to lack of signed div/mod. */ > + > /* { dg-do compile } */ > /* { dg-options "-O2 -mcpu=v3" } */ > /* { dg-final { scan-assembler "global\t__divdi3" } } */ > /* { dg-final { scan-assembler "global\t__moddi3" } } */ > > -int > -foo (unsigned int len) > +long > +foo (long len) > { > - return ((long)len) * 234 / 5; > + return len * 234 / 5; > } > > -int > -bar (unsigned int len) > +long > +bar (long len) > { > - return ((long)len) * 234 % 5; > + return len * 234 % 5; > } > diff --git a/gcc/testsuite/gcc.target/bpf/mult-large.c > b/gcc/testsuite/gcc.target/bpf/mult-large.c > new file mode 100644 > index 000000000000..4a5ef5da2b15 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/bpf/mult-large.c > @@ -0,0 +1,22 @@ > +/* The multiply core of memset-4.c: a memset of a non-constant value > + broadcasts a byte across the word with "x * 0x01010101". With the generic > + COSTS_N_INSNS (5) multiply cost this large-constant multiply was > + strength-reduced into a shift/add sequence; BPF has a single-instruction > + mul, so the native mul must be used instead. > + > + Use a full 32-bit input (not 'unsigned char'): for a byte 'x * 0x01010101' > + equals the carry-free broadcast 'x | x<<8 | x<<16 | x<<24', which the > + compiler could lower without a multiply at all, weakening the test. A > + 32-bit input has no such equivalence, so this is a genuine multiply. */ > + > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +unsigned > +bcast (unsigned x) > +{ > + return x * 0x01010101u; > +} > + > +/* { dg-final { scan-assembler {\*= 16843009} } } */ > +/* { dg-final { scan-assembler-not {<<=} } } */ > diff --git a/gcc/testsuite/gcc.target/bpf/mult-small.c > b/gcc/testsuite/gcc.target/bpf/mult-small.c > new file mode 100644 > index 000000000000..7c82f3276266 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/bpf/mult-small.c > @@ -0,0 +1,20 @@ > +/* Verify that a multiply by a small constant uses BPF's native single > + instruction mul rather than a synthesized shift/add(-sub) sequence. > + > + BPF has a single-instruction multiply, so "x * 7" should be "r0 *= 7", > + not the strength-reduced "(x << 3) - x". synth_mult () only avoids the > + native multiply when it finds a cheaper sequence, so the rtx_cost hook > + must report MULT as a single instruction (rather than the generic > + COSTS_N_INSNS (5) schoolbook default) for the native op to win. */ > + > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mcpu=v4" } */ > + > +unsigned > +mul7 (unsigned x) > +{ > + return x * 7; > +} > + > +/* { dg-final { scan-assembler {\*= 7} } } */ > +/* { dg-final { scan-assembler-not {<<=} } } */
