From 999c066978f30fa90fb38b35017db4aec97f8c2b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 14 Jul 2001 11:39:16 -0700 Subject: [PATCH] ifcvt.c (find_cond_trap): New. * ifcvt.c (find_cond_trap): New. (find_if_header): Call it. (merge_if_block): Relax existing jump sanity check. * jump.c (jump_optimize_1): Remove conditional trap handling. * gcc.dg/iftrap-1.c: New. From-SVN: r44006 --- gcc/ChangeLog | 7 ++ gcc/ifcvt.c | 134 +++++++++++++++++++++++++++++++- gcc/jump.c | 79 ------------------- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/iftrap-1.c | 38 +++++++++ 5 files changed, 180 insertions(+), 82 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/iftrap-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 098ffcdfba3..11aec1281cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2001-07-14 Richard Henderson + + * ifcvt.c (find_cond_trap): New. + (find_if_header): Call it. + (merge_if_block): Relax existing jump sanity check. + * jump.c (jump_optimize_1): Remove conditional trap handling. + 2001-07-14 Alan Modra * config/pa/pa.c (emit_hpdiv_const): Return reg is r2 for 64-bit diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 6cb2fabcd13..6196522d228 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -48,6 +48,12 @@ #ifndef HAVE_decscc #define HAVE_decscc 0 #endif +#ifndef HAVE_trap +#define HAVE_trap 0 +#endif +#ifndef HAVE_conditional_trap +#define HAVE_conditional_trap 0 +#endif #ifndef MAX_CONDITIONAL_EXECUTE #define MAX_CONDITIONAL_EXECUTE (BRANCH_COST + 1) @@ -97,6 +103,7 @@ 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)); static int find_if_case_2 PARAMS ((basic_block, edge, edge)); +static int find_cond_trap PARAMS ((basic_block, edge, edge)); static int find_memory PARAMS ((rtx *, void *)); static int dead_or_predicable PARAMS ((basic_block, basic_block, basic_block, rtx, int)); @@ -1757,10 +1764,9 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb) if (combo_bb->succ == NULL_EDGE) abort (); - /* There should sill be a branch at the end of the THEN or ELSE + /* There should still be a branch at the end of the THEN or ELSE blocks taking us to our final destination. */ - if (! any_uncondjump_p (combo_bb->end) - && ! returnjump_p (combo_bb->end)) + if (GET_CODE (combo_bb->end) != JUMP_INSN) abort (); } @@ -1835,6 +1841,9 @@ find_if_header (test_bb) if (find_if_block (test_bb, then_edge, else_edge)) goto success; + if (HAVE_trap && HAVE_conditional_trap + && find_cond_trap (test_bb, then_edge, else_edge)) + goto success; if (post_dominators && (! HAVE_conditional_execution || reload_completed)) { @@ -1965,6 +1974,125 @@ find_if_block (test_bb, then_edge, else_edge) return process_if_block (test_bb, then_bb, else_bb, join_bb); } +/* Convert a branch over a trap, or a branch 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; +{ + basic_block then_bb, else_bb, join_bb, trap_bb; + rtx trap, jump, cond, cond_earliest, seq; + enum rtx_code code; + + then_bb = then_edge->dest; + else_bb = else_edge->dest; + join_bb = NULL; + + /* Locate the block with the trap instruction. */ + /* ??? While we look for no successors, we really ought to allow + EH successors. Need to fix merge_if_block for that to work. */ + /* ??? We can't currently handle merging the blocks if they are not + already adjacent. Prevent losage in merge_if_block by detecting + this now. */ + if (then_bb->succ == NULL) + { + trap_bb = then_bb; + if (else_bb->index != then_bb->index + 1) + return FALSE; + join_bb = else_bb; + else_bb = NULL; + } + else if (else_bb->succ == NULL) + { + trap_bb = else_bb; + if (else_bb->index != then_bb->index + 1) + else_bb = NULL; + else if (then_bb->succ + && ! then_bb->succ->succ_next + && ! (then_bb->succ->flags & EDGE_COMPLEX) + && then_bb->succ->dest->index == else_bb->index + 1) + join_bb = then_bb->succ->dest; + } + else + return FALSE; + + /* The only instruction in the THEN block must be the trap. */ + trap = first_active_insn (trap_bb); + if (! (trap == trap_bb->end + && GET_CODE (PATTERN (trap)) == TRAP_IF + && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx)) + return FALSE; + + if (rtl_dump_file) + { + if (trap_bb == then_bb) + fprintf (rtl_dump_file, + "\nTRAP-IF block found, start %d, trap %d", + test_bb->index, then_bb->index); + else + fprintf (rtl_dump_file, + "\nTRAP-IF block found, start %d, then %d, trap %d", + test_bb->index, then_bb->index, trap_bb->index); + if (join_bb) + fprintf (rtl_dump_file, ", join %d\n", join_bb->index); + else + fputc ('\n', rtl_dump_file); + } + + /* If this is not a standard conditional jump, we can't parse it. */ + jump = test_bb->end; + cond = noce_get_condition (jump, &cond_earliest); + if (! cond) + return FALSE; + + /* If the conditional jump is more than just a conditional jump, + then we can not do if-conversion on this block. */ + if (! onlyjump_p (jump)) + return FALSE; + + /* We must be comparing objects whose modes imply the size. */ + if (GET_MODE (XEXP (cond, 0)) == BLKmode) + return FALSE; + + /* Reverse the comparison code, if necessary. */ + code = GET_CODE (cond); + if (then_bb == trap_bb) + { + code = reversed_comparison_code (cond, jump); + if (code == UNKNOWN) + return FALSE; + } + + /* Attempt to generate the conditional trap. */ + seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1), + TRAP_CODE (PATTERN (trap))); + if (seq == NULL) + return FALSE; + + /* Emit the new insns before cond_earliest; delete the old jump + and trap insns. */ + + emit_insn_before (seq, cond_earliest); + + test_bb->end = PREV_INSN (jump); + flow_delete_insn (jump); + + trap_bb->end = PREV_INSN (trap); + flow_delete_insn (trap); + + /* Merge the blocks! */ + if (trap_bb != then_bb && ! else_bb) + { + flow_delete_block (trap_bb); + num_removed_blocks++; + } + merge_if_block (test_bb, then_bb, else_bb, join_bb); + + return TRUE; +} + /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is transformable, but not necessarily the other. There need be no JOIN block. diff --git a/gcc/jump.c b/gcc/jump.c index ffe958e3926..f98da2d3681 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -208,9 +208,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, int first = 1; int max_uid = 0; rtx last_insn; -#ifdef HAVE_trap - enum rtx_code reversed_code; -#endif cross_jump_death_matters = (cross_jump == 2); max_uid = init_label_info (f) + 1; @@ -498,82 +495,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, changed = 1; next = NEXT_INSN (insn); } - -#ifdef HAVE_trap - /* Detect a conditional jump jumping over an unconditional trap. */ - if (HAVE_trap - && this_is_any_condjump && this_is_onlyjump - && reallabelprev != 0 - && GET_CODE (reallabelprev) == INSN - && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF - && TRAP_CONDITION (PATTERN (reallabelprev)) == const_true_rtx - && prev_active_insn (reallabelprev) == insn - && no_labels_between_p (insn, reallabelprev) - && (temp2 = get_condition (insn, &temp4)) - && ((reversed_code = reversed_comparison_code (temp2, insn)) - != UNKNOWN)) - { - rtx new = gen_cond_trap (reversed_code, - XEXP (temp2, 0), XEXP (temp2, 1), - TRAP_CODE (PATTERN (reallabelprev))); - - if (new) - { - emit_insn_before (new, temp4); - delete_insn (reallabelprev); - delete_jump (insn); - changed = 1; - continue; - } - } - /* Detect a jump jumping to an unconditional trap. */ - else if (HAVE_trap && this_is_onlyjump - && (temp = next_active_insn (JUMP_LABEL (insn))) - && GET_CODE (temp) == INSN - && GET_CODE (PATTERN (temp)) == TRAP_IF - && (this_is_any_uncondjump - || (this_is_any_condjump - && (temp2 = get_condition (insn, &temp4))))) - { - rtx tc = TRAP_CONDITION (PATTERN (temp)); - - if (tc == const_true_rtx - || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc))) - { - rtx new; - /* Replace an unconditional jump to a trap with a trap. */ - if (this_is_any_uncondjump) - { - emit_barrier_after (emit_insn_before (gen_trap (), insn)); - delete_jump (insn); - changed = 1; - continue; - } - new = gen_cond_trap (GET_CODE (temp2), XEXP (temp2, 0), - XEXP (temp2, 1), - TRAP_CODE (PATTERN (temp))); - if (new) - { - emit_insn_before (new, temp4); - delete_jump (insn); - changed = 1; - continue; - } - } - /* If the trap condition and jump condition are mutually - exclusive, redirect the jump to the following insn. */ - else if (GET_RTX_CLASS (GET_CODE (tc)) == '<' - && this_is_any_condjump - && swap_condition (GET_CODE (temp2)) == GET_CODE (tc) - && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0)) - && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1)) - && redirect_jump (insn, get_label_after (temp), 1)) - { - changed = 1; - continue; - } - } -#endif else { /* Now that the jump has been tensioned, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d9e01b8edd7..3075c3f90b8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-07-14 Richard Henderson + + * gcc.dg/iftrap-1.c: New. + 2001-07-11 David Billinghurst * g77.f-torture/execute/intrinsic77.f: New test. diff --git a/gcc/testsuite/gcc.dg/iftrap-1.c b/gcc/testsuite/gcc.dg/iftrap-1.c new file mode 100644 index 00000000000..a9f6a77edbe --- /dev/null +++ b/gcc/testsuite/gcc.dg/iftrap-1.c @@ -0,0 +1,38 @@ +/* Verify that we optimize to conditional traps. */ +/* { dg-options "-O" } */ +/* { dg-do compile { target rs6000-* powerpc-* sparc*-* } } */ +/* { dg-final { scan-assembler-not iftrap-1.c "^\t(trap|ta)\[ \t\]" } } */ + +void f1(int p) +{ + if (p) + __builtin_trap(); +} + +void f2(int p) +{ + if (p) + __builtin_trap(); + else + bar(); +} + +void f3(int p) +{ + if (p) + bar(); + else + __builtin_trap(); +} + +void f4(int p, int q) +{ + if (p) + { + bar(); + if (q) + bar(); + } + else + __builtin_trap(); +}