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);

Reply via email to