diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 129dd727ef3..80091d81bb4 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -2537,6 +2537,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	  in_late_binary_op = true;
 	  c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
 				      specs->declspec_il,
+				      specs->loops_state,
 				      specs->entry_bb_count);
 	  in_late_binary_op = saved;
 	}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c70f0ba5ab6..b2a5b75b05f 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -343,6 +343,9 @@ struct c_declspecs {
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
+  /* The loop specific IL state for __GIMPLE and __RTL, maps to
+     the enum in cfgloop.h.  */
+  unsigned loops_state : 8;
   /* The kind of type specifier if one has been seen, ctsk_none
      otherwise.  */
   ENUM_BITFIELD (c_typespec_kind) typespec_kind : 4;
diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc
index d1afd42556c..095684f549f 100644
--- a/gcc/c/gimple-parser.cc
+++ b/gcc/c/gimple-parser.cc
@@ -211,6 +211,7 @@ c_parser_gimple_parse_bb_spec_edge_probability (tree val,
 void
 c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
 			    enum c_declspec_il cdil,
+			    unsigned loops_state,
 			    profile_count entry_bb_count)
 {
   gimple_parser parser (cparser);
@@ -240,7 +241,11 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
          mark headers and leave the rest to fixup.  */
       set_loops_for_fn (cfun, ggc_cleared_alloc<struct loops> ());
       init_loops_structure (cfun, loops_for_fn (cfun), 1);
-      loops_state_set (cfun, LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+      if (loops_state == 0)
+	loops_state_set (cfun,
+			 LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+      else
+	loops_state_set (cfun, LOOPS_NEED_FIXUP|loops_state);
       cfun->curr_properties
 	|= PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_loops;
       if (cdil == cdil_gimple_ssa)
@@ -1975,6 +1980,36 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
 	  if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
 	    return;
 	}
+      else if (! strcmp (op, "loops"))
+	{
+	  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+	    {
+	      c_parser_consume_token (parser);
+	      while (c_parser_next_token_is (parser, CPP_NAME))
+		{
+		  const char *lop
+		    = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+		  c_parser_consume_token (parser);
+		  if (! strcmp (lop, "normal"))
+		    specs->loops_state |= LOOPS_NORMAL;
+		  else if (! strcmp (lop, "lcssa"))
+		    specs->loops_state |= LOOP_CLOSED_SSA;
+		  else
+		    {
+		      error_at (c_parser_peek_token (parser)->location,
+				"invalid loop state");
+		      return;
+		    }
+		  if (c_parser_next_token_is (parser, CPP_COMMA))
+		    c_parser_consume_token (parser);
+		}
+	      if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+		return;
+	    }
+	  else
+	    /* LOOPS_NORMAL */
+	    specs->loops_state = LOOPS_NORMAL;
+	}
       else if (specs->declspec_il != cdil_gimple)
 	/* Allow only one IL specifier and none on RTL.  */
 	;
diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
index 2881a657640..6aed6010343 100644
--- a/gcc/c/gimple-parser.h
+++ b/gcc/c/gimple-parser.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Gimple parsing functions.  */
 extern void c_parser_parse_gimple_body (c_parser *, char *,
 					enum c_declspec_il,
+					unsigned loops_state,
 					profile_count);
 extern void c_parser_gimple_or_rtl_pass_list (c_parser *, c_declspecs *);
 
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 18047c209a8..348ba878331 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -777,7 +777,9 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
 
   gcc_checking_assert (node->has_gimple_body_p ());
 
-  if (!opt_for_fn (node->decl, flag_ipa_cp_clone))
+  if (!opt_for_fn (node->decl, flag_ipa_cp_clone)
+      || (DECL_STRUCT_FUNCTION (node->decl)
+	  && DECL_STRUCT_FUNCTION (node->decl)->pass_startwith))
     {
       if (dump_file)
 	fprintf (dump_file, "Not considering %s for cloning; "
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 0d7e395c846..10b679bbb27 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -4354,7 +4354,9 @@ ipa_fn_summary_generate (void)
   FOR_EACH_DEFINED_FUNCTION (node)
     if (!node->alias
 	&& (flag_generate_lto || flag_generate_offload|| flag_wpa
-	    || opt_for_fn (node->decl, optimize)))
+	    || opt_for_fn (node->decl, optimize))
+	&& !(DECL_STRUCT_FUNCTION (node->decl)
+	     && DECL_STRUCT_FUNCTION (node->decl)->pass_startwith))
       inline_analyze_function (node);
 }
 
diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
index f8bb072c422..8352e9f0dce 100644
--- a/gcc/ipa-inline.cc
+++ b/gcc/ipa-inline.cc
@@ -1974,7 +1974,9 @@ inline_small_functions (void)
       {
 	if (!node->alias && node->analyzed
 	    && (node->has_gimple_body_p () || node->thunk)
-	    && opt_for_fn (node->decl, optimize))
+	    && opt_for_fn (node->decl, optimize)
+	    && !(DECL_STRUCT_FUNCTION (node->decl)
+		 && DECL_STRUCT_FUNCTION (node->decl)->pass_startwith))
 	  {
 	    class ipa_fn_summary *info = ipa_fn_summaries->get (node);
 	    struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux;
@@ -2792,7 +2794,9 @@ ipa_inline (void)
 	  bool update=false;
 
 	  if (!opt_for_fn (node->decl, optimize)
-	      || !opt_for_fn (node->decl, flag_inline_functions_called_once))
+	      || !opt_for_fn (node->decl, flag_inline_functions_called_once)
+	      || (DECL_STRUCT_FUNCTION (node->decl)
+		  && DECL_STRUCT_FUNCTION (node->decl)->pass_startwith))
 	    continue;
 
 	  for (edge = node->callees; edge; edge = next)
diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index acfd7d80ff8..0f9c98bcc03 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -3370,7 +3370,7 @@ modref_generate (void)
   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
     {
       function *f = DECL_STRUCT_FUNCTION (node->decl);
-      if (!f)
+      if (!f || f->pass_startwith)
 	continue;
       push_cfun (f);
       analyze_function (true);
diff --git a/gcc/passes.cc b/gcc/passes.cc
index 00f856e0754..4dbc405cfd4 100644
--- a/gcc/passes.cc
+++ b/gcc/passes.cc
@@ -2510,6 +2510,13 @@ should_skip_pass_p (opt_pass *pass)
   if (strstr (pass->name, "build_cgraph_edges") != NULL)
     return false;
 
+  /* When the function is in LCSSA arrange for SCEV to be initialized
+     via pass_tree_loop_init.  */
+  if (loops_for_fn (cfun)
+      && loops_state_satisfies_p (cfun, LOOP_CLOSED_SSA)
+      && strstr (pass->name, "loopinit") != NULL)
+    return false;
+
   /* Don't skip df init; later RTL passes need it.  */
   if (strstr (pass->name, "dfinit") != NULL
       || strstr (pass->name, "dfinish") != NULL)
diff --git a/gcc/testsuite/gcc.dg/gimplefe-50.c b/gcc/testsuite/gcc.dg/gimplefe-50.c
new file mode 100644
index 00000000000..3565615e80b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-50.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fgimple" } */
+
+void __GIMPLE (ssa,startwith("ivcanon"),loops(normal,lcssa))
+foo (int n, double * x)
+{
+  int i;
+  __SIZETYPE__ _1;
+  __SIZETYPE__ _2;
+  double * _3;
+  double _4;
+
+  __BB(2):
+  if (n_8(D) > 0)
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(5):
+  goto __BB3;
+
+  __BB(3,loop_header(1)):
+  i_14 = __PHI (__BB6: i_11, __BB5: 0);
+  _1 = (__SIZETYPE__) i_14;
+  _2 = _1 * _Literal (__SIZETYPE__) 8u;
+  _3 = x_9(D) + _2;
+  _4 = (double) i_14;
+  __MEM <double> (_3) = _4;
+  i_11 = i_14 + 1;
+  if (n_8(D) > i_11)
+    goto __BB6;
+  else
+    goto __BB4;
+
+  __BB(6):
+  goto __BB3;
+
+  __BB(4):
+  return;
+
+}
+
+int main()
+{
+  double x[1024];
+  foo (1024, x);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr89595.c b/gcc/testsuite/gcc.dg/torture/pr89595.c
index f45dc98c3f0..65c375f69cb 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89595.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89595.c
@@ -1,4 +1,5 @@
 /* { dg-do run } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-additional-options "-fgimple" } */
 
 int __attribute__((noipa))
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-48.c b/gcc/testsuite/gcc.dg/vect/bb-slp-48.c
index dfae6177b21..b54bc580920 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-48.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-48.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-additional-options "-fgimple -fdump-tree-optimized" } */
 /* { dg-require-effective-target vect_double } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-10a.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-10a.c
index d3c2c2d7f54..790e1e7eb14 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-10a.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-10a.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-require-effective-target vect_int } */
 /* { dg-additional-options "-fgimple" } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-10b.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-10b.c
index 6a0d55def30..25c261dfa82 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-10b.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-10b.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-require-effective-target vect_int } */
 /* { dg-additional-options "-fgimple" } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-10c.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-10c.c
index 20df2626764..f3502fd3e18 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-10c.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-10c.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-require-effective-target vect_int } */
 /* { dg-additional-options "-fgimple" } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-10d.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-10d.c
index 8a512d5c14d..77cf2fc4d9e 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-10d.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-10d.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-require-effective-target vect_int } */
 /* { dg-additional-options "-fgimple" } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-10e.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-10e.c
index 268ec9db77d..879d34708b4 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-10e.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-10e.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-require-effective-target vect_int } */
 /* { dg-additional-options "-fgimple" } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c b/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
index 38994ea82a5..49d3a17108a 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
 /* { dg-additional-options "-fgimple -fdump-tree-optimized -ffast-math" } */
 
 double __GIMPLE (ssa, startwith("loop"))
diff --git a/gcc/tree-ssa-loop.cc b/gcc/tree-ssa-loop.cc
index 73aa46627b4..21878342aed 100644
--- a/gcc/tree-ssa-loop.cc
+++ b/gcc/tree-ssa-loop.cc
@@ -354,9 +354,14 @@ pass_tree_loop_init::execute (function *fun ATTRIBUTE_UNUSED)
 					      | LOOP_CLOSED_SSA)
 	&& scev_initialized_p ())
   */
-  loop_optimizer_init (LOOPS_NORMAL
-		       | LOOPS_HAVE_RECORDED_EXITS);
-  rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+  /* When a __GIMPLE testcase starts with a pass inside the loop pipeline
+     we already are in loop-closed SSA but still need to initialize SCEV.  */
+  if (!loops_state_satisfies_p (fun, LOOP_CLOSED_SSA))
+    {
+      loop_optimizer_init (LOOPS_NORMAL
+			   | LOOPS_HAVE_RECORDED_EXITS);
+      rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+    }
   scev_initialize ();
 
   return 0;
