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  <i...@google.com>

        * 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  <i...@google.com>

        * 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));

Reply via email to