Makefile.in (lib2funcs): Add _clrsbsi2 and _clrsbdi2.
authorBernd Schmidt <bernds@codesourcery.com>
Tue, 21 Jun 2011 14:16:39 +0000 (14:16 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Tue, 21 Jun 2011 14:16:39 +0000 (14:16 +0000)
libgcc/
* Makefile.in (lib2funcs): Add _clrsbsi2 and _clrsbdi2.
* libgcc-std.ver.in (GCC_4.7.0): New section.

gcc/
* doc/extend.texi (__builtin_clrsb, __builtin_clrsbl,
__builtin_clrsbll): Document.
* doc/rtl.texi (clrsb): New entry.
* optabs.c (widen_leading): Renamed from widen_clz.  New argument
UNOPTAB.  All callers changed.  Use UNOPTAB instead of clz_optab.
(expand_unop): Handle clrsb_optab.
(init_optabs): Initialize it.
* optabs.h (enum optab_index): New entry OTI_clrsb.
(clrsb_optab): Define.
* genopinit.c (optabs): Add an entry for it.
* builtins.c (expand_builtin): Handle clrsb builtin functions.
* builtins.def (BUILT_IN_CLRSB, BUILT_IN_CLRSBIMAX, BUILT_IN_CLRSBL,
BUILT_IN_CLRSBLL): New.
* rtl.def (CLRSB): New code.
* dwarf2out.c (mem_loc_descriptor): Handle it.
* simplify-rtx.c (simplify_const_unary_operation): Likewise.
Use op_mode rather than mode when optimizing ffs, clz, ctz, parity
and popcount.
* libgcc2.c (__clrsbSI2, __clrsbDI2): New functions.
* libgcc2.h (__clrsbSI2, __clrsbDI2): Define and declare.
(__ctzDI2): Move declaration.
* config/bfin/bfin.md (clrsbsi2): New expander.
(signbitssi2): Use the CLRSB rtx.
(clrsbhi2): Renamed from signbitshi2.  Use the CLRSB rtx.
* config/bfin/bfin.c (bdesc_1arg): Changed accordingly.

gcc/testsuite/
* gcc.c-torture/excute/builtin-bitops-1.c (MAKE_FUNS): Make
my_clrsb test functions.
(main): Test clrsb.
* gcc.dg/builtin-protos-1.c (test_s, test_u, test_sl, test_ul,
test_sll, test_ull): Add clrsb tests.
* gcc.dg/torture/builtin-attr-1.c: Add tests for clrsb, clrsbl,
clrsbll.

From-SVN: r175261

22 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/config/bfin/bfin.c
gcc/config/bfin/bfin.md
gcc/doc/extend.texi
gcc/doc/rtl.texi
gcc/dwarf2out.c
gcc/genopinit.c
gcc/libgcc2.c
gcc/libgcc2.h
gcc/optabs.c
gcc/optabs.h
gcc/rtl.def
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/builtin-bitops-1.c
gcc/testsuite/gcc.dg/builtin-protos-1.c
gcc/testsuite/gcc.dg/torture/builtin-attr-1.c
libgcc/ChangeLog
libgcc/Makefile.in
libgcc/libgcc-std.ver.in

index 1685fb2342d76c72d4c063fbda89121d607aff86..af173123600745eb701cb969433759d77e612f62 100644 (file)
@@ -1,3 +1,31 @@
+2011-06-21  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * doc/extend.texi (__builtin_clrsb, __builtin_clrsbl,
+       __builtin_clrsbll): Document.
+       * doc/rtl.texi (clrsb): New entry.
+       * optabs.c (widen_leading): Renamed from widen_clz.  New argument
+       UNOPTAB.  All callers changed.  Use UNOPTAB instead of clz_optab.
+       (expand_unop): Handle clrsb_optab.
+       (init_optabs): Initialize it.
+       * optabs.h (enum optab_index): New entry OTI_clrsb.
+       (clrsb_optab): Define.
+       * genopinit.c (optabs): Add an entry for it.
+       * builtins.c (expand_builtin): Handle clrsb builtin functions.
+       * builtins.def (BUILT_IN_CLRSB, BUILT_IN_CLRSBIMAX, BUILT_IN_CLRSBL,
+       BUILT_IN_CLRSBLL): New.
+       * rtl.def (CLRSB): New code.
+       * dwarf2out.c (mem_loc_descriptor): Handle it.
+       * simplify-rtx.c (simplify_const_unary_operation): Likewise.
+       Use op_mode rather than mode when optimizing ffs, clz, ctz, parity
+       and popcount.
+       * libgcc2.c (__clrsbSI2, __clrsbDI2): New functions.
+       * libgcc2.h (__clrsbSI2, __clrsbDI2): Define and declare.
+       (__ctzDI2): Move declaration.
+       * config/bfin/bfin.md (clrsbsi2): New expander.
+       (signbitssi2): Use the CLRSB rtx.
+       (clrsbhi2): Renamed from signbitshi2.  Use the CLRSB rtx.
+       * config/bfin/bfin.c (bdesc_1arg): Changed accordingly.
+
 2011-06-21  Richard Guenther  <rguenther@suse.de>
 
        * ipa-inline-transform.c (inline_transform): Fix previous
index cf975e578a77c94a6414f6473cc0e6a13a3135a9..8fc5ac34e541b37276868e691e3769df4f0e9aa5 100644 (file)
@@ -5580,6 +5580,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
        return target;
       break;
 
+    CASE_INT_FN (BUILT_IN_CLRSB):
+    case BUILT_IN_CLRSBIMAX:
+      target = expand_builtin_unop (target_mode, exp, target,
+                                   subtarget, clrsb_optab);
+      if (target)
+       return target;
+      break;
+
     CASE_INT_FN (BUILT_IN_POPCOUNT):
     case BUILT_IN_POPCOUNTIMAX:
       target = expand_builtin_unop (target_mode, exp, target,
index 3e102e316253fbf49b081292b105467a8926c588..30699f3685a3c1a259462aaf2be8d11625a8540a 100644 (file)
@@ -620,6 +620,10 @@ DEF_GCC_BUILTIN        (BUILT_IN_CTZ, "ctz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_
 DEF_GCC_BUILTIN        (BUILT_IN_CTZIMAX, "ctzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CTZL, "ctzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CTZLL, "ctzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_CLRSB, "clrsb", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_CLRSBIMAX, "clrsbimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_CLRSBL, "clrsbl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_CLRSBLL, "clrsbll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_DCGETTEXT, "dcgettext", BT_FN_STRING_CONST_STRING_CONST_STRING_INT, ATTR_FORMAT_ARG_2)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_DGETTEXT, "dgettext", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2)
 DEF_GCC_BUILTIN        (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
index 72fc42383ee48cea9cb6ab2a9336ab91d2872ce6..22fdfb79b15e3b6de8134cdebe6ac1f1f38da6c8 100644 (file)
@@ -5879,11 +5879,11 @@ static const struct builtin_description bdesc_1arg[] =
 
   { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
 
-  { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
+  { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
   { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
   { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
 
-  { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
+  { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
   { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
   { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
   { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
index 903c8bb076f29a7920aaf90657d15b02c9946a90..a96d1a7bda6849d213b465ea902258a38b6c5588 100644 (file)
   "%0 = ~%1;"
   [(set_attr "type" "alu0")])
 
+(define_expand "clrsbsi2"
+  [(set (match_dup 2)
+       (clrsb:HI (match_operand:SI 1 "register_operand" "d")))
+   (set (match_operand:SI 0 "register_operand")
+       (zero_extend:SI (match_dup 2)))]
+  ""
+{
+  operands[2] = gen_reg_rtx (HImode);
+})
+
 (define_insn "signbitssi2"
   [(set (match_operand:HI 0 "register_operand" "=d")
-       (if_then_else:HI
-        (lt (match_operand:SI 1 "register_operand" "d") (const_int 0))
-        (clz:HI (not:SI (match_dup 1)))
-        (clz:HI (match_dup 1))))]
+       (clrsb:HI (match_operand:SI 1 "register_operand" "d")))]
   ""
   "%h0 = signbits %1%!"
   [(set_attr "type" "dsp32")])
   "%0 = -%1 (V)%!"
   [(set_attr "type" "dsp32")])
 
-(define_insn "signbitshi2"
+(define_insn "clrsbhi2"
   [(set (match_operand:HI 0 "register_operand" "=d")
-       (if_then_else:HI
-        (lt (match_operand:HI 1 "register_operand" "d") (const_int 0))
-        (clz:HI (not:HI (match_dup 1)))
-        (clz:HI (match_dup 1))))]
+       (clrsb:HI (match_operand:HI 1 "register_operand" "d")))]
   ""
   "%h0 = signbits %h1%!"
   [(set_attr "type" "dsp32")])
index 41c326b7b3ac9a2dc883454028893cdf24279155..2d9c689f98f16f263e71b64dd752185fb2378eea 100644 (file)
@@ -7828,6 +7828,12 @@ Returns the number of trailing 0-bits in @var{x}, starting at the least
 significant bit position.  If @var{x} is 0, the result is undefined.
 @end deftypefn
 
+@deftypefn {Built-in Function} int __builtin_clrsb (int x)
+Returns the number of leading redundant sign bits in @var{x}, i.e. the
+number of bits following the most significant bit which are identical
+to it.  There are no special cases for 0 or other values. 
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_popcount (unsigned int x)
 Returns the number of 1-bits in @var{x}.
 @end deftypefn
@@ -7852,6 +7858,11 @@ Similar to @code{__builtin_ctz}, except the argument type is
 @code{unsigned long}.
 @end deftypefn
 
+@deftypefn {Built-in Function} int __builtin_clrsbl (long)
+Similar to @code{__builtin_clrsb}, except the argument type is
+@code{long}.
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_popcountl (unsigned long)
 Similar to @code{__builtin_popcount}, except the argument type is
 @code{unsigned long}.
@@ -7877,6 +7888,11 @@ Similar to @code{__builtin_ctz}, except the argument type is
 @code{unsigned long long}.
 @end deftypefn
 
+@deftypefn {Built-in Function} int __builtin_clrsbll (long long)
+Similar to @code{__builtin_clrsb}, except the argument type is
+@code{long long}.
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_popcountll (unsigned long long)
 Similar to @code{__builtin_popcount}, except the argument type is
 @code{unsigned long long}.
index 6995a293c6ccc5a10b99ddbe8745941afb2ac9ce..ea30e38032e771e9cbfd050536535ec7752fb9fd 100644 (file)
@@ -2400,6 +2400,14 @@ zero if @var{x} is zero.)  The mode of @var{x} need not be @var{m};
 depending on the target machine, various mode combinations may be
 valid.
 
+@findex clrsb
+@item (clrsb:@var{m} @var{x})
+Represents the number of redundant leading sign bits in @var{x},
+represented as an integer of mode @var{m}, starting at the most
+significant bit position.  This is one less than the number of leading
+sign bits (either 0 or 1), with no special cases.  The mode of @var{x}
+will usually be an integer mode and may differ from @var{m}.
+
 @findex clz
 @item (clz:@var{m} @var{x})
 Represents the number of leading 0-bits in @var{x}, represented as an
index 71ba002cb85370f74099a53943b98e3a1975f848..480e4e06e77e23d903d849b3cf4fc4f9d302c712 100644 (file)
@@ -15377,6 +15377,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case STRICT_LOW_PART:
     case CONST_VECTOR:
     case CONST_FIXED:
+    case CLRSB:
       /* If delegitimize_address couldn't do anything with the UNSPEC, we
         can't express it in the debug info.  This can happen e.g. with some
         TLS UNSPECs.  */
index 35e994b024c5181e18d9e00cdacc41f999c09b11..570540dacb0542bd0107e11a5ab58602947a262d 100644 (file)
@@ -199,6 +199,7 @@ static const char * const optabs[] =
   "set_optab_handler (ffs_optab, $A, CODE_FOR_$(ffs$a2$))",
   "set_optab_handler (clz_optab, $A, CODE_FOR_$(clz$a2$))",
   "set_optab_handler (ctz_optab, $A, CODE_FOR_$(ctz$a2$))",
+  "set_optab_handler (clrsb_optab, $A, CODE_FOR_$(clrsb$a2$))",
   "set_optab_handler (popcount_optab, $A, CODE_FOR_$(popcount$a2$))",
   "set_optab_handler (parity_optab, $A, CODE_FOR_$(parity$a2$))",
   "set_optab_handler (mov_optab, $A, CODE_FOR_$(mov$a$))",
index fbf5dcc2155b9844c4c882b779b465f204566c24..57c40c5800f904d511f3f812aaebc14da774fb47 100644 (file)
@@ -762,7 +762,50 @@ __ctzDI2 (UDWtype x)
   return ret + add;
 }
 #endif
+\f
+#ifdef L_clrsbsi2
+#undef int
+int
+__clrsbSI2 (Wtype x)
+{
+  Wtype ret;
 
+  if (x < 0)
+    x = ~x;
+  if (x == 0)
+    return W_TYPE_SIZE - 1;
+  count_leading_zeros (ret, x);
+  return ret - 1;
+}
+#endif
+\f
+#ifdef L_clrsbdi2
+#undef int
+int
+__clrsbDI2 (DWtype x)
+{
+  const DWunion uu = {.ll = x};
+  UWtype word;
+  Wtype ret, add;
+
+  if (uu.s.high == 0)
+    word = uu.s.low, add = W_TYPE_SIZE;
+  else if (uu.s.high == -1)
+    word = ~uu.s.low, add = W_TYPE_SIZE;
+  else if (uu.s.high >= 0)
+    word = uu.s.high, add = 0;
+  else
+    word = ~uu.s.high, add = 0;
+
+  if (word == 0)
+    ret = W_TYPE_SIZE;
+  else
+    count_leading_zeros (ret, word);
+
+  return ret + add - 1;
+}
+#endif
+\f
 #ifdef L_popcount_tab
 const UQItype __popcount_tab[256] =
 {
index bb4e6f3147172e1fe35a23629efa99674c5e8845..0c7d0e15623be73e9e82ac29a74954e49a5ea775 100644 (file)
@@ -315,11 +315,13 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
 #define __ffsSI2       __NW(ffs,2)
 #define __clzSI2       __NW(clz,2)
 #define __ctzSI2       __NW(ctz,2)
+#define __clrsbSI2     __NW(clrsb,2)
 #define __popcountSI2  __NW(popcount,2)
 #define __paritySI2    __NW(parity,2)
 #define __ffsDI2       __NDW(ffs,2)
 #define __clzDI2       __NDW(clz,2)
 #define __ctzDI2       __NDW(ctz,2)
+#define __clrsbDI2     __NDW(clrsb,2)
 #define __popcountDI2  __NDW(popcount,2)
 #define __parityDI2    __NDW(parity,2)
 
@@ -508,9 +510,11 @@ extern const UQItype __clz_tab[256];
 extern int __clzDI2 (UDWtype);
 extern int __clzSI2 (UWtype);
 extern int __ctzSI2 (UWtype);
+extern int __ctzDI2 (UDWtype);
+extern int __clrsbSI2 (Wtype);
+extern int __clrsbDI2 (DWtype);
 extern int __ffsSI2 (UWtype);
 extern int __ffsDI2 (DWtype);
-extern int __ctzDI2 (UDWtype);
 extern int __popcountSI2 (UWtype);
 extern int __popcountDI2 (UDWtype);
 extern int __paritySI2 (UWtype);
index 224fb11b59b1210170b86a6fc5cb34c0df59c712..7448450d23643c8b8998de950f908f450877896c 100644 (file)
@@ -2327,9 +2327,12 @@ expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
 /* Try calculating
        (clz:narrow x)
    as
-       (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).  */
+       (clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).
+
+   A similar operation can be used for clrsb.  UNOPTAB says which operation
+   we are trying to expand.  */
 static rtx
-widen_clz (enum machine_mode mode, rtx op0, rtx target)
+widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
   if (CLASS_HAS_WIDER_MODES_P (mclass))
@@ -2339,7 +2342,7 @@ widen_clz (enum machine_mode mode, rtx op0, rtx target)
           wider_mode != VOIDmode;
           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
        {
-         if (optab_handler (clz_optab, wider_mode) != CODE_FOR_nothing)
+         if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
            {
              rtx xop0, temp, last;
 
@@ -2348,7 +2351,7 @@ widen_clz (enum machine_mode mode, rtx op0, rtx target)
              if (target == 0)
                target = gen_reg_rtx (mode);
              xop0 = widen_operand (op0, wider_mode, mode, true, false);
-             temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
+             temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, true);
              if (temp != 0)
                temp = expand_binop (wider_mode, sub_optab, temp,
                                     GEN_INT (GET_MODE_BITSIZE (wider_mode)
@@ -2844,7 +2847,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
   /* Widening (or narrowing) clz needs special treatment.  */
   if (unoptab == clz_optab)
     {
-      temp = widen_clz (mode, op0, target);
+      temp = widen_leading (mode, op0, target, unoptab);
       if (temp)
        return temp;
 
@@ -2856,7 +2859,15 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
            return temp;
        }
 
-       goto try_libcall;
+      goto try_libcall;
+    }
+
+  if (unoptab == clrsb_optab)
+    {
+      temp = widen_leading (mode, op0, target, unoptab);
+      if (temp)
+       return temp;
+      goto try_libcall;
     }
 
   /* Widening (or narrowing) bswap needs special treatment.  */
@@ -3011,7 +3022,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       /* All of these functions return small values.  Thus we choose to
         have them return something that isn't a double-word.  */
       if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
-         || unoptab == popcount_optab || unoptab == parity_optab)
+         || unoptab == clrsb_optab || unoptab == popcount_optab
+         || unoptab == parity_optab)
        outmode
          = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
                                          optab_libfunc (unoptab, mode)));
@@ -5958,6 +5970,7 @@ init_optabs (void)
   init_optab (ffs_optab, FFS);
   init_optab (clz_optab, CLZ);
   init_optab (ctz_optab, CTZ);
+  init_optab (clrsb_optab, CLRSB);
   init_optab (popcount_optab, POPCOUNT);
   init_optab (parity_optab, PARITY);
   init_optab (sqrt_optab, SQRT);
@@ -6188,6 +6201,9 @@ init_optabs (void)
   ctz_optab->libcall_basename = "ctz";
   ctz_optab->libcall_suffix = '2';
   ctz_optab->libcall_gen = gen_int_libfunc;
+  clrsb_optab->libcall_basename = "clrsb";
+  clrsb_optab->libcall_suffix = '2';
+  clrsb_optab->libcall_gen = gen_int_libfunc;
   popcount_optab->libcall_basename = "popcount";
   popcount_optab->libcall_suffix = '2';
   popcount_optab->libcall_gen = gen_int_libfunc;
index 62bc14e484034f33983753c0ce1b7490e554f104..477fce356c7e8604ce15838f5a098b424cc96be9 100644 (file)
@@ -220,6 +220,7 @@ enum optab_index
   OTI_ffs,
   OTI_clz,
   OTI_ctz,
+  OTI_clrsb,
   OTI_popcount,
   OTI_parity,
   /* Square root */
@@ -456,6 +457,7 @@ enum optab_index
 #define ffs_optab (&optab_table[OTI_ffs])
 #define clz_optab (&optab_table[OTI_clz])
 #define ctz_optab (&optab_table[OTI_ctz])
+#define clrsb_optab (&optab_table[OTI_clrsb])
 #define popcount_optab (&optab_table[OTI_popcount])
 #define parity_optab (&optab_table[OTI_parity])
 #define sqrt_optab (&optab_table[OTI_sqrt])
index cb5555ac59177ade6f5a69e48e78672685737ed9..8f04b2fe3cd2ff360c658f557016509ce781709e 100644 (file)
@@ -613,6 +613,10 @@ DEF_RTL_EXPR(BSWAP, "bswap", "e", RTX_UNARY)
    or 0 if arg is 0.  */
 DEF_RTL_EXPR(FFS, "ffs", "e", RTX_UNARY)
 
+/* Count number of leading redundant sign bits (number of leading
+   sign bits minus one).  */
+DEF_RTL_EXPR(CLRSB, "clrsb", "e", RTX_UNARY)
+
 /* Count leading zeros.  */
 DEF_RTL_EXPR(CLZ, "clz", "e", RTX_UNARY)
 
index 18f264b0ca96128171c8b8bbb54deee1d3100c64..3c4df973ff5053cabf578b82770da88038a10541 100644 (file)
@@ -1211,6 +1211,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
                                rtx op, enum machine_mode op_mode)
 {
   unsigned int width = GET_MODE_BITSIZE (mode);
+  unsigned int op_width = GET_MODE_BITSIZE (op_mode);
 
   if (code == VEC_DUPLICATE)
     {
@@ -1321,7 +1322,8 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
     }
 
   if (CONST_INT_P (op)
-      && width <= HOST_BITS_PER_WIDE_INT && width > 0)
+      && width <= HOST_BITS_PER_WIDE_INT
+      && op_width <= HOST_BITS_PER_WIDE_INT && op_width > 0)
     {
       HOST_WIDE_INT arg0 = INTVAL (op);
       HOST_WIDE_INT val;
@@ -1341,40 +1343,50 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case FFS:
-         arg0 &= GET_MODE_MASK (mode);
+         arg0 &= GET_MODE_MASK (op_mode);
          val = ffs_hwi (arg0);
          break;
 
        case CLZ:
-         arg0 &= GET_MODE_MASK (mode);
-         if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val))
+         arg0 &= GET_MODE_MASK (op_mode);
+         if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (op_mode, val))
            ;
          else
-           val = GET_MODE_BITSIZE (mode) - floor_log2 (arg0) - 1;
+           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (arg0) - 1;
+         break;
+
+       case CLRSB:
+         arg0 &= GET_MODE_MASK (op_mode);
+         if (arg0 == 0)
+           val = GET_MODE_BITSIZE (op_mode) - 1;
+         else if (arg0 >= 0)
+           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (arg0) - 2;
+         else if (arg0 < 0)
+           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (~arg0) - 2;
          break;
 
        case CTZ:
-         arg0 &= GET_MODE_MASK (mode);
+         arg0 &= GET_MODE_MASK (op_mode);
          if (arg0 == 0)
            {
              /* Even if the value at zero is undefined, we have to come
                 up with some replacement.  Seems good enough.  */
-             if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val))
-               val = GET_MODE_BITSIZE (mode);
+             if (! CTZ_DEFINED_VALUE_AT_ZERO (op_mode, val))
+               val = GET_MODE_BITSIZE (op_mode);
            }
          else
            val = ctz_hwi (arg0);
          break;
 
        case POPCOUNT:
