diff mbox series

[committed] d: Add support for vector comparison operators

Message ID 20221105191021.3081198-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Add support for vector comparison operators | expand

Commit Message

Iain Buclaw Nov. 5, 2022, 7:10 p.m. UTC
Hi,

The front-end added semantic support to permit comparing two vector
expressions.  This removes the restriction in the code generator, as
well as the intrisics that previously exposed the same operation.

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

Regards,
Iain.

---
gcc/d/ChangeLog:

	* d-target.cc (Target::isVectorOpSupported): Remove cases for
	comparison operators.
	* intrinsics.cc (maybe_set_intrinsic): Remove cases for vector
	comparison intrinsics.
	(maybe_warn_intrinsic_mismatch): Likewise.
	(expand_intrinsic_vec_cond): Remove.
	(maybe_expand_intrinsic): Remove cases for vector comparison
	intrinsics.
	* intrinsics.def (INTRINSIC_EQUALMASK): Remove.
	(INTRINSIC_NOTEQUALMASK): Remove.
	(INTRINSIC_GREATERMASK): Remove.
	(INTRINSIC_GREATEREQUALMASK): Remove.

libphobos/ChangeLog:

	* libdruntime/gcc/simd.d (equalMask): Implement using generics.
	(notEqualMask): Likewise.
	(greaterMask): Likewise.
	(greaterOrEqualMask): Likewise.
	(notMask): Likewise.
	(andAndMask): Likewise.
	(orOrMask): Likewise.

gcc/testsuite/ChangeLog:

	* gdc.dg/Wbuiltin_declaration_mismatch2.d: Remove comparision tests.
	* gdc.dg/simd2a.d: Update comparison tests.
	* 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                             |  6 --
 gcc/d/intrinsics.cc                           | 65 -------------------
 gcc/d/intrinsics.def                          |  8 ---
 .../gdc.dg/Wbuiltin_declaration_mismatch2.d   | 40 ------------
 gcc/testsuite/gdc.dg/simd2a.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2b.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2c.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2d.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2e.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2f.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2g.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2h.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2i.d                 | 12 ++--
 gcc/testsuite/gdc.dg/simd2j.d                 | 12 ++--
 libphobos/libdruntime/gcc/simd.d              | 26 ++++++--
 15 files changed, 79 insertions(+), 186 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d4350e593e4..d3244673f62 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -323,12 +323,6 @@  Target::isVectorOpSupported (Type *type, EXP op, Type *)
       /* Logical operators must have a result type of bool.  */
       return false;
 
-    case EXP::lessOrEqual:
-    case EXP::lessThan:
-    case EXP::greaterOrEqual:
-    case EXP::greaterThan:
-    case EXP::equal:
-    case EXP::notEqual:
     case EXP::identity:
     case EXP::notIdentity:
       /* Comparison operators must have a result type of bool.  */
diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index 75d43186909..6d9f74a6d7a 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -170,10 +170,6 @@  maybe_set_intrinsic (FuncDeclaration *decl)
 	    case INTRINSIC_SHUFFLEVECTOR:
 	    case INTRINSIC_CONVERTVECTOR:
 	    case INTRINSIC_BLENDVECTOR:
-	    case INTRINSIC_EQUALMASK:
-	    case INTRINSIC_NOTEQUALMASK:
-	    case INTRINSIC_GREATERMASK:
-	    case INTRINSIC_GREATEREQUALMASK:
 	    case INTRINSIC_VLOAD8:
 	    case INTRINSIC_VLOAD16:
 	    case INTRINSIC_VLOAD32:
@@ -487,29 +483,6 @@  maybe_warn_intrinsic_mismatch (tree function, tree callexp)
 
 	return false;
       }
-
-    case INTRINSIC_EQUALMASK:
-    case INTRINSIC_NOTEQUALMASK:
-    case INTRINSIC_GREATERMASK:
-    case INTRINSIC_GREATEREQUALMASK:
-      {
-	/* Expects the signature:
-	   vector(T) equalMask(vector(T), vector(T));
-	   vector(T) notEqualMask(vector(T), vector(T));
-	   vector(T) greaterMask(vector(T), vector(T));
-	   vector(T) greateOrEqualMask(vector(T), vector(T));  */
-	gcc_assert (call_expr_nargs (callexp) == 2);
-
-	tree vec0 = TREE_TYPE (CALL_EXPR_ARG (callexp, 0));
-	tree vec1 = TREE_TYPE (CALL_EXPR_ARG (callexp, 1));
-	if (!VECTOR_TYPE_P (TREE_TYPE (callexp))
-	    || !VECTOR_TYPE_P (vec0)
-	    || !VECTOR_TYPE_P (vec1)
-	    || TYPE_MAIN_VARIANT (vec0) != TYPE_MAIN_VARIANT (vec1))
-	  return warn_mismatched_return_type (callexp, "__vector(T)");
-
-	return false;
-      }
     }
 
   /* Generic mismatch warning if it hasn't already been handled.  */
