From 305eeaeb7a5acd2256d075f463fe32fe80781e85 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Tue, 9 Mar 2004 23:15:15 +0000 Subject: [PATCH] ifcvt.c (noce_try_sign_mask): New function to transform "x = (y < 0) ? z ... * ifcvt.c (noce_try_sign_mask): New function to transform "x = (y < 0) ? z : 0" into the equivalent "x = (y >> C) & z". (noce_process_if_block): Call noce_try_sign_mask. * gcc.c-torture/execute/20040309-1.c: New test case. Co-Authored-By: Andrew Pinski From-SVN: r79205 --- gcc/ChangeLog | 7 ++ gcc/ifcvt.c | 68 +++++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++ .../gcc.c-torture/execute/20040309-1.c | 24 +++++++ 4 files changed, 103 insertions(+) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20040309-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00bce6a1750..d27a00bda06 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-03-09 Roger Sayle + Andrew Pinski + + * ifcvt.c (noce_try_sign_mask): New function to transform + "x = (y < 0) ? z : 0" into the equivalent "x = (y >> C) & z". + (noce_process_if_block): Call noce_try_sign_mask. + 2004-03-09 Andrew Pinski * c-typeck.c (tagged_types_tu_compatible_p): diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 976098f4326..bb0aab3777e 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -612,6 +612,7 @@ 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 *); +static int noce_try_sign_mask (struct noce_if_info *); /* Helper function for noce_try_store_flag*. */ @@ -1702,6 +1703,71 @@ noce_try_abs (struct noce_if_info *if_info) return TRUE; } +/* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;". */ + +static int +noce_try_sign_mask (struct noce_if_info *if_info) +{ + rtx cond, t, m, c, seq; + enum machine_mode mode; + enum rtx_code code; + + if (no_new_pseudos) + return FALSE; + + cond = if_info->cond; + code = GET_CODE (cond); + m = XEXP (cond, 0); + c = XEXP (cond, 1); + + t = NULL_RTX; + if (if_info->a == const0_rtx) + { + if ((code == LT && c == const0_rtx) + || (code == LE && c == constm1_rtx)) + t = if_info->b; + } + else if (if_info->b == const0_rtx) + { + if ((code == GE && c == const0_rtx) + || (code == GT && c == constm1_rtx)) + t = if_info->a; + } + + if (! t || side_effects_p (t)) + return FALSE; + + /* We currently don't handle different modes. */ + mode = GET_MODE (t); + if (GET_MODE (m) != mode) + return FALSE; + + /* This is only profitable if T is cheap. */ + if (rtx_cost (t, SET) >= COSTS_N_INSNS (2)) + return FALSE; + + start_sequence (); + c = gen_int_mode (GET_MODE_BITSIZE (mode) - 1, mode); + m = expand_binop (mode, ashr_optab, m, c, NULL_RTX, 0, OPTAB_DIRECT); + t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT) + : NULL_RTX; + + if (!t) + { + end_sequence (); + return FALSE; + } + + noce_emit_move_insn (if_info->x, t); + 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; +} + + /* Similar to get_condition, only the resulting condition must be valid at JUMP, instead of at EARLIEST. */ @@ -2004,6 +2070,8 @@ noce_process_if_block (struct ce_if_block * ce_info) if (HAVE_conditional_move && noce_try_cmove_arith (&if_info)) goto success; + if (noce_try_sign_mask (&if_info)) + goto success; } return FALSE; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f61dd7e5e0..cf13c3e3bb4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-03-09 Roger Sayle + + * gcc.c-torture/execute/20040309-1.c: New test case. + 2004-03-09 Nathan Sidwell PR c++/14397 diff --git a/gcc/testsuite/gcc.c-torture/execute/20040309-1.c b/gcc/testsuite/gcc.c-torture/execute/20040309-1.c new file mode 100644 index 00000000000..49fa79560c6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20040309-1.c @@ -0,0 +1,24 @@ +extern void abort (); + +int foo(unsigned short x) +{ + unsigned short y; + y = x > 32767 ? x - 32768 : 0; + return y; +} + +int main() +{ + if (foo (0) != 0) + abort (); + if (foo (32767) != 0) + abort (); + if (foo (32768) != 0) + abort (); + if (foo (32769) != 1) + abort (); + if (foo (65535) != 32767) + abort (); + return 0; +} + -- 2.30.2