https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77966
Denis Vlasenko changed:
What|Removed |Added
CC||vda.linux at googlemail dot com
--- Comment #1 from Denis Vlasenko ---
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);
}
:
0: 53 push %rbx
1: 48 89 fbmov%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 jne18
f: 5b pop%rbx # yes, 0
10: e9 00 00 00 00 jmpq __sanitizer_cov_trace_pc #tail call
15: 0f 1f 00nopl (%rax)
18: e8 00 00 00 00 callq __sanitizer_cov_trace_pc
1d: 48 8b 7b 08 mov0x8(%rbx),%rdi
21: e8 00 00 00 00 callq ioread32
26: 83 3b 01cmpl $0x1,(%rbx) # snic->wq_count<=1?
29: 76 e4 jbef
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 01cmpl $0x1,(%rbx)
29: 76 e4 jbef
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