[llvm-bugs] [Bug 27158] New: AArch64InstrInfo::optimizeCompareInstr incorrectly removes compare instructions
via llvm-bugs
llvm-bugs at lists.llvm.org
Thu Mar 31 03:24:32 PDT 2016
https://llvm.org/bugs/show_bug.cgi?id=27158
Bug ID: 27158
Summary: AArch64InstrInfo::optimizeCompareInstr incorrectly
removes compare instructions
Product: libraries
Version: trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: Backend: AArch64
Assignee: unassignedbugs at nondot.org
Reporter: eastig at yandex.ru
CC: llvm-bugs at lists.llvm.org
Classification: Unclassified
Incorrect code is generated when the following test is compiled with -O3:
------------ test.c --------
// clang --target=aarch64-none-eabi -O3 -S test.c
#include <stdio.h>
static char c = 2;
static char d[4] = {1};
int main() {
c = d[3];
unsigned short f = d[1] << d[2];
if ((&c == &d[3]) <= f)
c = printf("checksum = 0\n");
}
------------------------------
When the produced binary is executed 'checksum = 0' is not printed.
It should be printed because the condition of the if statement should always be
true (the two addresses cannot be equal, so the inner comparison is false,
which gets converted to (int)0, and f is 0 because a and b are both 0). When
the program is compiled with O2 it works as expected.
With -O2 the generated code is
------------------------------
main: // @main
// BB#0: // %entry
adrp x8, d
add x8, x8, :lo12:d
ldrb w9, [x8, #3]!
adrp x12, c
add x12, x12, :lo12:c
ldurb w10, [x8, #-2]
ldurb w11, [x8, #-1]
cmp x8, x12
strb w9, [x12]
cset w9, eq
lsl w8, w10, w11
and w8, w8, #0xffff
cmp w8, w9
b.lo .LBB0_2
------------------------------
With -O3 the generated code is
------------------------------
main: // @main
// BB#0: // %entry
adrp x8, .L_MergedGlobals
add x8, x8, :lo12:.L_MergedGlobals
ldrb w9, [x8, #4]
ldrb w10, [x8, #2]
ldrb w11, [x8, #3]
strb w9, [x8]
lsl w8, w10, w11
tst w8, #0xffff
b.lo .LBB0_2
------------------------------
The O3 code is incorrect because CMP and TST set the carry flag to different
values. As a result Bcc which checks the carry flag is not working as expected.
The problem function is AArch64InstrInfo::optimizeCompareInstr from
AArch64InstrInfo.cpp.
It tries to remove a compare instruction. One case is comparison with 0:
CmpInst r, 0. It removes CmpInst and modifies the instruction defining r to the
S version.
It is not checked that the S version and CmpInst produce the same flags.
In case of the test above the following code:
%vreg7<def> = ANDWri %vreg6<kill>, 15; GPR32sp:%vreg7 GPR32:%vreg6
%vreg8<def> = SUBSWri %vreg7<kill>, 0, 0, %NZCV<imp-def>; GPR32:%vreg8
GPR32sp:%vreg7
Bcc 3, <BB#2>, %NZCV<imp-use>
is transformed into
%vreg7<def> = ANDSWri %vreg6<kill>, 15, %NZCV<imp-def>; GPR32common:%vreg7
GPR32:%vreg6
Bcc 3, <BB#2>, %NZCV<imp-use>
I have a fix of the bug. It was submitted for review as
http://reviews.llvm.org/D18318. It was recommended to split it into smaller
parts to simplify reviewing of it.
It is split into parts:
Part1 - refactoring of AArch64InstrInfo::optimizeCompareInstr
http://reviews.llvm.org/D18609
Part2 will contain the fix.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160331/1076036d/attachment-0001.html>
More information about the llvm-bugs
mailing list