The attached testcase triggers an ICE because it contains pragma Loop_Optimize 
which survives down to RTL expansion.  There are 2 bugs: first, this should 
not ICE but issue a "ignoring loop annotation" message (this was accidentally 
disabled in https://gcc.gnu.org/ml/gcc-patches/2014-04/msg00681.html) and, 
second, the code must look for IFN_ANNOTATE calls in the latch as well.

Tested on x86_64-suse-linux, applied on the mainline as obvious.


2014-11-15  Eric Botcazou  <ebotca...@adacore.com>

        * tree-cfg.c (replace_loop_annotate_in_block): New function extracted
        from...
        (replace_loop_annotate): ...here.  Call it on the header and on the
        latch block, if any.  Restore proper behavior of final cleanup.


2014-11-15  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt44.ad[sb]: New test.


-- 
Eric Botcazou
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 217538)
+++ tree-cfg.c	(working copy)
@@ -265,13 +265,56 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = NULL;
 }
 
+/* Look for ANNOTATE calls with loop annotation kind in BB; if found, remove
+   them and propagate the information to LOOP.  We assume that the annotations
+   come immediately before the condition in BB, if any.  */
+
+static void
+replace_loop_annotate_in_block (basic_block bb, struct loop *loop)
+{
+  gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  gimple stmt = gsi_stmt (gsi);
+
+  if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
+    return;
+
+  for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+    {
+      stmt = gsi_stmt (gsi);
+      if (gimple_code (stmt) != GIMPLE_CALL)
+	break;
+      if (!gimple_call_internal_p (stmt)
+	  || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+	break;
+
+      switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
+	{
+	case annot_expr_ivdep_kind:
+	  loop->safelen = INT_MAX;
+	  break;
+	case annot_expr_no_vector_kind:
+	  loop->dont_vectorize = true;
+	  break;
+	case annot_expr_vector_kind:
+	  loop->force_vectorize = true;
+	  cfun->has_force_vectorize_loops = true;
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+
+      stmt = gimple_build_assign (gimple_call_lhs (stmt),
+				  gimple_call_arg (stmt, 0));
+      gsi_replace (&gsi, stmt, true);
+    }
+}
 
 /* Look for ANNOTATE calls with loop annotation kind; if found, remove
    them and propagate the information to the loop.  We assume that the
    annotations come immediately before the condition of the loop.  */
 
 static void
-replace_loop_annotate ()
+replace_loop_annotate (void)
 {
   struct loop *loop;
   basic_block bb;
@@ -280,37 +323,12 @@ replace_loop_annotate ()
 
   FOR_EACH_LOOP (loop, 0)
     {
-      gsi = gsi_last_bb (loop->header);
-      stmt = gsi_stmt (gsi);
-      if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
-	continue;
-      for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
-	{
-	  stmt = gsi_stmt (gsi);
-	  if (gimple_code (stmt) != GIMPLE_CALL)
-	    break;
-	  if (!gimple_call_internal_p (stmt)
-	      || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-	    break;
-	  switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
-	    {
-	    case annot_expr_ivdep_kind:
-	      loop->safelen = INT_MAX;
-	      break;
-	    case annot_expr_no_vector_kind:
-	      loop->dont_vectorize = true;
-	      break;
-	    case annot_expr_vector_kind:
-	      loop->force_vectorize = true;
-	      cfun->has_force_vectorize_loops = true;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  stmt = gimple_build_assign (gimple_call_lhs (stmt),
-				      gimple_call_arg (stmt, 0));
-	  gsi_replace (&gsi, stmt, true);
-	}
+      /* First look into the header.  */
+      replace_loop_annotate_in_block (loop->header, loop);
+
+      /* Then look into the latch, if any.  */
+      if (loop->latch)
+	replace_loop_annotate_in_block (loop->latch, loop);
     }
 
   /* Remove IFN_ANNOTATE.  Safeguard for the case loop->latch == NULL.  */
@@ -320,10 +338,11 @@ replace_loop_annotate ()
 	{
 	  stmt = gsi_stmt (gsi);
 	  if (gimple_code (stmt) != GIMPLE_CALL)
-	    break;
+	    continue;
 	  if (!gimple_call_internal_p (stmt)
 	      || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-	    break;
+	    continue;
+
 	  switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
 	    {
 	    case annot_expr_ivdep_kind:
@@ -333,6 +352,7 @@ replace_loop_annotate ()
 	    default:
 	      gcc_unreachable ();
 	    }
+
 	  warning_at (gimple_location (stmt), 0, "ignoring loop annotation");
 	  stmt = gimple_build_assign (gimple_call_lhs (stmt),
 				      gimple_call_arg (stmt, 0));
-- { dg-do compile }
-- { dg-options "-O" }

package body Opt44 is

   procedure Addsub (X, Y : Sarray; R : out Sarray; N : Integer) is
   begin
      for I in Sarray'Range loop
         pragma Loop_Optimize (Ivdep);
         pragma Loop_Optimize (Vector);
         if N > 0 then
           R(I) := X(I) + Y(I);
         else
           R(I) := X(I) - Y(I);
         end if;
      end loop;
   end;

end Opt44;
package Opt44 is

   type Sarray is array (1 .. 4) of Float;
   for Sarray'Alignment use 16;

   procedure Addsub (X, Y : Sarray; R : out Sarray; N : Integer);

end Opt44;

Reply via email to