middle-end: do not widen a multiply-add across a shared conversion

convert_plusminus_to_widen folds a multiply and an addition into a single
WIDEN_MULT_PLUS_EXPR.  That is only a win if the multiply dies, so the pass
requires its result to be single-use.  When the multiply reaches the addition
through a conversion, the check is applied to the wrong value: the multiply is
single-use because only the conversion reads it, while the value the additions
actually share is the conversion result.  Each addition then gets its own copy
of the multiply and the original stays live.

For

  void f (const signed char *base, int i, const signed char **out)
  {
    unsigned long o = (unsigned long) ((long) i * 128);
    out[0] = base + o;
    out[1] = base + o + 16;
    out[2] = base + o + 32;
    out[3] = base + o + 48;
  }

the pass turns

  _2 = i_10(D) * 128;
  o_11 = (long unsigned int) _2;
  _3 = base_12(D) + o_11;
  _4 = o_11 + 16;
  _6 = o_11 + 32;
  _8 = o_11 + 48;

into

  _2 = i_10(D) w* 128;
  o_11 = (long unsigned int) _2;
  _3 = base_12(D) + o_11;
  _4 = WIDEN_MULT_PLUS_EXPR <i_10(D), 128, 16>;
  _6 = WIDEN_MULT_PLUS_EXPR <i_10(D), 128, 32>;
  _8 = WIDEN_MULT_PLUS_EXPR <i_10(D), 128, 48>;

which is four multiplies where there was one.  On AArch64 that is 3 SMADDL
plus the three constants in registers instead of one SBFIZ and three adds, and
because every address then needs its own register offset it also blocks LDP
formation.

Apply the same single-use requirement to the conversion result.

Found in the Stockfish NNUE sparse affine kernel, where the eight weight
column addresses share one scaled index.  On an AArch64 build the number of
SMADDL in the binary falls from 19 to 5, dynamic instruction count falls by
about 4.7%.

Bootstrapped and tested on aarch64-none-linux-gnu.

gcc/ChangeLog:

	* tree-ssa-math-opts.cc (convert_plusminus_to_widen): Require the
	result of an intervening conversion to be single-use.

gcc/testsuite/ChangeLog:

	* gcc.dg/widening-mul-conv-1.c: New test.

Signed-off-by: Kyrylo Tkachov <ktkachov@nvidia.com>
2 files changed