[Bug gcov-profile/55734] [4.8 Regression] gcov-io.c uses builtins not available in non-GCC compilers

tejohnson at google dot com gcc-bugzilla@gcc.gnu.org
Wed Dec 19 06:50:00 GMT 2012


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55734

--- Comment #13 from Teresa Johnson <tejohnson at google dot com> 2012-12-19 06:49:50 UTC ---
On Tue, Dec 18, 2012 at 2:48 PM, Teresa Johnson <tejohnson@google.com> wrote:
>
>
>
>
> On Tue, Dec 18, 2012 at 2:41 PM, aldyh at gcc dot gnu.org <gcc-bugzilla@gcc.gnu.org> wrote:
>>
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55734
>>
>> --- Comment #11 from Aldy Hernandez <aldyh at gcc dot gnu.org> 2012-12-18 22:41:13 UTC ---
>> Teresa, I think this is what you were referring to, and the reason for my
>> original patch:
>>
>> houston:/build/trunkboot$ ./install/bin/gcc a.c -fprofile-generate
>> /home/build/trunkboot/install/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/libgcov.a(_gcov.o):
>> In function `gcov_histo_index':
>> libgcov.c:(.text+0x213): undefined reference to `clz_hwi'
>> /home/build/trunkboot/install/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.0/libgcov.a(_gcov.o):
>> In function `__gcov_read_summary':
>> libgcov.c:(.text+0x7f3): undefined reference to `popcount_hwi'
>> collect2: error: ld returned 1 exit status
>
>
> Yep. I've got a patch in the works that is a slightly simplified version of what you did. I'll send that a little later today once I get it tested.


Here is the patch. I am doing some final regression testing on it, but
earlier testing and my own testing looked good. It is similar to what
Aldy did, pulling some of the hwi routines into a new hwint-helper.c
file. However, in this case, it is included normally into hwint.c, and
the routines are only pulled in as static copies to gcov-io.c when we
are building libgcov.a (in other cases gcov-io.c is being built when
system.h is included, which includes hwint.h already). In the case of
libgcov.a, I also had to add support for the fact that the HOST_*
variables that were being used in the hwint routines are not defined.

Richard, let me know if this looks like a reasonable approach. The
only other solution I had was to simply inline copies of popcount_hwi
and clz_hwi into gcov-io.c when we are building libgcov.a.

Thanks,
Teresa

2012-12-18  Teresa Johnson  <tejohnson@google.com>
            Aldy Hernandez  <aldyh@redhat.com>

* hwint-helper.c (floor_log2): Moved from hwint.c
(ceil_log2): Ditto.
(exact_log2): Ditto.
(ctz_hwi): Ditto.
(clz_hwi): Ditto.
(ffs_hwi): Ditto.
(popcount_hwi): Ditto.
* gcov-io.c (gcov_read_summary): Invoke popcount_hwi.
(gcov_histo_index): Invoke clz_hwi.
* Makefile.in (hwint.o): Depend on hwint-helper.c
* hwint.c (floor_log2): Moved to hwint-helper.c
(ceil_log2): Ditto.
(exact_log2): Ditto.
(ctz_hwi): Ditto.
(clz_hwi): Ditto.
(ffs_hwi): Ditto.
(popcount_hwi): Ditto.

