<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [mips] Incorrect code in case of applying 32-bit mask to result of 64-bit address loading"
   href="https://bugs.llvm.org/show_bug.cgi?id=42736">42736</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[mips] Incorrect code in case of applying 32-bit mask to result of 64-bit address loading
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: MIPS
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>simon@atanasyan.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>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</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>