blob: ee02cdb2001f0e72936f1b21bddfcf4207063c03 [file] [log] [blame]
Nicolas Capens3b0ad202022-06-02 15:02:31 -04001// Copyright 2022 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "SIMD.hpp"
16
Nicolas Capens01e41802022-06-29 23:12:57 -040017#include "Assert.hpp"
Nicolas Capens44f94692022-06-20 23:15:46 -040018#include "Debug.hpp"
Nicolas Capens01e41802022-06-29 23:12:57 -040019#include "Print.hpp"
Nicolas Capens44f94692022-06-20 23:15:46 -040020
21#include <cmath>
22
23namespace rr {
24
25SIMD::Int::Int()
Nicolas Capens7e960682022-06-30 15:53:27 -040026 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040027{
28}
29
30SIMD::Int::Int(RValue<SIMD::Float> cast)
Nicolas Capens7e960682022-06-30 15:53:27 -040031 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040032{
33 Value *xyzw = Nucleus::createFPToSI(cast.value(), SIMD::Int::type());
34
35 storeValue(xyzw);
36}
37
38SIMD::Int::Int(int broadcast)
Nicolas Capens7e960682022-06-30 15:53:27 -040039 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040040{
41 std::vector<int64_t> constantVector = { broadcast };
42 storeValue(Nucleus::createConstantVector(constantVector, type()));
43}
Nicolas Capens3b0ad202022-06-02 15:02:31 -040044
Nicolas Capensd1116fa2022-06-29 10:39:18 -040045SIMD::Int::Int(int x, int y, int z, int w)
46 : XYZW(this)
47{
48 std::vector<int64_t> constantVector = { x, y, z, w };
49 storeValue(Nucleus::createConstantVector(constantVector, type()));
50}
51
52SIMD::Int::Int(std::vector<int> v)
53 : XYZW(this)
54{
55 std::vector<int64_t> constantVector;
56 for(int i : v) { constantVector.push_back(i); }
57 storeValue(Nucleus::createConstantVector(constantVector, type()));
58}
59
Nicolas Capensbe30aa62022-08-10 11:34:51 -040060SIMD::Int::Int(std::function<int(int)> LaneValueProducer)
61 : XYZW(this)
62{
63 std::vector<int64_t> constantVector;
64 for(int i = 0; i < SIMD::Width; i++) { constantVector.push_back(LaneValueProducer(i)); }
65 storeValue(Nucleus::createConstantVector(constantVector, type()));
66}
67
Nicolas Capens3b0ad202022-06-02 15:02:31 -040068SIMD::Int::Int(RValue<SIMD::Int> rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040069 : XYZW(this)
Nicolas Capens3b0ad202022-06-02 15:02:31 -040070{
71 store(rhs);
72}
73
Nicolas Capens44f94692022-06-20 23:15:46 -040074SIMD::Int::Int(const SIMD::Int &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040075 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040076{
77 store(rhs.load());
78}
79
Nicolas Capens3b0ad202022-06-02 15:02:31 -040080SIMD::Int::Int(const Reference<SIMD::Int> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040081 : XYZW(this)
Nicolas Capens3b0ad202022-06-02 15:02:31 -040082{
Nicolas Capens44f94692022-06-20 23:15:46 -040083 store(rhs.load());
84}
85
86SIMD::Int::Int(RValue<SIMD::UInt> rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040087 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040088{
89 storeValue(rhs.value());
90}
91
92SIMD::Int::Int(const SIMD::UInt &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040093 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -040094{
Nicolas Capens3b0ad202022-06-02 15:02:31 -040095 storeValue(rhs.loadValue());
96}
97
Nicolas Capens44f94692022-06-20 23:15:46 -040098SIMD::Int::Int(const Reference<SIMD::UInt> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -040099 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400100{
101 storeValue(rhs.loadValue());
102}
103
104SIMD::Int::Int(const scalar::Int &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400105 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400106{
107 *this = RValue<scalar::Int>(rhs.loadValue());
108}
109
110SIMD::Int::Int(const Reference<scalar::Int> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400111 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400112{
113 *this = RValue<scalar::Int>(rhs.loadValue());
114}
115
116RValue<SIMD::Int> SIMD::Int::operator=(int x)
117{
118 return *this = SIMD::Int(x);
119}
120
121RValue<SIMD::Int> SIMD::Int::operator=(RValue<SIMD::Int> rhs)
122{
123 return store(rhs);
124}
125
126RValue<SIMD::Int> SIMD::Int::operator=(const SIMD::Int &rhs)
127{
128 return store(rhs.load());
129}
130
131RValue<SIMD::Int> SIMD::Int::operator=(const Reference<SIMD::Int> &rhs)
132{
133 return store(rhs.load());
134}
135
Nicolas Capens3b0ad202022-06-02 15:02:31 -0400136RValue<SIMD::Int> operator+(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
137{
138 return RValue<SIMD::Int>(Nucleus::createAdd(lhs.value(), rhs.value()));
139}
140
Nicolas Capens44f94692022-06-20 23:15:46 -0400141RValue<SIMD::Int> operator-(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
142{
143 return RValue<SIMD::Int>(Nucleus::createSub(lhs.value(), rhs.value()));
144}
145
146RValue<SIMD::Int> operator*(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
147{
148 return RValue<SIMD::Int>(Nucleus::createMul(lhs.value(), rhs.value()));
149}
150
151RValue<SIMD::Int> operator/(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
152{
153 return RValue<SIMD::Int>(Nucleus::createSDiv(lhs.value(), rhs.value()));
154}
155
156RValue<SIMD::Int> operator%(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
157{
158 return RValue<SIMD::Int>(Nucleus::createSRem(lhs.value(), rhs.value()));
159}
160
161RValue<SIMD::Int> operator&(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
162{
163 return RValue<SIMD::Int>(Nucleus::createAnd(lhs.value(), rhs.value()));
164}
165
166RValue<SIMD::Int> operator|(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
167{
168 return RValue<SIMD::Int>(Nucleus::createOr(lhs.value(), rhs.value()));
169}
170
171RValue<SIMD::Int> operator^(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
172{
173 return RValue<SIMD::Int>(Nucleus::createXor(lhs.value(), rhs.value()));
174}
175
176RValue<SIMD::Int> operator<<(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
177{
178 return RValue<SIMD::Int>(Nucleus::createShl(lhs.value(), rhs.value()));
179}
180
181RValue<SIMD::Int> operator>>(RValue<SIMD::Int> lhs, RValue<SIMD::Int> rhs)
182{
183 return RValue<SIMD::Int>(Nucleus::createAShr(lhs.value(), rhs.value()));
184}
185
186RValue<SIMD::Int> operator+=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
187{
188 return lhs = lhs + rhs;
189}
190
191RValue<SIMD::Int> operator-=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
192{
193 return lhs = lhs - rhs;
194}
195
196RValue<SIMD::Int> operator*=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
197{
198 return lhs = lhs * rhs;
199}
200
201// RValue<SIMD::Int> operator/=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
202// {
203// return lhs = lhs / rhs;
204// }
205
206// RValue<SIMD::Int> operator%=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
207// {
208// return lhs = lhs % rhs;
209// }
210
211RValue<SIMD::Int> operator&=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
212{
213 return lhs = lhs & rhs;
214}
215
216RValue<SIMD::Int> operator|=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
217{
218 return lhs = lhs | rhs;
219}
220
221RValue<SIMD::Int> operator^=(SIMD::Int &lhs, RValue<SIMD::Int> rhs)
222{
223 return lhs = lhs ^ rhs;
224}
225
226RValue<SIMD::Int> operator<<=(SIMD::Int &lhs, unsigned char rhs)
227{
228 return lhs = lhs << rhs;
229}
230
231RValue<SIMD::Int> operator>>=(SIMD::Int &lhs, unsigned char rhs)
232{
233 return lhs = lhs >> rhs;
234}
235
236RValue<SIMD::Int> operator+(RValue<SIMD::Int> val)
237{
238 return val;
239}
240
241RValue<SIMD::Int> operator-(RValue<SIMD::Int> val)
242{
243 return RValue<SIMD::Int>(Nucleus::createNeg(val.value()));
244}
245
246RValue<SIMD::Int> operator~(RValue<SIMD::Int> val)
247{
248 return RValue<SIMD::Int>(Nucleus::createNot(val.value()));
249}
250
251RValue<scalar::Int> Extract(RValue<SIMD::Int> x, int i)
252{
253 return RValue<scalar::Int>(Nucleus::createExtractElement(x.value(), scalar::Int::type(), i));
254}
255
256RValue<SIMD::Int> Insert(RValue<SIMD::Int> x, RValue<scalar::Int> element, int i)
257{
258 return RValue<SIMD::Int>(Nucleus::createInsertElement(x.value(), element.value(), i));
259}
260
261SIMD::UInt::UInt()
Nicolas Capens7e960682022-06-30 15:53:27 -0400262 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400263{
264}
265
266SIMD::UInt::UInt(int broadcast)
Nicolas Capens7e960682022-06-30 15:53:27 -0400267 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400268{
269 std::vector<int64_t> constantVector = { broadcast };
270 storeValue(Nucleus::createConstantVector(constantVector, type()));
271}
272
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400273SIMD::UInt::UInt(int x, int y, int z, int w)
274 : XYZW(this)
275{
276 std::vector<int64_t> constantVector = { x, y, z, w };
277 storeValue(Nucleus::createConstantVector(constantVector, type()));
278}
279
280SIMD::UInt::UInt(std::vector<int> v)
281 : XYZW(this)
282{
283 std::vector<int64_t> constantVector;
284 for(int i : v) { constantVector.push_back(i); }
285 storeValue(Nucleus::createConstantVector(constantVector, type()));
286}
287
Nicolas Capensbe30aa62022-08-10 11:34:51 -0400288SIMD::UInt::UInt(std::function<int(int)> LaneValueProducer)
289 : XYZW(this)
290{
291 std::vector<int64_t> constantVector;
292 for(int i = 0; i < SIMD::Width; i++) { constantVector.push_back(LaneValueProducer(i)); }
293 storeValue(Nucleus::createConstantVector(constantVector, type()));
294}
295
Nicolas Capens44f94692022-06-20 23:15:46 -0400296SIMD::UInt::UInt(RValue<SIMD::UInt> rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400297 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400298{
299 store(rhs);
300}
301
302SIMD::UInt::UInt(const SIMD::UInt &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400303 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400304{
305 store(rhs.load());
306}
307
308SIMD::UInt::UInt(const Reference<SIMD::UInt> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400309 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400310{
311 store(rhs.load());
312}
313
314SIMD::UInt::UInt(RValue<SIMD::Int> rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400315 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400316{
317 storeValue(rhs.value());
318}
319
320SIMD::UInt::UInt(const SIMD::Int &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400321 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400322{
323 storeValue(rhs.loadValue());
324}
325
326SIMD::UInt::UInt(const Reference<SIMD::Int> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400327 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400328{
329 storeValue(rhs.loadValue());
330}
331
332SIMD::UInt::UInt(const scalar::UInt &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400333 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400334{
335 *this = RValue<scalar::UInt>(rhs.loadValue());
336}
337
338SIMD::UInt::UInt(const Reference<scalar::UInt> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400339 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400340{
341 *this = RValue<scalar::UInt>(rhs.loadValue());
342}
343
344RValue<SIMD::UInt> SIMD::UInt::operator=(RValue<SIMD::UInt> rhs)
345{
346 return store(rhs);
347}
348
349RValue<SIMD::UInt> SIMD::UInt::operator=(const SIMD::UInt &rhs)
350{
351 return store(rhs.load());
352}
353
354RValue<SIMD::UInt> SIMD::UInt::operator=(const Reference<SIMD::UInt> &rhs)
355{
356 return store(rhs.load());
357}
358
359RValue<SIMD::UInt> operator+(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
360{
361 return RValue<SIMD::UInt>(Nucleus::createAdd(lhs.value(), rhs.value()));
362}
363
364RValue<SIMD::UInt> operator-(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
365{
366 return RValue<SIMD::UInt>(Nucleus::createSub(lhs.value(), rhs.value()));
367}
368
369RValue<SIMD::UInt> operator*(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
370{
371 return RValue<SIMD::UInt>(Nucleus::createMul(lhs.value(), rhs.value()));
372}
373
374RValue<SIMD::UInt> operator/(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
375{
376 return RValue<SIMD::UInt>(Nucleus::createUDiv(lhs.value(), rhs.value()));
377}
378
379RValue<SIMD::UInt> operator%(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
380{
381 return RValue<SIMD::UInt>(Nucleus::createURem(lhs.value(), rhs.value()));
382}
383
384RValue<SIMD::UInt> operator&(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
385{
386 return RValue<SIMD::UInt>(Nucleus::createAnd(lhs.value(), rhs.value()));
387}
388
389RValue<SIMD::UInt> operator|(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
390{
391 return RValue<SIMD::UInt>(Nucleus::createOr(lhs.value(), rhs.value()));
392}
393
394RValue<SIMD::UInt> operator^(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
395{
396 return RValue<SIMD::UInt>(Nucleus::createXor(lhs.value(), rhs.value()));
397}
398
399RValue<SIMD::UInt> operator<<(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
400{
401 return RValue<SIMD::UInt>(Nucleus::createShl(lhs.value(), rhs.value()));
402}
403
404RValue<SIMD::UInt> operator>>(RValue<SIMD::UInt> lhs, RValue<SIMD::UInt> rhs)
405{
406 return RValue<SIMD::UInt>(Nucleus::createLShr(lhs.value(), rhs.value()));
407}
408
409RValue<SIMD::UInt> operator+=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
410{
411 return lhs = lhs + rhs;
412}
413
414RValue<SIMD::UInt> operator-=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
415{
416 return lhs = lhs - rhs;
417}
418
419RValue<SIMD::UInt> operator*=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
420{
421 return lhs = lhs * rhs;
422}
423
424// RValue<SIMD::UInt> operator/=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
425// {
426// return lhs = lhs / rhs;
427// }
428
429// RValue<SIMD::UInt> operator%=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
430// {
431// return lhs = lhs % rhs;
432// }
433
434RValue<SIMD::UInt> operator&=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
435{
436 return lhs = lhs & rhs;
437}
438
439RValue<SIMD::UInt> operator|=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
440{
441 return lhs = lhs | rhs;
442}
443
444RValue<SIMD::UInt> operator^=(SIMD::UInt &lhs, RValue<SIMD::UInt> rhs)
445{
446 return lhs = lhs ^ rhs;
447}
448
449RValue<SIMD::UInt> operator<<=(SIMD::UInt &lhs, unsigned char rhs)
450{
451 return lhs = lhs << rhs;
452}
453
454RValue<SIMD::UInt> operator>>=(SIMD::UInt &lhs, unsigned char rhs)
455{
456 return lhs = lhs >> rhs;
457}
458
459RValue<SIMD::UInt> operator+(RValue<SIMD::UInt> val)
460{
461 return val;
462}
463
464RValue<SIMD::UInt> operator-(RValue<SIMD::UInt> val)
465{
466 return RValue<SIMD::UInt>(Nucleus::createNeg(val.value()));
467}
468
469RValue<SIMD::UInt> operator~(RValue<SIMD::UInt> val)
470{
471 return RValue<SIMD::UInt>(Nucleus::createNot(val.value()));
472}
473
474RValue<scalar::UInt> Extract(RValue<SIMD::UInt> x, int i)
475{
476 return RValue<scalar::UInt>(Nucleus::createExtractElement(x.value(), scalar::Int::type(), i));
477}
478
479RValue<SIMD::UInt> Insert(RValue<SIMD::UInt> x, RValue<scalar::UInt> element, int i)
480{
481 return RValue<SIMD::UInt>(Nucleus::createInsertElement(x.value(), element.value(), i));
482}
483
484SIMD::Float::Float(RValue<SIMD::Int> cast)
Nicolas Capens7e960682022-06-30 15:53:27 -0400485 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400486{
487 Value *xyzw = Nucleus::createSIToFP(cast.value(), SIMD::Float::type());
488
489 storeValue(xyzw);
490}
491
492SIMD::Float::Float(RValue<SIMD::UInt> cast)
Nicolas Capens7e960682022-06-30 15:53:27 -0400493 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400494{
495 RValue<SIMD::Float> result = SIMD::Float(SIMD::Int(cast & SIMD::UInt(0x7FFFFFFF))) +
496 As<SIMD::Float>((As<SIMD::Int>(cast) >> 31) & As<SIMD::Int>(SIMD::Float(0x80000000u)));
497
498 storeValue(result.value());
499}
500
501SIMD::Float::Float()
Nicolas Capens7e960682022-06-30 15:53:27 -0400502 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400503{
504}
505
506SIMD::Float::Float(float broadcast)
Nicolas Capens7e960682022-06-30 15:53:27 -0400507 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400508{
509 // See rr::Float(float) constructor for the rationale behind this assert.
510 ASSERT(std::isfinite(broadcast));
511
512 std::vector<double> constantVector = { broadcast };
513 storeValue(Nucleus::createConstantVector(constantVector, type()));
514}
515
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400516SIMD::Float::Float(float x, float y, float z, float w)
517 : XYZW(this)
518{
519 std::vector<double> constantVector = { x, y, z, w };
520 storeValue(Nucleus::createConstantVector(constantVector, type()));
521}
522
523SIMD::Float::Float(std::vector<float> v)
524 : XYZW(this)
525{
526 std::vector<double> constantVector;
527 for(int f : v) { constantVector.push_back(f); }
528 storeValue(Nucleus::createConstantVector(constantVector, type()));
529}
530
Nicolas Capensbe30aa62022-08-10 11:34:51 -0400531SIMD::Float::Float(std::function<float(int)> LaneValueProducer)
532 : XYZW(this)
533{
534 std::vector<double> constantVector;
535 for(int i = 0; i < SIMD::Width; i++) { constantVector.push_back(LaneValueProducer(i)); }
536 storeValue(Nucleus::createConstantVector(constantVector, type()));
537}
538
Nicolas Capens44f94692022-06-20 23:15:46 -0400539SIMD::Float SIMD::Float::infinity()
540{
541 SIMD::Float result;
542
543 constexpr double inf = std::numeric_limits<double>::infinity();
544 std::vector<double> constantVector = { inf };
545 result.storeValue(Nucleus::createConstantVector(constantVector, type()));
546
547 return result;
548}
549
550SIMD::Float::Float(RValue<SIMD::Float> rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400551 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400552{
553 store(rhs);
554}
555
556SIMD::Float::Float(const SIMD::Float &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400557 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400558{
559 store(rhs.load());
560}
561
562SIMD::Float::Float(const Reference<SIMD::Float> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400563 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400564{
565 store(rhs.load());
566}
567
568SIMD::Float::Float(const scalar::Float &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400569 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400570{
571 *this = RValue<scalar::Float>(rhs.loadValue());
572}
573
574SIMD::Float::Float(const Reference<scalar::Float> &rhs)
Nicolas Capens7e960682022-06-30 15:53:27 -0400575 : XYZW(this)
Nicolas Capens44f94692022-06-20 23:15:46 -0400576{
577 *this = RValue<scalar::Float>(rhs.loadValue());
578}
579
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400580SIMD::Float::Float(RValue<packed::Float4> rhs)
581 : XYZW(this)
582{
583 ASSERT(SIMD::Width == 4);
584 *this = Insert128(*this, rhs, 0);
585}
586
587RValue<SIMD::Float> SIMD::Float::operator=(RValue<packed::Float4> rhs)
588{
589 return *this = SIMD::Float(rhs);
590}
591
Nicolas Capens44f94692022-06-20 23:15:46 -0400592RValue<SIMD::Float> SIMD::Float::operator=(float x)
593{
594 return *this = SIMD::Float(x);
595}
596
597RValue<SIMD::Float> SIMD::Float::operator=(RValue<SIMD::Float> rhs)
598{
599 return store(rhs);
600}
601
602RValue<SIMD::Float> SIMD::Float::operator=(const SIMD::Float &rhs)
603{
604 return store(rhs.load());
605}
606
607RValue<SIMD::Float> SIMD::Float::operator=(const Reference<SIMD::Float> &rhs)
608{
609 return store(rhs.load());
610}
611
612RValue<SIMD::Float> SIMD::Float::operator=(RValue<scalar::Float> rhs)
613{
614 return *this = SIMD::Float(rhs);
615}
616
617RValue<SIMD::Float> SIMD::Float::operator=(const scalar::Float &rhs)
618{
619 return *this = SIMD::Float(rhs);
620}
621
622RValue<SIMD::Float> SIMD::Float::operator=(const Reference<scalar::Float> &rhs)
623{
624 return *this = SIMD::Float(rhs);
625}
626
627RValue<SIMD::Float> operator+(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
628{
629 return RValue<SIMD::Float>(Nucleus::createFAdd(lhs.value(), rhs.value()));
630}
631
632RValue<SIMD::Float> operator-(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
633{
634 return RValue<SIMD::Float>(Nucleus::createFSub(lhs.value(), rhs.value()));
635}
636
637RValue<SIMD::Float> operator*(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
638{
639 return RValue<SIMD::Float>(Nucleus::createFMul(lhs.value(), rhs.value()));
640}
641
642RValue<SIMD::Float> operator/(RValue<SIMD::Float> lhs, RValue<SIMD::Float> rhs)
643{
644 return RValue<SIMD::Float>(Nucleus::createFDiv(lhs.value(), rhs.value()));
645}
646
647RValue<SIMD::Float> operator+=(SIMD::Float &lhs, RValue<SIMD::Float> rhs)
648{
649 return lhs = lhs + rhs;
650}
651
652RValue<SIMD::Float> operator-=(SIMD::Float &lhs, RValue<SIMD::Float> rhs)
653{
654 return lhs = lhs - rhs;
655}
656
657RValue<SIMD::Float> operator*=(SIMD::Float &lhs, RValue<SIMD::Float> rhs)
658{
659 return lhs = lhs * rhs;
660}
661
662RValue<SIMD::Float> operator/=(SIMD::Float &lhs, RValue<SIMD::Float> rhs)
663{
664 return lhs = lhs / rhs;
665}
666
667RValue<SIMD::Float> operator%=(SIMD::Float &lhs, RValue<SIMD::Float> rhs)
668{
669 return lhs = lhs % rhs;
670}
671
672RValue<SIMD::Float> operator+(RValue<SIMD::Float> val)
673{
674 return val;
675}
676
677RValue<SIMD::Float> operator-(RValue<SIMD::Float> val)
678{
679 return RValue<SIMD::Float>(Nucleus::createFNeg(val.value()));
680}
681
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400682RValue<SIMD::Float> Rcp(RValue<SIMD::Float> x, bool relaxedPrecision, bool exactAtPow2)
683{
684 ASSERT(SIMD::Width == 4);
685 return SIMD::Float(Rcp(Extract128(x, 0), relaxedPrecision, exactAtPow2));
686}
687
688RValue<SIMD::Float> RcpSqrt(RValue<SIMD::Float> x, bool relaxedPrecision)
689{
690 ASSERT(SIMD::Width == 4);
691 return SIMD::Float(RcpSqrt(Extract128(x, 0), relaxedPrecision));
692}
693
Nicolas Capens44f94692022-06-20 23:15:46 -0400694RValue<SIMD::Float> Insert(RValue<SIMD::Float> x, RValue<scalar::Float> element, int i)
695{
696 return RValue<SIMD::Float>(Nucleus::createInsertElement(x.value(), element.value(), i));
697}
698
699RValue<scalar::Float> Extract(RValue<SIMD::Float> x, int i)
700{
701 return RValue<scalar::Float>(Nucleus::createExtractElement(x.value(), scalar::Float::type(), i));
702}
703
704RValue<SIMD::Int> IsInf(RValue<SIMD::Float> x)
705{
706 return CmpEQ(As<SIMD::Int>(x) & SIMD::Int(0x7FFFFFFF), SIMD::Int(0x7F800000));
707}
708
709RValue<SIMD::Int> IsNan(RValue<SIMD::Float> x)
710{
711 return ~CmpEQ(x, x);
712}
713
714RValue<SIMD::Float> Sin(RValue<SIMD::Float> x)
715{
716 return ScalarizeCall(sinf, x);
717}
718
719RValue<SIMD::Float> Cos(RValue<SIMD::Float> x)
720{
721 return ScalarizeCall(cosf, x);
722}
723
724RValue<SIMD::Float> Tan(RValue<SIMD::Float> x)
725{
726 return ScalarizeCall(tanf, x);
727}
728
729RValue<SIMD::Float> Asin(RValue<SIMD::Float> x)
730{
731 return ScalarizeCall(asinf, x);
732}
733
734RValue<SIMD::Float> Acos(RValue<SIMD::Float> x)
735{
736 return ScalarizeCall(acosf, x);
737}
738
739RValue<SIMD::Float> Atan(RValue<SIMD::Float> x)
740{
741 return ScalarizeCall(atanf, x);
742}
743
744RValue<SIMD::Float> Sinh(RValue<SIMD::Float> x)
745{
746 return ScalarizeCall(sinhf, x);
747}
748
749RValue<SIMD::Float> Cosh(RValue<SIMD::Float> x)
750{
751 return ScalarizeCall(coshf, x);
752}
753
754RValue<SIMD::Float> Tanh(RValue<SIMD::Float> x)
755{
756 return ScalarizeCall(tanhf, x);
757}
758
759RValue<SIMD::Float> Asinh(RValue<SIMD::Float> x)
760{
761 return ScalarizeCall(asinhf, x);
762}
763
764RValue<SIMD::Float> Acosh(RValue<SIMD::Float> x)
765{
766 return ScalarizeCall(acoshf, x);
767}
768
769RValue<SIMD::Float> Atanh(RValue<SIMD::Float> x)
770{
771 return ScalarizeCall(atanhf, x);
772}
773
774RValue<SIMD::Float> Atan2(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
775{
776 return ScalarizeCall(atan2f, x, y);
777}
778
779RValue<SIMD::Float> Pow(RValue<SIMD::Float> x, RValue<SIMD::Float> y)
780{
781 return ScalarizeCall(powf, x, y);
782}
783
784RValue<SIMD::Float> Exp(RValue<SIMD::Float> x)
785{
786 return ScalarizeCall(expf, x);
787}
788
789RValue<SIMD::Float> Log(RValue<SIMD::Float> x)
790{
791 return ScalarizeCall(logf, x);
792}
793
794RValue<SIMD::Float> Exp2(RValue<SIMD::Float> x)
795{
796 return ScalarizeCall(exp2f, x);
797}
798
799RValue<SIMD::Float> Log2(RValue<SIMD::Float> x)
800{
801 return ScalarizeCall(log2f, x);
802}
803
Nicolas Capens0e34c252022-06-30 14:02:00 -0400804RValue<Int> SignMask(RValue<SIMD::Int> x)
805{
806 ASSERT(SIMD::Width == 4);
807 return SignMask(Extract128(x, 0));
808}
809
810RValue<SIMD::UInt> Ctlz(RValue<SIMD::UInt> x, bool isZeroUndef)
811{
812 ASSERT(SIMD::Width == 4);
813 SIMD::UInt result;
814 return Insert128(result, Ctlz(Extract128(x, 0), isZeroUndef), 0);
815}
816
817RValue<SIMD::UInt> Cttz(RValue<SIMD::UInt> x, bool isZeroUndef)
818{
819 ASSERT(SIMD::Width == 4);
820 SIMD::UInt result;
821 return Insert128(result, Cttz(Extract128(x, 0), isZeroUndef), 0);
822}
823
824RValue<SIMD::Int> MulHigh(RValue<SIMD::Int> x, RValue<SIMD::Int> y)
825{
826 ASSERT(SIMD::Width == 4);
827 SIMD::Int result;
828 return Insert128(result, MulHigh(Extract128(x, 0), Extract128(y, 0)), 0);
829}
830
831RValue<SIMD::UInt> MulHigh(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y)
832{
833 ASSERT(SIMD::Width == 4);
834 SIMD::UInt result;
835 return Insert128(result, MulHigh(Extract128(x, 0), Extract128(y, 0)), 0);
836}
837
838RValue<Bool> AnyTrue(const RValue<SIMD::Int> &bools)
839{
840 ASSERT(SIMD::Width == 4);
841 return AnyTrue(Extract128(bools, 0));
842}
843
844RValue<Bool> AnyFalse(const RValue<SIMD::Int> &bools)
845{
846 ASSERT(SIMD::Width == 4);
847 return AnyFalse(Extract128(bools, 0));
848}
849
850RValue<Bool> Divergent(const RValue<SIMD::Int> &ints)
851{
852 ASSERT(SIMD::Width == 4);
853 return Divergent(Extract128(ints, 0));
854}
855
856RValue<SIMD::Int> Swizzle(RValue<SIMD::Int> x, uint16_t select)
857{
858 ASSERT(SIMD::Width == 4);
859 SIMD::Int result;
860 return Insert128(result, Swizzle(Extract128(x, 0), select), 0);
861}
862
863RValue<SIMD::UInt> Swizzle(RValue<SIMD::UInt> x, uint16_t select)
864{
865 ASSERT(SIMD::Width == 4);
866 SIMD::UInt result;
867 return Insert128(result, Swizzle(Extract128(x, 0), select), 0);
868}
869
870RValue<SIMD::Float> Swizzle(RValue<SIMD::Float> x, uint16_t select)
871{
872 ASSERT(SIMD::Width == 4);
873 SIMD::Float result;
874 return Insert128(result, Swizzle(Extract128(x, 0), select), 0);
875}
876
877RValue<SIMD::Int> Shuffle(RValue<SIMD::Int> x, RValue<SIMD::Int> y, uint16_t select)
878{
879 ASSERT(SIMD::Width == 4);
880 SIMD::Int result;
881 return Insert128(result, Shuffle(Extract128(x, 0), Extract128(y, 0), select), 0);
882}
883
884RValue<SIMD::UInt> Shuffle(RValue<SIMD::UInt> x, RValue<SIMD::UInt> y, uint16_t select)
885{
886 ASSERT(SIMD::Width == 4);
887 SIMD::UInt result;
888 return Insert128(result, Shuffle(Extract128(x, 0), Extract128(y, 0), select), 0);
889}
890
891RValue<SIMD::Float> Shuffle(RValue<SIMD::Float> x, RValue<SIMD::Float> y, uint16_t select)
892{
893 ASSERT(SIMD::Width == 4);
894 SIMD::Float result;
895 return Insert128(result, Shuffle(Extract128(x, 0), Extract128(y, 0), select), 0);
896}
897
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400898SIMD::Pointer::Pointer(scalar::Pointer<Byte> base, rr::Int limit)
Nicolas Capens01e41802022-06-29 23:12:57 -0400899 : base(base)
900 , dynamicLimit(limit)
901 , staticLimit(0)
902 , dynamicOffsets(0)
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400903 , staticOffsets(SIMD::Width)
Nicolas Capens01e41802022-06-29 23:12:57 -0400904 , hasDynamicLimit(true)
905 , hasDynamicOffsets(false)
906 , isBasePlusOffset(true)
907{}
908
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400909SIMD::Pointer::Pointer(scalar::Pointer<Byte> base, unsigned int limit)
Nicolas Capens01e41802022-06-29 23:12:57 -0400910 : base(base)
911 , dynamicLimit(0)
912 , staticLimit(limit)
913 , dynamicOffsets(0)
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400914 , staticOffsets(SIMD::Width)
Nicolas Capens01e41802022-06-29 23:12:57 -0400915 , hasDynamicLimit(false)
916 , hasDynamicOffsets(false)
917 , isBasePlusOffset(true)
918{}
919
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400920SIMD::Pointer::Pointer(scalar::Pointer<Byte> base, rr::Int limit, SIMD::Int offset)
Nicolas Capens01e41802022-06-29 23:12:57 -0400921 : base(base)
922 , dynamicLimit(limit)
923 , staticLimit(0)
924 , dynamicOffsets(offset)
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400925 , staticOffsets(SIMD::Width)
Nicolas Capens01e41802022-06-29 23:12:57 -0400926 , hasDynamicLimit(true)
927 , hasDynamicOffsets(true)
928 , isBasePlusOffset(true)
929{}
930
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400931SIMD::Pointer::Pointer(scalar::Pointer<Byte> base, unsigned int limit, SIMD::Int offset)
Nicolas Capens01e41802022-06-29 23:12:57 -0400932 : base(base)
933 , dynamicLimit(0)
934 , staticLimit(limit)
935 , dynamicOffsets(offset)
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400936 , staticOffsets(SIMD::Width)
Nicolas Capens01e41802022-06-29 23:12:57 -0400937 , hasDynamicLimit(false)
938 , hasDynamicOffsets(true)
939 , isBasePlusOffset(true)
940{}
941
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400942SIMD::Pointer::Pointer(std::vector<scalar::Pointer<Byte>> pointers)
Nicolas Capens01e41802022-06-29 23:12:57 -0400943 : pointers(pointers)
944 , isBasePlusOffset(false)
945{}
946
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400947SIMD::Pointer::Pointer(SIMD::UInt cast)
948 : pointers(SIMD::Width)
Nicolas Capens942c6392022-06-30 00:20:40 -0400949 , isBasePlusOffset(false)
950{
951 assert(sizeof(void *) == 4);
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400952 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens942c6392022-06-30 00:20:40 -0400953 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400954 pointers[i] = As<rr::Pointer<Byte>>(Extract(cast, i));
Nicolas Capens942c6392022-06-30 00:20:40 -0400955 }
956}
957
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400958SIMD::Pointer::Pointer(SIMD::UInt castLow, SIMD::UInt castHigh)
959 : pointers(SIMD::Width)
Nicolas Capens942c6392022-06-30 00:20:40 -0400960 , isBasePlusOffset(false)
961{
962 assert(sizeof(void *) == 8);
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400963 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens942c6392022-06-30 00:20:40 -0400964 {
965 UInt2 address;
966 address = Insert(address, Extract(castLow, i), 0);
967 address = Insert(address, Extract(castHigh, i), 1);
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400968 pointers[i] = As<rr::Pointer<Byte>>(address);
Nicolas Capens942c6392022-06-30 00:20:40 -0400969 }
970}
971
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400972SIMD::Pointer &SIMD::Pointer::operator+=(SIMD::Int i)
Nicolas Capens01e41802022-06-29 23:12:57 -0400973{
974 if(isBasePlusOffset)
975 {
976 dynamicOffsets += i;
977 hasDynamicOffsets = true;
978 }
979 else
980 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400981 for(int el = 0; el < SIMD::Width; el++) { pointers[el] += Extract(i, el); }
Nicolas Capens01e41802022-06-29 23:12:57 -0400982 }
983 return *this;
984}
985
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400986SIMD::Pointer SIMD::Pointer::operator+(SIMD::Int i)
Nicolas Capens01e41802022-06-29 23:12:57 -0400987{
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400988 SIMD::Pointer p = *this;
Nicolas Capens01e41802022-06-29 23:12:57 -0400989 p += i;
990 return p;
991}
992
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400993SIMD::Pointer &SIMD::Pointer::operator+=(int i)
Nicolas Capens01e41802022-06-29 23:12:57 -0400994{
995 if(isBasePlusOffset)
996 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400997 for(int el = 0; el < SIMD::Width; el++) { staticOffsets[el] += i; }
Nicolas Capens01e41802022-06-29 23:12:57 -0400998 }
999 else
1000 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001001 for(int el = 0; el < SIMD::Width; el++) { pointers[el] += i; }
Nicolas Capens01e41802022-06-29 23:12:57 -04001002 }
1003 return *this;
1004}
1005
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001006SIMD::Pointer SIMD::Pointer::operator+(int i)
Nicolas Capens01e41802022-06-29 23:12:57 -04001007{
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001008 SIMD::Pointer p = *this;
Nicolas Capens01e41802022-06-29 23:12:57 -04001009 p += i;
1010 return p;
1011}
1012
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001013SIMD::Int SIMD::Pointer::offsets() const
Nicolas Capens01e41802022-06-29 23:12:57 -04001014{
1015 ASSERT_MSG(isBasePlusOffset, "No offsets for this type of pointer");
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001016 return dynamicOffsets + SIMD::Int(staticOffsets);
Nicolas Capens01e41802022-06-29 23:12:57 -04001017}
1018
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001019SIMD::Int SIMD::Pointer::isInBounds(unsigned int accessSize, OutOfBoundsBehavior robustness) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001020{
1021 ASSERT(accessSize > 0);
1022
1023 if(isStaticallyInBounds(accessSize, robustness))
1024 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001025 return SIMD::Int(0xFFFFFFFF);
Nicolas Capens01e41802022-06-29 23:12:57 -04001026 }
1027
1028 if(!hasDynamicOffsets && !hasDynamicLimit)
1029 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001030 ASSERT(SIMD::Width == 4);
Nicolas Capens01e41802022-06-29 23:12:57 -04001031 // Common fast paths.
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001032 return SIMD::Int(
Nicolas Capens01e41802022-06-29 23:12:57 -04001033 (staticOffsets[0] + accessSize - 1 < staticLimit) ? 0xFFFFFFFF : 0,
1034 (staticOffsets[1] + accessSize - 1 < staticLimit) ? 0xFFFFFFFF : 0,
1035 (staticOffsets[2] + accessSize - 1 < staticLimit) ? 0xFFFFFFFF : 0,
1036 (staticOffsets[3] + accessSize - 1 < staticLimit) ? 0xFFFFFFFF : 0);
1037 }
1038
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001039 return CmpGE(offsets(), 0) & CmpLT(offsets() + SIMD::Int(accessSize - 1), limit());
Nicolas Capens01e41802022-06-29 23:12:57 -04001040}
1041
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001042bool SIMD::Pointer::isStaticallyInBounds(unsigned int accessSize, OutOfBoundsBehavior robustness) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001043{
1044 if(hasDynamicOffsets)
1045 {
1046 return false;
1047 }
1048
1049 if(hasDynamicLimit)
1050 {
1051 if(hasStaticEqualOffsets() || hasStaticSequentialOffsets(accessSize))
1052 {
1053 switch(robustness)
1054 {
1055 case OutOfBoundsBehavior::UndefinedBehavior:
1056 // With this robustness setting the application/compiler guarantees in-bounds accesses on active lanes,
1057 // but since it can't know in advance which branches are taken this must be true even for inactives lanes.
1058 return true;
1059 case OutOfBoundsBehavior::Nullify:
1060 case OutOfBoundsBehavior::RobustBufferAccess:
1061 case OutOfBoundsBehavior::UndefinedValue:
1062 return false;
1063 }
1064 }
1065 }
1066
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001067 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001068 {
1069 if(staticOffsets[i] + accessSize - 1 >= staticLimit)
1070 {
1071 return false;
1072 }
1073 }
1074
1075 return true;
1076}
1077
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001078SIMD::Int SIMD::Pointer::limit() const
Nicolas Capens01e41802022-06-29 23:12:57 -04001079{
1080 return dynamicLimit + staticLimit;
1081}
1082
Nicolas Capens43183d82022-06-30 02:28:48 -04001083// Returns true if all offsets are compile-time static and sequential
Nicolas Capens01e41802022-06-29 23:12:57 -04001084// (N+0*step, N+1*step, N+2*step, N+3*step)
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001085bool SIMD::Pointer::hasStaticSequentialOffsets(unsigned int step) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001086{
1087 ASSERT_MSG(isBasePlusOffset, "No offsets for this type of pointer");
1088 if(hasDynamicOffsets)
1089 {
1090 return false;
1091 }
Nicolas Capens43183d82022-06-30 02:28:48 -04001092
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001093 for(int i = 1; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001094 {
Nicolas Capens43183d82022-06-30 02:28:48 -04001095 if(staticOffsets[i - 1] + int32_t(step) != staticOffsets[i])
1096 {
1097 return false;
1098 }
Nicolas Capens01e41802022-06-29 23:12:57 -04001099 }
Nicolas Capens43183d82022-06-30 02:28:48 -04001100
Nicolas Capens01e41802022-06-29 23:12:57 -04001101 return true;
1102}
1103
Nicolas Capens43183d82022-06-30 02:28:48 -04001104// Returns true if all offsets are compile-time static and equal
Nicolas Capens01e41802022-06-29 23:12:57 -04001105// (N, N, N, N)
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001106bool SIMD::Pointer::hasStaticEqualOffsets() const
Nicolas Capens01e41802022-06-29 23:12:57 -04001107{
1108 ASSERT_MSG(isBasePlusOffset, "No offsets for this type of pointer");
1109 if(hasDynamicOffsets)
1110 {
1111 return false;
1112 }
Nicolas Capens43183d82022-06-30 02:28:48 -04001113
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001114 for(int i = 1; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001115 {
Nicolas Capens43183d82022-06-30 02:28:48 -04001116 if(staticOffsets[0] != staticOffsets[i])
1117 {
1118 return false;
1119 }
Nicolas Capens01e41802022-06-29 23:12:57 -04001120 }
Nicolas Capens43183d82022-06-30 02:28:48 -04001121
Nicolas Capens01e41802022-06-29 23:12:57 -04001122 return true;
1123}
1124
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001125scalar::Pointer<Byte> SIMD::Pointer::getUniformPointer() const
Nicolas Capens01e41802022-06-29 23:12:57 -04001126{
Nicolas Capens43183d82022-06-30 02:28:48 -04001127#ifndef NDEBUG
Nicolas Capens01e41802022-06-29 23:12:57 -04001128 if(isBasePlusOffset)
1129 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001130 SIMD::Int uniform = offsets();
1131 scalar::Int x = Extract(uniform, 0);
Nicolas Capens43183d82022-06-30 02:28:48 -04001132
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001133 for(int i = 1; i < SIMD::Width; i++)
Nicolas Capens43183d82022-06-30 02:28:48 -04001134 {
1135 Assert(x == Extract(uniform, i));
1136 }
Nicolas Capens01e41802022-06-29 23:12:57 -04001137 }
1138 else
1139 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001140 for(int i = 1; i < SIMD::Width; i++)
Nicolas Capens43183d82022-06-30 02:28:48 -04001141 {
1142 Assert(pointers[0] == pointers[i]);
1143 }
Nicolas Capens01e41802022-06-29 23:12:57 -04001144 }
Nicolas Capens43183d82022-06-30 02:28:48 -04001145#endif
1146
Nicolas Capens01e41802022-06-29 23:12:57 -04001147 return getPointerForLane(0);
1148}
1149
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001150scalar::Pointer<Byte> SIMD::Pointer::getPointerForLane(int lane) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001151{
1152 if(isBasePlusOffset)
1153 {
1154 return base + Extract(offsets(), lane);
1155 }
1156 else
1157 {
1158 return pointers[lane];
1159 }
1160}
1161
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001162void SIMD::Pointer::castTo(SIMD::UInt &bits) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001163{
Nicolas Capens942c6392022-06-30 00:20:40 -04001164 assert(sizeof(void *) == 4);
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001165 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001166 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001167 bits = Insert(bits, As<scalar::UInt>(pointers[i]), i);
Nicolas Capens01e41802022-06-29 23:12:57 -04001168 }
1169}
1170
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001171void SIMD::Pointer::castTo(SIMD::UInt &lowerBits, SIMD::UInt &upperBits) const
Nicolas Capens01e41802022-06-29 23:12:57 -04001172{
1173 assert(sizeof(void *) == 8);
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001174 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001175 {
1176 UInt2 address = As<UInt2>(pointers[i]);
1177 lowerBits = Insert(lowerBits, Extract(address, 0), i);
1178 upperBits = Insert(upperBits, Extract(address, 1), i);
1179 }
1180}
1181
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001182SIMD::Pointer SIMD::Pointer::IfThenElse(SIMD::Int condition, const SIMD::Pointer &lhs, const SIMD::Pointer &rhs)
Nicolas Capens01e41802022-06-29 23:12:57 -04001183{
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001184 std::vector<scalar::Pointer<Byte>> pointers(SIMD::Width);
1185 for(int i = 0; i < SIMD::Width; i++)
Nicolas Capens01e41802022-06-29 23:12:57 -04001186 {
1187 If(Extract(condition, i) != 0)
1188 {
1189 pointers[i] = lhs.getPointerForLane(i);
1190 }
1191 Else
1192 {
1193 pointers[i] = rhs.getPointerForLane(i);
1194 }
1195 }
Nicolas Capens942c6392022-06-30 00:20:40 -04001196
Nicolas Capens01e41802022-06-29 23:12:57 -04001197 return { pointers };
1198}
1199
1200#ifdef ENABLE_RR_PRINT
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001201std::vector<rr::Value *> SIMD::Pointer::getPrintValues() const
Nicolas Capens01e41802022-06-29 23:12:57 -04001202{
1203 if(isBasePlusOffset)
1204 {
1205 return PrintValue::vals(base, offsets());
1206 }
1207 else
1208 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -04001209 std::vector<Value *> vals;
1210 for(int i = 0; i < SIMD::Width; i++)
1211 {
1212 vals.push_back(RValue<scalar::Pointer<Byte>>(pointers[i]).value());
1213 }
1214 return vals;
Nicolas Capens01e41802022-06-29 23:12:57 -04001215 }
1216}
1217#endif
1218
Nicolas Capens44f94692022-06-20 23:15:46 -04001219} // namespace rr