Bug 2121683

Summary: __builtin_ia32_rdrand32_step() unconditionally emits cmov instruction for gcc -march=i586 compile
Product: Red Hat Enterprise Linux 9 Reporter: Taketo Kabe <rkabe>
Component: gccAssignee: Marek Polacek <mpolacek>
gcc sub component: gcc-toolset-11 QA Contact: qe-baseos-tools-bugs
Status: CLOSED NOTABUG Docs Contact:
Severity: medium    
Priority: unspecified CC: ahajkova, bstinson, fweimer, jakub, jwboyer, ohudlick, sipoyare
Version: CentOS Stream   
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-08-26 12:50:46 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Taketo Kabe 2022-08-26 08:26:39 UTC
Description of problem:
gcc builtin function __builtin_ia32_rdrand32_step() seems to emit
cmov instruction unconditionally,even if -march=i586 (no cmov capability)
is given to gcc.


Version-Release number of selected component (if applicable):
gcc version 11.3.1 20220421 (Red Hat 11.3.1-2) (GCC)

How reproducible:
always

Steps to Reproduce:
0. install glibc-devel.i686
sudo dnf install glibc-devel.i686

1. create rdrand.c file as follows:
/* gcc -mrdrnd -march=i586 -m32 rdrand.c */
#include <stdio.h>
int main()
{
        int s,r;
        s = __builtin_ia32_rdrand32_step(&r);
        printf("rdrand=%d status=%d\n", r, s);
}

2. Compile with:
gcc -mrdrnd -march=i586 -m32 rdrand.c

3. Examine the output by objdump -d:
objdump -d a.out | grep -C 3 cmov

Actual results:
[kabe@centos-s-9 ~]$ objdump -d a.out | grep -C 3 cmov
 80491a1:       0f c7 f0                rdrand %eax
 80491a4:       89 02                   mov    %eax,(%edx)
 80491a6:       ba 01 00 00 00          mov    $0x1,%edx
 80491ab:       0f 42 c2                cmovb  %edx,%eax
 80491ae:       89 45 f4                mov    %eax,-0xc(%ebp)
 80491b1:       8b 45 f0                mov    -0x10(%ebp),%eax
 80491b4:       83 ec 04                sub    $0x4,%esp


Expected results:
no match


Additional info:
gcc generates instructions on the fly for __builtin* functions.
cmov seems to be generated by usage of gen_rtx_IF_THEN_ELSE() in rdrand_step: branch of gcc's gcc/config/i386/i386-expand.c, but I could not trace the cause why -march=i586 is not honoured by the on-the-fly compiler.

Comment 1 Jakub Jelinek 2022-08-26 08:49:55 UTC
Is there any CPU which does support RDRND ISA but not CMOV?

Comment 2 Jakub Jelinek 2022-08-26 08:59:51 UTC
/* For sane SSE instruction set generation we need fcomi instruction.
   It is safe to enable all CMOVE instructions.  Also, RDRAND intrinsic
   expands to a sequence that includes conditional move. */
#define TARGET_CMOVE            (TARGET_CMOV || TARGET_SSE || TARGET_RDRND)

is the macro enabling the conditional move patterns.
For RDRND this was done in https://gcc.gnu.org/r0-108854 and for SSE in
https://gcc.gnu.org/r0-33571

Comment 5 Marek Polacek 2022-08-26 12:50:46 UTC
Given that this seems to be intentional and that we don't support i586 anyway, I'm closing this BZ.
Please feel free to open an upstream bug if you still think this is a bug.