public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Andrew Stubbs <ams@codesourcery.com>
To: Richard Biener <richard.guenther@gmail.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: Re: [patch] Warn on undefined loop exit
Date: Wed, 19 Nov 2014 16:39:00 -0000	[thread overview]
Message-ID: <546CC62B.1010109@codesourcery.com> (raw)
In-Reply-To: <54652425.9070104@codesourcery.com>

[-- Attachment #1: Type: text/plain, Size: 1804 bytes --]

On 13/11/14 21:35, Andrew Stubbs wrote:
> On 12/11/14 11:15, Richard Biener wrote:
>> Please find a better way to communicate possibly_undefined_stmt than
>> enlarging struct loop.  Like associating it with the niter bound
>> we record (so you can also have more than one).
>
> Unfortunately, the bounds get regenerated frequently, but the upper
> bound can only get reduced once, so the subsequent generations would
> lose the possibly_undefined_stmt.
>
> I did originally try warning at the point where the upper bound gets
> reduced, but there were too many false positives. The two part solution
> I found gives the result I was looking for, but maybe there is another way?

I've found a way to do this. There is no longer any need to store 
anything, but it did require duplicating a little code.

The new patch also reports if multiple undefined statements are 
detected, although the existing algorithm only finds one per basic 
block. (It also misses cases that occur after a loop-exit, but would be 
undefined in earlier passes through the loop, but that's another story; 
it catches all cases where a loop-exit can be eliminated.)

I've now got it emitting a warning for both the loop-exit and the 
problem statement. This makes sense to me (on the grounds that it is the 
removed loop-exit that prompted this whole exercise in the first place), 
but others may feel that a warning on the undefined statement itself is 
sufficient.

The new warning looks like this:

./undefined-loop-1.c: In function 'foo':
./undefined-loop-1.c:15:8: warning: Loop exit may only be reached after 
undefined behaviour. [-Waggressive-loop-optimizations]
         && i < 5;
         ^
./undefined-loop-1.c:14:13: note: possible undefined statement is here
         array[i]
              ^

OK to commit?

Andrew

[-- Attachment #2: undefined-loop.patch --]
[-- Type: text/x-patch, Size: 4588 bytes --]

2014-11-19  Andrew Stubbs  <ams@codesourcery.com>

	gcc/
	* tree-ssa-loop-niter.c (maybe_lower_iteration_bound): Warn if a loop
	condition would be removed due to undefined behaviour.

	gcc/testsuite/
	* gcc.dg/undefined-loop-1.c: New file.
	* gcc.dg/undefined-loop-2.c: New file.
---
 gcc/testsuite/gcc.dg/undefined-loop-1.c |   18 ++++++++++++
 gcc/testsuite/gcc.dg/undefined-loop-2.c |   22 +++++++++++++++
 gcc/tree-ssa-loop-niter.c               |   46 +++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/undefined-loop-1.c
 create mode 100644 gcc/testsuite/gcc.dg/undefined-loop-2.c

diff --git a/gcc/testsuite/gcc.dg/undefined-loop-1.c b/gcc/testsuite/gcc.dg/undefined-loop-1.c
new file mode 100644
index 0000000..bcb16e9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/undefined-loop-1.c
@@ -0,0 +1,18 @@
+/* Check that loops whose final iteration is undefined are detected.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Waggressive-loop-optimizations" } */
+
+void doSomething(char);
+
+char array[5];
+
+void
+foo (void)
+{
+  int i;
+  for (i = 0;
+       array[i]  /* { dg-message "note: possible undefined statement is here" } */
+       && i < 5; /* { dg-warning "Loop exit may only be reached after undefined behaviour." } */
+       i++)
+    doSomething(array[i]);
+}
diff --git a/gcc/testsuite/gcc.dg/undefined-loop-2.c b/gcc/testsuite/gcc.dg/undefined-loop-2.c
new file mode 100644
index 0000000..29bcae0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/undefined-loop-2.c
@@ -0,0 +1,22 @@
+/* Check that loops whose final iteration is undefined are detected.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Waggressive-loop-optimizations" } */
+
+void doSomething(char);
+
+char array1[5];
+char array2[5];
+
+void
+foo (int p)
+{
+  int i;
+  for (i=0;
+       (p
+        ? array1[i]  /* { dg-message "note: possible undefined statement is here" } */
+        : array2[i]) /* { dg-message "note: possible undefined statement is here" } */
+       && i < 5      /* { dg-warning "Loop exit may only be reached after undefined behaviour." } */
+       && i < 100;   /* { dg-warning "Loop exit may only be reached after undefined behaviour." } */
+       i++)
+    doSomething(array1[i]);
+}
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index fd32d28..7594717 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -3289,6 +3289,7 @@ maybe_lower_iteration_bound (struct loop *loop)
   struct nb_iter_bound *elt;
   bool found_exit = false;
   vec<basic_block> queue = vNULL;
+  vec<gimple> problem_stmts = vNULL;
   bitmap visited;
 
   /* Collect all statements with interesting (i.e. lower than
@@ -3334,6 +3335,7 @@ maybe_lower_iteration_bound (struct loop *loop)
 	  if (not_executed_last_iteration->contains (stmt))
 	    {
 	      stmt_found = true;
+	      problem_stmts.safe_push (stmt);
 	      break;
 	    }
 	  if (gimple_has_side_effects (stmt))
@@ -3377,9 +3379,53 @@ maybe_lower_iteration_bound (struct loop *loop)
 		 "undefined statement must be executed at the last iteration.\n");
       record_niter_bound (loop, loop->nb_iterations_upper_bound - 1,
 			  false, true);
+
+      if (OPT_Waggressive_loop_optimizations)
+	{
+	  bool exit_warned = false;
+	  for (elt = loop->bounds; elt; elt = elt->next)
+	    {
+	      if (elt->is_exit
+		  && wi::gtu_p (elt->bound, loop->nb_iterations_upper_bound))
+		{
+		  basic_block bb = gimple_bb (elt->stmt);
+		  edge exit_edge = EDGE_SUCC (bb, 0);
+		  struct tree_niter_desc niter;
+
+		  if (!loop_exit_edge_p (loop, exit_edge))
+		    exit_edge = EDGE_SUCC (bb, 1);
+
+		  if(number_of_iterations_exit (loop, exit_edge,
+						&niter, false, false)
+		     && integer_onep (niter.assumptions)
+		     && integer_zerop (niter.may_be_zero)
+		     && niter.niter
+		     && TREE_CODE (niter.niter) == INTEGER_CST
+		     && wi::ltu_p (loop->nb_iterations_upper_bound,
+				   wi::to_widest (niter.niter)))
+		   {
+		     if (warning_at (gimple_location (elt->stmt),
+				     OPT_Waggressive_loop_optimizations,
+				     "Loop exit may only be reached after undefined behaviour."))
+		       exit_warned = true;
+		   }
+		}
+	    }
+
+	  if (exit_warned && problem_stmts != vNULL)
+	    {
+	      gimple stmt;
+	      int index;
+	      FOR_EACH_VEC_ELT (problem_stmts, index, stmt)
+		inform (gimple_location (stmt),
+			"possible undefined statement is here");
+	    }
+      }
     }
+
   BITMAP_FREE (visited);
   queue.release ();
+  problem_stmts.release ();
   delete not_executed_last_iteration;
 }
 

  reply	other threads:[~2014-11-19 16:32 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-05 21:45 Andrew Stubbs
2014-11-12 10:37 ` Andrew Stubbs
2014-11-12 11:18 ` Richard Biener
2014-11-13 21:58   ` Andrew Stubbs
2014-11-19 16:39     ` Andrew Stubbs [this message]
2014-11-19 16:48       ` Marek Polacek
2014-11-19 20:43         ` Andrew Stubbs
2014-11-20 16:31           ` Richard Biener
2014-11-20 21:13             ` Marek Polacek
2014-11-21 10:31               ` Andrew Stubbs
2014-11-20 21:48             ` Andrew Stubbs
2015-02-18 14:06             ` Jakub Jelinek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=546CC62B.1010109@codesourcery.com \
    --to=ams@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).