This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[cfg-branch] branch combining code
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, gcc-pdo at gcc dot gnu dot org
- Date: Mon, 26 Nov 2001 12:58:55 +0100
- Subject: [cfg-branch] branch combining code
Hi,
this patch adds promised support for combining two conditionals into same
destination, such as those created from (cond1 || cond2) and (cond1 && cond2)
type of statements into ifcvt.c
Honza
Mon Nov 26 12:54:50 CET 2001 Jan Hubicka <jh@suse.cz>
* ifcvt.c: Include optabs.h
(num_possible_double_test_blocks, num_updated_double_test_blocks,
num_removed_blocks_double_test): New static variables.
(double_test_info): New structure.
(nonzero_test, double_test_ior_and, m1_test_find_double_test_blocks,
process_double_test_block, block_side_effects_p): New static functions.
(if_convert): Compute statistics.
(find_if_header): Call find_double_test_block.
*** /home/hubicka/egcs2/egcs/gcc/ifcvt.c Thu Nov 15 11:28:47 2001
--- ifcvt.c Thu Nov 22 19:17:03 2001
***************
*** 34,40 ****
#include "output.h"
#include "toplev.h"
#include "tm_p.h"
!
#ifndef HAVE_conditional_execution
#define HAVE_conditional_execution 0
--- 34,40 ----
#include "output.h"
#include "toplev.h"
#include "tm_p.h"
! #include "optabs.h"
#ifndef HAVE_conditional_execution
#define HAVE_conditional_execution 0
*************** static int num_possible_if_blocks;
*** 69,83 ****
--- 69,118 ----
execution. */
static int num_updated_if_blocks;
+ /* # of (test || test2) blocks we looked at */
+ static int num_possible_double_test_blocks;
+
+ /* # of (test || test2) blocks were converted to conditional
+ execution. */
+ static int num_updated_double_test_blocks;
+
/* # of basic blocks that were removed. */
static int num_removed_blocks;
+ /* # of basic blocks that were removed. */
+ static int num_removed_blocks_double_test;
+
/* True if life data ok at present. */
static bool life_data_ok;
/* The post-dominator relation on the original block numbers. */
static sbitmap *post_dominators;
+ struct double_test_info
+ {
+ /* Basic blocks containins first and second test. */
+ basic_block test1_bb, test2_bb;
+
+ /* Then_bb is basic block reached when one of tests above is true.
+ Else_bb is reached otherwise. */
+ basic_block then_bb, else_bb;
+
+ /* If reverse is true, jump info else_bb instead of then_bb after
+ combining an condition. */
+ bool reverse;
+
+ /* The conditions. */
+ enum rtx_code cond1_code, cond2_code;
+ rtx cond1_op0, cond1_op1, cond2_op0, cond2_op1;
+
+ /* Probability of the first and second condition to be true. */
+ int probability1, probability2;
+ gcov_type count1, count2;
+
+ /* Probability of the overall condition to be true. */
+ int probability;
+ };
+
/* Forward references. */
static int count_bb_insns PARAMS ((basic_block));
static rtx first_active_insn PARAMS ((basic_block));
*************** static int process_if_block PARAMS ((ba
*** 99,104 ****
--- 134,147 ----
static void merge_if_block PARAMS ((basic_block, basic_block,
basic_block, basic_block));
+ static rtx nonzero_test PARAMS ((enum rtx_code, rtx, rtx));
+ static rtx double_test_ior_and PARAMS ((struct double_test_info *, rtx *));
+ static rtx m1_test PARAMS ((enum rtx_code, rtx, rtx));
+ static int find_double_test_block PARAMS ((basic_block, edge, edge));
+ static bool process_double_test_block PARAMS ((basic_block, basic_block,
+ basic_block, basic_block,
+ int, int));
+ static bool block_side_effects_p PARAMS ((basic_block));
static int find_if_header PARAMS ((basic_block));
static int find_if_block PARAMS ((basic_block, edge, edge));
static int find_if_case_1 PARAMS ((basic_block, edge, edge));
*************** noce_operand_ok (op)
*** 1583,1588 ****
--- 1626,2105 ----
return ! may_trap_p (op);
}
+ /* Return true if block has side effects. */
+
+ static bool
+ block_side_effects_p (bb)
+ basic_block bb;
+ {
+ rtx insn;
+ for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
+ {
+ rtx set;
+ rtx dest;
+
+ if (!active_insn_p (insn))
+ continue;
+ set = single_set (insn);
+ if (!set)
+ return true;
+ dest = SET_DEST (set);
+ if (GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+ if (GET_CODE (dest) == SUBREG)
+ dest = SUBREG_REG (dest);
+ if (dest == pc_rtx || dest == cc0_rtx)
+ continue;
+ if (!REG_P (dest))
+ return true;
+ if (!life_data_ok || UPDATE_LIFE (bb))
+ return true;
+ if (REGNO_REG_SET_P (bb->global_live_at_end, REGNO (dest)))
+ return true;
+ if (!noce_operand_ok (PATTERN (insn)))
+ return true;
+ }
+ return false;
+ }
+
+ /* Emit code to set register nonzero iff condition is true. Return the
+ register. */
+
+ static rtx
+ nonzero_test (cond, op0, op1)
+ enum rtx_code cond;
+ rtx op0, op1;
+ {
+ rtx x;
+ enum machine_mode mode;
+ enum insn_code icode;
+
+ /* First special cases first. */
+ if (INTEGRAL_MODE_P (GET_MODE (op0)))
+ switch (cond)
+ {
+ case NE:
+ /* Convert (a != 0) into a, (a != b) into (a ^ b). */
+ if (op1 == const0_rtx)
+ {
+ rtx reg = gen_reg_rtx (GET_MODE (op0));
+
+ /* We must move the operand to new register, as operand of
+ first test may be clobbered while computing operand for
+ the second. */
+ emit_move_insn (reg, op0);
+ return reg;
+ }
+ if (BRANCH_COST > 0)
+ return expand_simple_binop (GET_MODE (op0), XOR, op0, op1, NULL_RTX, 1,
+ OPTAB_DIRECT);
+ break;
+ case LT:
+ /* Convert (a < 0) into (a >> (bits_per_mode - 1)). */
+ if (op1 == const0_rtx && BRANCH_COST > 0)
+ {
+ negative:
+ return expand_simple_binop (GET_MODE (op0), LSHIFTRT, op0,
+ GEN_INT (GET_MODE_BITSIZE
+ (GET_MODE (op0)) - 1),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ }
+ break;
+ case LE:
+ /* (a <= -1) is equivalent to (a < 0). */
+ if (op1 == constm1_rtx && BRANCH_COST > 0)
+ goto negative;
+ break;
+ case GT:
+ /* Convert (a > -1) into (~a < 0). */
+ if (op1 == constm1_rtx && BRANCH_COST > 1)
+ {
+ positive:
+ op0 = expand_simple_unop (GET_MODE (op0), NOT, op0, NULL_RTX, 1);
+ if (!op0)
+ return NULL;
+ goto negative;
+ }
+ break;
+ case GE:
+ /* Convert (a >= 0) into (~a < 0). */
+ if (op1 == const0_rtx && BRANCH_COST > 1)
+ goto positive;
+ break;
+ default:
+ break;
+ }
+ /* Try m1_test and add 1 to the result. */
+ x = m1_test (cond, op0, op1);
+ if (x)
+ return expand_simple_binop (GET_MODE (x), PLUS, x, const1_rtx, NULL_RTX,
+ 1, OPTAB_DIRECT);
+
+
+ if (BRANCH_COST < 2)
+ return NULL;
+
+ /* In case target do have setcc instruction, choose mode used by the pattern.
+ Otherwise use Pmode as it will probably combine well with the other
+ test. */
+
+ mode = Pmode;
+ icode = setcc_gen_code[(int) cond];
+ if (icode != CODE_FOR_nothing)
+ mode = insn_data[(int) icode].operand[0].mode;
+
+ /* Use store_flag as default. */
+ return emit_store_flag (gen_reg_rtx (mode),
+ cond, op0, op1, VOIDmode,
+ (cond == LTU || cond == LEU
+ || cond == GEU || cond == GTU), 0);
+ }
+
+ /* Emit code to set register -1 iff condition is false.
+ Handle only special cases we can do cheaply, as otherwise
+ the setcc instruction and | will be used instead. */
+
+ static rtx
+ m1_test (cond, op0, op1)
+ enum rtx_code cond;
+ rtx op0, op1;
+ {
+ /* Using AND allways adds extra instruction to compare with -1, so be
+ more strict about BRANCH_COST than nonzero_test. */
+ if (!BRANCH_COST)
+ return NULL;
+ /* First special cases first. */
+ if (INTEGRAL_MODE_P (GET_MODE (op0)))
+ switch (cond)
+ {
+ case NE:
+ if (op1 == constm1_rtx)
+ {
+ rtx reg = gen_reg_rtx (GET_MODE (op0));
+
+ /* We must move the operand to new register, as operand of
+ first test may be clobbered while computing operand for
+ the second. */
+ emit_move_insn (reg, op0);
+ return reg;
+ }
+ break;
+ case GE:
+ /* Convert (a >= 0) into (a >> (bits_per_mode - 1)) != -1. */
+ if (op1 == const0_rtx && BRANCH_COST > 1)
+ {
+ nonnegative:
+ return expand_simple_binop (GET_MODE (op0), ASHIFTRT, op0,
+ GEN_INT (GET_MODE_BITSIZE
+ (GET_MODE (op0)) - 1),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ }
+ break;
+ case GT:
+ /* (a > -1) is equivalent to (a >= 0). */
+ if (op1 == constm1_rtx && BRANCH_COST > 1)
+ goto nonnegative;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+ }
+
+ /* Attempt to convert double test of form (cond1 || cond2)
+ as (cond1 | cond2) or ((cond1 ? -1 : 0) & (cond2 ? -1 : 0)).
+
+ Return sequence containing the conditional jump. Set TEST
+ to the code to process operand0 before it is possibly clobbered
+ by the original code copied from TEST_BB. */
+
+ static rtx
+ double_test_ior_and (info, test)
+ struct double_test_info *info;
+ rtx *test;
+ {
+ rtx op0, op1, res;
+ rtx insn;
+ enum machine_mode mode;
+ bool and_code = true;
+
+ if (! general_operand (info->cond1_op0, GET_MODE (info->cond1_op0))
+ || ! general_operand (info->cond1_op1, GET_MODE (info->cond1_op1))
+ || ! general_operand (info->cond2_op0, GET_MODE (info->cond2_op0))
+ || ! general_operand (info->cond2_op1, GET_MODE (info->cond2_op1)))
+ return NULL;
+
+ /* Attempt to prepare operands for & or | operation. First try &,
+ as we make it suceed only when both tests are chaper than alternative
+ doable by |.
+
+ | has the advantage of comparing result with 0, so for instance i386 can
+ do it by one instruction, while for & we compare with -1. */
+
+ start_sequence ();
+ op0 = m1_test (info->cond1_code, info->cond1_op0, info->cond1_op1);
+ *test = gen_sequence ();
+ end_sequence ();
+
+ if (op0)
+ {
+ start_sequence ();
+ op1 = m1_test (info->cond2_code, info->cond2_op0, info->cond2_op1);
+ if (!op1)
+ end_sequence ();
+ }
+
+ if (!op0 || !op1)
+ {
+ start_sequence ();
+ op0 = nonzero_test (info->cond1_code, info->cond1_op0, info->cond1_op1);
+ if (!op0)
+ goto fail;
+ *test = gen_sequence ();
+ end_sequence ();
+
+ start_sequence ();
+ op1 = nonzero_test (info->cond2_code, info->cond2_op0, info->cond2_op1);
+ if (!op1)
+ goto fail;
+ and_code = false;
+ }
+
+ if (GET_MODE_BITSIZE (GET_MODE (op0)) > GET_MODE_BITSIZE (GET_MODE (op1)))
+ mode = GET_MODE (op0);
+ else
+ mode = GET_MODE (op1);
+
+ res = expand_simple_binop (mode, and_code ? AND : IOR,
+ op0, op1, NULL_RTX, !and_code, OPTAB_WIDEN);
+
+ if (!res)
+ goto fail;
+
+ emit_cmp_and_jump_insns (res, and_code ? constm1_rtx : const0_rtx,
+ info->reverse ? EQ : NE,
+ NULL_RTX, GET_MODE (res), and_code ? 1 : 0,
+ block_label (info->reverse
+ ? info->else_bb : info->then_bb));
+ insn = get_last_insn ();
+ mark_jump_label (PATTERN (insn), insn, 0);
+
+ insn = gen_sequence ();
+ end_sequence ();
+ return insn;
+
+ fail:
+ end_sequence ();
+ return NULL;
+ }
+
+ /* Attempt to reduce amount of exits from superblocks by converting
+ constructions of type (const1 || cond2) into (cond1 | cond2) when
+ profitable.
+
+ TEST_BB is the block with first condition, TEST2_BB second condition,
+ THEN_BB is block to jump into if eighter condition is true, ELSE_BB is
+ the other block. REVERSE1 and REVERSE2 specifies if the condition
+ in TEST_BB or TEST2_BB needs to be reversed. */
+
+ static bool
+ process_double_test_block (test_bb, test2_bb, then_bb, else_bb,
+ reverse1, reverse2)
+ basic_block test_bb; /* Basic block test is in */
+ basic_block test2_bb; /* Basic block second test is in */
+ basic_block then_bb; /* Basic block for case both conditions are met */
+ basic_block else_bb; /* Basic block other cases */
+ int reverse1, reverse2;
+ {
+ struct double_test_info info;
+ rtx cond1, cond2;
+ rtx jump1, jump2;
+ rtx earliest1, earliest2;
+ rtx insn;
+ rtx first, last;
+ rtx test_insn;
+ edge fallthru_edge = FALLTHRU_EDGE (test_bb);
+ edge branch_edge = BRANCH_EDGE (test_bb);
+ edge fallthru2_edge = FALLTHRU_EDGE (test2_bb);
+ edge branch2_edge = BRANCH_EDGE (test2_bb);
+ const char *purpose;
+
+ /* Currently we support no conversions that require no new pseudos. */
+ if (no_new_pseudos)
+ return false;
+
+ info.test1_bb = test_bb;
+ info.test2_bb = test2_bb;
+ info.then_bb = then_bb;
+ info.else_bb = else_bb;
+ info.probability1 =
+ reverse1 ? fallthru_edge->probability : branch_edge->probability;
+ info.probability2 =
+ reverse2 ? fallthru2_edge->probability : branch2_edge->probability;
+ info.probability =
+ (info.probability1 +
+ (REG_BR_PROB_BASE -
+ info.probability1) * info.probability2 / REG_BR_PROB_BASE);
+ info.count1 = reverse1 ? fallthru_edge->count : branch_edge->count;
+ info.count2 = reverse2 ? fallthru2_edge->count : branch2_edge->count;
+
+ if (rtl_dump_file)
+ {
+ fprintf (rtl_dump_file, " probability1: %.2f probability2: %.2f overall (%.2f)\n",
+ info.probability1 * 100.0 / REG_BR_PROB_BASE,
+ info.probability2 * 100.0 / REG_BR_PROB_BASE,
+ info.probability * 100.0 / REG_BR_PROB_BASE);
+ }
+
+ /* Ensure that the TEST2 block is inside same superblock. */
+ if (info.probability1 > 2 * REG_BR_PROB_BASE / 3)
+ {
+ purpose = "too high probability of first test.";
+ goto failed;
+ }
+
+ /* If the conditional jump is more than just a conditional jump,
+ then we can not do conversion on this block. */
+ jump1 = test_bb->end;
+ jump2 = test2_bb->end;
+ if (!onlyjump_p (jump1) || !onlyjump_p (jump2)
+ || !any_condjump_p (jump1) || !any_condjump_p (jump2))
+ {
+ purpose = "Not onlyjump.";
+ goto failed;
+ }
+
+ /* If this is not a standard conditional jump, we can't parse it. */
+ cond1 = noce_get_condition (jump1, &earliest1);
+ if (!cond1)
+ {
+ purpose = "Can not get first condition.";
+ goto failed;
+ }
+ cond2 = noce_get_condition (jump2, &earliest2);
+ if (!cond2)
+ {
+ purpose = "Can not get second condition.";
+ goto failed;
+ }
+
+ /* We require test2_bb to contain only loads of registers temporary
+ for test2_bb, so we can be sure that moving these on common path
+ won't cause side effects.
+
+ Limit number of instructions to avoid too expensive computations. */
+
+ if (count_bb_insns (test2_bb) >= BRANCH_COST + 2)
+ {
+ purpose = "Too many instructions in bb2.";
+ goto failed;
+ }
+ if (block_side_effects_p (test2_bb))
+ {
+ purpose = "Side effects in bb2.";
+ goto failed;
+ }
+
+ info.cond1_code = GET_CODE (cond1);
+ info.cond2_code = GET_CODE (cond2);
+ if (reverse1)
+ info.cond1_code = reversed_comparison_code (cond1, jump1);
+ if (reverse2)
+ info.cond2_code = reversed_comparison_code (cond2, jump2);
+ if (info.cond1_code == UNKNOWN || info.cond2_code == UNKNOWN)
+ return false;
+ info.cond1_op0 = XEXP (cond1, 0);
+ info.cond1_op1 = XEXP (cond1, 1);
+ info.cond2_op0 = XEXP (cond2, 0);
+ info.cond2_op1 = XEXP (cond2, 1);
+
+ info.reverse = (fallthru_edge->dest == then_bb
+ || (fallthru_edge->dest == test2_bb
+ && fallthru2_edge->dest == then_bb));
+
+ insn = double_test_ior_and (&info, &test_insn);
+ if (!insn)
+ {
+ purpose = "Failed to match.";
+ goto failed;
+ }
+
+ /* Fix up the flowgraph. */
+ delete_insn (jump1);
+
+ /* Relink insns from test2 blocks, as they may compute temporaries used
+ by test. */
+ first = (GET_CODE (test2_bb->head) == CODE_LABEL
+ ? NEXT_INSN (NEXT_INSN (test2_bb->head))
+ : NEXT_INSN (test2_bb->head));
+ last = PREV_INSN (test2_bb->end);
+
+ emit_insn_after (test_insn, test_bb->end);
+ if (first != NEXT_INSN (last))
+ {
+ squeeze_notes (&first, &last);
+ reorder_insns (first, last, test_bb->end);
+ }
+ emit_insn_after (insn, test_bb->end);
+
+ if (fallthru_edge->dest == then_bb)
+ redirect_edge_succ (branch_edge, else_bb);
+ else if (fallthru_edge->dest == else_bb)
+ redirect_edge_succ (branch_edge, then_bb);
+ else if (fallthru_edge->dest == test2_bb)
+ {
+ if (fallthru2_edge->dest == else_bb)
+ {
+ redirect_edge_succ (fallthru_edge, else_bb);
+ redirect_edge_succ (branch_edge, then_bb);
+ }
+ else if (fallthru2_edge->dest == then_bb)
+ {
+ redirect_edge_succ (fallthru_edge, then_bb);
+ redirect_edge_succ (branch_edge, else_bb);
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
+
+ if (fallthru_edge->dest == then_bb)
+ {
+ branch_edge->probability = REG_BR_PROB_BASE - info.probability;
+ fallthru_edge->probability = info.probability;
+ branch_edge->count = test_bb->count - info.count1 - info.count2;
+ fallthru_edge->count = info.count1 + info.count2;
+ }
+ else
+ {
+ fallthru_edge->probability = REG_BR_PROB_BASE - info.probability;
+ branch_edge->probability = info.probability;
+ fallthru_edge->count = test_bb->count - info.count1 - info.count2;
+ branch_edge->count = info.count1 + info.count2;
+ }
+
+ /* The test basic block may define some pseudos used by test2. We do not
+ want to make them appear alive anymore. */
+ test_bb->global_live_at_end = test2_bb->global_live_at_end;
+
+ /* Delete the second test basic block. */
+ if (test2_bb->pred != NULL_EDGE)
+ abort ();
+ flow_delete_block (test2_bb);
+ num_removed_blocks_double_test++;
+ num_updated_double_test_blocks++;
+ /* Make sure we update life info properly. */
+ SET_UPDATE_LIFE (test_bb);
+ return true;
+
+ failed:
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, " %s", purpose);
+ return false;
+ }
+
+
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
without using conditional execution. Return TRUE if we were
successful at converting the the block. */
*************** find_if_header (test_bb)
*** 1941,1946 ****
--- 2458,2470 ----
/* Otherwise this must be a multiway branch of some sort. */
return FALSE;
+ /* A loop as we may cascadely update the CFG. */
+ while (find_double_test_block (test_bb, then_edge, else_edge))
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Conversion succeeded.\n");
+ }
+
if (find_if_block (test_bb, then_edge, else_edge))
goto success;
if (HAVE_trap && HAVE_conditional_trap
*************** find_if_header (test_bb)
*** 1963,1968 ****
--- 2487,2583 ----
return TRUE;
}
+ /* Look for basic block constelation that result from
+ test1 || test2 type of conditions. */
+ static int
+ find_double_test_block (test_bb, then_edge, test2_edge)
+ basic_block test_bb;
+ edge then_edge, test2_edge;
+ {
+ int reverse_condition1 = 0;
+
+ /* Try both arms of the condition. */
+ for (reverse_condition1 = 0; reverse_condition1 <= 1; reverse_condition1++)
+ {
+ edge tmp;
+ basic_block then_bb;
+ basic_block test2_bb;
+ basic_block else_bb;
+ edge then2_edge, else_edge;
+ int reverse_condition2 = 0;
+
+ /* The then_edge is falltrought edge on entry. In case we don't
+ reverse condition, we require it to be false. */
+ tmp = then_edge;
+ then_edge = test2_edge;
+ test2_edge = tmp;
+
+ then_bb = then_edge->dest;
+ test2_bb = test2_edge->dest;
+
+ /* The test2 must be single basic block with the conditional jump. */
+ if (!test2_bb->succ || !test2_bb->succ->succ_next
+ || test2_bb->succ->succ_next->succ_next)
+ continue;
+ else_edge = test2_bb->succ;
+ then2_edge = test2_bb->succ->succ_next;
+
+ /* Avoid abnormal edges. */
+ if (then2_edge->flags & EDGE_COMPLEX
+ || else_edge->flags & EDGE_COMPLEX)
+ continue;
+
+ /* Get the fallthru edge to be else one. */
+ if (else_edge->flags & EDGE_FALLTHRU)
+ ;
+ else if (then2_edge->flags & EDGE_FALLTHRU)
+ {
+ tmp = then2_edge;
+ then2_edge = else_edge;
+ else_edge = tmp;
+ }
+ else
+ continue;
+
+ /* Find if some of edges points to the then_bb.
+ Otherwise give up. */
+ if (else_edge->dest == then_bb)
+ {
+ tmp = then2_edge;
+ then2_edge = else_edge;
+ else_edge = tmp;
+ reverse_condition2 = 1;
+ }
+ if (then2_edge->dest != then_bb)
+ continue;
+
+ else_bb = else_edge->dest;
+
+ /* Avoid multiple predecesors in the test2 block, as we are going
+ to remove it. */
+ if (test2_bb->pred->pred_next)
+ continue;
+
+ if (rtl_dump_file)
+ {
+ fprintf (rtl_dump_file,
+ "\nDOUBLE-TEST block found, test1 %d, test2 %d, then %d, else %d\n",
+ test_bb->index, test2_bb->index, then_bb->index,
+ else_bb->index);
+ fprintf (rtl_dump_file,
+ " reverse_condition1:%i, reverse_condition2:%i\n",
+ reverse_condition1, reverse_condition2);
+ }
+ num_possible_double_test_blocks ++;
+ if (process_double_test_block (test_bb, test2_bb, then_bb, else_bb,
+ reverse_condition1, reverse_condition2))
+ return TRUE;
+
+ }
+ return FALSE;
+ }
+
+
/* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
block. If so, we'll try to convert the insns to not require the branch.
Return TRUE if we were successful at converting the the block. */
*************** if_convert (x_life_data_ok)
*** 2682,2687 ****
--- 3297,3305 ----
num_possible_if_blocks = 0;
num_updated_if_blocks = 0;
num_removed_blocks = 0;
+ num_possible_double_test_blocks = 0;
+ num_updated_double_test_blocks = 0;
+ num_removed_blocks_double_test = 0;
life_data_ok = (x_life_data_ok != 0);
/* Free up basic_block_for_insn so that we don't have to keep it
*************** if_convert (x_life_data_ok)
*** 2717,2723 ****
fflush (rtl_dump_file);
/* Rebuild life info for basic blocks that require it. */
! if (num_removed_blocks && life_data_ok)
{
sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (update_life_blocks);
--- 3335,3341 ----
fflush (rtl_dump_file);
/* Rebuild life info for basic blocks that require it. */
! if ((num_removed_blocks || num_updated_double_test_blocks) && life_data_ok)
{
sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (update_life_blocks);
*************** if_convert (x_life_data_ok)
*** 2738,2744 ****
set of blocks don't let registers come live. */
update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL,
PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
! | PROP_KILL_DEAD_CODE);
sbitmap_free (update_life_blocks);
}
--- 3356,3362 ----
set of blocks don't let registers come live. */
update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL,
PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
! | PROP_KILL_DEAD_CODE | PROP_LOG_LINKS);
sbitmap_free (update_life_blocks);
}
*************** if_convert (x_life_data_ok)
*** 2756,2761 ****
--- 3374,3391 ----
fprintf (rtl_dump_file,
"%d basic blocks deleted.\n\n\n",
num_removed_blocks);
+ }
+ if (rtl_dump_file && num_possible_double_test_blocks > 0)
+ {
+ fprintf (rtl_dump_file,
+ "\n%d possible double test blocks searched.\n",
+ num_possible_double_test_blocks);
+ fprintf (rtl_dump_file,
+ "%d double test blocks converted.\n",
+ num_updated_double_test_blocks);
+ fprintf (rtl_dump_file,
+ "%d basic blocks deleted.\n\n\n",
+ num_removed_blocks_double_test);
}
#ifdef ENABLE_CHECKING