[Bug tree-optimization/59892] New: out of bounds array access is misoptimized
alexei.starovoitov at gmail dot com
gcc-bugzilla@gcc.gnu.org
Mon Jan 20 18:35:00 GMT 2014
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59892
Bug ID: 59892
Summary: out of bounds array access is misoptimized
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: alexei.starovoitov at gmail dot com
Created attachment 31901
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=31901&action=edit
test case
attached test case was narrowed down from linux kernel
file drivers/scsi/isci/host.h
#define for_each_isci_host(id, ihost, pdev) \
for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
ihost = to_pci_info(pdev)->hosts[++id])
'hosts' array has fixed size of 2:
struct isci_pci_info {
struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
struct isci_host *hosts[SCI_MAX_CONTROLLERS];
struct isci_orom *orom;
};
and loop is accessing 3rd element of the array.
Behavior is undefined, but gcc 4.7 and older were ok,
whereas GCC 4.8 and the latest 4.9 are misoptimizing the code
by dropping 'id < 2' loop condition.
$ gcc -O0 array_out_of_bounds.c
$ ./a.out
(0 < 2) == 1
(1 < 2) == 1
$ gcc -O2 array_out_of_bounds.c
$ ./a.out
(0 < 2) == 1
(1 < 2) == 1
Segmentation fault (core dumped)
'cunrolli' pass is confused with such loop condition and produces wrong tree:
<bb 3>:
_19 = (int) _16;
printf ("(%d < %d) == %d\n", 0, 2, _19);
i_21 = 1;
isci_host_22 = v.hosts[i_21];
_6 = i_21 <= 1;
_7 = isci_host_22 != 0B;
_8 = _6 & _7;
if (_8 != 0)
goto <bb 4>;
else
goto <bb 5>;
<bb 4>:
_9 = (int) _6;
printf ("(%d < %d) == %d\n", i_21, 2, _9);
i_11 = i_21 + 1;
__builtin_unreachable ();
if 'cunrolli' is disabled, the VRP pass is equally confused:
<bb 3>:
_9 = 1;
printf ("(%d < %d) == %d\n", i_1, 2, 1);
i_11 = i_1 + 1;
isci_host_12 = v.hosts[i_11];
<bb 4>:
# i_1 = PHI <0(2), i_11(3)>
# isci_host_2 = PHI <isci_host_5(2), isci_host_12(3)>
_6 = 1;
_7 = isci_host_2 != 0B;
_8 = _7;
if (_8 != 0)
goto <bb 3>;
else
goto <bb 5>;
<bb 5>:
return 0;
and optimizes i<=1 condition into _6 = 1 above, whereas bb4 can
be executed for i=2
worst is that compiler doesn't warn on the problem.
-Wall and -Warray-bounds don't see it.
Though the code is erroneous by C standard definition, GCC should be smarter
and prevent misoptimization where it can. As a minimum it should warn about
such cases.
More information about the Gcc-bugs
mailing list