[Bug gcov-profile/101618] New: [GCOV] Wrong coverage caused by call site in a "for" statement

njuwy at smail dot nju.edu.cn gcc-bugzilla@gcc.gnu.org
Sun Jul 25 07:55:50 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101618

            Bug ID: 101618
           Summary: [GCOV] Wrong coverage caused by call site in a "for"
                    statement
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: gcov-profile
          Assignee: unassigned at gcc dot gnu.org
          Reporter: njuwy at smail dot nju.edu.cn
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/10.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure -enable-checking=release -enable-languages=c,c++
-disable-multilib
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (GCC) 

$ cat test.c
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct obstack {};
struct bitmap_head_def;
typedef struct bitmap_head_def *bitmap;
typedef const struct bitmap_head_def *const_bitmap;
typedef unsigned long BITMAP_WORD;
typedef struct bitmap_obstack {
  struct bitmap_element_def *elements;
  struct bitmap_head_def *heads;
  struct obstack obstack;
} bitmap_obstack;
typedef struct bitmap_element_def {
  struct bitmap_element_def *next;
  struct bitmap_element_def *prev;
  unsigned int indx;
  BITMAP_WORD bits[((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u))];
} bitmap_element;

struct bitmap_descriptor;

typedef struct bitmap_head_def {
  bitmap_element *first;
  bitmap_element *current;
  unsigned int indx;
  bitmap_obstack *obstack;
} bitmap_head;

bitmap_element bitmap_zero_bits;

typedef struct {
  bitmap_element *elt1;
  bitmap_element *elt2;
  unsigned word_no;
  BITMAP_WORD bits;
} bitmap_iterator;

static void __attribute__((noinline))
bmp_iter_set_init(bitmap_iterator *bi, const_bitmap map, unsigned start_bit,
                  unsigned *bit_no) {
  bi->elt1 = map->first;
  bi->elt2 = ((void *)0);

  while (1) {
    if (!bi->elt1) {
      bi->elt1 = &bitmap_zero_bits;
      break;
    }

    if (bi->elt1->indx >=
        start_bit / (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)) * (8 * 8 * 1u)))
      break;
    bi->elt1 = bi->elt1->next;
  }

  if (bi->elt1->indx !=
      start_bit / (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)) * (8 * 8 * 1u)))
    start_bit = bi->elt1->indx *
                (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)) * (8 * 8 * 1u));

  bi->word_no =
      start_bit / (8 * 8 * 1u) % ((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u));
  bi->bits = bi->elt1->bits[bi->word_no];
  bi->bits >>= start_bit % (8 * 8 * 1u);

  start_bit += !bi->bits;

  *bit_no = start_bit;
}

static void __attribute__((noinline))
bmp_iter_next(bitmap_iterator *bi, unsigned *bit_no) {
  bi->bits >>= 1;
  *bit_no += 1;
}

static unsigned char __attribute__((noinline))
bmp_iter_set_tail(bitmap_iterator *bi, unsigned *bit_no) {
  while (!(bi->bits & 1)) {
    bi->bits >>= 1;
    *bit_no += 1;
  }
  return 1;
}

static __inline__ unsigned char bmp_iter_set(bitmap_iterator *bi,
                                             unsigned *bit_no) {
  unsigned bno = *bit_no;
  BITMAP_WORD bits = bi->bits;
  bitmap_element *elt1;

  if (bits) {
    while (!(bits & 1)) {
      bits >>= 1;
      bno += 1;
    }
    *bit_no = bno;
    return 1;
  }

  *bit_no = ((bno + 64 - 1) / 64 * 64);
  bi->word_no++;

  elt1 = bi->elt1;
  while (1) {
    while (bi->word_no != 2) {
      bi->bits = elt1->bits[bi->word_no];
      if (bi->bits) {
        bi->elt1 = elt1;
        return bmp_iter_set_tail(bi, bit_no);
      }
      *bit_no += 64;
      bi->word_no++;
    }
    elt1 = elt1->next;
    if (!elt1) {
      bi->elt1 = elt1;
      return 0;
    }
    *bit_no = elt1->indx * (2 * 64);
    bi->word_no = 0;
  }
}

