OSDN Git Service

PR middle-end/49489
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Jun 2011 16:25:57 +0000 (16:25 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Jun 2011 16:25:57 +0000 (16:25 +0000)
* builtins.c (expand_builtin_unop): Call expand_unop with 0 as
unsignedp argument instead of 1 for clrsb_optab.
(fold_builtin_bitop): Fix masking for width > HOST_BITS_PER_WIDE_INT
and < 2 * HOST_BITS_PER_WIDE_INT.  Optimize BUILT_IN_CLRSB*.
(fold_builtin_1): Call fold_builtin_binop for BUILT_IN_CLRSB*.
* optabs.c (widen_leading): Call widen_operand and expand_unop
with 0 as unsignedp argument instead of 1 for clrsb_optab.
(expand_unop): Subtract difference of mode sizes also for
clrsb_optab.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175265 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/optabs.c

index 0392ffc..db3b00b 100644 (file)
@@ -1,3 +1,16 @@
+2011-06-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/49489
+       * builtins.c (expand_builtin_unop): Call expand_unop with 0 as
+       unsignedp argument instead of 1 for clrsb_optab.
+       (fold_builtin_bitop): Fix masking for width > HOST_BITS_PER_WIDE_INT
+       and < 2 * HOST_BITS_PER_WIDE_INT.  Optimize BUILT_IN_CLRSB*.
+       (fold_builtin_1): Call fold_builtin_binop for BUILT_IN_CLRSB*.
+       * optabs.c (widen_leading): Call widen_operand and expand_unop
+       with 0 as unsignedp argument instead of 1 for clrsb_optab.
+       (expand_unop): Subtract difference of mode sizes also for
+       clrsb_optab.
+
 2011-06-21  Georg-Johann Lay  <avr@gjlay.de>
 
        * config/avr/avr.md (*jcindirect_jump): Fix build warning.
index 8fc5ac3..5a3835f 100644 (file)
@@ -4578,7 +4578,7 @@ expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
   /* Compute op, into TARGET if possible.
      Set TARGET to wherever the result comes back.  */
   target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 0))),
-                       op_optab, op0, target, 1);
+                       op_optab, op0, target, op_optab != clrsb_optab);
   gcc_assert (target);
 
   return convert_to_mode (target_mode, target, 0);
@@ -7265,7 +7265,8 @@ fold_builtin_bitop (tree fndecl, tree arg)
        {
          hi = TREE_INT_CST_HIGH (arg);
          if (width < 2 * HOST_BITS_PER_WIDE_INT)
-           hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
+           hi &= ~((unsigned HOST_WIDE_INT) (-1)
+                   << (width - HOST_BITS_PER_WIDE_INT));
        }
       else
        {
@@ -7303,6 +7304,26 @@ fold_builtin_bitop (tree fndecl, tree arg)
            result = width;
          break;
 
+       CASE_INT_FN (BUILT_IN_CLRSB):
+         if (width > HOST_BITS_PER_WIDE_INT
+             && (hi & ((unsigned HOST_WIDE_INT) 1
+                       << (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)
+           {
+             hi = ~hi & ~((unsigned HOST_WIDE_INT) (-1)
+                          << (width - HOST_BITS_PER_WIDE_INT - 1));
+             lo = ~lo;
+           }
+         else if (width <= HOST_BITS_PER_WIDE_INT
+                  && (lo & ((unsigned HOST_WIDE_INT) 1 << (width - 1))) != 0)
+           lo = ~lo & ~((unsigned HOST_WIDE_INT) (-1) << (width - 1));
+         if (hi != 0)
+           result = width - floor_log2 (hi) - 2 - HOST_BITS_PER_WIDE_INT;
+         else if (lo != 0)
+           result = width - floor_log2 (lo) - 2;
+         else
+           result = width - 1;
+         break;
+
        CASE_INT_FN (BUILT_IN_POPCOUNT):
          result = 0;
          while (lo)
@@ -9737,6 +9758,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     CASE_INT_FN (BUILT_IN_FFS):
     CASE_INT_FN (BUILT_IN_CLZ):
     CASE_INT_FN (BUILT_IN_CTZ):
+    CASE_INT_FN (BUILT_IN_CLRSB):
     CASE_INT_FN (BUILT_IN_POPCOUNT):
     CASE_INT_FN (BUILT_IN_PARITY):
       return fold_builtin_bitop (fndecl, arg0);
index 7448450..969d5cf 100644 (file)
@@ -1,7 +1,7 @@
 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -2350,8 +2350,10 @@ widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab)
 
              if (target == 0)
                target = gen_reg_rtx (mode);
-             xop0 = widen_operand (op0, wider_mode, mode, true, false);
-             temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, true);
+             xop0 = widen_operand (op0, wider_mode, mode,
+                                   unoptab != clrsb_optab, false);
+             temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
+                                 unoptab != clrsb_optab);
              if (temp != 0)
                temp = expand_binop (wider_mode, sub_optab, temp,
                                     GEN_INT (GET_MODE_BITSIZE (wider_mode)
@@ -3075,8 +3077,9 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
                                  unsignedp);
 
              /* If we are generating clz using wider mode, adjust the
-                result.  */
-             if (unoptab == clz_optab && temp != 0)
+                result.  Similarly for clrsb.  */
+             if ((unoptab == clz_optab || unoptab == clrsb_optab)
+                 && temp != 0)
                temp = expand_binop (wider_mode, sub_optab, temp,
                                     GEN_INT (GET_MODE_BITSIZE (wider_mode)
                                              - GET_MODE_BITSIZE (mode)),