[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