extern void abort(void);

static void __attribute__((noinline)) catchme(int i) {
  if (i != 0 && i != 64)
    abort();
}
static void __attribute__((noinline)) foobar(bitmap_head *chain) {
  bitmap_iterator rsi;
  unsigned int regno;
  for (bmp_iter_set_init(&(rsi), (chain), (0), &(regno));
       bmp_iter_set(&(rsi), &(regno)); bmp_iter_next(&(rsi), &(regno)))
    catchme(regno);
}

int main() {
  bitmap_element elem = {(void *)0, (void *)0, 0, {1, 1}};
  bitmap_head live_throughout = {&elem, &elem, 0, (void *)0};
  foobar(&live_throughout);
  return 0;
}

$ gcc -O0 --coverage test.c;./a.out;gcov test;cat test.c.gcov
File 'test.c'
Lines executed:80.88% of 68
Creating 'test.c.gcov'

        -:    0:Source:test.c
        -:    0:Graph:test.gcno
        -:    0:Data:test.gcda
        -:    0:Runs:1
        -:    1:#include <setjmp.h>
        -:    2:#include <stdio.h>
        -:    3:#include <stdlib.h>
        -:    4:#include <string.h>
        -:    5:struct obstack {};
        -:    6:struct bitmap_head_def;
        -:    7:typedef struct bitmap_head_def *bitmap;
        -:    8:typedef const struct bitmap_head_def *const_bitmap;
        -:    9:typedef unsigned long BITMAP_WORD;
        -:   10:typedef struct bitmap_obstack {
        -:   11:  struct bitmap_element_def *elements;
        -:   12:  struct bitmap_head_def *heads;
        -:   13:  struct obstack obstack;
        -:   14:} bitmap_obstack;
        -:   15:typedef struct bitmap_element_def {
        -:   16:  struct bitmap_element_def *next;
        -:   17:  struct bitmap_element_def *prev;
        -:   18:  unsigned int indx;
        -:   19:  BITMAP_WORD bits[((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u))];
        -:   20:} bitmap_element;
        -:   21:
        -:   22:struct bitmap_descriptor;
        -:   23:
        -:   24:typedef struct bitmap_head_def {
        -:   25:  bitmap_element *first;
        -:   26:  bitmap_element *current;
        -:   27:  unsigned int indx;
        -:   28:  bitmap_obstack *obstack;
        -:   29:} bitmap_head;
        -:   30:
        -:   31:bitmap_element bitmap_zero_bits;
        -:   32:
        -:   33:typedef struct {
        -:   34:  bitmap_element *elt1;
        -:   35:  bitmap_element *elt2;
        -:   36:  unsigned word_no;
        -:   37:  BITMAP_WORD bits;
        -:   38:} bitmap_iterator;
        -:   39:
        -:   40:static void __attribute__((noinline))
        1:   41:bmp_iter_set_init(bitmap_iterator *bi, const_bitmap map,
unsigned start_bit,
        -:   42:                  unsigned *bit_no) {
        1:   43:  bi->elt1 = map->first;
        1:   44:  bi->elt2 = ((void *)0);
        -:   45:
        -:   46:  while (1) {
        1:   47:    if (!bi->elt1) {
    #####:   48:      bi->elt1 = &bitmap_zero_bits;
    #####:   49:      break;
        -:   50:    }
        -:   51:
        1:   52:    if (bi->elt1->indx >=
        1:   53:        start_bit / (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u))
* (8 * 8 * 1u)))
        1:   54:      break;
    #####:   55:    bi->elt1 = bi->elt1->next;
        -:   56:  }
        -:   57:
        1:   58:  if (bi->elt1->indx !=
        1:   59:      start_bit / (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)) *
