aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos')
-rw-r--r--libphobos/libdruntime/Makefile.am16
-rw-r--r--libphobos/libdruntime/Makefile.in19
-rw-r--r--libphobos/libdruntime/gcc/simd.d359
3 files changed, 377 insertions, 17 deletions
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index d963aa9..56b332d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -207,14 +207,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \
- gcc/sections/package.d gcc/sections/pecoff.d gcc/unwind/arm.d \
- gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \
- gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \
- rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycat.d rt/cast_.d \
- rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
- rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
- rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
- rt/util/utility.d
+ gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
+ gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+ gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
+ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
+ rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d rt/deh.d \
+ rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d \
+ rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d rt/tlsgc.d \
+ rt/util/typeinfo.d rt/util/utility.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 45e086a..24865fb 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -236,7 +236,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \
gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \
gcc/sections/macho.lo gcc/sections/package.lo \
- gcc/sections/pecoff.lo gcc/unwind/arm.lo \
+ gcc/sections/pecoff.lo gcc/simd.lo gcc/unwind/arm.lo \
gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
@@ -874,14 +874,14 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \
gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \
- gcc/sections/package.d gcc/sections/pecoff.d gcc/unwind/arm.d \
- gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \
- gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \
- rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycat.d rt/cast_.d \
- rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \
- rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
- rt/profilegc.d rt/sections.d rt/tlsgc.d rt/util/typeinfo.d \
- rt/util/utility.d
+ gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \
+ gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
+ gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
+ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
+ rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d rt/deh.d \
+ rt/dmain2.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d \
+ rt/minfo.d rt/monitor_.d rt/profilegc.d rt/sections.d rt/tlsgc.d \
+ rt/util/typeinfo.d rt/util/utility.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/allocator.d core/stdcpp/array.d \
core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d \
@@ -1340,6 +1340,7 @@ gcc/sections/elf.lo: gcc/sections/$(am__dirstamp)
gcc/sections/macho.lo: gcc/sections/$(am__dirstamp)
gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp)
+gcc/simd.lo: gcc/$(am__dirstamp)
gcc/unwind/$(am__dirstamp):
@$(MKDIR_P) gcc/unwind
@: > gcc/unwind/$(am__dirstamp)
diff --git a/libphobos/libdruntime/gcc/simd.d b/libphobos/libdruntime/gcc/simd.d
new file mode 100644
index 0000000..ffca50f
--- /dev/null
+++ b/libphobos/libdruntime/gcc/simd.d
@@ -0,0 +1,359 @@
+// GNU D Compiler SIMD support functions and intrinsics.
+// Copyright (C) 2022 Free Software Foundation, Inc.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.simd;
+
+pure:
+nothrow:
+@safe:
+@nogc:
+pragma(inline, true):
+
+/**
+* Emit prefetch instruction.
+* Params:
+* address = address to be prefetched
+* writeFetch = true for write fetch, false for read fetch
+* locality = 0..3 (0 meaning least local, 3 meaning most local)
+*/
+void prefetch(bool writeFetch, ubyte locality)(const(void)* address)
+{
+ static assert(locality < 4, "0..3 expected for locality");
+ import gcc.builtins : __builtin_prefetch;
+ __builtin_prefetch(address, writeFetch, locality);
+}
+
+/**
+ * Load unaligned vector from address.
+ * This is a compiler intrinsic.
+ * Params:
+ * p = pointer to vector
+ * Returns:
+ * vector
+ */
+V loadUnaligned(V)(const V* p) if (isVectorType!V);
+
+/**
+ * Store vector to unaligned address.
+ * This is a compiler intrinsic.
+ * Params:
+ * p = pointer to vector
+ * value = value to store
+ * Returns:
+ * value
+ */
+V storeUnaligned(V)(V* p, V value) if (isVectorType!V);
+
+/**
+ * Construct a permutation of elements from one or two vectors, returning a
+ * vector of the same type as the input vector(s). The `mask` is an integral
+ * vector with the same width and element count as the output vector.
+ * Params:
+ * op1 = input vector
+ * op2 = input vector
+ * mask = integer vector mask
+ * Returns:
+ * vector with the same type as `op1` and `op2`
+ * Example:
+ * ---
+ * int4 a = [1, 2, 3, 4];
+ * int4 b = [5, 6, 7, 8];
+ * int4 mask1 = [0, 1, 1, 3];
+ * int4 mask2 = [0, 4, 2, 5];
+ * assert(shuffle(a, mask1).array == [1, 2, 2, 4]);
+ * assert(shuffle(a, b, mask2).array == [1, 5, 3, 6]);
+ * ---
+ */
+template shuffle(V0, V1, M)
+{
+ static assert(isVectorType!V0, "first argument must be vector");
+ static assert(isVectorType!V1, "second argument must be vector");
+ static assert(is(BaseType!V0 == BaseType!V1),
+ "first and second argument vectors must have the same element type");
+ static assert(isVectorType!M && is(BaseType!M : long),
+ "last argument must be an integer vector");
+ static assert(numElements!V0 == numElements!M && numElements!V1 == numElements!M,
+ "argument vectors and mask vector should have the same number of elements");
+ static assert(BaseType!V0.sizeof == BaseType!M.sizeof,
+ "argument vectors and mask vector should have the same element type size");
+
+ V0 shuffle(V0 op1, V1 op2, M mask);
+}
+
+/// Ditto
+template shuffle(V, M)
+{
+ static assert(isVectorType!V, "first argument must be a vector");
+ static assert(isVectorType!M && is(BaseType!M : long),
+ "last argument must be an integer vector");
+ static assert(numElements!V == numElements!M,
+ "argument vector and mask vector should have the same number of elements");
+ static assert(BaseType!V.sizeof == BaseType!M.sizeof,
+ "argument vector and mask vector should have the same element type size");
+
+ V shuffle(V op1, M mask)
+ {
+ return shuffle(op1, op1, mask);
+ }
+}
+
+/**
+ * Construct a permutation of elements from two vectors, returning a vector with
+ * the same element type as the input vector(s), and same length as the `mask`.
+ * Params:
+ * op1 = input vector
+ * op2 = input vector
+ * index = elements indices of the vectors that should be extracted and returned
+ * Returns:
+ * vector with the same element type as `op1` and `op2`, but has an element count
+ * equal to the number of indices in `index`.
+ * Example:
+ * ---
+ * int8 a = [1, -2, 3, -4, 5, -6, 7, -8];
+ * int4 b = shufflevector(a, a, 0, 2, 4, 6);
+ * assert(b.array == [1, 3, 5, 7]);
+ * int4 c = [-2, -4, -6, -8];
+ * int d = shufflevector(c, b, 4, 0, 5, 1, 6, 2, 7, 3);
+ * assert(d.array == a.array);
+ * ---
+ */
+template shufflevector(V1, V2, M...)
+{
+ static assert(isVectorType!V1, "first argument must be vector");
+ static assert(isVectorType!V2, "second argument must be vector");
+ static assert(is(BaseType!V1 == BaseType!V2),
+ "first and second argument vectors must have the same element type");
+ static assert(isPowerOf2!(M.length),
+ "number of index arguments must be a power of 2");
+
+ __vector(BaseType!V1[M.length]) shufflevector(V1 op1, V2 op2, M index);
+}
+
+/// Ditto
+template shufflevector(V, index...)
+{
+ // Defined for compatibility with LDC.
+ static assert(isVectorType!V, "first argument must be a vector type");
+ static assert(numElements!V == index.length,
+ "number of index arguments must be the same number of vector elements");
+
+ private template ctfeConstants(m...)
+ {
+ static if (m.length == 0) enum ctfeConstants = 1;
+ else enum ctfeConstants = m[0] | ctfeConstants!(m[1 .. $]);
+ }
+ static assert(__traits(compiles, ctfeConstants!index),
+ "all index arguments must be compile time constants");
+
+ private template validIndexes(m...)
+ {
+ static if (m.length == 0) enum validIndexes = true;
+ else enum validIndexes = (cast(long)m[0] > -1) && validIndexes!(m[1 .. $]);
+ }
+ static assert(validIndexes!index,
+ "all index arguments must be greater than or equal to 0");
+
+ V shufflevector(V op1, V op2)
+ {
+ return shufflevector(op1, op2, index);
+ }
+}
+
+/**
+ * Extracts a single scalar element from a vector at a specified index.
+ * Defined for compatibility with LDC.
+ * Params:
+ * val = vector to extract element from
+ * idx = index indicating the position from which to extract the element
+ * Returns:
+ * scalar of the same type as the element type of val
+ * Example:
+ * ---
+ * int4 a = [0, 10, 20, 30];
+ * int k = extractelement!(int4, 2)(a);
+ * assert(k == 20);
+ * ---
+ */
+BaseType!V extractelement(V, int idx)(V val)
+ if (isVectorType!V && idx < numElements!V)
+{
+ return val[idx];
+}
+
+/**
+ * Inserts a scalar element into a vector at a specified index.
+ * Defined for compatibility with LDC.
+ * Params:
+ * val = vector to assign element to
+ * elt = scalar whose type is the element type of val
+ * idx = index indicating the position from which to extract the element
+ * Returns:
+ * vector of the same type as val
+ * Example:
+ * ---
+ * int4 a = [0, 10, 20, 30];
+ * int4 b = insertelement!(int4, 2)(a, 50);
+ * assert(b.array == [0, 10, 50, 30]);
+ * ---
+ */
+V insertelement(V, int idx)(V val, BaseType!V elt)
+ if (isVectorType!V && idx < numElements!V)
+{
+ val[idx] = elt;
+ return val;
+}
+
+/**
+ * Convert a vector from one integral or floating vector type to another.
+ * The result is an integral or floating vector that has had every element
+ * cast to the element type of the return type.
+ * Params:
+ * from = input vector
+ * Returns:
+ * converted vector
+ * Example:
+ * ---
+ * int4 a = [1, -2, 3, -4];
+ * float4 b = [1.5, -2.5, 3, 7];
+ * assert(convertvector!float4(a).array == [1, -2, 3, -4]);
+ * assert(convertvector!double4(a).array == [1, -2, 3, -4]);
+ * assert(convertvector!double4(b).array == [1.5, -2.5, 3, 7]);
+ * assert(convertvector!int4(b).array == [1, -2, 3, 7]);
+ * ---
+ */
+
+template convertvector(V, T)
+{
+ static assert(isVectorType!V && (is(BaseType!V : long) || is(BaseType!V : real)),
+ "first argument must be an integer or floating vector type");
+ static assert(isVectorType!T && (is(BaseType!T : long) || is(BaseType!T : real)),
+ "second argument must be an integer or floating vector");
+ static assert(numElements!V == numElements!T,
+ "first and second argument vectors should have the same number of elements");
+
+ V convertvector(T);
+}
+
+/**
+ * Construct a conditional merge of elements from two vectors, returning a
+ * vector of the same type as the input vector(s). The `mask` is an integral
+ * vector with the same width and element count as the output vector.
+ * Params:
+ * op1 = input vector
+ * op2 = input vector
+ * mask = integer vector mask
+ * Returns:
+ * vector with the same type as `op1` and `op2`
+ * Example:
+ * ---
+ * int4 a = [1, 2, 3, 4];
+ * int4 b = [5, 6, 7, 8];
+ * int4 mask1 = [0, 1, 1, 3];
+ * int4 mask2 = [0, 4, 2, 5];
+ * assert(shuffle(a, mask1).array == [1, 2, 2, 4]);
+ * assert(shuffle(a, b, mask2).array == [1, 5, 3, 6]);
+ * ---
+ */
+template blendvector(V0, V1, M)
+{
+ static assert(isVectorType!V0, "first argument must be vector");
+ static assert(isVectorType!V1, "second argument must be vector");
+ static assert(is(BaseType!V0 == BaseType!V1),
+ "first and second argument vectors must have the same element type");
+ static assert(isVectorType!M && is(BaseType!M : long),
+ "last argument must be an integer vector");
+ static assert(numElements!V0 == numElements!M && numElements!V1 == numElements!M,
+ "argument vectors and mask vector should have the same number of elements");
+ static assert(BaseType!V0.sizeof == BaseType!M.sizeof,
+ "argument vectors and mask vector should have the same element type size");
+
+ V0 blendvector(V0 op1, V1 op2, M mask);
+}
+
+/**
+ * Perform an element-wise comparison between two vectors, producing `0` when
+ * the comparison is false and `-1` (all bits are set to 1) otherwise.
+ * Params:
+ * op1 = input vector
+ * op2 = input vector
+ * Returns:
+ * vector of the same width and number of elements as the comparison
+ * operands with a signed integral element type
+ * Example:
+ * ---
+ * float4 a = [1, 3, 5, 7];
+ * float4 b = [2, 3, 4, 5];
+ * int4 c = greaterMask!float4(a, b);
+ * assert(c.array == [0, 0, -1, -1]);
+ * ---
+ */
+V equalMask(V)(V op1, V op2) if (isVectorType!V);
+/// Ditto
+V notEqualMask(V)(V op1, V op2) if (isVectorType!V);
+/// Ditto
+V greaterMask(V)(V op1, V op2) if (isVectorType!V);
+/// Ditto
+V greaterOrEqualMask(V)(V op1, V op2) if (isVectorType!V);
+
+/**
+ * Perform an element-wise logical comparison between two vectors, producing
+ * `0` when the comparison is false and `-1` (all bits are set to 1) otherwise.
+ * Params:
+ * op1 = input vector
+ * op2 = input vector
+ * Returns:
+ * vector of the same width and number of elements as the comparison
+ * operands with a signed integral element type
+ */
+V notMask(V)(V op1) if (isVectorType!V)
+{
+ return equalMask(op1, 0);
+}
+
+/// Ditto
+V andAndMask(V)(V op1, V op2) if (isVectorType!V)
+{
+ return notEqualMask(op1, 0) & notEqualMask(op2, 0);
+}
+
+/// Ditto
+V orOrMask(V)(V op1, V op2) if (isVectorType!V)
+{
+ return notEqualMask(op1, 0) | notEqualMask(op2, 0);
+}
+
+// Private helper templates.
+private:
+
+enum bool isVectorType(T) = is(T : __vector(V[N]), V, size_t N);
+
+template BaseType(V)
+{
+ alias typeof(V.array[0]) BaseType;
+}
+
+template numElements(V)
+{
+ enum numElements = V.sizeof / BaseType!(V).sizeof;
+}
+
+enum bool isPowerOf2(int Y) = Y && (Y & -Y) == Y;