--- gcc/cfgloop.h.jj	2013-05-13 16:49:44.000000000 +0200
+++ gcc/cfgloop.h	2013-05-13 17:30:18.630883633 +0200
@@ -176,6 +176,12 @@ struct GTY ((chain_next ("%h.next"))) lo
 
   /* Number of iteration analysis data for RTL.  */
   struct niter_desc *simple_loop_desc;
+
+  /* If non-NULL, an INTEGER_CST, where the user asserted that for any
+     I in [ 0, nb_iterations ) and for any J in
+     [ I, min ( I + safelen, nb_iterations ) ), the Ith and Jth iterations
+     of the loop can be safely evaluated concurrently.  */
+  tree safelen;
 };
 
 /* Flags for state of loop structure.  */
--- gcc/omp-low.c.jj	2013-05-13 16:37:05.000000000 +0200
+++ gcc/omp-low.c	2013-05-13 18:46:18.310405585 +0200
@@ -4960,6 +4960,8 @@ expand_omp_simd (struct omp_region *regi
   edge e, ne;
   tree *counts = NULL;
   int i;
+  tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+				  OMP_CLAUSE_SAFELEN);
 
   type = TREE_TYPE (fd->loop.v);
   entry_bb = region->entry;
@@ -5157,6 +5159,22 @@ expand_omp_simd (struct omp_region *regi
   set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
   set_immediate_dominator (CDI_DOMINATORS, l2_bb, l1_bb);
   set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
+
+  if (!broken_loop)
+    {
+      struct loop *loop;
+      calculate_dominance_info (CDI_DOMINATORS);
+      fix_loop_structure (NULL);
+      loop = l1_bb->loop_father;
+      if (safelen == NULL_TREE)
+	{
+	  safelen = build_nonstandard_integer_type (TYPE_PRECISION (type), 1);
+	  safelen = TYPE_MAX_VALUE (safelen);
+	}
+      else
+	safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
+      loop->safelen = safelen;
+    }
 }
 
 
--- gcc/tree-vectorizer.c.jj	2013-05-13 16:49:03.000000000 +0200
+++ gcc/tree-vectorizer.c	2013-05-13 20:44:58.721863725 +0200
@@ -101,7 +101,8 @@ vectorize_loops (void)
      than all previously defined loops.  This fact allows us to run
      only over initial loops skipping newly generated ones.  */
   FOR_EACH_LOOP (li, loop, 0)
-    if (optimize_loop_nest_for_speed_p (loop))
+    if ((flag_tree_vectorize && optimize_loop_nest_for_speed_p (loop))
+	|| loop->safelen)
       {
 	loop_vec_info loop_vinfo;
 	vect_location = find_loop_location (loop);
@@ -122,6 +123,9 @@ vectorize_loops (void)
                        LOC_FILE (vect_location), LOC_LINE (vect_location));
 	vect_transform_loop (loop_vinfo);
 	num_vectorized_loops++;
+	/* Now that the loop has been vectorized, allow it to be unrolled
+	   etc.  */
+	loop->safelen = NULL_TREE;
       }
 
   vect_location = UNKNOWN_LOC;
--- gcc/tree-ssa-loop.c.jj	2013-05-13 16:46:36.000000000 +0200
+++ gcc/tree-ssa-loop.c	2013-05-13 19:12:57.301538324 +0200
@@ -225,7 +225,8 @@ tree_vectorize (void)
 static bool
 gate_tree_vectorize (void)
 {
-  return flag_tree_vectorize;
+  return flag_tree_vectorize
+	 || (flag_openmp && !global_options_set.x_flag_tree_vectorize);
 }
 
 struct gimple_opt_pass pass_vectorize =
--- gcc/tree-ssa-loop-ivcanon.c.jj	2013-05-13 16:46:36.000000000 +0200
+++ gcc/tree-ssa-loop-ivcanon.c	2013-05-13 20:06:44.176519188 +0200
@@ -1123,6 +1123,11 @@ tree_unroll_loops_completely_1 (bool may
   if (changed)
     return true;
 
+  /* Don't unroll #pragma omp simd loops until the vectorizer
+     attempts to vectorize those.  */
+  if (loop->safelen)
+    return false;
+
   /* Try to unroll this loop.  */
   loop_father = loop_outer (loop);
   if (!loop_father)
--- gcc/tree-vect-data-refs.c.jj	2013-05-13 16:49:08.000000000 +0200
+++ gcc/tree-vect-data-refs.c	2013-05-13 20:41:51.579889330 +0200
@@ -255,6 +255,16 @@ vect_analyze_data_ref_dependence (struct
   /* Unknown data dependence.  */
   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
     {
+      /* If user asserted there safelen consecutive iterations can be
+	 executed concurrently, and safelen >= *max_vf, assume
+	 independence.  */
+      if (loop->safelen)
+	{
+	  if (compare_tree_int (loop->safelen, *max_vf) < 0)
+	    *max_vf = tree_low_cst (loop->safelen, 0);
+	  return false;
+	}
+
       if (STMT_VINFO_GATHER_P (stmtinfo_a)
 	  || STMT_VINFO_GATHER_P (stmtinfo_b))
 	{
@@ -291,6 +301,16 @@ vect_analyze_data_ref_dependence (struct
   /* Known data dependence.  */
   if (DDR_NUM_DIST_VECTS (ddr) == 0)
     {
+      /* If user asserted there safelen consecutive iterations can be
+	 executed concurrently, and safelen >= *max_vf, assume
+	 independence.  */
+      if (loop->safelen)
+	{
+	  if (compare_tree_int (loop->safelen, *max_vf) < 0)
+	    *max_vf = tree_low_cst (loop->safelen, 0);
+	  return false;
+	}
+
       if (STMT_VINFO_GATHER_P (stmtinfo_a)
 	  || STMT_VINFO_GATHER_P (stmtinfo_b))
 	{
--- gcc/tree-if-conv.c.jj	2013-05-13 16:49:06.000000000 +0200
+++ gcc/tree-if-conv.c	2013-05-13 19:08:27.227188600 +0200
@@ -1822,6 +1822,10 @@ main_tree_if_conversion (void)
     return 0;
 
   FOR_EACH_LOOP (li, loop, 0)
+    if (flag_tree_loop_if_convert == 1
+	|| flag_tree_loop_if_convert_stores == 1
+	|| flag_tree_vectorize
+	|| loop->safelen)
     changed |= tree_if_conversion (loop);
 
   if (changed)
@@ -1848,7 +1852,9 @@ main_tree_if_conversion (void)
 static bool
 gate_tree_if_conversion (void)
 {
-  return ((flag_tree_vectorize && flag_tree_loop_if_convert != 0)
+  return (((flag_tree_vectorize
+	    || (flag_openmp && !global_options_set.x_flag_tree_vectorize))
+	   && flag_tree_loop_if_convert != 0)
 	  || flag_tree_loop_if_convert == 1
 	  || flag_tree_loop_if_convert_stores == 1);
 }
