Patchwork [i386] : Fix __builtin_ia32_rdrand*_step expansion

login
register
mail settings
Submitter Uros Bizjak
Date May 19, 2011, 7:32 p.m.
Message ID <BANLkTimhW_fN_Xa6o0UaPCzCSSjiVwt5jw@mail.gmail.com>
Download mbox | patch
Permalink /patch/96449/
State New
Headers show

Comments

Uros Bizjak - May 19, 2011, 7:32 p.m.
Hello!

Attached patch fixes ICE with -m32 -march=i386 -mrdrand on freebsd
[1]. The problem was that __builtin_ia32_rdrand*_step expands to a
sequence that includes conditional move, so we should set
TARGET_CMOVE. Additionally, the patch fixes expansion with void
return:

void
foo (unsigned short *x)
{
  _rdrand16_step (x);
}

And finally, move to the memory was moved closer to the producer, to
eventually generate few live registers.

2011-05-19  Uros Bizjak  <ubizjak@gmail.com>

	* config/i386/i386.c (option_override_internal): Enable TARGET_CMOVE
	when TARGET_RDRND is active.
	(ix86_expand_builtin) <case IX86_BUILTIN_RDRAND*_STEP>: Generate
	dummy SImode target register when target is NULL.

Patch was bootstrapped and tested on x86_64-pc-linux-gnu, will be
committed to SVN mainline and 4.6.

[1] http://gcc.gnu.org/ml/gcc-testresults/2011-05/msg01884.html

Patch

Index: i386.c
===================================================================
--- i386.c	(revision 173914)
+++ i386.c	(working copy)
@@ -4091,8 +4091,9 @@  ix86_option_override_internal (bool main
     }
 
   /* For sane SSE instruction set generation we need fcomi instruction.
-     It is safe to enable all CMOVE instructions.  */
-  if (TARGET_SSE)
+     It is safe to enable all CMOVE instructions.  Also, intrinsic expands
+     to a sequence that includes conditional move. */
+  if (TARGET_SSE || TARGET_RDRND)
     TARGET_CMOVE = 1;
 
   /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix.  */
@@ -27613,6 +27614,12 @@  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))
+	op1 = copy_addr_to_reg (op1);
+      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
+
       op1 = gen_reg_rtx (SImode);
       emit_move_insn (op1, CONST1_RTX (SImode));
 
@@ -27627,17 +27634,13 @@  rdrand_step:
       else
 	op2 = gen_rtx_SUBREG (SImode, op0, 0);
 
+      if (target == 0)
+	target = gen_reg_rtx (SImode);
+
       pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
 			 const0_rtx);
-      emit_insn (gen_rtx_SET (VOIDmode, op1,
+      emit_insn (gen_rtx_SET (VOIDmode, target,
 			      gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
-      emit_move_insn (target, op1);
-
-      arg0 = CALL_EXPR_ARG (exp, 0);
-      op1 = expand_normal (arg0);
-      if (!address_operand (op1, VOIDmode))
-	op1 = copy_addr_to_reg (op1);
-      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
       return target;
 
     default: