diff --git a/gcc/testsuite/gcc.dg/torture/pr110702.c b/gcc/testsuite/gcc.dg/torture/pr110702.c new file mode 100644 index 00000000000..aab9c7d923e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr110702.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +void abort (void); + +int a, b, c, d; +long e[9][7][4]; + +void f() +{ + for (; a >= 0; a--) + { + b = 0; + for (; b <= 3; b++) + { + c = 0; + for (; c <= 3; c++) + { + int *g = &d; + *g = e[0][0][b] | e[a][b][a]; + } + } + } +} + +int main() +{ + f(); + if (a != -1) + abort (); + return 0; +} diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc index 92fc1c7d734..934897af691 100644 --- a/gcc/tree-ssa-loop-ivopts.cc +++ b/gcc/tree-ssa-loop-ivopts.cc @@ -7630,7 +7630,22 @@ rewrite_use_address (struct ivopts_data *data, true, GSI_SAME_STMT); } else - copy_ref_info (ref, *use->op_p); + { + /* When we end up confused enough and have no suitable base but + stuffed everything to index2 use a LEA for the address and + create a plain MEM_REF to avoid basing a memory reference + on address zero which create_mem_ref_raw does as fallback. */ + if (TREE_CODE (ref) == TARGET_MEM_REF + && TMR_INDEX2 (ref) != NULL_TREE + && integer_zerop (TREE_OPERAND (ref, 0))) + { + ref = fold_build1 (ADDR_EXPR, TREE_TYPE (TREE_OPERAND (ref, 0)), ref); + ref = force_gimple_operand_gsi (&bsi, ref, true, NULL_TREE, + true, GSI_SAME_STMT); + ref = build2 (MEM_REF, type, ref, build_zero_cst (alias_ptr_type)); + } + copy_ref_info (ref, *use->op_p); + } *use->op_p = ref; }