Hello! We should not expand call arguments in between flags reg setting and flags reg using instructions, as it may expand with flags reg clobbering insn (ADD in this case).
Attached patch moves expansion out of the link. Also, change zero-extension to non-flags reg clobbering sequence in case we perform zero-extension with and. 2017-03-25 Uros Bizjak <ubiz...@gmail.com> PR target/80180 * config/i386/i386.c (ix86_expand_builtin) <IX86_BUILTIN_RDSEED{16,32,64}_STEP>: Do not expand arg0 between flags reg setting and flags reg using instructions. <IX86_BUILTIN_RDRAND{16,32,64}_STEP>: Ditto. Use non-flags reg clobbering instructions to zero extend op2. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN, will be backported to other release branches. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 246473) +++ config/i386/i386.c (working copy) @@ -37572,9 +37572,6 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub mode0 = DImode; rdrand_step: - op0 = gen_reg_rtx (mode0); - emit_insn (GEN_FCN (icode) (op0)); - arg0 = CALL_EXPR_ARG (exp, 0); op1 = expand_normal (arg0); if (!address_operand (op1, VOIDmode)) @@ -37582,6 +37579,10 @@ rdrand_step: op1 = convert_memory_address (Pmode, op1); op1 = copy_addr_to_reg (op1); } + + op0 = gen_reg_rtx (mode0); + emit_insn (GEN_FCN (icode) (op0)); + emit_move_insn (gen_rtx_MEM (mode0, op1), op0); op1 = gen_reg_rtx (SImode); @@ -37590,8 +37591,20 @@ rdrand_step: /* Emit SImode conditional move. */ if (mode0 == HImode) { - op2 = gen_reg_rtx (SImode); - emit_insn (gen_zero_extendhisi2 (op2, op0)); + if (TARGET_ZERO_EXTEND_WITH_AND + && optimize_function_for_speed_p (cfun)) + { + op2 = force_reg (SImode, const0_rtx); + + emit_insn (gen_movstricthi + (gen_lowpart (HImode, op2), op0)); + } + else + { + op2 = gen_reg_rtx (SImode); + + emit_insn (gen_zero_extendhisi2 (op2, op0)); + } } else if (mode0 == SImode) op2 = op0; @@ -37623,9 +37636,6 @@ rdrand_step: mode0 = DImode; rdseed_step: - op0 = gen_reg_rtx (mode0); - emit_insn (GEN_FCN (icode) (op0)); - arg0 = CALL_EXPR_ARG (exp, 0); op1 = expand_normal (arg0); if (!address_operand (op1, VOIDmode)) @@ -37633,6 +37643,10 @@ rdseed_step: op1 = convert_memory_address (Pmode, op1); op1 = copy_addr_to_reg (op1); } + + op0 = gen_reg_rtx (mode0); + emit_insn (GEN_FCN (icode) (op0)); + emit_move_insn (gen_rtx_MEM (mode0, op1), op0); op2 = gen_reg_rtx (QImode);