-         arg0 &= GET_MODE_MASK (mode);
+         arg0 &= GET_MODE_MASK (op_mode);
          val = 0;
          while (arg0)
            val++, arg0 &= arg0 - 1;
          break;
 
        case PARITY:
-         arg0 &= GET_MODE_MASK (mode);
+         arg0 &= GET_MODE_MASK (op_mode);
          val = 0;
          while (arg0)
            val++, arg0 &= arg0 - 1;
index 1415426df9f8350b8b7e5f067320913015526948..2f03f2ad508515a43f6ca1ba0f3da161c19ef914 100644 (file)
@@ -1,3 +1,13 @@
+2011-06-21  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * gcc.c-torture/excute/builtin-bitops-1.c (MAKE_FUNS): Make
+       my_clrsb test functions.
+       (main): Test clrsb.
+       * gcc.dg/builtin-protos-1.c (test_s, test_u, test_sl, test_ul,
+       test_sll, test_ull): Add clrsb tests.
+       * gcc.dg/torture/builtin-attr-1.c: Add tests for clrsb, clrsbl,
+       clrsbll.
+
 2011-06-21  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/49112
@@ -21,7 +31,7 @@
        * gcc.dg/vect/vect-peel-4.c: Likewise.
 
 2011-06-22  Christian Bruel  <christian.bruel@st.com>
