diff mbox series

[committed] d: Allow vectors to be compared for identity (PR108946)

Message ID 20230303001742.4148863-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Allow vectors to be compared for identity (PR108946) | expand

Commit Message

Iain Buclaw March 3, 2023, 12:17 a.m. UTC
Hi,

Vector equality and comparisons are now accepted by the language
implementation, but identity wasn't.  This patch implements it as an
extra integer comparison of the bit-casted bitmask.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, and
committed to mainline.

Regards,
Iain.

---
	PR d/108946

gcc/d/ChangeLog:

	* d-target.cc (Target::isVectorOpSupported): Allow identity ops.
	* expr.cc (ExprVisitor::visit (IdentityExp *)): Handle vector identity
	comparisons.

gcc/testsuite/ChangeLog:

	* gdc.dg/simd2a.d: Update test.
	* gdc.dg/simd2b.d: Likewise.
	* gdc.dg/simd2c.d: Likewise.
	* gdc.dg/simd2d.d: Likewise.
	* gdc.dg/simd2e.d: Likewise.
	* gdc.dg/simd2f.d: Likewise.
	* gdc.dg/simd2g.d: Likewise.
	* gdc.dg/simd2h.d: Likewise.
	* gdc.dg/simd2i.d: Likewise.
	* gdc.dg/simd2j.d: Likewise.
---
 gcc/d/d-target.cc             |  5 -----
 gcc/d/expr.cc                 | 25 +++++++++++++++++++++++++
 gcc/testsuite/gdc.dg/simd2a.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2b.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2c.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2d.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2e.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2f.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2g.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2h.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2i.d |  5 +++--
 gcc/testsuite/gdc.dg/simd2j.d |  5 +++--
 12 files changed, 55 insertions(+), 25 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 5eab5706ead..4c7a212703e 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -323,11 +323,6 @@  Target::isVectorOpSupported (Type *type, EXP op, Type *)
       /* Logical operators must have a result type of bool.  */
       return false;
 
-    case EXP::identity:
-    case EXP::notIdentity:
-      /* Comparison operators must have a result type of bool.  */
-      return false;
-
     default:
       break;
     }
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index c8ec37d7103..4311edcc2d6 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -313,6 +313,31 @@  public:
 
 	this->result_ = build_struct_comparison (code, ts->sym, t1, t2);
       }
+    else if (tb1->ty == TY::Tvector && tb2->ty == TY::Tvector)
+      {
+	/* For vectors, identity is defined as all values being equal.  */
+	tree t1 = build_expr (e->e1);
+	tree t2 = build_expr (e->e2);
+	tree mask = build_boolop (code, t1, t2);
+
+	/* To reinterpret the vector comparison as a boolean expression, bitcast
+	   the bitmask result and generate an additional integer comparison.  */
+	opt_scalar_int_mode mode =
+	  int_mode_for_mode (TYPE_MODE (TREE_TYPE (mask)));
+	gcc_assert (mode.exists ());
+
+	tree type = lang_hooks.types.type_for_mode (mode.require (), 1);
+	if (type == NULL_TREE)
+	  type = make_unsigned_type (GET_MODE_BITSIZE (mode.require ()));
+
+	/* In `t1 is t2', all mask bits must be set for vectors to be equal.
+	   Otherwise any bit set is enough for vectors to be not-equal.  */
+	tree mask_eq = (code == EQ_EXPR)
+	  ? build_all_ones_cst (type) : build_zero_cst (type);
+
+	this->result_ = build_boolop (code, mask_eq,
+				      build_vconvert (type, mask));
+      }
     else
       {
 	/* For operands of other types, identity is defined as being the
diff --git a/gcc/testsuite/gdc.dg/simd2a.d b/gcc/testsuite/gdc.dg/simd2a.d
index 373d5d1e229..d47175fd38b 100644
--- a/gcc/testsuite/gdc.dg/simd2a.d
+++ b/gcc/testsuite/gdc.dg/simd2a.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2a()
 {
     byte16 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2a()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2b.d b/gcc/testsuite/gdc.dg/simd2b.d
index e72da0d9b77..a1b2a10caaf 100644
--- a/gcc/testsuite/gdc.dg/simd2b.d
+++ b/gcc/testsuite/gdc.dg/simd2b.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2b()
 {
     ubyte16 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2b()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2c.d b/gcc/testsuite/gdc.dg/simd2c.d
index dc4954e2194..ca8d1000306 100644
--- a/gcc/testsuite/gdc.dg/simd2c.d
+++ b/gcc/testsuite/gdc.dg/simd2c.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2c()
 {
     short8 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2c()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2d.d b/gcc/testsuite/gdc.dg/simd2d.d
index 2d782bac89c..e928d4be601 100644
--- a/gcc/testsuite/gdc.dg/simd2d.d
+++ b/gcc/testsuite/gdc.dg/simd2d.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2d()
 {
     ushort8 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2d()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2e.d b/gcc/testsuite/gdc.dg/simd2e.d
index b6d4ed6ef3a..a611ea770c9 100644
--- a/gcc/testsuite/gdc.dg/simd2e.d
+++ b/gcc/testsuite/gdc.dg/simd2e.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2e()
 {
     int4 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2e()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2f.d b/gcc/testsuite/gdc.dg/simd2f.d
index df8f13fddd1..1e9d6c264a8 100644
--- a/gcc/testsuite/gdc.dg/simd2f.d
+++ b/gcc/testsuite/gdc.dg/simd2f.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2f()
 {
     uint4 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2f()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2g.d b/gcc/testsuite/gdc.dg/simd2g.d
index 028b25e7d17..7183304b223 100644
--- a/gcc/testsuite/gdc.dg/simd2g.d
+++ b/gcc/testsuite/gdc.dg/simd2g.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2g()
 {
     long2 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2g()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2h.d b/gcc/testsuite/gdc.dg/simd2h.d
index 6c3e91a8814..8c55e0117af 100644
--- a/gcc/testsuite/gdc.dg/simd2h.d
+++ b/gcc/testsuite/gdc.dg/simd2h.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2h()
 {
     ulong2 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2h()
     v1 = v2 ^ v3;
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2i.d b/gcc/testsuite/gdc.dg/simd2i.d
index 2fa7f3ad86e..d9ff6889ea2 100644
--- a/gcc/testsuite/gdc.dg/simd2i.d
+++ b/gcc/testsuite/gdc.dg/simd2i.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2i()
 {
     float4 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2i()
     static assert(!__traits(compiles, v1 ^ v2));
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));
diff --git a/gcc/testsuite/gdc.dg/simd2j.d b/gcc/testsuite/gdc.dg/simd2j.d
index 7c2d12f33cf..a84120f3cce 100644
--- a/gcc/testsuite/gdc.dg/simd2j.d
+++ b/gcc/testsuite/gdc.dg/simd2j.d
@@ -5,6 +5,7 @@  import core.simd;
 void test2j()
 {
     double2 v1, v2 = 1, v3 = 1;
+    bool b1;
     v1 = v2;
     v1 = v2 + v3;
     v1 = v2 - v3;
@@ -16,8 +17,8 @@  void test2j()
     static assert(!__traits(compiles, v1 ^ v2));
     static assert(!__traits(compiles, v1 ~ v2));
     static assert(!__traits(compiles, v1 ^^ v2));
-    static assert(!__traits(compiles, v1 is v2));
-    static assert(!__traits(compiles, v1 !is v2));
+    b1 = v1 is v2;
+    b1 = v1 !is v2;
     static assert( __traits(compiles, v1 == v2));
     static assert( __traits(compiles, v1 != v2));
     static assert( __traits(compiles, v1 < v2));