@@ -1072,32 +1045,6 @@  expand_volatile_store (tree callexp)
   return modify_expr (result, value);
 }
 
-/* Expand a front-end intrinsic call to a vector comparison intrinsic, which is
-   either a call to equalMask(), notEqualMask(), greaterMask(), or
-   greaterOrEqualMask().  These intrinsics take two arguments, the signature to
-   which can be either:
-
-	vector(T) equalMask(vector(T) vec0, vector(T) vec1);
-	vector(T) notEqualMask(vector(T) vec0, vector(T) vec1);
-	vector(T) greaterMask(vector(T) vec0, vector(T) vec1);
-	vector(T) greaterOrEqualMask(vector(T) vec0, vector(T) vec1);
-
-   This performs an element-wise comparison between two vectors VEC0 and VEC1,
-   returning a vector with signed integral elements.  */
-
-static tree
-expand_intrinsic_vec_cond (tree_code code, tree callexp)
-{
-  tree vec0 = CALL_EXPR_ARG (callexp, 0);
-  tree vec1 = CALL_EXPR_ARG (callexp, 1);
-  tree type = TREE_TYPE (callexp);
-
-  tree cmp = fold_build2_loc (EXPR_LOCATION (callexp), code,
-			      truth_type_for (type), vec0, vec1);
-  return fold_build3_loc (EXPR_LOCATION (callexp), VEC_COND_EXPR, type, cmp,
-			  build_minus_one_cst (type), build_zero_cst (type));
-}
-
 /* Expand a front-end instrinsic call to convertvector().  This takes one
    argument, the signature to which is:
 
@@ -1488,18 +1435,6 @@  maybe_expand_intrinsic (tree callexp)
     case INTRINSIC_BLENDVECTOR:
       return expand_intrinsic_vec_blend (callexp);
 
-    case INTRINSIC_EQUALMASK:
-      return expand_intrinsic_vec_cond (EQ_EXPR, callexp);
-
-    case INTRINSIC_NOTEQUALMASK:
-      return expand_intrinsic_vec_cond (NE_EXPR, callexp);
-
-    case INTRINSIC_GREATERMASK:
-      return expand_intrinsic_vec_cond (GT_EXPR, callexp);
-
-    case INTRINSIC_GREATEREQUALMASK:
-      return expand_intrinsic_vec_cond (GE_EXPR, callexp);
-
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def
index b8d1ec50d57..96f9b934697 100644
--- a/gcc/d/intrinsics.def
+++ b/gcc/d/intrinsics.def
@@ -266,14 +266,6 @@  DEF_D_BUILTIN (INTRINSIC_CONVERTVECTOR, BUILT_IN_NONE, "convertvector",
 	       "gcc.simd", "F@1TZ@1V")
 DEF_D_BUILTIN (INTRINSIC_BLENDVECTOR, BUILT_IN_NONE, "blendvector", "gcc.simd",
 	       "F@2V0@2V1@1MZ@2V0")
-DEF_D_BUILTIN (INTRINSIC_EQUALMASK, BUILT_IN_NONE, "equalMask", "gcc.simd",
-	       "F@1V@1VZ@1V")
-DEF_D_BUILTIN (INTRINSIC_NOTEQUALMASK, BUILT_IN_NONE, "notEqualMask",
-	       "gcc.simd", "F@1V@1VZ@1V")
-DEF_D_BUILTIN (INTRINSIC_GREATERMASK, BUILT_IN_NONE, "greaterMask", "gcc.simd",
-	       "F@1V@1VZ@1V")
-DEF_D_BUILTIN (INTRINSIC_GREATEREQUALMASK, BUILT_IN_NONE,
-	       "greaterOrEqualMask", "gcc.simd", "F@1V@1VZ@1V")
 
 #undef DEF_D_BUILTIN
 #undef DEF_CTFE_BUILTIN
diff --git a/gcc/testsuite/gdc.dg/Wbuiltin_declaration_mismatch2.d b/gcc/testsuite/gdc.dg/Wbuiltin_declaration_mismatch2.d
index 9e90c15deb6..7b83fffae58 100644
--- a/gcc/testsuite/gdc.dg/Wbuiltin_declaration_mismatch2.d
+++ b/gcc/testsuite/gdc.dg/Wbuiltin_declaration_mismatch2.d
@@ -191,41 +191,6 @@  void test_blendvector()
     blendvector!(byte16, byte16, byte16)(0, 0, 0);
 }
 
-void test_comparison()
-{
-    equalMask!int(0, 0); // { dg-warning "mismatch in return type" }
-    equalMask!double(0, 0); // { dg-warning "mismatch in return type" }
-    equalMask!int4(0, 0);
-    equalMask!short8(0, 0);
-    equalMask!float4(0, 0);
-    equalMask!byte16(0, 0);
-    equalMask!fake4(f, f); // { dg-warning "mismatch in return type" }
-
-    notEqualMask!int(0, 0); // { dg-warning "mismatch in return type" }
-    notEqualMask!double(0, 0); // { dg-warning "mismatch in return type" }
-    notEqualMask!int4(0, 0);
-    notEqualMask!short8(0, 0);
-    notEqualMask!float4(0, 0);
-    notEqualMask!byte16(0, 0);
-    notEqualMask!fake4(f, f); // { dg-warning "mismatch in return type" }
-
-    greaterMask!int(0, 0); // { dg-warning "mismatch in return type" }
-    greaterMask!double(0, 0); // { dg-warning "mismatch in return type" }
-    greaterMask!int4(0, 0);
-    greaterMask!short8(0, 0);
-    greaterMask!float4(0, 0);
-    greaterMask!byte16(0, 0);
-    greaterMask!fake4(f, f); // { dg-warning "mismatch in return type" }
-
-    greaterOrEqualMask!int(0, 0); // { dg-warning "mismatch in return type" }
-    greaterOrEqualMask!double(0, 0); // { dg-warning "mismatch in return type" }
-    greaterOrEqualMask!int4(0, 0);
-    greaterOrEqualMask!short8(0, 0);
-    greaterOrEqualMask!float4(0, 0);
-    greaterOrEqualMask!byte16(0, 0);
-    greaterOrEqualMask!fake4(f, f); // { dg-warning "mismatch in return type" }
-}
-
 // The following declarations of the simd intrinsics are without any guards
 // to verify `d/intrinsics.cc` is doing checks to prevent invalid lowerings.
 V loadUnaligned(V)(const V*);
@@ -243,8 +208,3 @@  __vector(E!V1[M.length]) shufflevector(V1, V2, M...)(V1, V2, M) if (isV!V1 && is
 
 V convertvector(V, T)(T);
 V0 blendvector(V0, V1, M)(V0, V1, M);
-
-V equalMask(V)(V, V);
-V notEqualMask(V)(V, V);
-V greaterMask(V)(V, V);
-V greaterOrEqualMask(V)(V, V);
diff --git a/gcc/testsuite/gdc.dg/simd2a.d b/gcc/testsuite/gdc.dg/simd2a.d
index 0fb391cc057..d64f704683f 100644
--- a/gcc/testsuite/gdc.dg/simd2a.d
+++ b/gcc/testsuite/gdc.dg/simd2a.d
@@ -18,12 +18,12 @@  void test2a()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2b.d b/gcc/testsuite/gdc.dg/simd2b.d
index 41a4eb3c34a..71abd78b301 100644
--- a/gcc/testsuite/gdc.dg/simd2b.d
+++ b/gcc/testsuite/gdc.dg/simd2b.d
@@ -18,12 +18,12 @@  void test2b()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2c.d b/gcc/testsuite/gdc.dg/simd2c.d
index a9957094998..4806b48029f 100644
--- a/gcc/testsuite/gdc.dg/simd2c.d
+++ b/gcc/testsuite/gdc.dg/simd2c.d
@@ -18,12 +18,12 @@  void test2c()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2d.d b/gcc/testsuite/gdc.dg/simd2d.d
index d578734368e..ce447e180e8 100644
--- a/gcc/testsuite/gdc.dg/simd2d.d
+++ b/gcc/testsuite/gdc.dg/simd2d.d
@@ -18,12 +18,12 @@  void test2d()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2e.d b/gcc/testsuite/gdc.dg/simd2e.d
index d33574ad005..464d1a51a5e 100644
--- a/gcc/testsuite/gdc.dg/simd2e.d
+++ b/gcc/testsuite/gdc.dg/simd2e.d
@@ -18,12 +18,12 @@  void test2e()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2f.d b/gcc/testsuite/gdc.dg/simd2f.d
index 5845249e693..d7e67fc4112 100644
--- a/gcc/testsuite/gdc.dg/simd2f.d
+++ b/gcc/testsuite/gdc.dg/simd2f.d
@@ -18,12 +18,12 @@  void test2f()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2g.d b/gcc/testsuite/gdc.dg/simd2g.d
index ce438f2c3db..3d158691abb 100644
--- a/gcc/testsuite/gdc.dg/simd2g.d
+++ b/gcc/testsuite/gdc.dg/simd2g.d
@@ -18,12 +18,12 @@  void test2g()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2h.d b/gcc/testsuite/gdc.dg/simd2h.d
index c631c760ffb..849b6adc626 100644
--- a/gcc/testsuite/gdc.dg/simd2h.d
+++ b/gcc/testsuite/gdc.dg/simd2h.d
@@ -18,12 +18,12 @@  void test2h()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     v1 = v2 << 1;
     v1 = v2 >> 1;
     v1 = v2 >>> 1;
diff --git a/gcc/testsuite/gdc.dg/simd2i.d b/gcc/testsuite/gdc.dg/simd2i.d
index 6946c79987a..03130b7a663 100644
--- a/gcc/testsuite/gdc.dg/simd2i.d
+++ b/gcc/testsuite/gdc.dg/simd2i.d
@@ -18,12 +18,12 @@  void test2i()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     static assert(!__traits(compiles, v1 << 1));
     static assert(!__traits(compiles, v1 >> 1));
     static assert(!__traits(compiles, v1 >>> 1));
diff --git a/gcc/testsuite/gdc.dg/simd2j.d b/gcc/testsuite/gdc.dg/simd2j.d
index ecfdbf3bbc1..f86a448f138 100644
--- a/gcc/testsuite/gdc.dg/simd2j.d
+++ b/gcc/testsuite/gdc.dg/simd2j.d
@@ -18,12 +18,12 @@  void test2j()
     static assert(!__traits(compiles, v1 ^^ v2));
     static assert(!__traits(compiles, v1 is v2));
     static assert(!__traits(compiles, v1 !is v2));
-    static assert(!__traits(compiles, v1 == v2));
-    static assert(!__traits(compiles, v1 != v2));
-    static assert(!__traits(compiles, v1 < v2));
-    static assert(!__traits(compiles, v1 > v2));
-    static assert(!__traits(compiles, v1 <= v2));
-    static assert(!__traits(compiles, v1 >= v2));
+    v1 = v1 == v2;
+    v1 = v1 != v2;
+    v1 = v1 < v2;
+    v1 = v1 > v2;
+    v1 = v1 <= v2;
+    v1 = v1 >= v2;
     static assert(!__traits(compiles, v1 << 1));
     static assert(!__traits(compiles, v1 >> 1));
     static assert(!__traits(compiles, v1 >>> 1));
diff --git a/libphobos/libdruntime/gcc/simd.d b/libphobos/libdruntime/gcc/simd.d
index ffca50f2a5e..ebd94bf93e2 100644
--- a/libphobos/libdruntime/gcc/simd.d
+++ b/libphobos/libdruntime/gcc/simd.d
@@ -306,13 +306,25 @@  template blendvector(V0, V1, M)
  * assert(c.array == [0, 0, -1, -1]);
  * ---
  */
