[llvm-bugs] [Bug 42736] New: [mips] Incorrect code in case of applying 32-bit mask to result of 64-bit address loading

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Jul 24 04:10:54 PDT 2019


https://bugs.llvm.org/show_bug.cgi?id=42736

            Bug ID: 42736
           Summary: [mips] Incorrect code in case of applying 32-bit mask
                    to result of 64-bit address loading
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: MIPS
          Assignee: unassignedbugs at nondot.org
          Reporter: simon at atanasyan.com
                CC: llvm-bugs at lists.llvm.org

If result of 64-bit address loading combines with 32-bit mask, LLVM tries to
optimize the code and remove "redundant" loading of upper 32-bits of the
address. Unfortunately it leads to incorrect code on MIPS64 targets.
----------
$ cat test.ll
define dso_local void @bar1() {
entry:
  %val = alloca i64, align 8
  store i64 ptrtoint (void (...)* @foo to i64), i64* %val, align 8
  %0 = load i64, i64* %val, align 8
  ret void
}

define dso_local void @bar2() {
entry:
  %val = alloca i64, align 8
  store i64 and (i64 ptrtoint (void (...)* @foo to i64), i64 268435455), i64*
%val, align 8
  %0 = load i64, i64* %val, align 8
  ret void
}

declare dso_local void @foo(...)

$ llc -march=mips64 -relocation-model=static -mattr noabicalls < test.ll
bar1:
...
        lui     $1, %highest(foo)    # load highest 16-bits of address, shift
and store
        daddiu  $1, $1, %higher(foo) # add next 16-bits of address
        dsll    $1, $1, 16           # shift result left
        daddiu  $1, $1, %hi(foo)     # add hi 16-bits of address
        dsll    $1, $1, 16           # shift result left
        daddiu  $1, $1, %lo(foo)     # add low 16-bits of address
...
bar2:
...
        lui     $1, 4095             # prepare 0x0FFFFFFF mask
        ori     $1, $1, 65535        #
        lui     $2, %hi(foo)         # load hi 16-bits of address, shift and
store
        dsll    $2, $2, 16           # <<<< unnecessary instruction, bits
already shifted by `lui`
        daddiu  $2, $2, %lo(foo)     # add low 16-bits of address
        and     $1, $2, $1           # apply the mask
----------

The problem is in the code optimization phase. MIPS backend creates the
following chain of commands to load 64-bit address in the
MipsTargetLowering::getAddrNonPICSym64 method:

(add (shl (add (shl (add %highest(sym), %higher(sym)),
                    16),
               %high(sym)),
          16),
     %lo(%sym))

Without the mask it successfully translates to the following instructions:

lui     at,0x0
    R_MIPS_HIGHEST   foo
daddiu  at,at,0
    R_MIPS_HIGHER   foo
dsll    at,at,0x10
daddiu  at,at,0
    R_MIPS_HI16     foo
dsll    at,at,0x10
daddiu  at,at,0
    R_MIPS_LO16     foo

If the mask presents, LLVM decides to optimize the chain of commands. It really
does not make sense to load upper 32-bits because the 0x0fffffff mask anyway
clears them. So "unnecessary" commands removed and we get this chain:

(add (shl (%high(sym), 16), %lo(%sym))

As a result we get incorrect set of instructions:

lui     at,0x0
    R_MIPS_HI16     foo
dsll    at,at,0x10
daddiu  at,at,0
    R_MIPS_LO16     foo

-- 
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/20190724/1fbf93d4/attachment-0001.html>


More information about the llvm-bugs mailing list