<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>