Hi,

this adds support for 2 optimization hints pertaining to loops in Ada, namely 
Loop_Optimize (No_Vector) and Loop_Optimize (Vector), by reusing the Ivdep 
approach in the middle-end (ANNOTATE_EXPR node) and directly setting the 
dont_vectorize and force_vectorize bits of the 'loop' structure.

Tested on x86_64-suse-linux, OK for the mainline?


2014-04-14  Eric Botcazou  <ebotca...@adacore.com>

        * cfgloop.h (struct loop): Move force_vectorize down.
        * gimplify.c (gimple_boolify) <ANNOTATE_EXPR>: Handle new kinds.
        (gimplify_expr) <ANNOTATE_EXPR>: Minor tweak.
        * lto-streamer-in.c (input_cfg): Read dont_vectorize field.
        * lto-streamer-out.c (output_cfg): Write dont_vectorize field.
        * tree-cfg.c (replace_loop_annotate): Revamp and handle new kinds.
        * tree-core.h (enum annot_expr_kind): Add new kind values.
        * tree-inline.c (copy_loops): Copy dont_vectorize field and reorder.
        * tree-pretty-print.c (dump_generic_node) <ANNOTATE_EXPR>: Handle new
        kinds.
        * tree.def (ANNOTATE_EXPR): Tweak comment.
ada/
        * gcc-interface/trans.c (gnat_gimplify_stmt): Propagate loop hints.


2014-04-14  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/vect12.ad[sb]: New test.
        * gnat.dg/vect13.ad[sb]: Likewise.


-- 
Eric Botcazou
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 209334)
+++ tree-pretty-print.c	(working copy)
@@ -2105,13 +2105,21 @@ dump_generic_node (pretty_printer *buffe
 
     case ANNOTATE_EXPR:
       pp_string (buffer, "ANNOTATE_EXPR <");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
       switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (node, 1)))
 	{
 	case annot_expr_ivdep_kind:
-	  pp_string (buffer, "ivdep, ");
+	  pp_string (buffer, ", ivdep");
+	  break;
+	case annot_expr_no_vector_kind:
+	  pp_string (buffer, ", no-vector");
 	  break;
+	case annot_expr_vector_kind:
+	  pp_string (buffer, ", vector");
+	  break;
+	default:
+	  gcc_unreachable ();
 	}
-      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
       pp_greater (buffer);
       break;
 
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 209362)
+++ lto-streamer-out.c	(working copy)
@@ -1693,6 +1693,7 @@ output_cfg (struct output_block *ob, str
 
       /* Write OMP SIMD related info.  */
       streamer_write_hwi (ob, loop->safelen);
+      streamer_write_hwi (ob, loop->dont_vectorize);
       streamer_write_hwi (ob, loop->force_vectorize);
       stream_write_tree (ob, loop->simduid, true);
     }
Index: ada/gcc-interface/trans.c
===================================================================
--- ada/gcc-interface/trans.c	(revision 209375)
+++ ada/gcc-interface/trans.c	(working copy)
@@ -7761,6 +7761,15 @@ gnat_gimplify_stmt (tree *stmt_p)
 				 build_int_cst (integer_type_node,
 						annot_expr_ivdep_kind));
 
+	    if (LOOP_STMT_NO_VECTOR (stmt))
+	      gnu_cond = build2 (ANNOTATE_EXPR, TREE_TYPE (gnu_cond), gnu_cond,
+				 build_int_cst (integer_type_node,
+						annot_expr_no_vector_kind));
+	    if (LOOP_STMT_VECTOR (stmt))
+	      gnu_cond = build2 (ANNOTATE_EXPR, TREE_TYPE (gnu_cond), gnu_cond,
+				 build_int_cst (integer_type_node,
+						annot_expr_vector_kind));
+
 	    gnu_cond
 	      = build3 (COND_EXPR, void_type_node, gnu_cond, NULL_TREE,
 			build1 (GOTO_EXPR, void_type_node, gnu_end_label));
Index: lto-streamer-in.c
===================================================================
--- lto-streamer-in.c	(revision 209362)
+++ lto-streamer-in.c	(working copy)
@@ -718,6 +718,7 @@ input_cfg (struct lto_input_block *ib, s
 
       /* Read OMP SIMD related info.  */
       loop->safelen = streamer_read_hwi (ib);
+      loop->dont_vectorize = streamer_read_hwi (ib);
       loop->force_vectorize = streamer_read_hwi (ib);
       loop->simduid = stream_read_tree (ib, data_in);
 
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 209334)
+++ gimplify.c	(working copy)
@@ -2813,15 +2813,18 @@ gimple_boolify (tree expr)
       return expr;
 
     case ANNOTATE_EXPR:
-      if ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1))
-	  == annot_expr_ivdep_kind)
+      switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
 	{
+	case annot_expr_ivdep_kind:
+	case annot_expr_no_vector_kind:
+	case annot_expr_vector_kind:
 	  TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
 	  if (TREE_CODE (type) != BOOLEAN_TYPE)
 	    TREE_TYPE (expr) = boolean_type_node;
 	  return expr;
+	default:
+	  gcc_unreachable ();
 	}
-      /* FALLTHRU */
 
     default:
       if (COMPARISON_CLASS_P (expr))
@@ -7528,7 +7531,7 @@ gimplify_expr (tree *expr_p, gimple_seq
 	case ANNOTATE_EXPR:
 	  {
 	    tree cond = TREE_OPERAND (*expr_p, 0);
-	    tree id = TREE_OPERAND (*expr_p, 1);
+	    tree kind = TREE_OPERAND (*expr_p, 1);
 	    tree type = TREE_TYPE (cond);
 	    if (!INTEGRAL_TYPE_P (type))
 	      {
@@ -7538,8 +7541,8 @@ gimplify_expr (tree *expr_p, gimple_seq
 	      }
 	    tree tmp = create_tmp_var (type, NULL);
 	    gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
-	    gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2,
-						      cond, id);
+	    gimple call
+	      = gimple_build_call_internal (IFN_ANNOTATE, 2, cond, kind);
 	    gimple_call_set_lhs (call, tmp);
 	    gimplify_seq_add_stmt (pre_p, call);
 	    *expr_p = tmp;
Index: tree.def
===================================================================
--- tree.def	(revision 209334)
+++ tree.def	(working copy)
@@ -1280,7 +1280,7 @@ DEFTREECODE (TARGET_OPTION_NODE, "target
 
 /* ANNOTATE_EXPR.
    Operand 0 is the expression to be annotated.
-   Operand 1 is the annotation id. */
+   Operand 1 is the annotation kind.  */
 DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2)
 
 /* Cilk spawn statement
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 209362)
+++ tree-inline.c	(working copy)
@@ -2349,17 +2349,18 @@ copy_loops (copy_body_data *id,
 	  place_new_loop (cfun, dest_loop);
 	  flow_loop_tree_node_add (dest_parent, dest_loop);
 
-	  if (src_loop->simduid)
-	    {
-	      dest_loop->simduid = remap_decl (src_loop->simduid, id);
-	      cfun->has_simduid_loops = true;
-	    }
+	  dest_loop->safelen = src_loop->safelen;
+	  dest_loop->dont_vectorize = src_loop->dont_vectorize;
 	  if (src_loop->force_vectorize)
 	    {
 	      dest_loop->force_vectorize = true;
 	      cfun->has_force_vectorize_loops = true;
 	    }
-	  dest_loop->safelen = src_loop->safelen;
+	  if (src_loop->simduid)
+	    {
+	      dest_loop->simduid = remap_decl (src_loop->simduid, id);
+	      cfun->has_simduid_loops = true;
+	    }
 
 	  /* Recurse.  */
 	  copy_loops (id, dest_loop, src_loop);
Index: cfgloop.h
===================================================================
--- cfgloop.h	(revision 209362)
+++ cfgloop.h	(working copy)
@@ -173,12 +173,12 @@ struct GTY ((chain_next ("%h.next"))) lo
      of the loop can be safely evaluated concurrently.  */
   int safelen;
 
-  /* True if we should try harder to vectorize this loop.  */
-  bool force_vectorize;
-
   /* True if this loop should never be vectorized.  */
   bool dont_vectorize;
 
+  /* True if we should try harder to vectorize this loop.  */
+  bool force_vectorize;
+
   /* For SIMD loops, this is a unique identifier of the loop, referenced
      by IFN_GOMP_SIMD_VF, IFN_GOMP_SIMD_LANE and IFN_GOMP_SIMD_LAST_LANE
      builtins.  */
Index: tree-core.h
===================================================================
--- tree-core.h	(revision 209334)
+++ tree-core.h	(working copy)
@@ -657,7 +657,10 @@ enum tree_node_kind {
 };
 
 enum annot_expr_kind {
-  annot_expr_ivdep_kind
+  annot_expr_ivdep_kind,
+  annot_expr_no_vector_kind,
+  annot_expr_vector_kind,
+  annot_expr_kind_last
 };
 
 
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 209362)
+++ tree-cfg.c	(working copy)
@@ -250,9 +250,9 @@ build_gimple_cfg (gimple_seq seq)
 }
 
 
-/* Search for ANNOTATE call with annot_expr_ivdep_kind; if found, remove
-   it and set loop->safelen to INT_MAX.  We assume that the annotation
-   comes immediately before the condition.  */
+/* 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 ()
@@ -266,50 +266,62 @@ replace_loop_annotate ()
     {
       gsi = gsi_last_bb (loop->header);
       stmt = gsi_stmt (gsi);
-      if (stmt && gimple_code (stmt) == GIMPLE_COND)
+      if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
+	continue;
+      for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
 	{
-	  gsi_prev_nondebug (&gsi);
-	  if (gsi_end_p (gsi))
-	    continue;
 	  stmt = gsi_stmt (gsi);
 	  if (gimple_code (stmt) != GIMPLE_CALL)
-		continue;
+	    break;
 	  if (!gimple_call_internal_p (stmt)
-		  || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-	    continue;
-	  if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))
-	      != annot_expr_ivdep_kind)
-	    continue;
+	      || 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);
-	  loop->safelen = INT_MAX;
 	}
     }
 
-  /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL.  */
+  /* Remove IFN_ANNOTATE.  Safeguard for the case loop->latch == NULL.  */
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gsi = gsi_last_bb (bb);
-      stmt = gsi_stmt (gsi);
-      if (stmt && gimple_code (stmt) == GIMPLE_COND)
-	gsi_prev_nondebug (&gsi);
-      if (gsi_end_p (gsi))
-	continue;
-      stmt = gsi_stmt (gsi);
-      if (gimple_code (stmt) != GIMPLE_CALL)
-	continue;
-      if (!gimple_call_internal_p (stmt)
-	  || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-	continue;
-      if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))
-	  != annot_expr_ivdep_kind)
-	continue;
-      warning_at (gimple_location (stmt), 0, "ignoring %<GCC ivdep%> "
-		  "annotation");
-      stmt = gimple_build_assign (gimple_call_lhs (stmt),
-				  gimple_call_arg (stmt, 0));
-      gsi_replace (&gsi, stmt, true);
+      for (gsi = gsi_last_bb (bb); !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:
+	    case annot_expr_no_vector_kind:
+	    case annot_expr_vector_kind:
+	      break;
+	    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));
+	  gsi_replace (&gsi, stmt, true);
+	}
     }
 }
 
-- { dg-do compile { target i?86-*-* x86_64-*-* } }
-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }

package body Vect12 is

   function "+" (X, Y : Sarray) return Sarray is
      R : Sarray;
   begin
      for I in Sarray'Range loop
         pragma Loop_Optimize (No_Vector);
         R(I) := X(I) + Y(I);
      end loop;
      return R;
   end;

   procedure Add (X, Y : Sarray; R : out Sarray) is
   begin
      for I in Sarray'Range loop
         pragma Loop_Optimize (No_Vector);
         R(I) := X(I) + Y(I);
      end loop;
   end;

end Vect12;

-- { dg-final { scan-tree-dump-not "vectorized 1 loops" "vect"  } }
-- { dg-final { cleanup-tree-dump "vect" } }
package Vect12 is

   -- Constrained array types are vectorizable
   type Sarray is array (1 .. 4) of Float;
   for Sarray'Alignment use 16;

   function "+" (X, Y : Sarray) return Sarray;
   procedure Add (X, Y : Sarray; R : out Sarray);

end Vect12;
-- { dg-do compile { target i?86-*-* x86_64-*-* } }
-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }

package body Vect13 is

   function "+" (X, Y : Sarray) return Sarray is
      R : Sarray;
   begin
      for I in Sarray'Range loop
         pragma Loop_Optimize (Vector);
         R(I) := X(I) + Y(I);
      end loop;
      return R;
   end;

   procedure Add (X, Y : Sarray; R : out Sarray) is
   begin
      for I in Sarray'Range loop
         pragma Loop_Optimize (Vector);
         R(I) := X(I) + Y(I);
      end loop;
   end;

end Vect13;

-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect"  } }
-- { dg-final { cleanup-tree-dump "vect" } }
package Vect13 is

   -- Constrained array types are vectorizable
   type Sarray is array (1 .. 4) of Float;
   for Sarray'Alignment use 16;

   function "+" (X, Y : Sarray) return Sarray;
   procedure Add (X, Y : Sarray; R : out Sarray);

end Vect13;

Reply via email to