-V equalMask(V)(V op1, V op2) if (isVectorType!V);
+V equalMask(V)(V op1, V op2) if (isVectorType!V)
+{
+    return op1 == op2;
+}
 /// Ditto
-V notEqualMask(V)(V op1, V op2) if (isVectorType!V);
+V notEqualMask(V)(V op1, V op2) if (isVectorType!V)
+{
+    return op1 != op2;
+}
 /// Ditto
-V greaterMask(V)(V op1, V op2) if (isVectorType!V);
+V greaterMask(V)(V op1, V op2) if (isVectorType!V)
+{
+    return op1 > op2;
+}
 /// Ditto
-V greaterOrEqualMask(V)(V op1, V op2) if (isVectorType!V);
+V greaterOrEqualMask(V)(V op1, V op2) if (isVectorType!V)
+{
+    return op1 >= op2;
+}
 
 /**
  * Perform an element-wise logical comparison between two vectors, producing
@@ -326,19 +338,19 @@  V greaterOrEqualMask(V)(V op1, V op2) if (isVectorType!V);
  */
 V notMask(V)(V op1) if (isVectorType!V)
 {
-    return equalMask(op1, 0);
+    return op1 == 0;
 }
 
 /// Ditto
 V andAndMask(V)(V op1, V op2) if (isVectorType!V)
 {
-    return notEqualMask(op1, 0) & notEqualMask(op2, 0);
+    return (op1 != 0) & (op2 != 0);
 }
 
 /// Ditto
 V orOrMask(V)(V op1, V op2) if (isVectorType!V)
 {
-    return notEqualMask(op1, 0) | notEqualMask(op2, 0);
+    return (op1 != 0) | (op2 != 0);
 }
 
 // Private helper templates.