blob: 37402242f5c1881d47694cdbbea5c662559b3bed [file] [log] [blame]
Antonio Maioranoe6ab4702019-11-29 11:26:30 -05001#include "EmulatedReactor.hpp"
2
3#include <cmath>
4#include <functional>
5#include <utility>
6
Nicolas Capens157ba262019-12-10 17:49:14 -05007namespace rr {
8namespace {
9
10template <typename T>
11struct UnderlyingType
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050012{
Nicolas Capens157ba262019-12-10 17:49:14 -050013 using Type = typename decltype(rr::Extract(std::declval<RValue<T>>(), 0))::rvalue_underlying_type;
14};
15
16template <typename T>
17using UnderlyingTypeT = typename UnderlyingType<T>::Type;
18
19// Call single arg function on a vector type
20template <typename Func, typename T>
21RValue<T> call4(Func func, const RValue<T>& x)
22{
23 T result;
24 result = Insert(result, Call(func, Extract(x, 0)), 0);
25 result = Insert(result, Call(func, Extract(x, 1)), 1);
26 result = Insert(result, Call(func, Extract(x, 2)), 2);
27 result = Insert(result, Call(func, Extract(x, 3)), 3);
28 return result;
29}
30
31// Call two arg function on a vector type
32template <typename Func, typename T>
33RValue<T> call4(Func func, const RValue<T>& x, const RValue<T>& y)
34{
35 T result;
36 result = Insert(result, Call(func, Extract(x, 0), Extract(y, 0)), 0);
37 result = Insert(result, Call(func, Extract(x, 1), Extract(y, 1)), 1);
38 result = Insert(result, Call(func, Extract(x, 2), Extract(y, 2)), 2);
39 result = Insert(result, Call(func, Extract(x, 3), Extract(y, 3)), 3);
40 return result;
41}
42
43template <typename T, typename EL = UnderlyingTypeT<T>>
44void gather(T& out, RValue<Pointer<EL>> base, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment, bool zeroMaskedLanes)
45{
46 constexpr bool atomic = false;
47 constexpr std::memory_order order = std::memory_order_relaxed;
48
49 Pointer<Byte> baseBytePtr = base;
50
51 out = T(0);
Nicolas Capens81bc9d92019-12-16 15:05:57 -050052 for(int i = 0; i < 4; i++)
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050053 {
Nicolas Capens157ba262019-12-10 17:49:14 -050054 If(Extract(mask, i) != 0)
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050055 {
Nicolas Capens157ba262019-12-10 17:49:14 -050056 auto offset = Extract(offsets, i);
57 auto el = Load(Pointer<EL>(&baseBytePtr[offset]), alignment, atomic, order);
58 out = Insert(out, el, i);
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050059 }
Nicolas Capens157ba262019-12-10 17:49:14 -050060 Else If(zeroMaskedLanes)
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050061 {
Nicolas Capens157ba262019-12-10 17:49:14 -050062 out = Insert(out, EL(0), i);
Antonio Maioranoe6ab4702019-11-29 11:26:30 -050063 }
64 }
65}
Nicolas Capens157ba262019-12-10 17:49:14 -050066
67template <typename T, typename EL = UnderlyingTypeT<T>>
68void scatter(RValue<Pointer<EL>> base, RValue<T> val, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment)
69{
70 constexpr bool atomic = false;
71 constexpr std::memory_order order = std::memory_order_relaxed;
72
73 Pointer<Byte> baseBytePtr = base;
74
Nicolas Capens81bc9d92019-12-16 15:05:57 -050075 for(int i = 0; i < 4; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -050076 {
77 If(Extract(mask, i) != 0)
78 {
79 auto offset = Extract(offsets, i);
80 Store(Extract(val, i), Pointer<EL>(&baseBytePtr[offset]), alignment, atomic, order);
81 }
82 }
83}
84
85} // anonymous namespace
86
87namespace emulated {
88
89RValue<Float4> Gather(RValue<Pointer<Float>> base, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment, bool zeroMaskedLanes /* = false */)
90{
91 Float4 result{};
92 gather(result, base, offsets, mask, alignment, zeroMaskedLanes);
93 return result;
94}
95
96RValue<Int4> Gather(RValue<Pointer<Int>> base, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment, bool zeroMaskedLanes /* = false */)
97{
98 Int4 result{};
99 gather(result, base, offsets, mask, alignment, zeroMaskedLanes);
100 return result;
101}
102
103void Scatter(RValue<Pointer<Float>> base, RValue<Float4> val, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment)
104{
105 scatter(base, val, offsets, mask, alignment);
106}
107
108void Scatter(RValue<Pointer<Int>> base, RValue<Int4> val, RValue<Int4> offsets, RValue<Int4> mask, unsigned int alignment)
109{
110 scatter<Int4>(base, val, offsets, mask, alignment);
111}
112
113RValue<Float> Exp2(RValue<Float> x)
114{
115 return Call(exp2f, x);
116}
117
118RValue<Float> Log2(RValue<Float> x)
119{
120 return Call(log2f, x);
121}
122
123RValue<Float4> Sin(RValue<Float4> x)
124{
125 return call4(sinf, x);
126}
127
128RValue<Float4> Cos(RValue<Float4> x)
129{
130 return call4(cosf, x);
131}
132
133RValue<Float4> Tan(RValue<Float4> x)
134{
135 return call4(tanf, x);
136}
137
138RValue<Float4> Asin(RValue<Float4> x)
139{
140 return call4(asinf, x);
141}
142
143RValue<Float4> Acos(RValue<Float4> x)
144{
145 return call4(acosf, x);
146}
147
148RValue<Float4> Atan(RValue<Float4> x)
149{
150 return call4(atanf, x);
151}
152
153RValue<Float4> Sinh(RValue<Float4> x)
154{
155 return call4(sinhf, x);
156}
157
158RValue<Float4> Cosh(RValue<Float4> x)
159{
160 return call4(coshf, x);
161}
162
163RValue<Float4> Tanh(RValue<Float4> x)
164{
165 return call4(tanhf, x);
166}
167
168RValue<Float4> Asinh(RValue<Float4> x)
169{
170 return call4(asinhf, x);
171}
172
173RValue<Float4> Acosh(RValue<Float4> x)
174{
175 return call4(acoshf, x);
176}
177
178RValue<Float4> Atanh(RValue<Float4> x)
179{
180 return call4(atanhf, x);
181}
182
183RValue<Float4> Atan2(RValue<Float4> x, RValue<Float4> y)
184{
185 return call4(atan2f, x, y);
186}
187
188RValue<Float4> Pow(RValue<Float4> x, RValue<Float4> y)
189{
190 return call4(powf, x, y);
191}
192
193RValue<Float4> Exp(RValue<Float4> x)
194{
195 return call4(expf, x);
196}
197
198RValue<Float4> Log(RValue<Float4> x)
199{
200 return call4(logf, x);
201}
202
203RValue<Float4> Exp2(RValue<Float4> x)
204{
205 return call4(exp2f, x);
206}
207
208RValue<Float4> Log2(RValue<Float4> x)
209{
210 return call4(log2f, x);
211}
212
213} // namespace emulated
214} // namespace rr