diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 32eb882f40e..6b6add62651 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+	PR tree-optimization/60003
+	* gimple-low.c (lower_builtin_setjmp): Set cfun->has_nonlocal_label.
+	* profile.c (branch_prob): Use gimple_call_builtin_p
+	to check for BUILT_IN_SETJMP_RECEIVER.
+	* tree-inline.c (copy_bb): Call notice_special_calls.
+
 2014-01-31  Vladimir Makarov  <vmakarov@redhat.com>
 
 	PR bootstrap/59985
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index c60e8177d38..5fbcf3f34ac 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -709,6 +709,12 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi)
   tree dest, t, arg;
   gimple g;
 
+  /* __builtin_setjmp_{setup,receiver} aren't ECF_RETURNS_TWICE and for RTL
+     these builtins are modelled as non-local label jumps to the label
+     that is passed to these two builtins, so pretend we have a non-local
+     label during GIMPLE passes too.  See PR60003.  */ 
+  cfun->has_nonlocal_label = true;
+
   /* NEXT_LABEL is the label __builtin_longjmp will jump to.  Its address is
      passed to both __builtin_setjmp_setup and __builtin_setjmp_receiver.  */
   FORCED_LABEL (next_label) = 1;
diff --git a/gcc/profile.c b/gcc/profile.c
index 752d89fc3d8..83cbc07967b 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -1104,7 +1104,6 @@ branch_prob (void)
 	    {
 	      gimple_stmt_iterator gsi;
 	      gimple first;
-	      tree fndecl;
 
 	      gsi = gsi_start_nondebug_after_labels_bb (bb);
 	      gcc_checking_assert (!gsi_end_p (gsi));
@@ -1114,10 +1113,7 @@ branch_prob (void)
 		 special and don't expect anything to be inserted before
 		 them.  */
 	      if (is_gimple_call (first)
-		  && (((fndecl = gimple_call_fndecl (first)) != NULL
-		       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-		       && (DECL_FUNCTION_CODE (fndecl)
-			   == BUILT_IN_SETJMP_RECEIVER))
+		  && (gimple_call_builtin_p (first, BUILT_IN_SETJMP_RECEIVER)
 		      || (gimple_call_flags (first) & ECF_RETURNS_TWICE)
 		      || (gimple_call_internal_p (first)
 			  && (gimple_call_internal_fn (first)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b1a657aea92..302425935df 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-01  Jakub Jelinek  <jakub@redhat.com>
+
+	PR tree-optimization/60003
+	* gcc.c-torture/execute/pr60003.c: New test.
+
 2014-01-31  Vladimir Makarov  <vmakarov@redhat.com>
 
 	PR bootstrap/59985
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60003.c b/gcc/testsuite/gcc.c-torture/execute/pr60003.c
new file mode 100644
index 00000000000..94d9cf88698
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60003.c
@@ -0,0 +1,48 @@
+/* PR tree-optimization/60003 */
+
+extern void abort (void);
+
+unsigned long long jmp_buf[5];
+
+__attribute__((noinline, noclone)) void
+baz (void)
+{
+  __builtin_longjmp (&jmp_buf, 1);
+}
+
+void
+bar (void)
+{
+  baz ();
+}
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+  int a = 0;
+
+  if (__builtin_setjmp (&jmp_buf) == 0)
+    {
+      while (1)
+	{
+	  a = 1;
+	  bar ();  /* OK if baz () instead */
+	}
+    }
+  else
+    {
+      if (a == 0)
+	return 0;
+      else
+	return x;
+    }
+}
+
+int
+main ()
+{
+  if (foo (1) == 0)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 79a39bca136..439ef4c2933 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1745,7 +1745,6 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 	  if (is_gimple_call (stmt))
 	    {
 	      struct cgraph_edge *edge;
-	      int flags;
 
 	      switch (id->transform_call_graph_edges)
 		{
@@ -1868,11 +1867,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 		    }
 		}
 
-	      flags = gimple_call_flags (stmt);
-	      if (flags & ECF_MAY_BE_ALLOCA)
-		cfun->calls_alloca = true;
-	      if (flags & ECF_RETURNS_TWICE)
-		cfun->calls_setjmp = true;
+	      notice_special_calls (stmt);
 	    }
 
 	  maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,