From a5a4c20a5c922f2faa66b9326b336b5d7eb5065e Mon Sep 17 00:00:00 2001
From: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
Date: Mon, 25 Mar 2013 15:20:44 +0000
Subject: [PATCH] arm.md (f_sels, f_seld): New types.

gcc/
2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

	* config/arm/arm.md (f_sels, f_seld): New types.
	(*cmov<mode>): New pattern.
	* config/arm/predicates.md (arm_vsel_comparison_operator): New
	predicate.

gcc/testsuite/
2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

	* gcc.target/arm/vseleqdf.c: New test.
	* gcc.target/arm/vseleqsf.c: Likewise.
	* gcc.target/arm/vselgedf.c: Likewise.
	* gcc.target/arm/vselgesf.c: Likewise.
	* gcc.target/arm/vselgtdf.c: Likewise.
	* gcc.target/arm/vselgtsf.c: Likewise.
	* gcc.target/arm/vselledf.c: Likewise.
	* gcc.target/arm/vsellesf.c: Likewise.
	* gcc.target/arm/vselltdf.c: Likewise.
	* gcc.target/arm/vselltsf.c: Likewise.
	* gcc.target/arm/vselnedf.c: Likewise.
	* gcc.target/arm/vselnesf.c: Likewise.
	* gcc.target/arm/vselvcdf.c: Likewise.
	* gcc.target/arm/vselvcsf.c: Likewise.
	* gcc.target/arm/vselvsdf.c: Likewise.
	* gcc.target/arm/vselvssf.c: Likewise.

From-SVN: r197052
---
 gcc/ChangeLog                           |  7 +++++
 gcc/config/arm/arm.md                   | 35 +++++++++++++++++++++++++
 gcc/config/arm/predicates.md            | 12 +++++++++
 gcc/testsuite/ChangeLog                 | 19 ++++++++++++++
 gcc/testsuite/gcc.target/arm/vseleqdf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vseleqsf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselgedf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselgesf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselgtdf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselgtsf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselledf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vsellesf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselltdf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselltsf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselnedf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselnesf.c | 13 +++++++++
 gcc/testsuite/gcc.target/arm/vselvcdf.c | 12 +++++++++
 gcc/testsuite/gcc.target/arm/vselvcsf.c | 12 +++++++++
 gcc/testsuite/gcc.target/arm/vselvsdf.c | 12 +++++++++
 gcc/testsuite/gcc.target/arm/vselvssf.c | 12 +++++++++
 20 files changed, 277 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/arm/vseleqdf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vseleqsf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselgedf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselgesf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselgtdf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselgtsf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselledf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vsellesf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselltdf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselltsf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselnedf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselnesf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselvcdf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselvcsf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselvsdf.c
 create mode 100644 gcc/testsuite/gcc.target/arm/vselvssf.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f48ead2329f7..fe328374d97f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+	* config/arm/arm.md (f_sels, f_seld): New types.
+	(*cmov<mode>): New pattern.
+	* config/arm/predicates.md (arm_vsel_comparison_operator): New
+	predicate.
+
 2013-03-25  Kai Tietz  <ktietz@redhat.com>
 
 	* config/i386/xm-mingw32.h (__USE_MINGW_ANSI_STDIO): Enable
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index d48bc8c01239..8895080cb032 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -288,6 +288,8 @@
   f_2_r,\
   r_2_f,\
   f_cvt,\
+  f_sels,\
+  f_seld,\
   branch,\
   call,\
   load_byte,\
@@ -8102,6 +8104,39 @@
   }"
 )
 
