data-ref: Rework integer handling in split_constant_offset [PR98069]
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 10 Dec 2020 12:10:00 +0000 (12:10 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Thu, 10 Dec 2020 12:10:00 +0000 (12:10 +0000)
commit4cf70c20cb10acd6fb1016611d05540728176b60
tree38f42677ac409708a94e8d82faaf428f6f31c885
parentf5b902a9af9d1cce6c540c7f71e02e22e45c23ef
data-ref: Rework integer handling in split_constant_offset [PR98069]

PR98069 is about a case in which split_constant_offset miscategorises
an expression of the form:

  int foo;
  …
  POINTER_PLUS_EXPR<base, (sizetype)(INT_MIN - foo) * size>

as:

  base: base
  offset: (sizetype) (-foo) * size
  init: INT_MIN * size

“-foo” overflows when “foo” is INT_MIN, whereas the original expression
didn't overflow in that case.

As discussed in the PR trail, we could simply ignore the fact that
int overflow is undefined and treat it as a wrapping type, but that
is likely to pessimise quite a few cases.

This patch instead reworks split_constant_offset so that:

- it treats integer operations as having an implicit cast to sizetype
- for integer operations, the returned VAR has type sizetype

In other words, the problem becomes to express:

  (sizetype) (OP0 CODE OP1)

as:

  VAR:sizetype + (sizetype) OFF:ssizetype

The top-level integer split_constant_offset will (usually) be a sizetype
POINTER_PLUS operand, so the extra cast to sizetype disappears.  But adding
the cast allows the conversion handling to defer a lot of the difficult
cases to the recursive split_constant_offset call, which can detect
overflow on individual operations.

The net effect is to analyse the access above as:

  base: base
  offset: -(sizetype) foo * size
  init: INT_MIN * size

See the comments in the patch for more details.

gcc/
PR tree-optimization/98069
* tree-data-ref.c (compute_distributive_range): New function.
(nop_conversion_for_offset_p): Likewise.
(split_constant_offset): In the internal overload, treat integer
expressions as having an implicit cast to sizetype and express
them accordingly.  Pass back the range of the original (uncast)
expression in a new range parameter.
(split_constant_offset_1): Likewise.  Rework the handling of
conversions to account for the implicit sizetype casts.
gcc/testsuite/gcc.dg/vect/pr98069.c [new file with mode: 0644]
gcc/tree-data-ref.c