-       
+
        PR middle-end/49139
        * gcc.dg/always_inline.c: Removed -Winline. Update checks
        * gcc.dg/always_inline2.c: Likewise.
@@ -41,7 +51,7 @@
        * gcc.dg/uninit-pred-5_a.c: Likewise.
        * gcc.dg/uninit-pred-5_b.c: Likewise.
        * gcc.dg/fail_always_inline.c: New.
-       
+
 2011-06-21  Jakub Jelinek  <jakub@redhat.com>
 
        * Make-lang.in (check_gfortran_parallelize): Parallelize dg.exp
index 8c3122cc6332beea5a4648844b31d93fa7f22b00..7907a753341cc0e0502f359a30a27e1472ebf326 100644 (file)
@@ -62,6 +62,16 @@ int my_clz##suffix(type x) {                                         \
     return i;                                                          \
 }                                                                      \
                                                                        \
+int my_clrsb##suffix(type x) {                                         \
+    int i;                                                             \
+    int leading = (x >> CHAR_BIT * sizeof (type) - 1) & 1;             \
+    for (i = 1; i < CHAR_BIT * sizeof (type); i++)                     \
+       if (((x >> ((CHAR_BIT * sizeof (type)) - i - 1)) & 1)           \
+           != leading)                                                 \
+           break;                                                      \
+    return i - 1;                                                      \
+}                                                                      \
+                                                                       \
 int my_popcount##suffix(type x) {                                      \
     int i;                                                             \
     int count = 0;                                                     \
