We were crashing because size_binop_loc got operands of different types: sizetype and ssizetype. Richi suggested performing the computation in offset_int which my patch tries to do. Unsure about the sdiv_trunc part, what do I use instead of EXACT_DIV_EXPR?
Bootstrapped/regtested on x86_64-linux, ok for trunk? Testing on ppc64le in progress. 2017-08-04 Marek Polacek <pola...@redhat.com> PR middle-end/81695 * fold-const.c (fold_indirect_ref_1): For ((int *)&a + 4 -> a[1], perform the computation in offset_int. * gcc.dg/pr81695.c: New test. diff --git gcc/fold-const.c gcc/fold-const.c index ed6c289a64b..64a84eb0197 100644 --- gcc/fold-const.c +++ gcc/fold-const.c @@ -14106,14 +14106,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) && type == TREE_TYPE (op00type)) { tree type_domain = TYPE_DOMAIN (op00type); - tree min_val = size_zero_node; - if (type_domain && TYPE_MIN_VALUE (type_domain)) - min_val = TYPE_MIN_VALUE (type_domain); - op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01, - TYPE_SIZE_UNIT (type)); - op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val); - return build4_loc (loc, ARRAY_REF, type, op00, op01, - NULL_TREE, NULL_TREE); + tree min = TYPE_MIN_VALUE (type_domain); + if (min && TREE_CODE (min) == INTEGER_CST) + { + offset_int off = wi::to_offset (op01); + offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type)); + off = wi::sdiv_trunc (off, el_sz); + off = off + wi::to_offset (min); + op01 = wide_int_to_tree (sizetype, off); + return build4_loc (loc, ARRAY_REF, type, op00, op01, + NULL_TREE, NULL_TREE); + } } } } diff --git gcc/testsuite/gcc.dg/pr81695.c gcc/testsuite/gcc.dg/pr81695.c index e69de29bb2d..c3452580f1c 100644 --- gcc/testsuite/gcc.dg/pr81695.c +++ gcc/testsuite/gcc.dg/pr81695.c @@ -0,0 +1,11 @@ +/* PR middle-end/81695 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +int z[] = { }; + +int +main (void) +{ + __builtin_printf ("%d\n", *(z + 1)); +} Marek