Index: hwint-helper.c
===================================================================
--- hwint-helper.c (revision 0)
+++ hwint-helper.c (revision 0)
@@ -0,0 +1,130 @@
+/* Supporting bit functions for older versions of GCC, and non-GCC
+   bootstrap compilers.
+
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2012 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#if GCC_VERSION < 3004
+
+/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
+   and exact_log2 are defined as inline functions in hwint.h
+   if GCC_VERSION >= 3004.
+   The definitions here are used for older versions of GCC and
+   non-GCC bootstrap compilers.  */
+
+/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
+   If X is 0, return -1.  */
+
+HWINT_LINKAGE int
+floor_log2 (HWINT_TYPE x)
+{
+  int t = 0;
+
+  if (x == 0)
+    return -1;
+
+  if (HWINT_TYPE_SIZE > 64)
+    if (x >= (HWINT_TYPE) 1 << (t + 64))
+      t += 64;
+  if (HWINT_TYPE_SIZE > 32)
+    if (x >= ((HWINT_TYPE) 1) << (t + 32))
+      t += 32;
+  if (x >= ((HWINT_TYPE) 1) << (t + 16))
+    t += 16;
+  if (x >= ((HWINT_TYPE) 1) << (t + 8))
+    t += 8;
+  if (x >= ((HWINT_TYPE) 1) << (t + 4))
+    t += 4;
+  if (x >= ((HWINT_TYPE) 1) << (t + 2))
+    t += 2;
+  if (x >= ((HWINT_TYPE) 1) << (t + 1))
+    t += 1;
+
+  return t;
+}
+
+/* Given X, an unsigned number, return the largest Y such that 2**Y >= X.  */
+
+HWINT_LINKAGE int
+ceil_log2 (HWINT_TYPE x)
+{
+  return floor_log2 (x - 1) + 1;
+}
+
+/* Return the logarithm of X, base 2, considering X unsigned,
+   if X is a power of 2.  Otherwise, returns -1.  */
+
+HWINT_LINKAGE int
+exact_log2 (HWINT_TYPE x)
+{
+  if (x != (x & -x))
+    return -1;
+  return floor_log2 (x);
+}
+
+/* Given X, an unsigned number, return the number of least significant bits
+   that are zero.  When X == 0, the result is the word size.  */
+
+HWINT_LINKAGE int
+ctz_hwi (HWINT_TYPE x)
+{
+  return x ? floor_log2 (x & -x) : HWINT_TYPE_SIZE;
+}
+
+/* Similarly for most significant bits.  */
+
+HWINT_LINKAGE int
+clz_hwi (HWINT_TYPE x)
+{
+  return HWINT_TYPE_SIZE - 1 - floor_log2 (x);
+}
+
+/* Similar to ctz_hwi, except that the least significant bit is numbered
+   starting from 1, and X == 0 yields 0.  */
+
+HWINT_LINKAGE int
+ffs_hwi (HWINT_TYPE x)
+{
+  return 1 + floor_log2 (x & -x);
+}
+
+/* Return the number of set bits in X.  */
+
+HWINT_LINKAGE int
+popcount_hwi (HWINT_TYPE x)
+{
+  int i, ret = 0;
+  size_t bits = sizeof (x) * CHAR_BIT;
+
+  for (i = 0; i < (int)bits; i += 1)
+    {
+      ret += x & 1;
+      x >>= 1;
+    }
+
+  return ret;
+}
+
+#endif /* GCC_VERSION < 3004 */
Index: gcov-io.c
===================================================================
--- gcov-io.c (revision 194585)
+++ gcov-io.c (working copy)
@@ -517,6 +517,18 @@ gcov_read_string (void)
 }
 #endif

+#if IN_LIBGCOV
+#if GCC_VERSION < 3004
+#define HWINT_LINKAGE inline static
+#define HWINT_TYPE gcov_type_unsigned
+#define HWINT_TYPE_SIZE LONG_LONG_TYPE_SIZE
+#include "hwint-helper.c"
+#else
+#define popcount_hwi __builtin_popcountll
+#define clz_hwi __builtin_clzll
+#endif
+#endif
+
 GCOV_LINKAGE void
 gcov_read_summary (struct gcov_summary *summary)
 {
@@ -538,7 +550,7 @@ gcov_read_summary (struct gcov_summary *summary)
       for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
         {
           histo_bitvector[bv_ix] = gcov_read_unsigned ();
-          h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]);
+          h_cnt += popcount_hwi (histo_bitvector[bv_ix]);
         }
       bv_ix = 0;
       h_ix = 0;
@@ -642,7 +654,7 @@ gcov_histo_index (gcov_type value)

   /* Find the place of the most-significant bit set.  */
   if (v > 0)
