As discussed at https://gcc.gnu.org/ml/gcc/2016-01/msg00023.html , the
Go frontend needs some way to prevent ivopts from temporarily removing
all pointers into a memory block. This patch adds a new option
-fcollectible-pointers which makes that happen. This is not the best
way to solve the problem, but it seems safe for GCC 6.
I made the option -fcollectible-pointers intending that any similar
optimizations (or, rather, non-optimizations) can be captured in the
same option. And if we develop a better approach for ivopts, it can
still be covered under this option name.
Bootstrapped and tested on x86_64-pc-linux-gnu. OK for mainline?
Ian
gcc/ChangeLog:
2016-01-19 Ian Lance Taylor <[email protected]>
* common.opt (fcollectible-pointers): New option.
* tree-ssa-loop-ivopts.c (add_autoinc_candidates): If
-fcollectible-pointers, skip pointers.
* doc/invoke.texi (Optimize Options): Document
-fcollectible-pointers
gcc/testsuite/ChangeLog:
2016-01-19 Ian Lance Taylor <[email protected]>
* gcc.dg/tree-ssa/ivopt_5.c: New test.
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (revision 232580)
+++ gcc/common.opt (working copy)
@@ -1025,6 +1025,10 @@
Common Var(flag_checking) Init(CHECKING_P)
Perform internal consistency checkings.
+fcollectible-pointers
+Common Report Var(flag_collectible_pointers) Optimization
+Ensure that pointers are always collectible by a garbage collector.
+
fcombine-stack-adjustments
Common Report Var(flag_combine_stack_adjustments) Optimization
Looks for opportunities to reduce stack adjustments and stack references.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 232580)
+++ gcc/doc/invoke.texi (working copy)
@@ -6621,6 +6621,17 @@
If you use @option{-Wunsafe-loop-optimizations}, the compiler warns you
if it finds this kind of loop.
+@item -fcollectible-pointers
+@opindex fcollectible-pointers
+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: gcc/testsuite/gcc.dg/tree-ssa/ivopt_5.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ivopt_5.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/ivopt_5.c (working copy)
@@ -0,0 +1,14 @@
+/* { dg-options "-O2 -fdump-tree-ivopts -fcollectible-pointers" } */
+
+/* No ivopts here when using -fcollectible-pointers. */
+void foo (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: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c (revision 232580)
+++ gcc/tree-ssa-loop-ivopts.c (working copy)
@@ -2956,6 +2956,17 @@
|| !cst_and_fits_in_hwi (step))
return;
+ // -fcollectible-pointers 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_collectible_pointers && POINTER_TYPE_P (TREE_TYPE (base)))
+ return;
+
cstepi = int_cst_value (step);
mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));