https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77966
Denis Vlasenko <vda.linux at googlemail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |vda.linux at googlemail dot com --- Comment #1 from Denis Vlasenko <vda.linux at googlemail dot com> --- Simplified a bit: - spinlock_t is not essential - mempool_t is not essential - snic_log_q_error_err_status variable is not necessary - __attribute__ ((__aligned__)) can be dropped too - struct vnic_wq can be folded OTOH: - struct vnic_wq_ctrl wrapping of int variable is necessary - wq_lock[1] unused member is necessary (makes gcc "know for sure" that wq[1] is 1-element array) - each of -O2 -fno-reorder-blocks -fsanitize-coverage=trace-pc are necessary extern unsigned int ioread32(void *); struct vnic_wq_ctrl { unsigned int error_status; }; struct snic { unsigned int wq_count; struct vnic_wq_ctrl *wq[1]; int wq_lock[1]; }; void snic_log_q_error(struct snic *snic) { unsigned int i; for (i = 0; i < snic->wq_count; i++) ioread32(&snic->wq[i]->error_status); } <snic_log_q_error>: 0: 53 push %rbx 1: 48 89 fb mov %rdi,%rbx 4: e8 00 00 00 00 callq __sanitizer_cov_trace_pc 9: 8b 03 mov (%rbx),%eax b: 85 c0 test %eax,%eax # snic->wq_count==0? d: 75 09 jne 18 f: 5b pop %rbx # yes, 0 10: e9 00 00 00 00 jmpq __sanitizer_cov_trace_pc #tail call 15: 0f 1f 00 nopl (%rax) 18: e8 00 00 00 00 callq __sanitizer_cov_trace_pc 1d: 48 8b 7b 08 mov 0x8(%rbx),%rdi 21: e8 00 00 00 00 callq ioread32 26: 83 3b 01 cmpl $0x1,(%rbx) # snic->wq_count<=1? 29: 76 e4 jbe f 2b: e8 00 00 00 00 callq __sanitizer_cov_trace_pc Looks like gcc thinks that the loop can execute only zero or one time (or else we run off wq[1]). So when it iterated once: 21: e8 00 00 00 00 callq ioread32 it checks that snic->wq_count <= 1 26: 83 3b 01 cmpl $0x1,(%rbx) 29: 76 e4 jbe f and if not, we are in "impossible" land and just stop codegen. -fsanitize-coverage=trace-pc generator twitches one last time: 2b: e8 00 00 00 00 callq __sanitizer_cov_trace_pc <end>