/usr/include/d/ldc/simd.di is in libphobos2-ldc-dev 1:0.17.1-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | module ldc.simd;
import core.simd;
pure:
nothrow:
@nogc:
@trusted:
private template isFloatingPoint(T)
{
enum isFloatingPoint =
is(T == float) ||
is(T == double) ||
is(T == real);
}
private template isIntegral(T)
{
enum isIntegral =
is(T == byte) ||
is(T == ubyte) ||
is(T == short) ||
is(T == ushort) ||
is(T == int) ||
is(T == uint) ||
is(T == long) ||
is(T == ulong);
}
private template isSigned(T)
{
enum isSigned =
is(T == byte) ||
is(T == short) ||
is(T == int) ||
is(T == long);
}
private template IntOf(T)
if(isIntegral!T || isFloatingPoint!T)
{
enum n = T.sizeof;
static if(n == 1)
alias byte IntOf;
else static if(n == 2)
alias short IntOf;
else static if(n == 4)
alias int IntOf;
else static if(n == 8)
alias long IntOf;
else
static assert(0, "Type not supported");
}
private template BaseType(V)
{
alias typeof(V.array[0]) BaseType;
}
private template numElements(V)
{
enum numElements = V.sizeof / BaseType!(V).sizeof;
}
private template llvmType(T)
{
static if(is(T == float))
enum llvmType = "float";
else static if(is(T == double))
enum llvmType = "double";
else static if(is(T == byte) || is(T == ubyte) || is(T == void))
enum llvmType = "i8";
else static if(is(T == short) || is(T == ushort))
enum llvmType = "i16";
else static if(is(T == int) || is(T == uint))
enum llvmType = "i32";
else static if(is(T == long) || is(T == ulong))
enum llvmType = "i64";
else
static assert(0,
"Can't determine llvm type for D type " ~ T.stringof);
}
private template llvmVecType(V)
{
static if(is(V == void16))
enum llvmVecType = "<16 x i8>";
else static if(is(V == void32))
enum llvmVecType = "<32 x i8>";
else
{
alias BaseType!V T;
enum int n = numElements!V;
enum llvmT = llvmType!T;
enum llvmVecType = "<"~n.stringof~" x "~llvmT~">";
}
}
pragma(LDC_inline_ir)
R inlineIR(string s, R, P...)(P);
/**
This template provides access to
$(LINK2 http://llvm.org/docs/LangRef.html#i_shufflevector,
LLVM's shufflevector instruction).
Example:
---
int4 a = [0, 10, 20, 30];
int4 b = [40, 50, 60, 70];
int4 c = shufflevector!(int4, 0, 2, 4, 6)(a, b);
assert(c.array == [0, 20, 40, 60]);
---
*/
template shufflevector(V, mask...)
if(is(typeof(llvmVecType!V)) && mask.length == numElements!V)
{
enum int n = mask.length;
enum llvmV = llvmVecType!V;
template genMaskIr(string ir, m...)
{
static if(m.length == 0)
enum genMaskIr = ir;
else
{
enum int mfront = m[0];
enum genMaskIr =
genMaskIr!(ir ~ ", i32 " ~ mfront.stringof, m[1 .. $]);
}
}
enum maskIr = genMaskIr!("", mask)[2 .. $];
enum ir = `
%r = shufflevector `~llvmV~` %0, `~llvmV~` %1, <`~n.stringof~` x i32> <`~maskIr~`>
ret `~llvmV~` %r`;
alias inlineIR!(ir, V, V, V) shufflevector;
}
/**
This template provides access to
$(LINK2 http://llvm.org/docs/LangRef.html#i_extractelement,
LLVM's extractelement instruction).
Example:
---
int4 a = [0, 10, 20, 30];
int k = extractelement!(int4, 2)(a);
assert(k == 20);
---
*/
template extractelement(V, int i)
if(is(typeof(llvmVecType!V)) && i < numElements!V)
{
enum llvmT = llvmType!(BaseType!V);
enum llvmV = llvmVecType!V;
enum ir = `
%r = extractelement `~llvmV~` %0, i32 `~i.stringof~`
ret `~llvmT~` %r`;
alias inlineIR!(ir, BaseType!V, V) extractelement;
}
/**
This template provides access to
$(LINK2 http://llvm.org/docs/LangRef.html#i_insertelement,
LLVM's insertelement instruction).
Example:
---
int4 a = [0, 10, 20, 30];
int b = insertelement!(int4, 2)(a, 50);
assert(b.array == [0, 10, 50, 30]);
---
*/
template insertelement(V, int i)
if(is(typeof(llvmVecType!V)) && i < numElements!V)
{
enum llvmT = llvmType!(BaseType!V);
enum llvmV = llvmVecType!V;
enum ir = `
%r = insertelement `~llvmV~` %0, `~llvmT~` %1, i32 `~i.stringof~`
ret `~llvmV~` %r`;
alias inlineIR!(ir, V, V, BaseType!V) insertelement;
}
/**
loadUnaligned: Loads a vector from an unaligned pointer.
Example:
---
int[4] a = [0, 10, 20, 30];
int4 v = loadUnaligned!int4(a.ptr);
assert(v.array == a);
---
*/
template loadUnaligned(V)
if(is(typeof(llvmVecType!V)))
{
alias BaseType!V T;
enum llvmT = llvmType!T;
enum llvmV = llvmVecType!V;
enum ir = `
%p = bitcast `~llvmT~`* %0 to `~llvmV~`*
%r = load `~llvmV~`* %p, align 1
ret `~llvmV~` %r`;
alias inlineIR!(ir, V, T*) loadUnaligned;
}
private enum Cond{ eq, ne, gt, ge }
private template cmpMask(Cond cond)
{
template cmpMask(V)
if(is(IntOf!(BaseType!V)))
{
alias BaseType!V T;
enum llvmT = llvmType!T;
alias IntOf!T Relem;
enum int n = numElements!V;
alias __vector(Relem[n]) R;
enum llvmV = llvmVecType!V;
enum llvmR = llvmVecType!R;
enum sign =
(cond == Cond.eq || cond == Cond.ne) ? "" :
isSigned!T ? "s" : "u";
enum condStr =
cond == Cond.eq ? "eq" :
cond == Cond.ne ? "ne" :
cond == Cond.ge ? "ge" : "gt";
enum op =
isFloatingPoint!T ? "fcmp o"~condStr : "icmp "~sign~condStr;
enum ir = `
%cmp = `~op~` `~llvmV~` %0, %1
%r = sext <`~n.stringof~` x i1> %cmp to `~llvmR~`
ret `~llvmR~` %r`;
alias inlineIR!(ir, R, V, V) cmpMask;
}
}
/**
equalMask, notEqualMask, greaterMask and greaterOrEqualMask perform an
element-wise comparison between two vectors and return a vector with
signed integral elements. The number of elements in the returned vector
and their size is the same as in parameter vectors. If the condition in
the name of the function holds for elements of the parameter vectors at
a given index, all bits of the element of the result at that index are
set to 1, otherwise the element of the result is zero.
Example:
---
float4 a = [1, 3, 5, 7];
float4 b = [2, 3, 4, 5];
int4 c = greaterMask!float4(a, b);
writeln(c.array);
assert(c.array == [0, 0, 0xffff_ffff, 0xffff_ffff]);
---
*/
alias cmpMask!(Cond.eq) equalMask;
alias cmpMask!(Cond.ne) notEqualMask; /// Ditto
alias cmpMask!(Cond.gt) greaterMask; /// Ditto
alias cmpMask!(Cond.ge) greaterOrEqualMask; /// Ditto
|