Updated patch. I've verified that I'm changing the only relevant place in tree-ssa-loop-ivopts.c that creates a POINTER_PLUS_EXPR, so I do think that this is the only changed to fix the problem for ivopts.
OK for mainline? Ian gcc/ChangeLog: 2016-01-22 Ian Lance Taylor <i...@google.com> * common.opt (fkeep-gc-roots-live): New option. * tree-ssa-loop-ivopts.c (add_autoinc_candidates): If -fkeep-gc-roots-live, skip pointers. * doc/invoke.texi (Optimize Options): Document -fkeep-gc-roots-live. gcc/testsuite/ChangeLog: 2016-01-22 Ian Lance Taylor <i...@google.com> * gcc.dg/tree-ssa/ivopt_5.c: New test.
Index: common.opt =================================================================== --- common.opt (revision 232580) +++ common.opt (working copy) @@ -1380,6 +1380,10 @@ Enable hoisting adjacent loads to encourage generating conditional move instructions. +fkeep-gc-roots-live +Common Report Var(flag_keep_gc_roots_live) Optimization +Always keep a pointer to a live memory block + floop-parallelize-all Common Report Var(flag_loop_parallelize_all) Optimization Mark all loops as parallel. Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 232580) +++ doc/invoke.texi (working copy) @@ -359,7 +359,7 @@ -fno-ira-share-spill-slots @gol -fisolate-erroneous-paths-dereference -fisolate-erroneous-paths-attribute @gol -fivopts -fkeep-inline-functions -fkeep-static-functions @gol --fkeep-static-consts -flive-range-shrinkage @gol +-fkeep-static-consts -fkeep-gc-roots-live -flive-range-shrinkage @gol -floop-block -floop-interchange -floop-strip-mine @gol -floop-unroll-and-jam -floop-nest-optimize @gol -floop-parallelize-all -flra-remat -flto -flto-compression-level @gol @@ -6621,6 +6621,17 @@ If you use @option{-Wunsafe-loop-optimizations}, the compiler warns you if it finds this kind of loop. +@item -fkeep-gc-roots-live +@opindex fkeep-gc-roots-live +This option tells the compiler that a garbage collector will be used, +and that therefore the compiled code must retain a live pointer into +all memory blocks. The compiler is permitted to construct a pointer +that is outside the bounds of a memory block, but it must ensure that +given a pointer into memory, some pointer into that memory remains +live in the compiled code whenever it is live in the source code. +This option is disabled by default for most languages, enabled by +default for languages that use garbage collection. + @item -fcrossjumping @opindex fcrossjumping Perform cross-jumping transformation. Index: testsuite/gcc.dg/tree-ssa/ivopt_5.c =================================================================== --- testsuite/gcc.dg/tree-ssa/ivopt_5.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/ivopt_5.c (working copy) @@ -0,0 +1,23 @@ +/* { dg-options "-O2 -fdump-tree-ivopts -fkeep-gc-roots-live" } */ + +/* No ivopts here when using -fkeep-gc-roots-live. */ + +void foo (char *pstart, int n) +{ + char *p; + char *pend = pstart + n; + + for (p = pstart; p < pend; p++) + *p = 1; +} + +void foo1 (char *pstart, int n) +{ + char *p; + char *pend = pstart + n; + + for (p = pstart; p != pend; p++) + *p = 1; +} + +/* { dg-final { scan-tree-dump-times "ivtmp.\[0-9_\]* = PHI <" 0 "ivopts"} } */ Index: tree-ssa-loop-ivopts.c =================================================================== --- tree-ssa-loop-ivopts.c (revision 232580) +++ tree-ssa-loop-ivopts.c (working copy) @@ -2956,6 +2956,16 @@ || !cst_and_fits_in_hwi (step)) return; + /* -fkeep-gc-roots-live means that we have to keep a real pointer + live, but the ivopts code may replace a real pointer with one + pointing before or after the memory block that is then adjusted + into the memory block during the loop. FIXME: It would likely be + better to actually force the pointer live and still use ivopts; + for example, it would be enough to write the pointer into memory + and keep it there until after the loop. */ + if (flag_keep_gc_roots_live && POINTER_TYPE_P (TREE_TYPE (base))) + return; + cstepi = int_cst_value (step); mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));