Beispiel #1
0
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;
}
Beispiel #2
0
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;
    }
}