diff --git a/gcc/testsuite/gcc.dg/torture/pr110702.c b/gcc/testsuite/gcc.dg/torture/pr110702.c new file mode 100644 index 0000000000000000000000000000000000000000..aab9c7d923ee1c80a234097521b6acf4fc41c5b3 --- /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 0dd47910f97a8b7aa1a303f87dbedaa753b861d0..6c89b3d3580d02f1ed16608758a8da7c9991fd4e 100644 --- a/gcc/tree-ssa-loop-ivopts.cc +++ b/gcc/tree-ssa-loop-ivopts.cc @@ -7616,7 +7616,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; }