@@ -176,6 +186,8 @@ main (void)
       if (ints[i] != 0
          && __builtin_ctz (ints[i]) != my_ctz (ints[i]))
        abort ();
+      if (__builtin_clrsb (ints[i]) != my_clrsb (ints[i]))
+       abort ();
       if (__builtin_popcount (ints[i]) != my_popcount (ints[i]))
        abort ();
       if (__builtin_parity (ints[i]) != my_parity (ints[i]))
@@ -192,6 +204,8 @@ main (void)
       if (longs[i] != 0
          && __builtin_ctzl (longs[i]) != my_ctzl (longs[i]))
        abort ();
+      if (__builtin_clrsbl (longs[i]) != my_clrsbl (longs[i]))
+       abort ();
       if (__builtin_popcountl (longs[i]) != my_popcountl (longs[i]))
        abort ();
       if (__builtin_parityl (longs[i]) != my_parityl (longs[i]))
@@ -208,6 +222,8 @@ main (void)
       if (longlongs[i] != 0
          && __builtin_ctzll (longlongs[i]) != my_ctzll (longlongs[i]))
        abort ();
+      if (__builtin_clrsbll (longlongs[i]) != my_clrsbll (longlongs[i]))
+       abort ();
       if (__builtin_popcountll (longlongs[i]) != my_popcountll (longlongs[i]))
        abort ();
       if (__builtin_parityll (longlongs[i]) != my_parityll (longlongs[i]))
