ifcvt.c (noce_try_sign_mask): New function to transform "x = (y < 0) ? z ...
authorRoger Sayle <roger@eyesopen.com>
Tue, 9 Mar 2004 23:15:15 +0000 (23:15 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 9 Mar 2004 23:15:15 +0000 (23:15 +0000)
* 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

gcc/ChangeLog
gcc/ifcvt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20040309-1.c [new file with mode: 0644]

index 00bce6a17504c0a8918e3584e4fa39557e499c7e..d27a00bda068790cad66a3edb454bc960c2bf2f8 100644 (file)
@@ -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):
index 976098f4326a024504ca4d6943da951746fa1563..bb0aab3777e3db1507b5185d7ddb1a16ab4353a4 100644 (file)
@@ -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;
index 6f61dd7e5e0eedc6832307c8112ba88ed24fb763..cf13c3e3bb44712d527a66ad1c8a436e42414a01 100644 (file)
@@ -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 (file)
index 0000000..49fa795
--- /dev/null
@@ -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;
+}
+