-    r = 63 - __builtin_clzll (v);
+    r = 63 - clz_hwi (v);

   /* If at most the 2 least significant bits are set (value is
      0 - 3) then that value is our index into the lowest set of
Index: Makefile.in
===================================================================
--- Makefile.in (revision 194585)
+++ Makefile.in (working copy)
@@ -2701,7 +2701,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) corety
    $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
    tsan.h

-hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
+hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H) hwint-helper.c

 passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(FUNCTION_H) $(FLAGS_H) $(INPUT_H) $(INSN_ATTR_H) output.h \
Index: hwint.c
===================================================================
--- hwint.c (revision 194585)
+++ hwint.c (working copy)
@@ -23,109 +23,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "diagnostic-core.h"

-#if GCC_VERSION < 3004
+#define HWINT_LINKAGE
+#define HWINT_TYPE unsigned HOST_WIDE_INT
+#define HWINT_TYPE_SIZE HOST_BITS_PER_WIDE_INT
+#include "hwint-helper.c"

-/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
-   and exact_log2 are defined as inline functions in hwint.h
-   if GCC_VERSION >= 3004.
-   The definitions here are used for older versions of GCC and
-   non-GCC bootstrap compilers.  */
-
-/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
-   If X is 0, return -1.  */
-
-int
-floor_log2 (unsigned HOST_WIDE_INT x)
-{
-  int t = 0;
-
-  if (x == 0)
-    return -1;
-
-  if (HOST_BITS_PER_WIDE_INT > 64)
-    if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
-      t += 64;
-  if (HOST_BITS_PER_WIDE_INT > 32)
-    if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
-      t += 32;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
-    t += 16;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
-    t += 8;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
-    t += 4;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
-    t += 2;
-  if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
-    t += 1;
-
-  return t;
-}
-
-/* Given X, an unsigned number, return the largest Y such that 2**Y >= X.  */
-
-int
-ceil_log2 (unsigned HOST_WIDE_INT x)
-{
-  return floor_log2 (x - 1) + 1;
-}
-
-/* Return the logarithm of X, base 2, considering X unsigned,
-   if X is a power of 2.  Otherwise, returns -1.  */
-
-int
-exact_log2 (unsigned HOST_WIDE_INT x)
-{
-  if (x != (x & -x))
-    return -1;
-  return floor_log2 (x);
-}
-
-/* Given X, an unsigned number, return the number of least significant bits
-   that are zero.  When X == 0, the result is the word size.  */
-
-int
-ctz_hwi (unsigned HOST_WIDE_INT x)
-{
-  return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
-}
-
-/* Similarly for most significant bits.  */
-
-int
-clz_hwi (unsigned HOST_WIDE_INT x)
-{
-  return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
-}
-
-/* Similar to ctz_hwi, except that the least significant bit is numbered
-   starting from 1, and X == 0 yields 0.  */
-
-int
-ffs_hwi (unsigned HOST_WIDE_INT x)
-{
-  return 1 + floor_log2 (x & -x);
-}
-
-/* Return the number of set bits in X.  */
-
-int
-popcount_hwi (unsigned HOST_WIDE_INT x)
-{
-  int i, ret = 0;
-  size_t bits = sizeof (x) * CHAR_BIT;
-
-  for (i = 0; i < bits; i += 1)
-    {
-      ret += x & 1;
-      x >>= 1;
-    }
-
-  return ret;
-}
-
-#endif /* GCC_VERSION < 3004 */
-
 /* Compute the absolute value of X.  */

 HOST_WIDE_INT

>
> Teresa
>>
>>
>> --
>> Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email
>> ------- You are receiving this mail because: -------
>> You are on the CC list for the bug.
>
>
>
>
> --
> Teresa Johnson | Software Engineer |  tejohnson@google.com |  408-460-2413
>



--
Teresa Johnson | Software Engineer |  tejohnson@google.com |  408-460-2413



More information about the Gcc-bugs mailing list