+(define_insn "*cmov<mode>"
+    [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
+	(if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
+			  [(match_operand 2 "cc_register" "") (const_int 0)])
+			  (match_operand:SDF 3 "s_register_operand"
+			                      "<F_constraint>")
+			  (match_operand:SDF 4 "s_register_operand"
+			                      "<F_constraint>")))]
+  "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
+  "*
+  {
+    enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
+    switch (code)
+      {
+      case ARM_GE:
+      case ARM_GT:
+      case ARM_EQ:
+      case ARM_VS:
+        return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
+      case ARM_LT:
+      case ARM_LE:
+      case ARM_NE:
+      case ARM_VC:
+        return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
+      default:
+        gcc_unreachable ();
+      }
+    return \"\";
+  }"
+  [(set_attr "conds" "use")
+   (set_attr "type" "f_sel<vfp_type>")]
+)
+
 (define_insn "*movsicc_insn"
   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
 	(if_then_else:SI
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index f493d8284a67..f301df2fcdb9 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -270,6 +270,18 @@
 (define_special_predicate "lt_ge_comparison_operator"
   (match_code "lt,ge"))
 
+;; The vsel instruction only accepts the ARM condition codes listed below.
+(define_special_predicate "arm_vsel_comparison_operator"
+  (and (match_operand 0 "expandable_comparison_operator")
+       (match_test "maybe_get_arm_condition_code (op) == ARM_GE
+                    || maybe_get_arm_condition_code (op) == ARM_GT
+                    || maybe_get_arm_condition_code (op) == ARM_EQ
+                    || maybe_get_arm_condition_code (op) == ARM_VS
+                    || maybe_get_arm_condition_code (op) == ARM_LT
+                    || maybe_get_arm_condition_code (op) == ARM_LE
+                    || maybe_get_arm_condition_code (op) == ARM_NE
+                    || maybe_get_arm_condition_code (op) == ARM_VC")))
+
 (define_special_predicate "noov_comparison_operator"
   (match_code "lt,ge,eq,ne"))
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f6addcf762d3..b8073921b28a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,22 @@
+2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+	* gcc.target/arm/vseleqdf.c: New test.
+	* gcc.target/arm/vseleqsf.c: Likewise.
+	* gcc.target/arm/vselgedf.c: Likewise.
+	* gcc.target/arm/vselgesf.c: Likewise.
+	* gcc.target/arm/vselgtdf.c: Likewise.
+	* gcc.target/arm/vselgtsf.c: Likewise.
+	* gcc.target/arm/vselledf.c: Likewise.
+	* gcc.target/arm/vsellesf.c: Likewise.
+	* gcc.target/arm/vselltdf.c: Likewise.
+	* gcc.target/arm/vselltsf.c: Likewise.
+	* gcc.target/arm/vselnedf.c: Likewise.
+	* gcc.target/arm/vselnesf.c: Likewise.
+	* gcc.target/arm/vselvcdf.c: Likewise.
+	* gcc.target/arm/vselvcsf.c: Likewise.
+	* gcc.target/arm/vselvsdf.c: Likewise.
+	* gcc.target/arm/vselvssf.c: Likewise.
+
 2013-03-25  Kyrylo Tkachov  <kyrylo.tkachov at arm.com>
 
 	* gcc.target/aarch64/atomic-comp-swap-release-acquire.c: Move test
diff --git a/gcc/testsuite/gcc.target/arm/vseleqdf.c b/gcc/testsuite/gcc.target/arm/vseleqdf.c
new file mode 100644
index 000000000000..86e147b1f28d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vseleqdf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i == 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vseleq.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vseleqsf.c b/gcc/testsuite/gcc.target/arm/vseleqsf.c
new file mode 100644
index 000000000000..120f44bf0133
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vseleqsf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i == 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vseleq.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselgedf.c b/gcc/testsuite/gcc.target/arm/vselgedf.c
new file mode 100644
index 000000000000..cea08d12ea4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselgedf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i >= 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselge.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselgesf.c b/gcc/testsuite/gcc.target/arm/vselgesf.c
new file mode 100644
index 000000000000..86f2a04907fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselgesf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i >= 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselge.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselgtdf.c b/gcc/testsuite/gcc.target/arm/vselgtdf.c
new file mode 100644
index 000000000000..2c4a6ba906d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselgtdf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i > 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselgt.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselgtsf.c b/gcc/testsuite/gcc.target/arm/vselgtsf.c
new file mode 100644
index 000000000000..388e74c11144
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselgtsf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i > 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselgt.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselledf.c b/gcc/testsuite/gcc.target/arm/vselledf.c
new file mode 100644
index 000000000000..088dc04b2749
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselledf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i <= 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselgt.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vsellesf.c b/gcc/testsuite/gcc.target/arm/vsellesf.c
new file mode 100644
index 000000000000..d0afdbcec512
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vsellesf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i <= 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselgt.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselltdf.c b/gcc/testsuite/gcc.target/arm/vselltdf.c
new file mode 100644
index 000000000000..fbcb9ea2b33b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselltdf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i < 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselge.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselltsf.c b/gcc/testsuite/gcc.target/arm/vselltsf.c
new file mode 100644
index 000000000000..959dab7fa32f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselltsf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i < 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselge.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselnedf.c b/gcc/testsuite/gcc.target/arm/vselnedf.c
new file mode 100644
index 000000000000..cf67f29f3f8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselnedf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  volatile int i = 0;
+  return i != 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vseleq.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselnesf.c b/gcc/testsuite/gcc.target/arm/vselnesf.c
new file mode 100644
index 000000000000..2e16423b5741
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselnesf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  volatile int i = 0;
+  return i != 0 ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vseleq.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselvcdf.c b/gcc/testsuite/gcc.target/arm/vselvcdf.c
new file mode 100644
index 000000000000..7f30270c5022
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselvcdf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  return !__builtin_isunordered (x, y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselvs.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselvcsf.c b/gcc/testsuite/gcc.target/arm/vselvcsf.c
new file mode 100644
index 000000000000..1bb736925f9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselvcsf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  return !__builtin_isunordered (x, y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselvs.f32\ts\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselvsdf.c b/gcc/testsuite/gcc.target/arm/vselvsdf.c
new file mode 100644
index 000000000000..83ad5bf69510
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselvsdf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+double
+foo (double x, double y)
+{
+  return __builtin_isunordered (x, y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselvs.f64\td\[0-9\]+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/vselvssf.c b/gcc/testsuite/gcc.target/arm/vselvssf.c
new file mode 100644
index 000000000000..7d762899cb38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/vselvssf.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_vfp_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_v8_vfp } */
+
+float
+foo (float x, float y)
+{
+  return __builtin_isunordered (x, y) ? x : y;
+}
+
+/* { dg-final { scan-assembler-times "vselvs.f32\ts\[0-9\]+" 1 } } */
-- 
GitLab