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