diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index be3f64dad304bc2aad8fd564d08fbdddb856f0bf..f0ecfdde5b5045fab136b4490a719e2708a924c4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2014-11-13  Tom de Vries  <tom@codesourcery.com>
+
+	* omp-low.c (pass_data_expand_omp): Set properties_provided to
+	PROP_gimple_eomp.
+	(pass_expand_omp::gate): Remove function.  Move gate expression to ...
+	(pass_expand_omp::execute): ... here, as new variable gate.  Add early
+	exit if gate is false.
+	(pass_data pass_data_expand_omp_ssa): New pass_data.
+	(class pass_expand_omp_ssa): New pass.
+	(make_pass_expand_omp_ssa): New function.
+	* passes.def (pass_parallelize_loops): Use PUSH_INSERT_PASSES_WITHIN
+	instead of NEXT_PASS.
+	(pass_expand_omp_ssa): Add after pass_parallelize_loops.
+	* tree-parloops.c (gen_parallel_loop): Remove call to omp_expand_local.
+	(pass_parallelize_loops::execute): Don't do cleanups TODO_cleanup_cfg
+	and TODO_rebuild_alias yet.  Add TODO_update_ssa.  Set
+	cfun->omp_expand_needed.
+	* tree-pass.h: Add define PROP_gimple_eomp.
+	(make_pass_expand_omp_ssa): Declare.
+
 2014-11-13  Marek Polacek  <polacek@redhat.com>
 
 	* tree.h (TYPE_OVERFLOW_SANITIZED): Define.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index b59d069ac144c222911d8cfebbc0a680a8d0ae5a..e7d8a7e916e6e408a237097a019269b98b4061ab 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -8801,7 +8801,7 @@ const pass_data pass_data_expand_omp =
   OPTGROUP_NONE, /* optinfo_flags */
   TV_NONE, /* tv_id */
   PROP_gimple_any, /* properties_required */
-  0, /* properties_provided */
+  PROP_gimple_eomp, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
   0, /* todo_flags_finish */
@@ -8815,13 +8815,18 @@ public:
   {}
 
   /* opt_pass methods: */
-  virtual bool gate (function *)
+  virtual unsigned int execute (function *)
     {
-      return ((flag_openmp != 0 || flag_openmp_simd != 0
-	       || flag_cilkplus != 0) && !seen_error ());
-    }
+      bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
+		    || flag_cilkplus != 0) && !seen_error ());
 
-  virtual unsigned int execute (function *) { return execute_expand_omp (); }
+      /* This pass always runs, to provide PROP_gimple_eomp.
+	 But there is nothing to do unless -fopenmp is given.  */
+      if (!gate)
+	return 0;
+
+      return execute_expand_omp ();
+    }
 
 }; // class pass_expand_omp
 
@@ -8832,6 +8837,45 @@ make_pass_expand_omp (gcc::context *ctxt)
 {
   return new pass_expand_omp (ctxt);
 }
+
+namespace {
+
+const pass_data pass_data_expand_omp_ssa =
+{
+  GIMPLE_PASS, /* type */
+  "ompexpssa", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  PROP_cfg | PROP_ssa, /* properties_required */
+  PROP_gimple_eomp, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
+};
+
+class pass_expand_omp_ssa : public gimple_opt_pass
+{
+public:
+  pass_expand_omp_ssa (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *fun)
+    {
+      return !(fun->curr_properties & PROP_gimple_eomp);
+    }
+  virtual unsigned int execute (function *) { return execute_expand_omp (); }
+
+}; // class pass_expand_omp_ssa
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_expand_omp_ssa (gcc::context *ctxt)
+{
+  return new pass_expand_omp_ssa (ctxt);
+}
 
 /* Routines to lower OpenMP directives into OMP-GIMPLE.  */
 
diff --git a/gcc/passes.def b/gcc/passes.def
index 2305d670663de3dba18fe9ef71cafec216d6d18e..ebd2b9547cee8dea90e68f64d55fdfa4fe36c6e1 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -241,6 +241,9 @@ along with GCC; see the file COPYING3.  If not see
 	  POP_INSERT_PASSES ()
 	  NEXT_PASS (pass_iv_canon);
 	  NEXT_PASS (pass_parallelize_loops);
+	  PUSH_INSERT_PASSES_WITHIN (pass_parallelize_loops)
+	      NEXT_PASS (pass_expand_omp_ssa);
+	  POP_INSERT_PASSES ()
 	  NEXT_PASS (pass_if_conversion);
 	  /* pass_vectorize must immediately follow pass_if_conversion.
 	     Please do not add any other passes in between.  */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 09b3f163c11ab0519a18dab479cff6348a3bf1a0..e5dca78082cfe0756cffdf8a8197aec2a851c79d 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1753,7 +1753,6 @@ gen_parallel_loop (struct loop *loop,
   tree many_iterations_cond, type, nit;
   tree arg_struct, new_arg_struct;
   gimple_seq stmts;
-  basic_block parallel_head;
   edge entry, exit;
   struct clsn_data clsn_data;
   unsigned prob;
@@ -1891,8 +1890,8 @@ gen_parallel_loop (struct loop *loop,
   cond_stmt = last_stmt (loop->header);
   if (cond_stmt)
     loc = gimple_location (cond_stmt);
-  parallel_head = create_parallel_loop (loop, create_loop_fn (loc), arg_struct,
-					new_arg_struct, n_threads, loc);
+  create_parallel_loop (loop, create_loop_fn (loc), arg_struct,
+			new_arg_struct, n_threads, loc);
   if (reduction_list->elements () > 0)
     create_call_for_reduction (loop, reduction_list, &clsn_data);
 
@@ -1906,13 +1905,6 @@ gen_parallel_loop (struct loop *loop,
      removed statements.  */
   FOR_EACH_LOOP (loop, 0)
     free_numbers_of_iterations_estimates_loop (loop);
-
-  /* Expand the parallel constructs.  We do it directly here instead of running
-     a separate expand_omp pass, since it is more efficient, and less likely to
-     cause troubles with further analyses not being able to deal with the
-     OMP trees.  */
-
-  omp_expand_local (parallel_head);
 }
 
 /* Returns true when LOOP contains vector phi nodes.  */
@@ -2284,7 +2276,11 @@ pass_parallelize_loops::execute (function *fun)
     return 0;
 
   if (parallelize_loops ())
-    return TODO_cleanup_cfg | TODO_rebuild_alias;
+    {
+      fun->curr_properties &= ~(PROP_gimple_eomp);
+      return TODO_update_ssa;
+    }
+
   return 0;
 }
 
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index a3efdd84b081a81e7de678eb80d00861105e40a3..25ff364a1ad159523c136a755c1759654af62c60 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -220,6 +220,7 @@ protected:
 #define PROP_gimple_lcx		(1 << 10)       /* lowered complex */
 #define PROP_loops		(1 << 11)	/* preserve loop structures */
 #define PROP_gimple_lvec	(1 << 12)       /* lowered vector */
+#define PROP_gimple_eomp	(1 << 13)       /* no OpenMP directives */
 
 #define PROP_trees \
   (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
@@ -399,6 +400,7 @@ extern gimple_opt_pass *make_pass_lower_vector_ssa (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_lower_omp (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_diagnose_omp_blocks (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_expand_omp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_expand_omp_ssa (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_fold_builtins (gcc::context *ctxt);