+static tree
+find_reachable_label_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
+{
+ switch (TREE_CODE (*tp))
+ {
+ case LABEL_STMT:
+ case CASE_LABEL:
+ return *tp;
+
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
+/* Determine whether expression EXP contains a potentially
+ reachable label. */
+static tree
+find_reachable_label (tree exp)
+{
+ location_t saved_loc = input_location;
+ tree ret = walk_tree_without_duplicates
+ (&exp, find_reachable_label_1, NULL);
+ input_location = saved_loc;
+ return ret;
+}
+
+/* Expand an unreachable if statement, T. This function returns
+ true if the IF_STMT contains a potentially reachable code_label. */
+static bool
+expand_unreachable_if_stmt (tree t)
+{
+ tree n;
+
+ if (find_reachable_label (IF_COND (t)) != NULL_TREE)
+ {
+ genrtl_if_stmt (t);
+ return true;
+ }
+
+ if (THEN_CLAUSE (t) && ELSE_CLAUSE (t))
+ {
+ n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
+
+ if (n != NULL_TREE)
+ {
+ rtx label;
+ expand_stmt (n);
+ label = gen_label_rtx ();
+ emit_jump (label);
+ expand_stmt (expand_unreachable_stmt (ELSE_CLAUSE (t), 0));
+ emit_label (label);
+ return true;
+ }
+ else
+ n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+ }
+ else if (THEN_CLAUSE (t))
+ n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
+ else if (ELSE_CLAUSE (t))
+ n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+ else
+ n = NULL_TREE;
+
+ expand_stmt (n);
+
+ return n != NULL_TREE;
+}
+
+/* Expand an unreachable statement list. This function skips all
+ statements preceding the first potentially reachable label and
+ then returns the label (or, in same cases, the statement after
+ one containing the label). */
+static tree
+expand_unreachable_stmt (tree t, int warn)
+{
+ int saved;
+
+ while (t && t != error_mark_node)
+ {
+ if (warn)
+ switch (TREE_CODE (t))
+ {
+ case BREAK_STMT:
+ case CONTINUE_STMT:
+ case EXPR_STMT:
+ case GOTO_STMT:
+ case IF_STMT:
+ case RETURN_STMT:
+ if (!STMT_LINENO_FOR_FN_P (t))
+ input_line = STMT_LINENO (t);
+ warning("will never be executed");
+ warn = false;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (TREE_CODE (t))
+ {
+ case GOTO_STMT:
+ case CONTINUE_STMT:
+ case BREAK_STMT:
+ break;
+
+ case FILE_STMT:
+ input_filename = FILE_STMT_FILENAME (t);
+ break;
+
+ case RETURN_STMT:
+ if (find_reachable_label (RETURN_STMT_EXPR (t)) != NULL_TREE)
+ return t;
+ break;
+
+ case EXPR_STMT:
+ if (find_reachable_label (EXPR_STMT_EXPR (t)) != NULL_TREE)
+ return t;
+ break;
+
+ case IF_STMT:
+ if (expand_unreachable_if_stmt (t))
+ return TREE_CHAIN (t);
+ break;
+
+ case WHILE_STMT:
+ /* If the start of a while statement is unreachable, there is
+ no need to rotate the loop, instead the WHILE_STMT can be
+ expanded like a DO_STMT. */
+ genrtl_do_stmt_1 (WHILE_COND (t), WHILE_BODY (t));
+ return TREE_CHAIN (t);
+
+ case COMPOUND_STMT:
+ {
+ tree n;
+ n = expand_unreachable_stmt (COMPOUND_BODY (t), warn);
+ if (n != NULL_TREE)
+ {
+ expand_stmt (n);
+ return TREE_CHAIN (t);
+ }
+ warn = false;
+ break;
+ }
+
+ case SCOPE_STMT:
+ saved = stmts_are_full_exprs_p ();
+ prep_stmt (t);
+ genrtl_scope_stmt (t);
+ current_stmt_tree ()->stmts_are_full_exprs_p = saved;
+ break;
+
+ default:
+ return t;
+ }