<html>
<head>
<base href="https://llvm.org/bugs/" />
</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 --- - llvm does not recognize widening vector multiplication"
href="https://llvm.org/bugs/show_bug.cgi?id=30845">30845</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>llvm does not recognize widening vector multiplication
</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>Backend: X86
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>sroland@vmware.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>Since llvm does not have widening muls (I'm looking at unsigned 32/32->64bit
specifically), this has to be done by using zext on the inputs (I didn't try
signed, but the same logic should apply using sext), followed by the mul.
Unfortunately, llvm will not recognize that this is really a 32/32->64bit mul,
which can be done natively with pmuludq, and instead perform "real"
64/64->64bit mul (3 pmuludq, 4 shifts, 3 adds as far as arithmetic goes instead
of a single pmuludq).
Requiring the high bits of the mul result is an operation needed quite a bit
(e.g. opencl mul_hi will return the high bits of such a 32/32->64bit mul, or if
you want to simply do overflow checking on a 32bit mul).
This code basically does such a mul_hi returning the high bits of a
32/32->64bit unsigned mul (obviously, this actually needs 2 pmuludq plus some
input/output shuffling (or shifts instead of shuffles)):
; llc-3.7 -mattr=sse2 -o - umul.ll
define <4 x i32> @umul(<4 x i32> %val1, <4 x i32> %val2) {
entry:
%val1a = zext <4 x i32> %val1 to <4 x i64>
%val2a = zext <4 x i32> %val2 to <4 x i64>
%res64 = mul <4 x i64> %val1a, %val2a
%rescast = bitcast <4 x i64> %res64 to <8 x i32>
%res = shufflevector <8 x i32> %rescast, <8 x i32> undef, <4 x i32> <i32 1,
i32 3, i32 5, i32 7>
ret <4 x i32> %res
}
And it compiles to this monstrosity (with llvm master, but pretty much the same
with older versions):
pxor %xmm4, %xmm4
movdqa %xmm0, %xmm2
punpckhdq %xmm4, %xmm2 # xmm2 =
xmm2[2],xmm4[2],xmm2[3],xmm4[3]
punpckldq %xmm4, %xmm0 # xmm0 =
xmm0[0],xmm4[0],xmm0[1],xmm4[1]
movdqa %xmm1, %xmm3
punpckhdq %xmm4, %xmm3 # xmm3 =
xmm3[2],xmm4[2],xmm3[3],xmm4[3]
punpckldq %xmm4, %xmm1 # xmm1 =
xmm1[0],xmm4[0],xmm1[1],xmm4[1]
movdqa %xmm0, %xmm4
pmuludq %xmm1, %xmm4
movdqa %xmm1, %xmm5
psrlq $32, %xmm5
pmuludq %xmm0, %xmm5
psllq $32, %xmm5
psrlq $32, %xmm0
pmuludq %xmm1, %xmm0
psllq $32, %xmm0
paddq %xmm5, %xmm0
paddq %xmm4, %xmm0
movdqa %xmm2, %xmm1
pmuludq %xmm3, %xmm1
movdqa %xmm3, %xmm4
psrlq $32, %xmm4
pmuludq %xmm2, %xmm4
psllq $32, %xmm4
psrlq $32, %xmm2
pmuludq %xmm3, %xmm2
psllq $32, %xmm2
paddq %xmm4, %xmm2
paddq %xmm1, %xmm2
pshufd $237, %xmm2, %xmm1 # xmm1 = xmm2[1,3,2,3]
pshufd $237, %xmm0, %xmm0 # xmm0 = xmm0[1,3,2,3]
punpcklqdq %xmm1, %xmm0 # xmm0 = xmm0[0],xmm1[0]
retq
The failure to recognize the widening pattern also happens with avx2, or if
just multiplying the lower 2 of the 4 numbers, returning 64bit results (though
obviously there's only half as much code in this case, skipping the second
half).</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>