diff options
Diffstat (limited to 'contrib/gcc/ifcvt.c')
-rw-r--r-- | contrib/gcc/ifcvt.c | 779 |
1 files changed, 437 insertions, 342 deletions
diff --git a/contrib/gcc/ifcvt.c b/contrib/gcc/ifcvt.c index c336004..640ab2c 100644 --- a/contrib/gcc/ifcvt.c +++ b/contrib/gcc/ifcvt.c @@ -1,5 +1,5 @@ /* If-conversion support. - Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -20,6 +20,8 @@ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "rtl.h" #include "regs.h" @@ -33,8 +35,11 @@ #include "expr.h" #include "real.h" #include "output.h" +#include "optabs.h" #include "toplev.h" #include "tm_p.h" +#include "cfgloop.h" +#include "target.h" #ifndef HAVE_conditional_execution @@ -70,8 +75,8 @@ static int num_possible_if_blocks; execution. */ static int num_updated_if_blocks; -/* # of basic blocks that were removed. */ -static int num_removed_blocks; +/* # of changes made which require life information to be updated. */ +static int num_true_changes; /* Whether conditional execution changes were made. */ static int cond_exec_changed_p; @@ -79,51 +84,76 @@ static int cond_exec_changed_p; /* True if life data ok at present. */ static bool life_data_ok; -/* The post-dominator relation on the original block numbers. */ -static dominance_info post_dominators; - /* Forward references. */ -static int count_bb_insns PARAMS ((basic_block)); -static rtx first_active_insn PARAMS ((basic_block)); -static rtx last_active_insn PARAMS ((basic_block, int)); -static int seq_contains_jump PARAMS ((rtx)); -static basic_block block_fallthru PARAMS ((basic_block)); -static int cond_exec_process_insns PARAMS ((ce_if_block_t *, - rtx, rtx, rtx, rtx, int)); -static rtx cond_exec_get_condition PARAMS ((rtx)); -static int cond_exec_process_if_block PARAMS ((ce_if_block_t *, int)); -static rtx noce_get_condition PARAMS ((rtx, rtx *)); -static int noce_operand_ok PARAMS ((rtx)); -static int noce_process_if_block PARAMS ((ce_if_block_t *)); -static int process_if_block PARAMS ((ce_if_block_t *)); -static void merge_if_block PARAMS ((ce_if_block_t *)); -static int find_cond_trap PARAMS ((basic_block, edge, edge)); -static basic_block find_if_header PARAMS ((basic_block, int)); -static int block_jumps_and_fallthru_p PARAMS ((basic_block, basic_block)); -static int find_if_block PARAMS ((ce_if_block_t *)); -static int find_if_case_1 PARAMS ((basic_block, edge, edge)); -static int find_if_case_2 PARAMS ((basic_block, edge, edge)); -static int find_memory PARAMS ((rtx *, void *)); -static int dead_or_predicable PARAMS ((basic_block, basic_block, - basic_block, basic_block, int)); -static void noce_emit_move_insn PARAMS ((rtx, rtx)); -static rtx block_has_only_trap PARAMS ((basic_block)); +static int count_bb_insns (basic_block); +static rtx first_active_insn (basic_block); +static rtx last_active_insn (basic_block, int); +static int seq_contains_jump (rtx); +static basic_block block_fallthru (basic_block); +static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int); +static rtx cond_exec_get_condition (rtx); +static int cond_exec_process_if_block (ce_if_block_t *, int); +static rtx noce_get_condition (rtx, rtx *); +static int noce_operand_ok (rtx); +static int noce_process_if_block (ce_if_block_t *); +static int process_if_block (ce_if_block_t *); +static void merge_if_block (ce_if_block_t *); +static int find_cond_trap (basic_block, edge, edge); +static basic_block find_if_header (basic_block, int); +static int block_jumps_and_fallthru_p (basic_block, basic_block); +static int find_if_block (ce_if_block_t *); +static int find_if_case_1 (basic_block, edge, edge); +static int find_if_case_2 (basic_block, edge, edge); +static int find_memory (rtx *, void *); +static int dead_or_predicable (basic_block, basic_block, basic_block, + basic_block, int); +static void noce_emit_move_insn (rtx, rtx); +static rtx block_has_only_trap (basic_block); +static void mark_loop_exit_edges (void); +/* Sets EDGE_LOOP_EXIT flag for all loop exits. */ +static void +mark_loop_exit_edges (void) +{ + struct loops loops; + basic_block bb; + edge e; + + flow_loops_find (&loops, LOOP_TREE); + free_dominance_info (CDI_DOMINATORS); + + if (loops.num > 1) + { + FOR_EACH_BB (bb) + { + for (e = bb->succ; e; e = e->succ_next) + { + if (find_common_loop (bb->loop_father, e->dest->loop_father) + != bb->loop_father) + e->flags |= EDGE_LOOP_EXIT; + else + e->flags &= ~EDGE_LOOP_EXIT; + } + } + } + + flow_loops_free (&loops); +} + /* Count the number of non-jump active insns in BB. */ static int -count_bb_insns (bb) - basic_block bb; +count_bb_insns (basic_block bb) { int count = 0; - rtx insn = bb->head; + rtx insn = BB_HEAD (bb); while (1) { if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN) count++; - if (insn == bb->end) + if (insn == BB_END (bb)) break; insn = NEXT_INSN (insn); } @@ -134,21 +164,20 @@ count_bb_insns (bb) /* Return the first non-jump active insn in the basic block. */ static rtx -first_active_insn (bb) - basic_block bb; +first_active_insn (basic_block bb) { - rtx insn = bb->head; + rtx insn = BB_HEAD (bb); if (GET_CODE (insn) == CODE_LABEL) { - if (insn == bb->end) + if (insn == BB_END (bb)) return NULL_RTX; insn = NEXT_INSN (insn); } while (GET_CODE (insn) == NOTE) { - if (insn == bb->end) + if (insn == BB_END (bb)) return NULL_RTX; insn = NEXT_INSN (insn); } @@ -162,12 +191,10 @@ first_active_insn (bb) /* Return the last non-jump active (non-jump) insn in the basic block. */ static rtx -last_active_insn (bb, skip_use_p) - basic_block bb; - int skip_use_p; +last_active_insn (basic_block bb, int skip_use_p) { - rtx insn = bb->end; - rtx head = bb->head; + rtx insn = BB_END (bb); + rtx head = BB_HEAD (bb); while (GET_CODE (insn) == NOTE || GET_CODE (insn) == JUMP_INSN @@ -186,14 +213,13 @@ last_active_insn (bb, skip_use_p) return insn; } -/* It is possible, especially when having dealt with multi-word +/* It is possible, especially when having dealt with multi-word arithmetic, for the expanders to have emitted jumps. Search through the sequence and return TRUE if a jump exists so that we can abort the conversion. */ static int -seq_contains_jump (insn) - rtx insn; +seq_contains_jump (rtx insn) { while (insn) { @@ -205,8 +231,7 @@ seq_contains_jump (insn) } static basic_block -block_fallthru (bb) - basic_block bb; +block_fallthru (basic_block bb) { edge e; @@ -223,13 +248,12 @@ block_fallthru (bb) insns were processed. */ static int -cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok) - ce_if_block_t *ce_info ATTRIBUTE_UNUSED; /* if block information */ - rtx start; /* first insn to look at */ - rtx end; /* last insn to look at */ - rtx test; /* conditional execution test */ - rtx prob_val; /* probability of branch taken. */ - int mod_ok; /* true if modifications ok last insn. */ +cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED, + /* if block information */rtx start, + /* first insn to look at */rtx end, + /* last insn to look at */rtx test, + /* conditional execution test */rtx prob_val, + /* probability of branch taken. */int mod_ok) { int must_be_last = FALSE; rtx insn; @@ -250,7 +274,7 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok) /* Remove USE insns that get in the way. */ if (reload_completed && GET_CODE (PATTERN (insn)) == USE) { - /* ??? Ug. Actually unlinking the thing is problematic, + /* ??? Ug. Actually unlinking the thing is problematic, given what we'd have to coordinate with our callers. */ PUT_CODE (insn, NOTE); NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; @@ -314,8 +338,7 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok) /* Return the condition for a jump. Do not do any special processing. */ static rtx -cond_exec_get_condition (jump) - rtx jump; +cond_exec_get_condition (rtx jump) { rtx test_if, cond; @@ -346,9 +369,8 @@ cond_exec_get_condition (jump) converting the block. */ static int -cond_exec_process_if_block (ce_info, do_multiple_p) - ce_if_block_t * ce_info; /* if block information */ - int do_multiple_p; /* != 0 if we should handle && and || blocks */ +cond_exec_process_if_block (ce_if_block_t * ce_info, + /* if block information */int do_multiple_p) { basic_block test_bb = ce_info->test_bb; /* last test block */ basic_block then_bb = ce_info->then_bb; /* THEN */ @@ -383,13 +405,13 @@ cond_exec_process_if_block (ce_info, do_multiple_p) /* Find the conditional jump to the ELSE or JOIN part, and isolate the test. */ - test_expr = cond_exec_get_condition (test_bb->end); + test_expr = cond_exec_get_condition (BB_END (test_bb)); if (! test_expr) return FALSE; /* If the conditional jump is more than just a conditional jump, then we can not do conditional execution conversion on this block. */ - if (! onlyjump_p (test_bb->end)) + if (! onlyjump_p (BB_END (test_bb))) return FALSE; /* Collect the bounds of where we're to search, skipping any labels, jumps @@ -413,10 +435,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p) /* Map test_expr/test_jump into the appropriate MD tests to use on the conditionally executed code. */ - + true_expr = test_expr; - false_code = reversed_comparison_code (true_expr, test_bb->end); + false_code = reversed_comparison_code (true_expr, BB_END (test_bb)); if (false_code != UNKNOWN) false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr), XEXP (true_expr, 0), XEXP (true_expr, 1)); @@ -428,12 +450,12 @@ cond_exec_process_if_block (ce_info, do_multiple_p) conditional execution register from a comparison, it can do so here. */ IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr); - /* See if the conversion failed */ + /* See if the conversion failed. */ if (!true_expr || !false_expr) goto fail; #endif - true_prob_val = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX); + true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX); if (true_prob_val) { true_prob_val = XEXP (true_prob_val, 0); @@ -467,11 +489,11 @@ cond_exec_process_if_block (ce_info, do_multiple_p) /* If the conditional jump is more than just a conditional jump, then we can not do conditional execution conversion on this block. */ - if (! onlyjump_p (bb->end)) + if (! onlyjump_p (BB_END (bb))) goto fail; /* Find the conditional jump and isolate the test. */ - t = cond_exec_get_condition (bb->end); + t = cond_exec_get_condition (BB_END (bb)); if (! t) goto fail; @@ -497,7 +519,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p) #ifdef IFCVT_MODIFY_MULTIPLE_TESTS IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f); - /* See if the conversion failed */ + /* See if the conversion failed. */ if (!t || !f) goto fail; #endif @@ -539,7 +561,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p) } #ifdef IFCVT_MODIFY_FINAL - /* Do any machine dependent final modifications */ + /* Do any machine dependent final modifications. */ IFCVT_MODIFY_FINAL (ce_info); #endif @@ -563,10 +585,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p) return FALSE; } -/* Used by noce_process_if_block to communicate with its subroutines. +/* Used by noce_process_if_block to communicate with its subroutines. The subroutines know that A and B may be evaluated freely. They - know that X is a register. They should insert new instructions + know that X is a register. They should insert new instructions before cond_earliest. */ struct noce_if_info @@ -577,29 +599,25 @@ struct noce_if_info rtx jump, cond, cond_earliest; }; -static rtx noce_emit_store_flag PARAMS ((struct noce_if_info *, - rtx, int, int)); -static int noce_try_store_flag PARAMS ((struct noce_if_info *)); -static int noce_try_store_flag_inc PARAMS ((struct noce_if_info *)); -static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *)); -static int noce_try_store_flag_mask PARAMS ((struct noce_if_info *)); -static rtx noce_emit_cmove PARAMS ((struct noce_if_info *, - rtx, enum rtx_code, rtx, - rtx, rtx, rtx)); -static int noce_try_cmove PARAMS ((struct noce_if_info *)); -static int noce_try_cmove_arith PARAMS ((struct noce_if_info *)); -static rtx noce_get_alt_condition PARAMS ((struct noce_if_info *, - rtx, rtx *)); -static int noce_try_minmax PARAMS ((struct noce_if_info *)); -static int noce_try_abs PARAMS ((struct noce_if_info *)); +static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int); +static int noce_try_move (struct noce_if_info *); +static int noce_try_store_flag (struct noce_if_info *); +static int noce_try_addcc (struct noce_if_info *); +static int noce_try_store_flag_constants (struct noce_if_info *); +static int noce_try_store_flag_mask (struct noce_if_info *); +static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx, + rtx, rtx, rtx); +static int noce_try_cmove (struct noce_if_info *); +static int noce_try_cmove_arith (struct noce_if_info *); +static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *); +static int noce_try_minmax (struct noce_if_info *); +static int noce_try_abs (struct noce_if_info *); /* Helper function for noce_try_store_flag*. */ static rtx -noce_emit_store_flag (if_info, x, reversep, normalize) - struct noce_if_info *if_info; - rtx x; - int reversep, normalize; +noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep, + int normalize) { rtx cond = if_info->cond; int cond_complex; @@ -655,10 +673,11 @@ noce_emit_store_flag (if_info, x, reversep, normalize) || code == GEU || code == GTU), normalize); } -/* Emit instruction to move an rtx into STRICT_LOW_PART. */ +/* Emit instruction to move an rtx, possibly into STRICT_LOW_PART. + X is the destination/target and Y is the value to copy. */ + static void -noce_emit_move_insn (x, y) - rtx x, y; +noce_emit_move_insn (rtx x, rtx y) { enum machine_mode outmode, inmode; rtx outer, inner; @@ -679,6 +698,69 @@ noce_emit_move_insn (x, y) GET_MODE_BITSIZE (inmode)); } +/* Unshare sequence SEQ produced by if conversion. We care to mark + all arguments that may be shared with outer instruction stream. */ +static void +unshare_ifcvt_sequence (struct noce_if_info *if_info, rtx seq) +{ + set_used_flags (if_info->x); + set_used_flags (if_info->cond); + unshare_all_rtl_in_chain (seq); +} + +/* Convert "if (a != b) x = a; else x = b" into "x = a" and + "if (a == b) x = a; else x = b" into "x = b". */ + +static int +noce_try_move (struct noce_if_info *if_info) +{ + rtx cond = if_info->cond; + enum rtx_code code = GET_CODE (cond); + rtx y, seq; + + if (code != NE && code != EQ) + return FALSE; + + /* This optimization isn't valid if either A or B could be a NaN + or a signed zero. */ + if (HONOR_NANS (GET_MODE (if_info->x)) + || HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))) + return FALSE; + + /* Check whether the operands of the comparison are A and in + either order. */ + if ((rtx_equal_p (if_info->a, XEXP (cond, 0)) + && rtx_equal_p (if_info->b, XEXP (cond, 1))) + || (rtx_equal_p (if_info->a, XEXP (cond, 1)) + && rtx_equal_p (if_info->b, XEXP (cond, 0)))) + { + y = (code == EQ) ? if_info->a : if_info->b; + + /* Avoid generating the move if the source is the destination. */ + if (! rtx_equal_p (if_info->x, y)) + { + start_sequence (); + noce_emit_move_insn (if_info->x, y); + seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); + end_sequence (); + + /* Make sure that all of the instructions emitted are + recognizable. As an excersise for the reader, build + a general mechanism that allows proper placement of + required clobbers. */ + for (y = seq; y ; y = NEXT_INSN (y)) + if (recog_memoized (y) == -1) + return FALSE; + + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATOR (if_info->insn_a)); + } + return TRUE; + } + return FALSE; +} + /* Convert "if (test) x = 1; else x = 0". Only try 0 and STORE_FLAG_VALUE here. Other combinations will be @@ -686,8 +768,7 @@ noce_emit_move_insn (x, y) a go at the conversion. */ static int -noce_try_store_flag (if_info) - struct noce_if_info *if_info; +noce_try_store_flag (struct noce_if_info *if_info) { int reversep; rtx target, seq; @@ -714,8 +795,9 @@ noce_try_store_flag (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); end_sequence (); - emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); return TRUE; } @@ -729,8 +811,7 @@ noce_try_store_flag (if_info) /* Convert "if (test) x = a; else x = b", for A and B constant. */ static int -noce_try_store_flag_constants (if_info) - struct noce_if_info *if_info; +noce_try_store_flag_constants (struct noce_if_info *if_info) { rtx target, seq; int reversep; @@ -780,7 +861,7 @@ noce_try_store_flag_constants (if_info) return FALSE; if (reversep) - { + { tmp = itrue; itrue = ifalse; ifalse = tmp; diff = trunc_int_for_mode (-diff, mode); } @@ -845,12 +926,13 @@ noce_try_store_flag_constants (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); end_sequence (); if (seq_contains_jump (seq)) return FALSE; - emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); return TRUE; } @@ -858,65 +940,96 @@ noce_try_store_flag_constants (if_info) return FALSE; } -/* Convert "if (test) foo++" into "foo += (test != 0)", and +/* Convert "if (test) foo++" into "foo += (test != 0)", and similarly for "foo--". */ static int -noce_try_store_flag_inc (if_info) - struct noce_if_info *if_info; +noce_try_addcc (struct noce_if_info *if_info) { rtx target, seq; int subtract, normalize; if (! no_new_pseudos - && (BRANCH_COST >= 2 - || HAVE_incscc - || HAVE_decscc) - /* Should be no `else' case to worry about. */ - && if_info->b == if_info->x && GET_CODE (if_info->a) == PLUS - && (XEXP (if_info->a, 1) == const1_rtx - || XEXP (if_info->a, 1) == constm1_rtx) - && rtx_equal_p (XEXP (if_info->a, 0), if_info->x) + && rtx_equal_p (XEXP (if_info->a, 0), if_info->b) && (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)) { - if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) - subtract = 0, normalize = 0; - else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) - subtract = 1, normalize = 0; - else - subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1)); - - start_sequence (); - - target = noce_emit_store_flag (if_info, - gen_reg_rtx (GET_MODE (if_info->x)), - 1, normalize); + rtx cond = if_info->cond; + enum rtx_code code = reversed_comparison_code (cond, if_info->jump); - if (target) - target = expand_simple_binop (GET_MODE (if_info->x), - subtract ? MINUS : PLUS, - if_info->x, target, if_info->x, - 0, OPTAB_WIDEN); - if (target) + /* First try to use addcc pattern. */ + if (general_operand (XEXP (cond, 0), VOIDmode) + && general_operand (XEXP (cond, 1), VOIDmode)) { - if (target != if_info->x) - noce_emit_move_insn (if_info->x, target); - - seq = get_insns (); + start_sequence (); + target = emit_conditional_add (if_info->x, code, + XEXP (cond, 0), + XEXP (cond, 1), + VOIDmode, + if_info->b, + XEXP (if_info->a, 1), + GET_MODE (if_info->x), + (code == LTU || code == GEU + || code == LEU || code == GTU)); + if (target) + { + if (target != if_info->x) + noce_emit_move_insn (if_info->x, target); + + seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); + end_sequence (); + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATOR (if_info->insn_a)); + return TRUE; + } end_sequence (); + } - if (seq_contains_jump (seq)) - return FALSE; + /* If that fails, construct conditional increment or decrement using + setcc. */ + if (BRANCH_COST >= 2 + && (XEXP (if_info->a, 1) == const1_rtx + || XEXP (if_info->a, 1) == constm1_rtx)) + { + start_sequence (); + if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) + subtract = 0, normalize = 0; + else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) + subtract = 1, normalize = 0; + else + subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1)); - emit_insn_before_scope (seq, if_info->jump, - INSN_SCOPE (if_info->insn_a)); - return TRUE; - } + target = noce_emit_store_flag (if_info, + gen_reg_rtx (GET_MODE (if_info->x)), + 1, normalize); - end_sequence (); + if (target) + target = expand_simple_binop (GET_MODE (if_info->x), + subtract ? MINUS : PLUS, + if_info->b, target, if_info->x, + 0, OPTAB_WIDEN); + if (target) + { + if (target != if_info->x) + noce_emit_move_insn (if_info->x, target); + + seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); + end_sequence (); + + if (seq_contains_jump (seq)) + return FALSE; + + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATOR (if_info->insn_a)); + + return TRUE; + } + end_sequence (); + } } return FALSE; @@ -925,8 +1038,7 @@ noce_try_store_flag_inc (if_info) /* Convert "if (test) x = 0;" to "x &= -(test == 0);" */ static int -noce_try_store_flag_mask (if_info) - struct noce_if_info *if_info; +noce_try_store_flag_mask (struct noce_if_info *if_info) { rtx target, seq; int reversep; @@ -949,7 +1061,8 @@ noce_try_store_flag_mask (if_info) reversep, -1); if (target) target = expand_simple_binop (GET_MODE (if_info->x), AND, - if_info->x, target, if_info->x, 0, + if_info->x, + target, if_info->x, 0, OPTAB_WIDEN); if (target) @@ -958,13 +1071,14 @@ noce_try_store_flag_mask (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); end_sequence (); if (seq_contains_jump (seq)) return FALSE; - emit_insn_before_scope (seq, if_info->jump, - INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATOR (if_info->insn_a)); return TRUE; } @@ -978,10 +1092,8 @@ noce_try_store_flag_mask (if_info) /* Helper function for noce_try_cmove and noce_try_cmove_arith. */ static rtx -noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue) - struct noce_if_info *if_info; - rtx x, cmp_a, cmp_b, vfalse, vtrue; - enum rtx_code code; +noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, + rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue) { /* If earliest == jump, try to build the cmove insn directly. This is helpful when combine has created some complex condition @@ -1024,7 +1136,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue) #else /* We'll never get here, as noce_process_if_block doesn't call the functions involved. Ifdef code, however, should be discouraged - because it leads to typos in the code not selected. However, + because it leads to typos in the code not selected. However, emit_conditional_move won't exist either. */ return NULL_RTX; #endif @@ -1035,8 +1147,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue) has had a go at it. */ static int -noce_try_cmove (if_info) - struct noce_if_info *if_info; +noce_try_cmove (struct noce_if_info *if_info) { enum rtx_code code; rtx target, seq; @@ -1058,9 +1169,10 @@ noce_try_cmove (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); + unshare_ifcvt_sequence (if_info, seq); end_sequence (); - emit_insn_before_scope (seq, if_info->jump, - INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATOR (if_info->insn_a)); return TRUE; } else @@ -1076,8 +1188,7 @@ noce_try_cmove (if_info) /* Try more complex cases involving conditional_move. */ static int -noce_try_cmove_arith (if_info) - struct noce_if_info *if_info; +noce_try_cmove_arith (struct noce_if_info *if_info) { rtx a = if_info->a; rtx b = if_info->b; @@ -1113,7 +1224,7 @@ noce_try_cmove_arith (if_info) if (test) x = y; */ - + code = GET_CODE (if_info->cond); insn_a = if_info->insn_a; insn_b = if_info->insn_b; @@ -1139,7 +1250,7 @@ noce_try_cmove_arith (if_info) /* If either operand is complex, load it into a register first. The best way to do this is to copy the original insn. In this - way we preserve any clobbers etc that the insn may have had. + way we preserve any clobbers etc that the insn may have had. This is of course not possible in the IS_MEM case. */ if (! general_operand (a, GET_MODE (a))) { @@ -1176,18 +1287,11 @@ noce_try_cmove_arith (if_info) if (is_mem) { tmp = gen_reg_rtx (GET_MODE (b)); - tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b)); + tmp = emit_insn (gen_rtx_SET (VOIDmode, + tmp, + b)); } - else if (! insn_b -#if 0 - /* In the case we are going to duplicate insn originally - present in the front of comparsion, verify that the - comparsion didn't clobbered the operands. */ - || modified_between_p (SET_SRC (single_set (insn_b)), - if_info->cond_earliest, - NEXT_INSN (if_info->jump))) -#endif - ) + else if (! insn_b) goto end_seq_and_fail; else { @@ -1230,8 +1334,9 @@ noce_try_cmove_arith (if_info) noce_emit_move_insn (x, target); tmp = get_insns (); + unshare_ifcvt_sequence (if_info, tmp); end_sequence (); - emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a)); return TRUE; end_seq_and_fail: @@ -1244,10 +1349,8 @@ noce_try_cmove_arith (if_info) For these we wish to know that it is A or B in the condition. */ static rtx -noce_get_alt_condition (if_info, target, earliest) - struct noce_if_info *if_info; - rtx target; - rtx *earliest; +noce_get_alt_condition (struct noce_if_info *if_info, rtx target, + rtx *earliest) { rtx cond, set, insn; int reverse; @@ -1368,7 +1471,7 @@ noce_get_alt_condition (if_info, target, earliest) } cond = canonicalize_condition (if_info->jump, cond, reverse, - earliest, target); + earliest, target, false); if (! cond || ! reg_mentioned_p (target, cond)) return NULL; @@ -1393,9 +1496,8 @@ noce_get_alt_condition (if_info, target, earliest) /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */ static int -noce_try_minmax (if_info) - struct noce_if_info *if_info; -{ +noce_try_minmax (struct noce_if_info *if_info) +{ rtx cond, earliest, target, seq; enum rtx_code code, op; int unsignedp; @@ -1478,12 +1580,13 @@ noce_try_minmax (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); - end_sequence (); + unshare_ifcvt_sequence (if_info, seq); + end_sequence (); if (seq_contains_jump (seq)) return FALSE; - emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); if_info->cond = cond; if_info->cond_earliest = earliest; @@ -1493,9 +1596,8 @@ noce_try_minmax (if_info) /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc. */ static int -noce_try_abs (if_info) - struct noce_if_info *if_info; -{ +noce_try_abs (struct noce_if_info *if_info) +{ rtx cond, earliest, target, seq, a, b, c; int negate; @@ -1515,7 +1617,7 @@ noce_try_abs (if_info) } else return FALSE; - + cond = noce_get_alt_condition (if_info, b, &earliest); if (!cond) return FALSE; @@ -1534,9 +1636,9 @@ noce_try_abs (if_info) { rtx insn, note = NULL; for (insn = earliest; - insn != if_info->test_bb->head; + insn != BB_HEAD (if_info->test_bb); insn = PREV_INSN (insn)) - if (INSN_P (insn) + if (INSN_P (insn) && ((note = find_reg_note (insn, REG_EQUAL, c)) || (note = find_reg_note (insn, REG_EQUIV, c)))) break; @@ -1550,7 +1652,7 @@ noce_try_abs (if_info) c = get_pool_constant (XEXP (c, 0)); /* Work around funny ideas get_condition has wrt canonicalization. - Note that these rtx constants are known to be CONST_INT, and + Note that these rtx constants are known to be CONST_INT, and therefore imply integer comparisons. */ if (c == constm1_rtx && GET_CODE (cond) == GT) ; @@ -1579,9 +1681,9 @@ noce_try_abs (if_info) start_sequence (); - target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0); + target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1); - /* ??? It's a quandry whether cmove would be better here, especially + /* ??? It's a quandary whether cmove would be better here, especially for integers. Perhaps combine will clean things up. */ if (target && negate) target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0); @@ -1596,12 +1698,13 @@ noce_try_abs (if_info) noce_emit_move_insn (if_info->x, target); seq = get_insns (); - end_sequence (); + unshare_ifcvt_sequence (if_info, seq); + end_sequence (); if (seq_contains_jump (seq)) return FALSE; - emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a)); + emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); if_info->cond = cond; if_info->cond_earliest = earliest; @@ -1612,9 +1715,7 @@ noce_try_abs (if_info) valid at JUMP, instead of at EARLIEST. */ static rtx -noce_get_condition (jump, earliest) - rtx jump; - rtx *earliest; +noce_get_condition (rtx jump, rtx *earliest) { rtx cond, set, tmp, insn; bool reverse; @@ -1646,7 +1747,8 @@ noce_get_condition (jump, earliest) /* Otherwise, fall back on canonicalize_condition to do the dirty work of manipulating MODE_CC values and COMPARE rtx codes. */ - tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX); + tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX, + false); if (!tmp) return NULL_RTX; @@ -1665,7 +1767,8 @@ noce_get_condition (jump, earliest) tmp = XEXP (tmp, 0); if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT) return NULL_RTX; - tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp); + tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp, + false); if (!tmp) return NULL_RTX; @@ -1680,8 +1783,7 @@ noce_get_condition (jump, earliest) /* Return true if OP is ok for if-then-else processing. */ static int -noce_operand_ok (op) - rtx op; +noce_operand_ok (rtx op) { /* We special-case memories, so handle any of them with no address side effects. */ @@ -1699,8 +1801,7 @@ noce_operand_ok (op) successful at converting the block. */ static int -noce_process_if_block (ce_info) - struct ce_if_block * ce_info; +noce_process_if_block (struct ce_if_block * ce_info) { basic_block test_bb = ce_info->test_bb; /* test block */ basic_block then_bb = ce_info->then_bb; /* THEN */ @@ -1735,7 +1836,7 @@ noce_process_if_block (ce_info) } /* If this is not a standard conditional jump, we can't parse it. */ - jump = test_bb->end; + jump = BB_END (test_bb); cond = noce_get_condition (jump, &if_info.cond_earliest); if (! cond) return FALSE; @@ -1800,7 +1901,7 @@ noce_process_if_block (ce_info) /* If x has side effects then only the if-then-else form is safe to convert. But even in that case we would need to restore any notes - (such as REG_INC) at then end. That can be tricky if + (such as REG_INC) at then end. That can be tricky if noce_emit_move_insn expands to more than one insn, so disable the optimization entirely for now if there are side effects. */ if (side_effects_p (x)) @@ -1815,7 +1916,7 @@ noce_process_if_block (ce_info) || (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER)) { - if (no_new_pseudos) + if (no_new_pseudos || GET_MODE (x) == BLKmode) return FALSE; x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART ? XEXP (x, 0) : x)); @@ -1851,8 +1952,8 @@ noce_process_if_block (ce_info) { rtx note; - if (else_bb && insn_b == else_bb->end) - else_bb->end = PREV_INSN (insn_b); + if (else_bb && insn_b == BB_END (else_bb)) + BB_END (else_bb) = PREV_INSN (insn_b); reorder_insns (insn_b, insn_b, PREV_INSN (jump)); /* If there was a REG_EQUAL note, delete it since it may have been @@ -1866,11 +1967,32 @@ noce_process_if_block (ce_info) x must be executed twice. */ else if (insn_b && side_effects_p (orig_x)) return FALSE; - + x = orig_x; goto success; } + /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;") + for most optimizations if writing to x may trap, i.e. its a memory + other than a static var or a stack slot. */ + if (! set_b + && GET_CODE (orig_x) == MEM + && ! MEM_NOTRAP_P (orig_x) + && rtx_addr_can_trap_p (XEXP (orig_x, 0))) + { + if (HAVE_conditional_move) + { + if (noce_try_cmove (&if_info)) + goto success; + if (! HAVE_conditional_execution + && noce_try_cmove_arith (&if_info)) + goto success; + } + return FALSE; + } + + if (noce_try_move (&if_info)) + goto success; if (noce_try_store_flag (&if_info)) goto success; if (noce_try_minmax (&if_info)) @@ -1884,7 +2006,7 @@ noce_process_if_block (ce_info) { if (noce_try_store_flag_constants (&if_info)) goto success; - if (noce_try_store_flag_inc (&if_info)) + if (noce_try_addcc (&if_info)) goto success; if (noce_try_store_flag_mask (&if_info)) goto success; @@ -1917,11 +2039,13 @@ noce_process_if_block (ce_info) if (orig_x != x) { start_sequence (); - noce_emit_move_insn (copy_rtx (orig_x), x); + noce_emit_move_insn (orig_x, x); insn_b = get_insns (); + set_used_flags (orig_x); + unshare_all_rtl_in_chain (insn_b); end_sequence (); - emit_insn_after_scope (insn_b, test_bb->end, INSN_SCOPE (insn_a)); + emit_insn_after_setloc (insn_b, BB_END (test_bb), INSN_LOCATOR (insn_a)); } /* Merge the blocks! */ @@ -1934,8 +2058,7 @@ noce_process_if_block (ce_info) straight line code. Return true if successful. */ static int -process_if_block (ce_info) - struct ce_if_block * ce_info; +process_if_block (struct ce_if_block * ce_info) { if (! reload_completed && noce_process_if_block (ce_info)) @@ -1965,8 +2088,7 @@ process_if_block (ce_info) /* Merge the blocks and mark for local life update. */ static void -merge_if_block (ce_info) - struct ce_if_block * ce_info; +merge_if_block (struct ce_if_block * ce_info) { basic_block test_bb = ce_info->test_bb; /* last test block */ basic_block then_bb = ce_info->then_bb; /* THEN */ @@ -1985,15 +2107,15 @@ merge_if_block (ce_info) basic_block bb = test_bb; basic_block last_test_bb = ce_info->last_test_bb; basic_block fallthru = block_fallthru (bb); - + do { bb = fallthru; fallthru = block_fallthru (bb); - if (post_dominators) - delete_from_dominance_info (post_dominators, bb); - merge_blocks_nomove (combo_bb, bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, bb); + merge_blocks (combo_bb, bb); + num_true_changes++; } while (bb != last_test_bb); } @@ -2007,10 +2129,10 @@ merge_if_block (ce_info) if (combo_bb->global_live_at_end) COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end); - if (post_dominators) - delete_from_dominance_info (post_dominators, then_bb); - merge_blocks_nomove (combo_bb, then_bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb); + merge_blocks (combo_bb, then_bb); + num_true_changes++; } /* The ELSE block, if it existed, had a label. That label count @@ -2018,10 +2140,10 @@ merge_if_block (ce_info) get their addresses taken. */ if (else_bb) { - if (post_dominators) - delete_from_dominance_info (post_dominators, else_bb); - merge_blocks_nomove (combo_bb, else_bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb); + merge_blocks (combo_bb, else_bb); + num_true_changes++; } /* If there was no join block reported, that means it was not adjacent @@ -2029,7 +2151,7 @@ merge_if_block (ce_info) if (! join_bb) { - rtx last = combo_bb->end; + rtx last = BB_END (combo_bb); /* The outgoing edge for the current COMBO block should already be correct. Verify this. */ @@ -2064,7 +2186,7 @@ merge_if_block (ce_info) Since we've already merged the TEST, THEN and ELSE blocks, we should have only one remaining edge from our if-then-else diamond. If there is more than one remaining edge, it must come from elsewhere. There - may be zero incoming edges if the THEN block didn't actually join + may be zero incoming edges if the THEN block didn't actually join back up (as with a call to abort). */ else if ((join_bb->pred == NULL || join_bb->pred->pred_next == NULL) @@ -2075,10 +2197,10 @@ merge_if_block (ce_info) COPY_REG_SET (combo_bb->global_live_at_end, join_bb->global_live_at_end); - if (post_dominators) - delete_from_dominance_info (post_dominators, join_bb); - merge_blocks_nomove (combo_bb, join_bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, join_bb); + merge_blocks (combo_bb, join_bb); + num_true_changes++; } else { @@ -2104,9 +2226,7 @@ merge_if_block (ce_info) first block if some transformation was done. Return NULL otherwise. */ static basic_block -find_if_header (test_bb, pass) - basic_block test_bb; - int pass; +find_if_header (basic_block test_bb, int pass) { ce_if_block_t ce_info; edge then_edge; @@ -2123,6 +2243,11 @@ find_if_header (test_bb, pass) || (else_edge->flags & EDGE_COMPLEX)) return NULL; + /* Nor exit the loop. */ + if ((then_edge->flags & EDGE_LOOP_EXIT) + || (else_edge->flags & EDGE_LOOP_EXIT)) + return NULL; + /* The THEN edge is canonically the one that falls through. */ if (then_edge->flags & EDGE_FALLTHRU) ; @@ -2136,7 +2261,7 @@ find_if_header (test_bb, pass) /* Otherwise this must be a multiway branch of some sort. */ return NULL; - memset ((PTR) &ce_info, '\0', sizeof (ce_info)); + memset (&ce_info, '\0', sizeof (ce_info)); ce_info.test_bb = test_bb; ce_info.then_bb = then_edge->dest; ce_info.else_bb = else_edge->dest; @@ -2153,7 +2278,7 @@ find_if_header (test_bb, pass) && find_cond_trap (test_bb, then_edge, else_edge)) goto success; - if (post_dominators + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY && (! HAVE_conditional_execution || reload_completed)) { if (find_if_case_1 (test_bb, then_edge, else_edge)) @@ -2176,9 +2301,7 @@ find_if_header (test_bb, pass) of non-note, non-jump, non-USE/CLOBBER insns in the block. */ static int -block_jumps_and_fallthru_p (cur_bb, target_bb) - basic_block cur_bb; - basic_block target_bb; +block_jumps_and_fallthru_p (basic_block cur_bb, basic_block target_bb) { edge cur_edge; int fallthru_p = FALSE; @@ -2219,8 +2342,8 @@ block_jumps_and_fallthru_p (cur_bb, target_bb) together for conditional execution support. ??? we should support conditional execution support across calls for IA-64 some day, but for now it makes the code simpler. */ - end = cur_bb->end; - insn = cur_bb->head; + end = BB_END (cur_bb); + insn = BB_HEAD (cur_bb); while (insn != NULL_RTX) { @@ -2247,8 +2370,7 @@ block_jumps_and_fallthru_p (cur_bb, target_bb) Return TRUE if we were successful at converting the block. */ static int -find_if_block (ce_info) - struct ce_if_block * ce_info; +find_if_block (struct ce_if_block * ce_info) { basic_block test_bb = ce_info->test_bb; basic_block then_bb = ce_info->then_bb; @@ -2276,7 +2398,7 @@ find_if_block (ce_info) int max_insns = MAX_CONDITIONAL_EXECUTE; int n_insns; - /* Determine if the preceeding block is an && or || block. */ + /* Determine if the preceding block is an && or || block. */ if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0) { ce_info->and_and_p = TRUE; @@ -2284,7 +2406,7 @@ find_if_block (ce_info) } else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0) { - ce_info->and_and_p = FALSE; + ce_info->and_and_p = FALSE; target_bb = then_bb; } else @@ -2352,7 +2474,7 @@ find_if_block (ce_info) if (then_succ != NULL_EDGE && (then_succ->succ_next != NULL_EDGE || (then_succ->flags & EDGE_COMPLEX) - || (flow2_completed && tablejump_p (then_bb->end)))) + || (flow2_completed && tablejump_p (BB_END (then_bb), NULL, NULL)))) return FALSE; /* If the THEN block has no successors, conditional execution can still @@ -2365,11 +2487,11 @@ find_if_block (ce_info) { if (else_bb->pred->pred_next == NULL_EDGE) { - rtx last_insn = then_bb->end; + rtx last_insn = BB_END (then_bb); while (last_insn && GET_CODE (last_insn) == NOTE - && last_insn != then_bb->head) + && last_insn != BB_HEAD (then_bb)) last_insn = PREV_INSN (last_insn); if (last_insn @@ -2400,12 +2522,12 @@ find_if_block (ce_info) && else_bb->pred->pred_next == NULL_EDGE && else_succ->succ_next == NULL_EDGE && ! (else_succ->flags & EDGE_COMPLEX) - && ! (flow2_completed && tablejump_p (else_bb->end))) + && ! (flow2_completed && tablejump_p (BB_END (else_bb), NULL, NULL))) join_bb = else_succ->dest; /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */ else - return FALSE; + return FALSE; num_possible_if_blocks++; @@ -2414,15 +2536,15 @@ find_if_block (ce_info) fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]", (else_bb) ? "-ELSE" : "", ce_info->pass, - test_bb->index, (test_bb->head) ? (int)INSN_UID (test_bb->head) : -1, - then_bb->index, (then_bb->head) ? (int)INSN_UID (then_bb->head) : -1); + test_bb->index, (BB_HEAD (test_bb)) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1, + then_bb->index, (BB_HEAD (then_bb)) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1); if (else_bb) fprintf (rtl_dump_file, ", else %d [%d]", - else_bb->index, (else_bb->head) ? (int)INSN_UID (else_bb->head) : -1); + else_bb->index, (BB_HEAD (else_bb)) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1); fprintf (rtl_dump_file, ", join %d [%d]", - join_bb->index, (join_bb->head) ? (int)INSN_UID (join_bb->head) : -1); + join_bb->index, (BB_HEAD (join_bb)) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1); if (ce_info->num_multiple_test_blocks > 0) fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]", @@ -2430,8 +2552,8 @@ find_if_block (ce_info) (ce_info->and_and_p) ? "&&" : "||", (ce_info->num_multiple_test_blocks == 1) ? "" : "s", ce_info->last_test_bb->index, - ((ce_info->last_test_bb->head) - ? (int)INSN_UID (ce_info->last_test_bb->head) + ((BB_HEAD (ce_info->last_test_bb)) + ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb)) : -1)); fputc ('\n', rtl_dump_file); @@ -2467,9 +2589,7 @@ find_if_block (ce_info) to a trap, into a conditional trap. */ static int -find_cond_trap (test_bb, then_edge, else_edge) - basic_block test_bb; - edge then_edge, else_edge; +find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge) { basic_block then_bb = then_edge->dest; basic_block else_bb = else_edge->dest; @@ -2494,7 +2614,7 @@ find_cond_trap (test_bb, then_edge, else_edge) } /* If this is not a standard conditional jump, we can't parse it. */ - jump = test_bb->end; + jump = BB_END (test_bb); cond = noce_get_condition (jump, &cond_earliest); if (! cond) return FALSE; @@ -2518,22 +2638,24 @@ find_cond_trap (test_bb, then_edge, else_edge) } /* Attempt to generate the conditional trap. */ - seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1), + seq = gen_cond_trap (code, XEXP (cond, 0), + XEXP (cond, 1), TRAP_CODE (PATTERN (trap))); if (seq == NULL) return FALSE; + num_true_changes++; + /* Emit the new insns before cond_earliest. */ - emit_insn_before_scope (seq, cond_earliest, INSN_SCOPE (trap)); + emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap)); /* Delete the trap block if possible. */ remove_edge (trap_bb == then_bb ? then_edge : else_edge); if (trap_bb->pred == NULL) { - if (post_dominators) - delete_from_dominance_info (post_dominators, trap_bb); - flow_delete_block (trap_bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, trap_bb); + delete_block (trap_bb); } /* If the non-trap block and the test are now adjacent, merge them. @@ -2542,7 +2664,7 @@ find_cond_trap (test_bb, then_edge, else_edge) { struct ce_if_block new_ce_info; delete_insn (jump); - memset ((PTR) &new_ce_info, '\0', sizeof (new_ce_info)); + memset (&new_ce_info, '\0', sizeof (new_ce_info)); new_ce_info.test_bb = test_bb; new_ce_info.then_bb = NULL; new_ce_info.else_bb = NULL; @@ -2565,12 +2687,11 @@ find_cond_trap (test_bb, then_edge, else_edge) return TRUE; } -/* Subroutine of find_cond_trap: if BB contains only a trap insn, +/* Subroutine of find_cond_trap: if BB contains only a trap insn, return it. */ static rtx -block_has_only_trap (bb) - basic_block bb; +block_has_only_trap (basic_block bb) { rtx trap; @@ -2584,7 +2705,7 @@ block_has_only_trap (bb) /* The only instruction in the THEN block must be the trap. */ trap = first_active_insn (bb); - if (! (trap == bb->end + if (! (trap == BB_END (bb) && GET_CODE (PATTERN (trap)) == TRAP_IF && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx)) return NULL_RTX; @@ -2670,9 +2791,7 @@ block_has_only_trap (bb) /* Tests for case 1 above. */ static int -find_if_case_1 (test_bb, then_edge, else_edge) - basic_block test_bb; - edge then_edge, else_edge; +find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge) { basic_block then_bb = then_edge->dest; basic_block else_bb = else_edge->dest, new_bb; @@ -2706,7 +2825,7 @@ find_if_case_1 (test_bb, then_edge, else_edge) return FALSE; /* Registers set are dead, or are predicable. */ - if (! dead_or_predicable (test_bb, then_bb, else_bb, + if (! dead_or_predicable (test_bb, then_bb, else_bb, then_bb->succ->dest, 1)) return FALSE; @@ -2716,12 +2835,12 @@ find_if_case_1 (test_bb, then_edge, else_edge) bitmap_operation (test_bb->global_live_at_end, else_bb->global_live_at_start, then_bb->global_live_at_end, BITMAP_IOR); - + new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb); then_bb_index = then_bb->index; - if (post_dominators) - delete_from_dominance_info (post_dominators, then_bb); - flow_delete_block (then_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb); + delete_block (then_bb); /* Make rest of code believe that the newly created block is the THEN_BB block we removed. */ @@ -2729,13 +2848,13 @@ find_if_case_1 (test_bb, then_edge, else_edge) { new_bb->index = then_bb_index; BASIC_BLOCK (then_bb_index) = new_bb; - if (post_dominators) - add_to_dominance_info (post_dominators, new_bb); + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + add_to_dominance_info (CDI_POST_DOMINATORS, new_bb); } /* We've possibly created jump to next insn, cleanup_cfg will solve that later. */ - num_removed_blocks++; + num_true_changes++; num_updated_if_blocks++; return TRUE; @@ -2744,9 +2863,7 @@ find_if_case_1 (test_bb, then_edge, else_edge) /* Test for case 2 above. */ static int -find_if_case_2 (test_bb, then_edge, else_edge) - basic_block test_bb; - edge then_edge, else_edge; +find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) { basic_block then_bb = then_edge->dest; basic_block else_bb = else_edge->dest; @@ -2770,11 +2887,11 @@ find_if_case_2 (test_bb, then_edge, else_edge) return FALSE; /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */ - note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX); + note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX); if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ; else if (else_succ->dest->index < 0 - || dominated_by_p (post_dominators, then_bb, + || dominated_by_p (CDI_POST_DOMINATORS, then_bb, else_succ->dest)) ; else @@ -2800,12 +2917,12 @@ find_if_case_2 (test_bb, then_edge, else_edge) bitmap_operation (test_bb->global_live_at_end, then_bb->global_live_at_start, else_bb->global_live_at_end, BITMAP_IOR); - - if (post_dominators) - delete_from_dominance_info (post_dominators, else_bb); - flow_delete_block (else_bb); - num_removed_blocks++; + if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY) + delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb); + delete_block (else_bb); + + num_true_changes++; num_updated_if_blocks++; /* ??? We may now fallthru from one of THEN's successors into a join @@ -2818,9 +2935,7 @@ find_if_case_2 (test_bb, then_edge, else_edge) Return 1 if a memory is found. */ static int -find_memory (px, data) - rtx *px; - void *data ATTRIBUTE_UNUSED; +find_memory (rtx *px, void *data ATTRIBUTE_UNUSED) { return GET_CODE (*px) == MEM; } @@ -2834,18 +2949,16 @@ find_memory (px, data) REVERSEP is true if the sense of the branch should be reversed. */ static int -dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) - basic_block test_bb, merge_bb, other_bb; - basic_block new_dest; - int reversep; +dead_or_predicable (basic_block test_bb, basic_block merge_bb, + basic_block other_bb, basic_block new_dest, int reversep) { rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX; - jump = test_bb->end; + jump = BB_END (test_bb); /* Find the extent of the real code in the merge block. */ - head = merge_bb->head; - end = merge_bb->end; + head = BB_HEAD (merge_bb); + end = BB_END (merge_bb); if (GET_CODE (head) == CODE_LABEL) head = NEXT_INSN (head); @@ -2861,28 +2974,11 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) if (GET_CODE (end) == JUMP_INSN) { - rtx tmp, insn, label; - if (head == end) { head = end = NULL_RTX; goto no_body; } - - /* If there is a jump table following merge_bb, fail - if there are any insn between head and PREV_INSN (end) - references it. */ - if ((label = JUMP_LABEL (end)) != NULL_RTX - && (tmp = NEXT_INSN (label)) != NULL_RTX - && GET_CODE (tmp) == JUMP_INSN - && (GET_CODE (PATTERN (tmp)) == ADDR_VEC - || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)) - { - for (insn = head; insn != PREV_INSN (end); insn = NEXT_INSN (insn)) - if (find_reg_note (insn, REG_LABEL, label)) - return FALSE; - } - end = PREV_INSN (end); } @@ -2892,8 +2988,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) if (HAVE_conditional_execution) { /* In the conditional execution case, we have things easy. We know - the condition is reversable. We don't have to check life info, - becase we're going to conditionally execute the code anyway. + the condition is reversible. We don't have to check life info + because we're going to conditionally execute the code anyway. All that's left is making sure the insns involved can actually be predicated. */ @@ -2979,7 +3075,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) test_set = INITIALIZE_REG_SET (test_set_head); /* ??? bb->local_set is only valid during calculate_global_regs_live, - so we must recompute usage for MERGE_BB. Not so bad, I suppose, + so we must recompute usage for MERGE_BB. Not so bad, I suppose, since we've already asserted that MERGE_BB is small. */ propagate_block (merge_bb, tmp, merge_set, merge_set, 0); @@ -3082,8 +3178,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) /* Move the insns out of MERGE_BB to before the branch. */ if (head != NULL) { - if (end == merge_bb->end) - merge_bb->end = PREV_INSN (head); + if (end == BB_END (merge_bb)) + BB_END (merge_bb) = PREV_INSN (head); if (squeeze_notes (&head, &end)) return TRUE; @@ -3110,27 +3206,27 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep) /* Main entry point for all if-conversion. */ void -if_convert (x_life_data_ok) - int x_life_data_ok; +if_convert (int x_life_data_ok) { basic_block bb; int pass; num_possible_if_blocks = 0; num_updated_if_blocks = 0; - num_removed_blocks = 0; + num_true_changes = 0; life_data_ok = (x_life_data_ok != 0); + if (! (* targetm.cannot_modify_jumps_p) ()) + mark_loop_exit_edges (); + /* Free up basic_block_for_insn so that we don't have to keep it - up to date, either here or in merge_blocks_nomove. */ + up to date, either here or in merge_blocks. */ free_basic_block_vars (1); /* Compute postdominators if we think we'll use them. */ - post_dominators = NULL; if (HAVE_conditional_execution || life_data_ok) - { - post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS); - } + calculate_dominance_info (CDI_POST_DOMINATORS); + if (life_data_ok) clear_bb_flags (); @@ -3167,8 +3263,7 @@ if_convert (x_life_data_ok) fprintf (rtl_dump_file, "\n\n========== no more changes\n"); #endif - if (post_dominators) - free_dominance_info (post_dominators); + free_dominance_info (CDI_POST_DOMINATORS); if (rtl_dump_file) fflush (rtl_dump_file); @@ -3176,7 +3271,7 @@ if_convert (x_life_data_ok) clear_aux_for_blocks (); /* Rebuild life info for basic blocks that require it. */ - if (num_removed_blocks && life_data_ok) + if (num_true_changes && life_data_ok) { /* If we allocated new pseudos, we must resize the array for sched1. */ if (max_regno < max_reg_num ()) @@ -3199,8 +3294,8 @@ if_convert (x_life_data_ok) "%d IF blocks converted.\n", num_updated_if_blocks); fprintf (rtl_dump_file, - "%d basic blocks deleted.\n\n\n", - num_removed_blocks); + "%d true changes made.\n\n\n", + num_true_changes); } #ifdef ENABLE_CHECKING |