@@ -223,6 +239,8 @@ main (void)
     abort ();                                                          \
   if (x != 0 && __builtin_ctz##suffix (x) != my_ctz##suffix (x))       \
     abort ();                                                          \
+  if (__builtin_clrsb##suffix (x) != my_clrsb##suffix (x))             \
+    abort ();                                                          \
   if (__builtin_popcount##suffix (x) != my_popcount##suffix (x))       \
     abort ();                                                          \
   if (__builtin_parity##suffix (x) != my_parity##suffix (x))           \
index 85f96cff0c1c6af01e00904b30242a33903e1c69..b9e939699fb9061b2f0cda07a411a9d0fe38183a 100644 (file)
@@ -7,6 +7,7 @@ test_s (signed int x)
   return __builtin_abs (x)     /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_clz (x)                /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_ctz (x)                /* { dg-warning "as unsigned due to prototype" } */
+    + __builtin_clrsb (x)      /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_ffs (x)                /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_parity (x)     /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_popcount (x);  /* { dg-warning "as unsigned due to prototype" } */
@@ -18,6 +19,7 @@ test_u (unsigned int x)
   return __builtin_abs (x)     /* { dg-warning "as signed due to prototype" } */
     + __builtin_clz (x)                /* { dg-bogus "as signed due to prototype" } */
     + __builtin_ctz (x)                /* { dg-bogus "as signed due to prototype" } */
+    + __builtin_clrsb (x)      /* { dg-warning "as signed due to prototype" } */
     + __builtin_ffs (x)                /* { dg-warning "as signed due to prototype" } */
     + __builtin_parity (x)     /* { dg-bogus "as signed due to prototype" } */
     + __builtin_popcount (x);  /* { dg-bogus "as signed due to prototype" } */
@@ -29,6 +31,7 @@ test_sl (signed long x)
   return __builtin_labs (x)    /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_clzl (x)       /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_ctzl (x)       /* { dg-warning "as unsigned due to prototype" } */
+    + __builtin_clrsbl (x)     /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_ffsl (x)       /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_parityl (x)    /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_popcountl (x); /* { dg-warning "as unsigned due to prototype" } */
@@ -40,6 +43,7 @@ test_ul (unsigned long x)
   return __builtin_labs (x)    /* { dg-warning "as signed due to prototype" } */
     + __builtin_clzl (x)       /* { dg-bogus "as signed due to prototype" } */
     + __builtin_ctzl (x)       /* { dg-bogus "as signed due to prototype" } */
+    + __builtin_clrsbl (x)     /* { dg-warning "as signed due to prototype" } */
     + __builtin_ffsl (x)       /* { dg-warning "as signed due to prototype" } */
     + __builtin_parityl (x)    /* { dg-bogus "as signed due to prototype" } */
     + __builtin_popcountl (x); /* { dg-bogus "as signed due to prototype" } */
@@ -51,6 +55,7 @@ test_sll (signed long long x)
   return __builtin_llabs (x)   /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_clzll (x)      /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_ctzll (x)      /* { dg-warning "as unsigned due to prototype" } */
+    + __builtin_clrsbll (x)    /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_ffsll (x)      /* { dg-bogus "as unsigned due to prototype" } */
     + __builtin_parityll (x)   /* { dg-warning "as unsigned due to prototype" } */
     + __builtin_popcountll (x);        /* { dg-warning "as unsigned due to prototype" } */
@@ -62,6 +67,7 @@ test_ull (unsigned long long x)
   return __builtin_llabs (x)   /* { dg-warning "as signed due to prototype" } */
     + __builtin_clzll (x)      /* { dg-bogus "as signed due to prototype" } */
     + __builtin_ctzll (x)      /* { dg-bogus "as signed due to prototype" } */
+    + __builtin_clrsbll (x)    /* { dg-warning "as signed due to prototype" } */
     + __builtin_ffsll (x)      /* { dg-warning "as signed due to prototype" } */
     + __builtin_parityll (x)   /* { dg-bogus "as signed due to prototype" } */
     + __builtin_popcountll (x);        /* { dg-bogus "as signed due to prototype" } */
index bd383a2b34b13493338ad53de6ff28a75efdfdfa..c138b92342aba3f64738e82b6007e885c873c4b2 100644 (file)
@@ -416,6 +416,9 @@ BUILTIN_TEST1 (clzll, long long)
 BUILTIN_TEST1 (ctz, int)
 BUILTIN_TEST1 (ctzl, long)
 BUILTIN_TEST1 (ctzll, long long)
+BUILTIN_TEST1 (clrsb, int)
+BUILTIN_TEST1 (clrsbl, long)
+BUILTIN_TEST1 (clrsbll, long long)
 TEST1         (ffs, int, int)
 TEST1         (ffsl, long, int)
 TEST1         (ffsll, long long, int)
index 0f2384ea5dec87ec72e7fb2ccac6ba9ecf102284..08d8ef9a6a700cf9a7a8808e8a13750823bcef3c 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-21  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * Makefile.in (lib2funcs): Add _clrsbsi2 and _clrsbdi2.
+       * libgcc-std.ver.in (GCC_4.7.0): New section.
+
 2011-06-16  Georg-Johann Lay  <avr@gjlay.de>
        
        PR target/49313
index 383a6614b1c0485c55cb3ddc1dde468389b29578..d0a1d1582ee638965340494fc47a8b76fd53aa7c 100644 (file)
@@ -323,7 +323,7 @@ lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2        \
            _ctzsi2 _ctzdi2 _popcount_tab _popcountsi2 _popcountdi2        \
            _paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2      \
            _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3 _divxc3        \
-           _divtc3 _bswapsi2 _bswapdi2
+           _divtc3 _bswapsi2 _bswapdi2 _clrsbsi2 _clrsbdi2
 
 # The floating-point conversion routines that involve a single-word integer.
 # XX stands for the integer mode.
index e468ec589bad62d9bffca29701b41f2729f5777f..5552a6f001b0427d65dc59e2ca4e5cbce95e3434 100644 (file)
@@ -1920,3 +1920,10 @@ GCC_4.6.0 {
   __morestack_initial_sp
   __splitstack_find
 }
+
+%inherit GCC_4.7.0 GCC_4.6.0
+GCC_4.7.0 {
+  __PFX__clrsbsi2
+  __PFX__clrsbdi2
+  __PFX__clrsbti2
+}