static basic_block expand_gimple_cond_expr (basic_block bb, tree stmt) { basic_block new_bb, dest; edge new_edge; edge true_edge; edge false_edge; tree pred = COND_EXPR_COND (stmt); tree then_exp = COND_EXPR_THEN (stmt); tree else_exp = COND_EXPR_ELSE (stmt); rtx last2, last; last2 = last = get_last_insn (); extract_true_false_edges_from_block (bb, &true_edge, &false_edge); if (EXPR_LOCUS (stmt)) { emit_line_note (*(EXPR_LOCUS (stmt))); record_block_change (TREE_BLOCK (stmt)); } /* These flags have no purpose in RTL land. */ true_edge->flags &= ~EDGE_TRUE_VALUE; false_edge->flags &= ~EDGE_FALSE_VALUE; /* We can either have a pure conditional jump with one fallthru edge or two-way jump that needs to be decomposed into two basic blocks. */ if (TREE_CODE (then_exp) == GOTO_EXPR && IS_EMPTY_STMT (else_exp)) { jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp))); add_reg_br_prob_note (dump_file, last, true_edge->probability); maybe_dump_rtl_for_tree_stmt (stmt, last); if (EXPR_LOCUS (then_exp)) emit_line_note (*(EXPR_LOCUS (then_exp))); return NULL; } if (TREE_CODE (else_exp) == GOTO_EXPR && IS_EMPTY_STMT (then_exp)) { jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp))); add_reg_br_prob_note (dump_file, last, false_edge->probability); maybe_dump_rtl_for_tree_stmt (stmt, last); if (EXPR_LOCUS (else_exp)) emit_line_note (*(EXPR_LOCUS (else_exp))); return NULL; } gcc_assert (TREE_CODE (then_exp) == GOTO_EXPR && TREE_CODE (else_exp) == GOTO_EXPR); jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp))); add_reg_br_prob_note (dump_file, last, true_edge->probability); last = get_last_insn (); expand_expr (else_exp, const0_rtx, VOIDmode, 0); BB_END (bb) = last; if (BARRIER_P (BB_END (bb))) BB_END (bb) = PREV_INSN (BB_END (bb)); update_bb_for_insn (bb); new_bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb); dest = false_edge->dest; redirect_edge_succ (false_edge, new_bb); false_edge->flags |= EDGE_FALLTHRU; new_bb->count = false_edge->count; new_bb->frequency = EDGE_FREQUENCY (false_edge); new_edge = make_edge (new_bb, dest, 0); new_edge->probability = REG_BR_PROB_BASE; new_edge->count = new_bb->count; if (BARRIER_P (BB_END (new_bb))) BB_END (new_bb) = PREV_INSN (BB_END (new_bb)); update_bb_for_insn (new_bb); maybe_dump_rtl_for_tree_stmt (stmt, last2); if (EXPR_LOCUS (else_exp)) emit_line_note (*(EXPR_LOCUS (else_exp))); return new_bb; }
void expand_stmt (tree t) { while (t && t != error_mark_node) { int saved_stmts_are_full_exprs_p; /* Set up context appropriately for handling this statement. */ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); prep_stmt (t); switch (TREE_CODE (t)) { case FILE_STMT: input_filename = FILE_STMT_FILENAME (t); break; case RETURN_STMT: genrtl_return_stmt (t); t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); goto process_t; case EXPR_STMT: genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t), TREE_CHAIN (t) == NULL || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT && TREE_CHAIN (TREE_CHAIN (t)) == NULL)); break; case DECL_STMT: genrtl_decl_stmt (t); break; case FOR_STMT: genrtl_for_stmt (t); break; case WHILE_STMT: genrtl_while_stmt (t); break; case DO_STMT: genrtl_do_stmt (t); break; case IF_STMT: genrtl_if_stmt (t); break; case COMPOUND_STMT: genrtl_compound_stmt (t); break; case BREAK_STMT: genrtl_break_stmt (); t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); goto process_t; case CONTINUE_STMT: genrtl_continue_stmt (); t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); goto process_t; case SWITCH_STMT: genrtl_switch_stmt (t); break; case CASE_LABEL: genrtl_case_label (t); break; case LABEL_STMT: expand_label (LABEL_STMT_LABEL (t)); break; case GOTO_STMT: /* Emit information for branch prediction. */ if (!GOTO_FAKE_P (t) && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL && flag_guess_branch_prob) { rtx note = emit_note (NOTE_INSN_PREDICTION); NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN); } genrtl_goto_stmt (GOTO_DESTINATION (t)); t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached); goto process_t; case ASM_STMT: genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t), ASM_INPUT_P (t)); break; case SCOPE_STMT: genrtl_scope_stmt (t); break; case CLEANUP_STMT: genrtl_cleanup_stmt (t); break; default: if (lang_expand_stmt) (*lang_expand_stmt) (t); else abort (); break; } /* Go on to the next statement in this scope. */ t = TREE_CHAIN (t); process_t: /* Restore saved state. */ current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; } }