<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 - The number of SIMD loads increases unnecessarily"
href="https://bugs.llvm.org/show_bug.cgi?id=47558">47558</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>The number of SIMD loads increases unnecessarily
</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>Linux
</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>Scalar Optimizations
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>kazu@google.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>This patch:
<a href="https://github.com/llvm/llvm-project/commit/8fb055932c085da21f3b721995a06f42006744bd">https://github.com/llvm/llvm-project/commit/8fb055932c085da21f3b721995a06f42006744bd</a>
increases the number of memory loads in certain cases.
Consider:
target triple = "x86_64-unknown-linux-gnu"
declare dso_local float* @getscaleptr() #0
define void @foo(<2 x float>* nonnull %resultptr, <2 x float>* nonnull %opptr)
{
%scaleptr = call nonnull align 16 dereferenceable(64) float* @getscaleptr()
%op = load <2 x float>, <2 x float>* %opptr, align 4
%scale = load float, float* %scaleptr, align 16
%op0 = extractelement <2 x float> %op, i32 0
%product0 = fmul float %op0, %scale
%result0 = insertelement <2 x float> undef, float %product0, i32 0
%op1 = extractelement <2 x float> %op, i32 1
%product1 = fmul float %op1, %scale
%result1 = insertelement <2 x float> %result0, float %product1, i32 1
store <2 x float> %result1, <2 x float>* %resultptr, align 8
ret void
}
This testcase multiplies a <2 x float> value by a scalar float value
and stores the result back to memory.
Compile like so:
$ clang -O2 -msse4.2 -S bug.ll -o bug.s
Then with and without the patch, I get the following assembly diff:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
callq getscaleptr
movsd (%rbx), %xmm0 # xmm0 = mem[0],zero
- movss (%rax), %xmm1 # xmm1 = mem[0],zero,zero,zero
- movsldup %xmm1, %xmm1 # xmm1 = xmm1[0,0,2,2]
+ movaps (%rax), %xmm1
+ insertps $16, (%rax), %xmm1 # xmm1 =
xmm1[0],mem[0],xmm1[2,3]
mulps %xmm0, %xmm1
movlps %xmm1, (%r14)
addq $8, %rsp
popq %rbx
popq %r14
retq
Note that the patch replaces movsldup with insertps, which reads from
the same location as movaps, increasing the number of loads.
Here is the "IR Dump After Optimize scalar/vector ops".
Without the patch:
%scaleptr = tail call nonnull align 16 dereferenceable(64) float*
@getscaleptr()
%op = load <2 x float>, <2 x float>* %opptr, align 4
%scale = load float, float* %scaleptr, align 16
%1 = insertelement <2 x float> undef, float %scale, i32 0
%2 = insertelement <2 x float> %1, float %scale, i32 1
%3 = fmul <2 x float> %op, %2
%4 = extractelement <2 x float> %3, i32 0
%result0 = insertelement <2 x float> undef, float %4, i32 0
%5 = extractelement <2 x float> %3, i32 1
%result1 = insertelement <2 x float> %result0, float %5, i32 1
store <2 x float> %result1, <2 x float>* %resultptr, align 8
ret void
With the patch:
%scaleptr = tail call nonnull align 16 dereferenceable(64) float*
@getscaleptr()
%op = load <2 x float>, <2 x float>* %opptr, align 4
%1 = bitcast float* %scaleptr to <4 x float>*
%2 = load <4 x float>, <4 x float>* %1, align 16
%3 = shufflevector <4 x float> %2, <4 x float> undef, <2 x i32> <i32 0, i32
1>
%scale = load float, float* %scaleptr, align 16
%4 = insertelement <2 x float> %3, float %scale, i32 1
%5 = fmul <2 x float> %op, %4
%6 = extractelement <2 x float> %5, i32 0
%result0 = insertelement <2 x float> undef, float %6, i32 0
%7 = extractelement <2 x float> %5, i32 1
%result1 = insertelement <2 x float> %result0, float %7, i32 1
store <2 x float> %result1, <2 x float>* %resultptr, align 8
ret void
Notice the three loads with the patch.
Here is the final LLVM IR.
Without the patch:
%scaleptr = tail call nonnull align 16 dereferenceable(64) float*
@getscaleptr()
%op = load <2 x float>, <2 x float>* %opptr, align 4
%scale = load float, float* %scaleptr, align 16
%1 = insertelement <2 x float> undef, float %scale, i32 0
%2 = shufflevector <2 x float> %1, <2 x float> undef, <2 x i32>
zeroinitializer
%3 = fmul <2 x float> %op, %2
store <2 x float> %3, <2 x float>* %resultptr, align 8
ret void
With the patch:
%scaleptr = tail call nonnull align 16 dereferenceable(64) float*
@getscaleptr()
%op = load <2 x float>, <2 x float>* %opptr, align 4
%1 = bitcast float* %scaleptr to <4 x float>*
%2 = load <4 x float>, <4 x float>* %1, align 16
%3 = shufflevector <4 x float> %2, <4 x float> undef, <2 x i32> <i32 0, i32
undef>
%scale = load float, float* %scaleptr, align 16
%4 = insertelement <2 x float> %3, float %scale, i32 1
%5 = fmul <2 x float> %op, %4
store <2 x float> %5, <2 x float>* %resultptr, align 8
ret void</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>