<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 - [X86] CMOV_GR8 is pseudo, and is expanded."
href="https://bugs.llvm.org/show_bug.cgi?id=40965">40965</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[X86] CMOV_GR8 is pseudo, and is expanded.
</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>lebedev.ri@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>craig.topper@gmail.com, llvm-bugs@lists.llvm.org, llvm-dev@redking.me.uk, spatel+llvm@rotateright.com
</td>
</tr></table>
<p>
<div>
<pre>mclow brought up this issue up in IRC, it came up during implementation of
libc++ std::midpoint implementation.
<a href="https://godbolt.org/z/oLrHBP">https://godbolt.org/z/oLrHBP</a>
If std::midpoint() is used on 'int', then final x86 asm uses CMOV.
If std::midpoint() is used on 'signed char', then final x86 asm contains
branch.
The produced IR is more or less the same, is optimal, no branches.
If we look in `llc -print-after-all`
# *** IR Dump After X86 DAG->DAG Instruction Selection ***:
# Machine code for function main: IsSSA, TracksLiveness
bb.0 (%ir-block.0):
%0:gr8 = MOV8rm $rip, 1, $noreg, @a, $noreg :: (dereferenceable load 1 from
@a, !tbaa !2)
%1:gr8 = MOV8rm $rip, 1, $noreg, @b, $noreg :: (dereferenceable load 1 from
@b, !tbaa !2)
%2:gr8 = SUB8rr %0:gr8(tied-def 0), %1:gr8, implicit-def $eflags
%3:gr8 = SETLEr implicit $eflags
%4:gr8 = CMOV_GR8 %0:gr8, %1:gr8, 5, implicit $eflags
%5:gr8 = CMOV_GR8 %1:gr8, %0:gr8, 6, implicit $eflags
%6:gr8 = ADD8rr %3:gr8(tied-def 0), %3:gr8, implicit-def dead $eflags
%7:gr8 = ADD8ri %6:gr8(tied-def 0), -1, implicit-def dead $eflags
%8:gr8 = SUB8rr %5:gr8(tied-def 0), killed %4:gr8, implicit-def dead $eflags
%9:gr8 = SHR8r1 %8:gr8(tied-def 0), implicit-def dead $eflags
$al = COPY %9:gr8
MUL8r killed %7:gr8, implicit-def $al, implicit-def dead $eflags,
implicit-def $ax, implicit $al
%10:gr8 = COPY $al
%11:gr8 = ADD8rr %10:gr8(tied-def 0), %0:gr8, implicit-def dead $eflags
%12:gr32 = MOVSX32rr8 killed %11:gr8
$eax = COPY %12:gr32
RET 0, $eax
# End machine code for function main.
# *** IR Dump After Expand ISel Pseudo-instructions ***:
# Machine code for function main: IsSSA, TracksLiveness
bb.0 (%ir-block.0):
successors: %bb.1(0x40000000), %bb.2(0x40000000); %bb.1(50.00%),
%bb.2(50.00%)
%0:gr8 = MOV8rm $rip, 1, $noreg, @a, $noreg :: (dereferenceable load 1 from
@a, !tbaa !2)
%1:gr8 = MOV8rm $rip, 1, $noreg, @b, $noreg :: (dereferenceable load 1 from
@b, !tbaa !2)
%2:gr8 = SUB8rr %0:gr8(tied-def 0), %1:gr8, implicit-def $eflags
%3:gr8 = SETLEr implicit $eflags
JG_1 %bb.2, implicit $eflags
bb.1 (%ir-block.0):
; predecessors: %bb.0
successors: %bb.2(0x80000000); %bb.2(100.00%)
liveins: $eflags
bb.2 (%ir-block.0):
; predecessors: %bb.0, %bb.1
successors: %bb.3(0x40000000), %bb.4(0x40000000); %bb.3(50.00%),
%bb.4(50.00%)
liveins: $eflags
%4:gr8 = PHI %0:gr8, %bb.1, %1:gr8, %bb.0
JGE_1 %bb.4, implicit $eflags
bb.3 (%ir-block.0):
; predecessors: %bb.2
successors: %bb.4(0x80000000); %bb.4(100.00%)
bb.4 (%ir-block.0):
; predecessors: %bb.2, %bb.3
%5:gr8 = PHI %1:gr8, %bb.3, %0:gr8, %bb.2
%6:gr8 = ADD8rr %3:gr8(tied-def 0), %3:gr8, implicit-def dead $eflags
%7:gr8 = ADD8ri %6:gr8(tied-def 0), -1, implicit-def dead $eflags
%8:gr8 = SUB8rr %5:gr8(tied-def 0), killed %4:gr8, implicit-def dead $eflags
%9:gr8 = SHR8r1 %8:gr8(tied-def 0), implicit-def dead $eflags
$al = COPY %9:gr8
MUL8r killed %7:gr8, implicit-def $al, implicit-def dead $eflags,
implicit-def $ax, implicit $al
%10:gr8 = COPY $al
%11:gr8 = ADD8rr %10:gr8(tied-def 0), %0:gr8, implicit-def dead $eflags
%12:gr32 = MOVSX32rr8 killed %11:gr8
$eax = COPY %12:gr32
RET 0, $eax
# End machine code for function main.
We can see that "Expand ISel Pseudo-instructions" (ExpandISelPseudos)
has expanded `CMOV_GR8`.
Which makes sense, is there a 1-byte version of cmov?
Not as per <a href="https://www.felixcloutier.com/x86/cmovcc">https://www.felixcloutier.com/x86/cmovcc</a> or Intel SDM.
I do think it is better to avoid branch here.
Can we instead widen to 32-bit (i think we try to avoid 16-bit in x86?), and
keep CMOV?
Thoughts?</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>