Hello! The missing return in _xgetbv is a bug and will be backported to release branches.
2018-05-10 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (ix86_expand_builtin) <case IX86_BUILTIN_RDPID>: Generate SImode target register for null target. <case IX86_BUILTIN_XGETBV>: Ditto. <case IX86_BUILTIN_XSETBV>: Optimize LSHIFTRT generation. * config/i386/xsaveintrin.h (_xgetbv): Add missing return. testsuite/ChangeLog: 2018-05-10 Uros Bizjak <ubiz...@gmail.com> * gcc.target/i386/xgetsetbv.c: Check also variable arguments. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 260116) +++ config/i386/i386.c (working copy) @@ -37085,7 +37085,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub case IX86_BUILTIN_RDPID: - op0 = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); + op0 = gen_reg_rtx (word_mode); if (TARGET_64BIT) { @@ -37094,18 +37094,16 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub } else insn = gen_rdpid (op0); + emit_insn (insn); - if (target == 0) - { - /* mode is VOIDmode if __builtin_rdpid has been called - without lhs. */ - if (mode == VOIDmode) - return target; - target = gen_reg_rtx (mode); - } + if (target == 0 + || !register_operand (target, SImode)) + target = gen_reg_rtx (SImode); + emit_move_insn (target, op0); return target; + case IX86_BUILTIN_RDPMC: case IX86_BUILTIN_RDTSC: case IX86_BUILTIN_RDTSCP: @@ -37164,14 +37162,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub emit_move_insn (gen_rtx_MEM (SImode, op4), op2); } - if (target == 0) - { - /* mode is VOIDmode if __builtin_rd* has been called - without lhs. */ - if (mode == VOIDmode) - return target; - target = gen_reg_rtx (mode); - } + if (target == 0 + || !register_operand (target, DImode)) + target = gen_reg_rtx (DImode); if (TARGET_64BIT) { @@ -37260,25 +37253,23 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub if (!REG_P (op0)) op0 = copy_to_mode_reg (SImode, op0); + op1 = force_reg (DImode, op1); + if (TARGET_64BIT) { op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32), NULL, 1, OPTAB_DIRECT); + icode = CODE_FOR_xsetbv_rex64; + op2 = gen_lowpart (SImode, op2); op1 = gen_lowpart (SImode, op1); - if (!REG_P (op1)) - op1 = copy_to_mode_reg (SImode, op1); - if (!REG_P (op2)) - op2 = copy_to_mode_reg (SImode, op2); - icode = CODE_FOR_xsetbv_rex64; pat = GEN_FCN (icode) (op0, op1, op2); } else { - if (!REG_P (op1)) - op1 = copy_to_mode_reg (DImode, op1); icode = CODE_FOR_xsetbv; + pat = GEN_FCN (icode) (op0, op1); } if (pat) Index: config/i386/xsaveintrin.h =================================================================== --- config/i386/xsaveintrin.h (revision 260116) +++ config/i386/xsaveintrin.h (working copy) @@ -59,7 +59,7 @@ extern __inline long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _xgetbv (unsigned int __A) { - __builtin_ia32_xgetbv (__A); + return __builtin_ia32_xgetbv (__A); } #ifdef __x86_64__ Index: testsuite/gcc.target/i386/xgetsetbv.c =================================================================== --- testsuite/gcc.target/i386/xgetsetbv.c (revision 260116) +++ testsuite/gcc.target/i386/xgetsetbv.c (working copy) @@ -1,13 +1,27 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mxsave" } */ -/* { dg-final { scan-assembler "xgetbv" } } */ -/* { dg-final { scan-assembler "xsetbv" } } */ +/* { dg-final { scan-assembler-times "xgetbv" 3 } } */ +/* { dg-final { scan-assembler-times "xsetbv" 3 } } */ #include <x86intrin.h> -unsigned int -xgetsetbv (void) +unsigned long long +foo (unsigned x, unsigned y) { + _xsetbv (x, y); + return _xgetbv (x); +} + +unsigned long long +bar (unsigned x, unsigned long long y) +{ + _xsetbv (x, y); + return _xgetbv (x); +} + +unsigned long long +baz (void) +{ _xsetbv (0, 0); return _xgetbv (0); }