(8 * 8 * 1u)))
    #####:   60:    start_bit = bi->elt1->indx *
        -:   61:                (((128 + (8 * 8 * 1u) - 1) / (8 * 8 * 1u)) * (8
* 8 * 1u));
        -:   62:
        1:   63:  bi->word_no =
        1:   64:      start_bit / (8 * 8 * 1u) % ((128 + (8 * 8 * 1u) - 1) / (8
* 8 * 1u));
        1:   65:  bi->bits = bi->elt1->bits[bi->word_no];
        1:   66:  bi->bits >>= start_bit % (8 * 8 * 1u);
        -:   67:
        1:   68:  start_bit += !bi->bits;
        -:   69:
        1:   70:  *bit_no = start_bit;
        1:   71:}
        -:   72:
        -:   73:static void __attribute__((noinline))
        2:   74:bmp_iter_next(bitmap_iterator *bi, unsigned *bit_no) {
        2:   75:  bi->bits >>= 1;
        2:   76:  *bit_no += 1;
        2:   77:}
        -:   78:
        -:   79:static unsigned char __attribute__((noinline))
        1:   80:bmp_iter_set_tail(bitmap_iterator *bi, unsigned *bit_no) {
        1:   81:  while (!(bi->bits & 1)) {
    #####:   82:    bi->bits >>= 1;
    #####:   83:    *bit_no += 1;
        -:   84:  }
        1:   85:  return 1;
        -:   86:}
        -:   87:
        3:   88:static __inline__ unsigned char bmp_iter_set(bitmap_iterator
*bi,
        -:   89:                                             unsigned *bit_no)
{
        3:   90:  unsigned bno = *bit_no;
        3:   91:  BITMAP_WORD bits = bi->bits;
        -:   92:  bitmap_element *elt1;
        -:   93:
        3:   94:  if (bits) {
        1:   95:    while (!(bits & 1)) {
    #####:   96:      bits >>= 1;
    #####:   97:      bno += 1;
        -:   98:    }
        1:   99:    *bit_no = bno;
        1:  100:    return 1;
        -:  101:  }
        -:  102:
        2:  103:  *bit_no = ((bno + 64 - 1) / 64 * 64);
        2:  104:  bi->word_no++;
        -:  105:
        2:  106:  elt1 = bi->elt1;
        -:  107:  while (1) {
        2:  108:    while (bi->word_no != 2) {
        1:  109:      bi->bits = elt1->bits[bi->word_no];
        1:  110:      if (bi->bits) {
        1:  111:        bi->elt1 = elt1;
        1:  112:        return bmp_iter_set_tail(bi, bit_no);
        -:  113:      }
    #####:  114:      *bit_no += 64;
    #####:  115:      bi->word_no++;
        -:  116:    }
        1:  117:    elt1 = elt1->next;
        1:  118:    if (!elt1) {
        1:  119:      bi->elt1 = elt1;
        1:  120:      return 0;
        -:  121:    }
    #####:  122:    *bit_no = elt1->indx * (2 * 64);
    #####:  123:    bi->word_no = 0;
        -:  124:  }
        -:  125:}
        -:  126:
        -:  127:extern void abort(void);
        -:  128:
        2:  129:static void __attribute__((noinline)) catchme(int i) {
        2:  130:  if (i != 0 && i != 64)
    #####:  131:    abort();
        2:  132:}
        1:  133:static void __attribute__((noinline)) foobar(bitmap_head
*chain) {
        -:  134:  bitmap_iterator rsi;
        -:  135:  unsigned int regno;
        4:  136:  for (bmp_iter_set_init(&(rsi), (chain), (0), &(regno));
        3:  137:       bmp_iter_set(&(rsi), &(regno)); bmp_iter_next(&(rsi),
&(regno)))
        2:  138:    catchme(regno);
        1:  139:}
        -:  140:
        1:  141:int main() {
        1:  142:  bitmap_element elem = {(void *)0, (void *)0, 0, {1, 1}};
        1:  143:  bitmap_head live_throughout = {&elem, &elem, 0, (void *)0};
        1:  144:  foobar(&live_throughout);
        1:  145:  return 0;
        -:  146:}

The coverage of line 136 was wrongly marked as 4


More information about the Gcc-bugs mailing list