From 5e86e5405761d9accc2780c524946e29e00b6608 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hongjiu.lu@intel.com>
Date: Wed, 7 Jul 2010 13:33:04 +0000
Subject: [PATCH] Retry rdrand if the carry flag isn't valid.

gcc/

2010-07-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/44844
	* config/i386/i386.md (rdrand<mode>): Changed to expand to
	retry if the carry flag isn't valid.
	(rdrand<mode>_1): New.

gcc/testsuite/

2010-07-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/44844
	* gcc.target/i386/rdrand-1.c: Scan "jnc".
	* gcc.target/i386/rdrand-2.c: Likewise.
	* gcc.target/i386/rdrand-3.c: Likewise.

From-SVN: r161910
---
 gcc/ChangeLog                            |  7 ++++++
 gcc/config/i386/i386.md                  | 27 +++++++++++++++++++++++-
 gcc/testsuite/ChangeLog                  |  7 ++++++
 gcc/testsuite/gcc.target/i386/rdrand-1.c |  1 +
 gcc/testsuite/gcc.target/i386/rdrand-2.c |  1 +
 gcc/testsuite/gcc.target/i386/rdrand-3.c |  1 +
 6 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3fccd832d2aa..88b7319cb0ac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR target/44844
+	* config/i386/i386.md (rdrand<mode>): Changed to expand to
+	retry if the carry flag isn't valid.
+	(rdrand<mode>_1): New.
+
 2010-07-07  Richard Guenther  <rguenther@suse.de>
 
 	PR middle-end/44790
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 4170711b9185..12e0579e8561 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18494,7 +18494,32 @@
   [(set_attr "type" "other")
    (set_attr "prefix_extra" "2")])
 
-(define_insn "rdrand<mode>"
+(define_expand "rdrand<mode>"
+  [(set (match_operand:SWI248 0 "register_operand" "=r")
+	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
+  "TARGET_RDRND"
+{
+  rtx retry_label, insn, ccc;
+
+  retry_label = gen_label_rtx ();
+
+  emit_label (retry_label);
+
+  /* Generate rdrand.  */
+  emit_insn (gen_rdrand<mode>_1 (operands[0]));
+
+  /* Retry if the carry flag isn't valid.  */
+  ccc = gen_rtx_REG (CCCmode, FLAGS_REG);
+  ccc = gen_rtx_EQ (VOIDmode, ccc, const0_rtx);
+  ccc = gen_rtx_IF_THEN_ELSE (VOIDmode, ccc, pc_rtx,
+			      gen_rtx_LABEL_REF (VOIDmode, retry_label));
+  insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, ccc));
+  JUMP_LABEL (insn) = retry_label;
+
+  DONE;
+})
+
+(define_insn "rdrand<mode>_1"
   [(set (match_operand:SWI248 0 "register_operand" "=r")
 	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))]
   "TARGET_RDRND"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 63a468ba35d3..a031acc4098c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR target/44844
+	* gcc.target/i386/rdrand-1.c: Scan "jnc".
+	* gcc.target/i386/rdrand-2.c: Likewise.
+	* gcc.target/i386/rdrand-3.c: Likewise.
+
 2010-07-07  Jan Hubicka  <jh@suse.cz>
 
 	PR middle-end/44813
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-1.c b/gcc/testsuite/gcc.target/i386/rdrand-1.c
index 9af6bc563d58..4f6b9e177e07 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-1.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-1.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mrdrnd " } */
 /* { dg-final { scan-assembler "rdrand\[ \t]+(%|)ax" } } */
+/* { dg-final { scan-assembler "jnc\[ \t]+" } } */
 
 #include <immintrin.h>
 
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-2.c b/gcc/testsuite/gcc.target/i386/rdrand-2.c
index f35676390c1b..22973834dca3 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-2.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-2.c
@@ -1,6 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mrdrnd " } */
 /* { dg-final { scan-assembler "rdrand\[ \t]+(%|)eax" } } */
+/* { dg-final { scan-assembler "jnc\[ \t]+" } } */
 
 #include <immintrin.h>
 
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-3.c b/gcc/testsuite/gcc.target/i386/rdrand-3.c
index b18e2e8a0485..17c7c6fff245 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-3.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-3.c
@@ -2,6 +2,7 @@
 /* { dg-require-effective-target lp64 } */
 /* { dg-options "-O2 -mrdrnd " } */
 /* { dg-final { scan-assembler "rdrand\[ \t]+(%|)rax" } } */
+/* { dg-final { scan-assembler "jnc\[ \t]+" } } */
 
 #include <immintrin.h>
 
-- 
GitLab