aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-03-09 23:15:15 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2004-03-09 23:15:15 +0000
commit305eeaeb7a5acd2256d075f463fe32fe80781e85 (patch)
treefde015febed56df30084c4c77d4752554520bbcd
parenta4f74b5884a2cb8760d36141ff6ad43183f3088a (diff)
downloadgcc-305eeaeb7a5acd2256d075f463fe32fe80781e85.zip
gcc-305eeaeb7a5acd2256d075f463fe32fe80781e85.tar.gz
gcc-305eeaeb7a5acd2256d075f463fe32fe80781e85.tar.bz2
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 <pinskia@physics.uc.edu> From-SVN: r79205
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ifcvt.c68
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20040309-1.c24
4 files changed, 103 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00bce6a175..d27a00b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2004-03-09 Roger Sayle <roger@eyesopen.com>
+ Andrew Pinski <pinskia@physics.uc.edu>
+
+ * 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 <apinski@apple.com>
* c-typeck.c (tagged_types_tu_compatible_p):
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 976098f..bb0aab3 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 6f61dd7..cf13c3e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-03-09 Roger Sayle <roger@eyesopen.com>
+
+ * gcc.c-torture/execute/20040309-1.c: New test case.
+
2004-03-09 Nathan Sidwell <nathan@codesourcery.com>
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 0000000..49fa795
--- /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;
+}
+