Commit cb99630f by Richard Biener

fold undefined pointer offsetting

This avoids breaking the old broken pointer offsetting via
(T)(ptr - ((T)0)->x) which should have used offsetof.  Breakage
was exposed by the introduction of POINTER_DIFF_EXPR and making
PTA not considering that producing a pointer.  The mitigation
for simple cases is to canonicalize

  _2 = _1 - 8B;
  o_9 = (struct obj *) _2;

to

  o_9 = &MEM[_1 + -8B];

eliding one statement and the offending pointer subtraction.

2020-03-11  Richard Biener  <rguenther@suse.de>

	* match.pd ((T *)(ptr - ptr-cst) -> &MEM[ptr + -ptr-cst]):
	New pattern.

	* gcc.dg/torture/20200311-1.c: New testcase.
parent d564c5e2
2020-03-11 Richard Biener <rguenther@suse.de>
* match.pd ((T *)(ptr - ptr-cst) -> &MEM[ptr + -ptr-cst]):
New pattern.
2020-03-11 Eric Botcazou <ebotcazou@adacore.com> 2020-03-11 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/93961 PR middle-end/93961
......
...@@ -1864,6 +1864,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -1864,6 +1864,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (ptr_difference_const (@0, @1, &diff)) (if (ptr_difference_const (@0, @1, &diff))
{ build_int_cst_type (type, diff); })))) { build_int_cst_type (type, diff); }))))
/* Canonicalize (T *)(ptr - ptr-cst) to &MEM[ptr + -ptr-cst]. */
(simplify
(convert (pointer_diff @0 INTEGER_CST@1))
(if (POINTER_TYPE_P (type))
{ build_fold_addr_expr_with_type
(build2 (MEM_REF, char_type_node, @0,
wide_int_to_tree (ptr_type_node, wi::neg (wi::to_wide (@1)))),
type); }))
/* If arg0 is derived from the address of an object or function, we may /* If arg0 is derived from the address of an object or function, we may
be able to fold this expression using the object or function's be able to fold this expression using the object or function's
alignment. */ alignment. */
......
2020-03-11 Richard Biener <rguenther@suse.de>
* gcc.dg/torture/20200311-1.c: New testcase.
2020-03-11 Matthew Malcomson <matthew.malcomson@arm.com> 2020-03-11 Matthew Malcomson <matthew.malcomson@arm.com>
* lib/scanasm.exp (parse_function_bodies): Lines starting with '@' also * lib/scanasm.exp (parse_function_bodies): Lines starting with '@' also
......
/* { dg-do run } */
struct list { struct list *n; };
struct obj {
int n;
struct list l;
} _o;
struct list _l = { .n = &_o.l };
int main(int argc, char *argv[])
{
struct obj *o = &_o;
_o.l.n = &_l;
while (&o->l != &_l)
/* Note the following is invoking undefined behavior but in
this kind of "obvious" cases we don't want to break things
unnecessarily and thus we avoid analyzing o as pointing
to nothing via the undefined pointer subtraction. Instead
we canonicalize the pointer subtraction followed by the
pointer conversion to pointer offsetting. */
o = ((struct obj *)((const char *)(o->l.n)
- (const char *)&((struct obj *)0)->l));
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment