diff mbox series

[committed] Add OpenMP lastprivate conditional support for simd construct

Message ID 20190531215304.GK19695@tucnak
State New
Headers show
Series [committed] Add OpenMP lastprivate conditional support for simd construct | expand

Commit Message

Jakub Jelinek May 31, 2019, 9:53 p.m. UTC
Hi!

The following patch adds lastprivate(conditional:) support for simd
construct (at least when not combined with worksharing construct, that will
be done incrementally).

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2019-05-31  Jakub Jelinek  <jakub@redhat.com>

	* tree.h (OMP_CLAUSE__CONDTEMP__ITER): Define.
	* gimplify.c (gimplify_scan_omp_clauses): Allow lastprivate conditional
	on OMP_SIMD if not nested inside of worksharing loop that also has
	lastprivate conditional clause for the same decl.
	(gimplify_omp_for): Add _condtemp_ clauses to OMP_SIMD if needed.
	* omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE__CONDTEMP_ also
	on simd.
	(lower_rec_input_clauses): Likewise.  Handle lastprivate conditional
	on simd construct.
	(lower_lastprivate_conditional_clauses): Handle lastprivate conditional
	on simd construct.
	(lower_lastprivate_clauses): Likewise.
	(lower_omp_sections): Call lower_lastprivate_conditional_clauses before
	calling lower_rec_input_clauses.
	(lower_omp_for): Likewise.
	(lower_omp_1): Use first rather than second OMP_CLAUSE__CONDTEMP_
	clause on simd construct.
	* omp-expand.c (expand_omp_simd): Initialize cond_var if
	OMP_CLAUSE__CONDTEMP_ clause is present.

	* c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
	a sorry on lastprivate conditional on simd construct.
	* gcc.dg/vect/vect-simd-6.c: New test.
	* gcc.dg/vect/vect-simd-7.c: New test.


	Jakub
diff mbox series

Patch

--- gcc/tree.h.jj	2019-05-29 09:42:27.337398449 +0200
+++ gcc/tree.h	2019-05-31 15:22:18.098541471 +0200
@@ -1752,6 +1752,10 @@  class auto_suppress_location_wrappers
 #define OMP_CLAUSE__GRIDDIM__GROUP(NODE) \
   OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__GRIDDIM_), 1)
 
+/* _CONDTEMP_ holding temporary with iteration count.  */
+#define OMP_CLAUSE__CONDTEMP__ITER(NODE) \
+  (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__CONDTEMP_)->base.public_flag)
+
 /* SSA_NAME accessors.  */
 
 /* Whether SSA_NAME NODE is a virtual operand.  This simply caches the
--- gcc/gimplify.c.jj	2019-05-30 23:19:14.464931841 +0200
+++ gcc/gimplify.c	2019-05-31 18:52:21.487672269 +0200
@@ -8146,17 +8146,29 @@  gimplify_scan_omp_clauses (tree *list_p,
 	    }
 	  if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
 	    {
-	      if (code == OMP_FOR
-		  || code == OMP_SECTIONS
-		  || region_type == ORT_COMBINED_PARALLEL)
-		flags |= GOVD_LASTPRIVATE_CONDITIONAL;
-	      else
+	      splay_tree_node n = NULL;
+	      if (code == OMP_SIMD
+		  && outer_ctx
+		  && outer_ctx->region_type == ORT_WORKSHARE)
+		{
+		  n = splay_tree_lookup (outer_ctx->variables,
+					 (splay_tree_key) decl);
+		  if (n == NULL
+		      && outer_ctx->outer_context
+		      && (outer_ctx->outer_context->region_type
+			  == ORT_COMBINED_PARALLEL))
+		    n = splay_tree_lookup (outer_ctx->outer_context->variables,
+					   (splay_tree_key) decl);
+		}
+	      if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
 		{
 		  sorry_at (OMP_CLAUSE_LOCATION (c),
 			    "%<conditional%> modifier on %<lastprivate%> "
 			    "clause not supported yet");
 		  OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
 		}
+	      else
+		flags |= GOVD_LASTPRIVATE_CONDITIONAL;
 	    }
 	  if (outer_ctx
 	      && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
@@ -11559,6 +11571,28 @@  gimplify_omp_for (tree *expr_p, gimple_s
 	  omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
 	}
     }
+  else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
+    {
+      unsigned lastprivate_conditional = 0;
+      for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+	    && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+	  ++lastprivate_conditional;
+      if (lastprivate_conditional)
+	{
+	  struct omp_for_data fd;
+	  omp_extract_for_data (gfor, &fd, NULL);
+	  tree type = unsigned_type_for (fd.iter_type);
+	  while (lastprivate_conditional--)
+	    {
+	      tree c = build_omp_clause (UNKNOWN_LOCATION,
+					 OMP_CLAUSE__CONDTEMP_);
+	      OMP_CLAUSE_DECL (c) = create_tmp_var (type);
+	      OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
+	      gimple_omp_for_set_clauses (gfor, c);
+	    }
+	}
+    }
 
   if (ret != GS_ALL_DONE)
     return GS_ERROR;
--- gcc/omp-low.c.jj	2019-05-31 11:52:20.491195088 +0200
+++ gcc/omp-low.c	2019-05-31 19:35:04.980181644 +0200
@@ -1414,12 +1414,16 @@  scan_sharing_clauses (tree clauses, omp_
 	  break;
 
 	case OMP_CLAUSE__CONDTEMP_:
+	  decl = OMP_CLAUSE_DECL (c);
 	  if (is_parallel_ctx (ctx))
 	    {
-	      decl = OMP_CLAUSE_DECL (c);
 	      install_var_field (decl, false, 3, ctx);
 	      install_var_local (decl, ctx);
 	    }
+	  else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+		   && (gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+		   && !OMP_CLAUSE__CONDTEMP__ITER (c))
+	    install_var_local (decl, ctx);
 	  break;
 
 	case OMP_CLAUSE__CACHE_:
@@ -3840,6 +3844,11 @@  lower_rec_input_clauses (tree clauses, g
 	  if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
 	    sctx.max_vf = 1;
 	  break;
+	case OMP_CLAUSE__CONDTEMP_:
+	  /* FIXME: lastprivate(conditional:) not handled for SIMT yet.  */
+	  if (sctx.is_simt)
+	    sctx.max_vf = 1;
+	  break;
 	default:
 	  continue;
 	}
@@ -4054,7 +4063,8 @@  lower_rec_input_clauses (tree clauses, g
 		}
 	      continue;
 	    case OMP_CLAUSE__CONDTEMP_:
-	      if (is_parallel_ctx (ctx))
+	      if (is_parallel_ctx (ctx)
+		  || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
 		break;
 	      continue;
 	    default:
@@ -4730,6 +4740,11 @@  lower_rec_input_clauses (tree clauses, g
 		  SET_DECL_VALUE_EXPR (new_var, x);
 		  DECL_HAS_VALUE_EXPR_P (new_var) = 1;
 		}
+	      else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
+		{
+		  x = build_zero_cst (TREE_TYPE (var));
+		  goto do_private;
+		}
 	      break;
 
 	    case OMP_CLAUSE_LASTPRIVATE:
@@ -4757,15 +4772,52 @@  lower_rec_input_clauses (tree clauses, g
 		{
 		  tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
 		  if ((TREE_ADDRESSABLE (new_var) || nx || y
-		       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+		       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+		       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
 		      && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
 						       ivar, lvar))
 		    {
 		      if (nx)
 			x = lang_hooks.decls.omp_clause_default_ctor
 						(c, unshare_expr (ivar), x);
+		      else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
+			{
+			  x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
+				      unshare_expr (ivar), x);
+			  nx = x;
+			}
 		      if (nx && x)
 			gimplify_and_add (x, &llist[0]);
+		      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+			  && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+			{
+			  tree v
+			    = *ctx->lastprivate_conditional_map->get (new_var);
+			  tree t = create_tmp_var (TREE_TYPE (v));
+			  tree z = build_zero_cst (TREE_TYPE (v));
+			  tree orig_v
+			    = build_outer_var_ref (var, ctx,
+						   OMP_CLAUSE_LASTPRIVATE);
+			  gimple_seq_add_stmt (dlist,
+					       gimple_build_assign (t, z));
+			  gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
+			  tree civar = DECL_VALUE_EXPR (v);
+			  gcc_assert (TREE_CODE (civar) == ARRAY_REF);
+			  civar = unshare_expr (civar);
+			  TREE_OPERAND (civar, 1) = sctx.idx;
+			  x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
+				      unshare_expr (civar));
+			  x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
+				      build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
+					      orig_v, unshare_expr (ivar)));
+			  tree cond = build2 (LT_EXPR, boolean_type_node, t,
+					      civar);
+			  x = build3 (COND_EXPR, void_type_node, cond, x,
+				      void_node);
+			  gimple_seq tseq = NULL;
+			  gimplify_and_add (x, &tseq);
+			  gimple_seq_add_seq (&llist[1], tseq);
+			}
 		      if (y)
 			{
 			  y = lang_hooks.decls.omp_clause_dtor (c, ivar);
@@ -5222,7 +5274,17 @@  lower_rec_input_clauses (tree clauses, g
     }
 
   if (known_eq (sctx.max_vf, 1U))
-    sctx.is_simt = false;
+    {
+      sctx.is_simt = false;
+      if (ctx->lastprivate_conditional_map)
+	{
+	  /* When not vectorized, treat lastprivate(conditional:) like
+	     normal lastprivate, as there will be just one simd lane
+	     writing the privatized variable.  */
+	  delete ctx->lastprivate_conditional_map;
+	  ctx->lastprivate_conditional_map = NULL;
+	}
+    }
 
   if (nonconst_simd_if)
     {
@@ -5398,10 +5460,39 @@  lower_lastprivate_conditional_clauses (t
   tree iter_type = NULL_TREE;
   tree cond_ptr = NULL_TREE;
   tree iter_var = NULL_TREE;
+  bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+		  && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
+  tree next = *clauses;
   for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
 	&& OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
       {
+	if (is_simd)
+	  {
+	    tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
+	    gcc_assert (cc);
+	    if (iter_type == NULL_TREE)
+	      {
+		iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
+		iter_var = create_tmp_var_raw (iter_type);
+		DECL_CONTEXT (iter_var) = current_function_decl;
+		DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+		DECL_CHAIN (iter_var) = ctx->block_vars;
+		ctx->block_vars = iter_var;
+		tree c3
+		  = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+		OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
+		OMP_CLAUSE_DECL (c3) = iter_var;
+		OMP_CLAUSE_CHAIN (c3) = *clauses;
+		*clauses = c3;
+		ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+	      }
+	    next = OMP_CLAUSE_CHAIN (cc);
+	    tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+	    tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
+	    ctx->lastprivate_conditional_map->put (o, v);
+	    continue;
+	  }
 	if (iter_type == NULL)
 	  {
 	    if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
@@ -5440,6 +5531,7 @@  lower_lastprivate_conditional_clauses (t
 	    ctx->block_vars = iter_var;
 	    tree c3
 	      = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+	    OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
 	    OMP_CLAUSE_DECL (c3) = iter_var;
 	    OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
 	    OMP_CLAUSE_CHAIN (c2) = c3;
@@ -5559,9 +5651,12 @@  lower_lastprivate_clauses (tree clauses,
       tree lab2 = NULL_TREE;
 
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
-	  && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+	  && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+	  && ctx->lastprivate_conditional_map)
 	{
-	  gcc_assert (body_p && ctx->lastprivate_conditional_map);
+	  gcc_assert (body_p);
+	  if (simduid)
+	    goto next;
 	  if (cond_ptr == NULL_TREE)
 	    {
 	      cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
@@ -5701,6 +5796,7 @@  lower_lastprivate_clauses (tree clauses,
 	    gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
 	}
 
+     next:
       c = OMP_CLAUSE_CHAIN (c);
       if (c == NULL && !par_clauses)
 	{
@@ -6826,15 +6922,15 @@  lower_omp_sections (gimple_stmt_iterator
       gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
     }
 
+  tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
+  lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
+
   lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
       			   &ilist, &dlist, ctx, NULL);
 
   control = create_tmp_var (unsigned_type_node, ".section");
   gimple_omp_sections_set_control (stmt, control);
 
-  tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
-  lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
-
   new_body = gimple_omp_body (stmt);
   gimple_omp_set_body (stmt, NULL);
   tgsi = gsi_start (new_body);
@@ -8486,14 +8582,14 @@  lower_omp_for (gimple_stmt_iterator *gsi
       gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
     }
 
+  lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
+					 ctx);
+
   lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
 			   fdp);
   gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
 		      gimple_omp_for_pre_body (stmt));
 
-  lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
-					 ctx);
-
   lower_omp (gimple_omp_body_ptr (stmt), ctx);
 
   /* Lower the header expressions.  At this point, we can assume that
@@ -10721,8 +10817,10 @@  lower_omp_1 (gimple_stmt_iterator *gsi_p
 		else
 		  clauses = gimple_omp_sections_clauses (up->stmt);
 		tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
-		c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
-				     OMP_CLAUSE__CONDTEMP_);
+		if (!OMP_CLAUSE__CONDTEMP__ITER (c))
+		  c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+				       OMP_CLAUSE__CONDTEMP_);
+		gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
 		gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
 		gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
 	      }
--- gcc/omp-expand.c.jj	2019-05-30 23:19:14.470931743 +0200
+++ gcc/omp-expand.c	2019-05-31 17:53:31.488672774 +0200
@@ -4908,7 +4908,10 @@  expand_omp_simd (struct omp_region *regi
 			      OMP_CLAUSE_IF);
   tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
 				  OMP_CLAUSE_SIMDLEN);
+  tree condtemp = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+				   OMP_CLAUSE__CONDTEMP_);
   tree n1, n2;
+  tree cond_var = condtemp ? OMP_CLAUSE_DECL (condtemp) : NULL_TREE;
 
   if (safelen)
     {
@@ -5038,6 +5041,18 @@  expand_omp_simd (struct omp_region *regi
 	    expand_omp_build_assign (&gsi, fd->loops[i].v, t);
 	  }
     }
+  if (cond_var)
+    {
+      if (POINTER_TYPE_P (type)
+	  || TREE_CODE (n1) != INTEGER_CST
+	  || fd->loop.cond_code != LT_EXPR
+	  || tree_int_cst_sgn (n1) != 1)
+	expand_omp_build_assign (&gsi, cond_var,
+				 build_one_cst (TREE_TYPE (cond_var)));
+      else
+	expand_omp_build_assign (&gsi, cond_var,
+				 fold_convert (TREE_TYPE (cond_var), n1));
+    }
 
   /* Remove the GIMPLE_OMP_FOR statement.  */
   gsi_remove (&gsi, true);
@@ -5103,6 +5118,19 @@  expand_omp_simd (struct omp_region *regi
 	      expand_omp_build_assign (&gsi, fd->loops[i].v, t);
 	    }
 	}
+      if (cond_var)
+	{
+	  if (POINTER_TYPE_P (type)
+	      || TREE_CODE (n1) != INTEGER_CST
+	      || fd->loop.cond_code != LT_EXPR
+	      || tree_int_cst_sgn (n1) != 1)
+	    t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+			     build_one_cst (TREE_TYPE (cond_var)));
+	  else
+	    t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+			     fold_convert (TREE_TYPE (cond_var), step));
+	  expand_omp_build_assign (&gsi, cond_var, t);
+	}
 
       /* Remove GIMPLE_OMP_CONTINUE.  */
       gsi_remove (&gsi, true);
--- gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c.jj	2019-05-29 09:49:20.450598508 +0200
+++ gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c	2019-05-31 19:49:36.577018973 +0200
@@ -8,7 +8,7 @@  foo (int *p)
   for (i = 0; i < 32; i++)
     if (p[i])
       a = i;
-  #pragma omp simd lastprivate (conditional: b) /* { dg-message "not supported yet" } */
+  #pragma omp simd lastprivate (conditional: b)
   for (i = 0; i < 32; i++)
     if (p[i])
       b = i;
--- gcc/testsuite/gcc.dg/vect/vect-simd-6.c.jj	2019-05-31 18:33:20.810088504 +0200
+++ gcc/testsuite/gcc.dg/vect/vect-simd-6.c	2019-05-31 18:39:27.113174246 +0200
@@ -0,0 +1,52 @@ 
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-final { scan-tree-dump-times "vectorized \[12] loops" 2 "vect" { target vect_condition } } } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+  int x = 5;
+  #pragma omp simd lastprivate (conditional: x)
+  for (int i = 0; i < 128; i++)
+    if (a[i])
+      x = a[i];
+  return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp simd lastprivate (conditional: x, v)
+  for (int i = 16; i < 128; ++i)
+    {
+      if (a[i])
+	x = a[i];
+      if (b[i])
+	v = b[i] + 10;
+    }
+  return x;
+}
+
+int
+main ()
+{
+  int a[128], b[128], i;
+  check_vect ();
+  for (i = 0; i < 128; i++)
+    {
+      a[i] = ((i % 11) == 2) ? i + 10 : 0;
+      asm volatile ("" : "+g" (i));
+      b[i] = ((i % 13) == 5) ? i * 2 : 0;
+    }
+  if (foo (a) != 133)
+    abort ();
+  if (bar (b, a) != 244)
+    abort ();
+  if (v != 143)
+    abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/vect/vect-simd-7.c.jj	2019-05-31 19:36:59.609320792 +0200
+++ gcc/testsuite/gcc.dg/vect/vect-simd-7.c	2019-05-31 19:37:18.718010587 +0200
@@ -0,0 +1,51 @@ 
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+  int x = 5;
+  #pragma omp simd lastprivate (conditional: x) safelen (1)
+  for (int i = 0; i < 128; i++)
+    if (a[i])
+      x = a[i];
+  return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+  int x = 0;
+  #pragma omp simd lastprivate (conditional: x, v) if (0)
+  for (int i = 16; i < 128; ++i)
+    {
+      if (a[i])
+	x = a[i];
+      if (b[i])
+	v = b[i] + 10;
+    }
+  return x;
+}
+
+int
+main ()
+{
+  int a[128], b[128], i;
+  check_vect ();
+  for (i = 0; i < 128; i++)
+    {
+      a[i] = ((i % 11) == 2) ? i + 10 : 0;
+      asm volatile ("" : "+g" (i));
+      b[i] = ((i % 13) == 5) ? i * 2 : 0;
+    }
+  if (foo (a) != 133)
+    abort ();
+  if (bar (b, a) != 244)
+    abort ();
+  if (v != 143)
+    abort ();
+  return 0;
+}