1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "Reactor.hpp"
17 #include "gtest/gtest.h"
23 int reference(int *p, int y)
28 for(int i = 0; i < 10; i++)
30 z += (2 << i) - (i / 3);
38 TEST(ReactorUnitTests, Sample)
40 Routine *routine = nullptr;
43 Function<Int(Pointer<Int>, Int)> function;
45 Pointer<Int> p = function.Arg<0>();
47 Int y = function.Arg<1>();
50 For(Int i = 0, i < 10, i++)
52 z += (2 << i) - (i / 3);
57 z = As<Int>(Float(Float4(v.xzxx).y));
64 routine = function("one");
68 int (*callable)(int*, int) = (int(*)(int*,int))routine->getEntry();
70 int result = callable(&one[1], 2);
71 EXPECT_EQ(result, reference(&one[1], 2));
78 TEST(ReactorUnitTests, Uninitialized)
80 Routine *routine = nullptr;
83 Function<Int()> function;
99 Return(a + z + q + c);
102 routine = function("one");
106 int (*callable)() = (int(*)())routine->getEntry();
107 int result = callable();
108 EXPECT_EQ(result, result); // Anything is fine, just don't crash
115 TEST(ReactorUnitTests, Unreachable)
117 Routine *routine = nullptr;
120 Function<Int(Int)> function;
122 Int a = function.Arg<0>();
127 // Code beyond this point is unreachable but should not cause any
128 // compilation issues.
133 routine = function("one");
137 int (*callable)(int) = (int(*)(int))routine->getEntry();
138 int result = callable(16);
139 EXPECT_EQ(result, 20);
146 TEST(ReactorUnitTests, VariableAddress)
148 Routine *routine = nullptr;
151 Function<Int(Int)> function;
153 Int a = function.Arg<0>();
161 routine = function("one");
165 int (*callable)(int) = (int(*)(int))routine->getEntry();
166 int result = callable(16);
167 EXPECT_EQ(result, 20);
174 TEST(ReactorUnitTests, SubVectorLoadStore)
176 Routine *routine = nullptr;
179 Function<Int(Pointer<Byte>, Pointer<Byte>)> function;
181 Pointer<Byte> in = function.Arg<0>();
182 Pointer<Byte> out = function.Arg<1>();
184 *Pointer<Int4>(out + 16 * 0) = *Pointer<Int4>(in + 16 * 0);
185 *Pointer<Short4>(out + 16 * 1) = *Pointer<Short4>(in + 16 * 1);
186 *Pointer<Byte8>(out + 16 * 2) = *Pointer<Byte8>(in + 16 * 2);
187 *Pointer<Byte4>(out + 16 * 3) = *Pointer<Byte4>(in + 16 * 3);
188 *Pointer<Short2>(out + 16 * 4) = *Pointer<Short2>(in + 16 * 4);
193 routine = function("one");
197 int8_t in[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
198 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
199 25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0,
200 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 37, 38, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
203 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
204 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
205 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
206 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
209 int (*callable)(void*, void*) = (int(*)(void*,void*))routine->getEntry();
212 for(int row = 0; row < 5; row++)
214 for(int col = 0; col < 16; col++)
216 int i = row * 16 + col;
220 EXPECT_EQ(out[i], -1) << "Row " << row << " column " << col << " not left untouched.";
224 EXPECT_EQ(out[i], in[i]) << "Row " << row << " column " << col << " not equal to input.";
234 TEST(ReactorUnitTests, VectorConstant)
236 Routine *routine = nullptr;
239 Function<Int(Pointer<Byte>)> function;
241 Pointer<Byte> out = function.Arg<0>();
243 *Pointer<Int4>(out + 16 * 0) = Int4(0x04030201, 0x08070605, 0x0C0B0A09, 0x100F0E0D);
244 *Pointer<Short4>(out + 16 * 1) = Short4(0x1211, 0x1413, 0x1615, 0x1817);
245 *Pointer<Byte8>(out + 16 * 2) = Byte8(0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20);
246 *Pointer<Int2>(out + 16 * 3) = Int2(0x24232221, 0x28272625);
251 routine = function("one");
255 int8_t out[16 * 4] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
256 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
257 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
258 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
260 int8_t exp[16 * 4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
261 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1,
262 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1,
263 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, -1, -1};
265 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
268 for(int row = 0; row < 4; row++)
270 for(int col = 0; col < 16; col++)
272 int i = row * 16 + col;
274 EXPECT_EQ(out[i], exp[i]);
283 TEST(ReactorUnitTests, Concatenate)
285 Routine *routine = nullptr;
288 Function<Int(Pointer<Byte>)> function;
290 Pointer<Byte> out = function.Arg<0>();
292 *Pointer<Int4>(out + 16 * 0) = Int4(Int2(0x04030201, 0x08070605), Int2(0x0C0B0A09, 0x100F0E0D));
293 *Pointer<Short8>(out + 16 * 1) = Short8(Short4(0x0201, 0x0403, 0x0605, 0x0807), Short4(0x0A09, 0x0C0B, 0x0E0D, 0x100F));
298 routine = function("one");
302 int8_t ref[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
303 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
305 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
306 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
308 int (*callable)(void*) = (int(*)(void*))routine->getEntry();
311 for(int row = 0; row < 2; row++)
313 for(int col = 0; col < 16; col++)
315 int i = row * 16 + col;
317 EXPECT_EQ(out[i], ref[i]) << "Row " << row << " column " << col << " not equal to reference.";
326 TEST(ReactorUnitTests, Swizzle)
328 Routine *routine = nullptr;
331 Function<Int(Pointer<Byte>)> function;
333 Pointer<Byte> out = function.Arg<0>();
335 for(int i = 0; i < 256; i++)
337 *Pointer<Float4>(out + 16 * i) = Swizzle(Float4(1.0f, 2.0f, 3.0f, 4.0f), i);
340 for(int i = 0; i < 256; i++)
342 *Pointer<Float4>(out + 16 * (256 + i)) = ShuffleLowHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f), i);
345 *Pointer<Float4>(out + 16 * (512 + 0)) = UnpackLow(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f));
346 *Pointer<Float4>(out + 16 * (512 + 1)) = UnpackHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f));
347 *Pointer<Int2>(out + 16 * (512 + 2)) = UnpackLow(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8));
348 *Pointer<Int2>(out + 16 * (512 + 3)) = UnpackHigh(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8));
349 *Pointer<Short4>(out + 16 * (512 + 4)) = UnpackLow(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16));
350 *Pointer<Short4>(out + 16 * (512 + 5)) = UnpackHigh(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16));
352 for(int i = 0; i < 256; i++)
354 *Pointer<Short4>(out + 16 * (512 + 6) + (8 * i)) =
355 Swizzle(Short4(1, 2, 3, 4), i);
358 for(int i = 0; i < 256; i++)
360 *Pointer<Int4>(out + 16 * (512 + 6 + i) + (8 * 256)) =
361 Swizzle(Int4(1, 2, 3, 4), i);
367 routine = function("one");
373 float f[256 + 256 + 2][4];
377 memset(&out, 0, sizeof(out));
379 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
382 for(int i = 0; i < 256; i++)
384 EXPECT_EQ(out.f[i][0], float((i >> 0) & 0x03) + 1.0f);
385 EXPECT_EQ(out.f[i][1], float((i >> 2) & 0x03) + 1.0f);
386 EXPECT_EQ(out.f[i][2], float((i >> 4) & 0x03) + 1.0f);
387 EXPECT_EQ(out.f[i][3], float((i >> 6) & 0x03) + 1.0f);
390 for(int i = 0; i < 256; i++)
392 EXPECT_EQ(out.f[256 + i][0], float((i >> 0) & 0x03) + 1.0f);
393 EXPECT_EQ(out.f[256 + i][1], float((i >> 2) & 0x03) + 1.0f);
394 EXPECT_EQ(out.f[256 + i][2], float((i >> 4) & 0x03) + 5.0f);
395 EXPECT_EQ(out.f[256 + i][3], float((i >> 6) & 0x03) + 5.0f);
398 EXPECT_EQ(out.f[512 + 0][0], 1.0f);
399 EXPECT_EQ(out.f[512 + 0][1], 5.0f);
400 EXPECT_EQ(out.f[512 + 0][2], 2.0f);
401 EXPECT_EQ(out.f[512 + 0][3], 6.0f);
403 EXPECT_EQ(out.f[512 + 1][0], 3.0f);
404 EXPECT_EQ(out.f[512 + 1][1], 7.0f);
405 EXPECT_EQ(out.f[512 + 1][2], 4.0f);
406 EXPECT_EQ(out.f[512 + 1][3], 8.0f);
408 EXPECT_EQ(out.i[0][0], 0x00050001);
409 EXPECT_EQ(out.i[0][1], 0x00060002);
410 EXPECT_EQ(out.i[0][2], 0x00000000);
411 EXPECT_EQ(out.i[0][3], 0x00000000);
413 EXPECT_EQ(out.i[1][0], 0x00070003);
414 EXPECT_EQ(out.i[1][1], 0x00080004);
415 EXPECT_EQ(out.i[1][2], 0x00000000);
416 EXPECT_EQ(out.i[1][3], 0x00000000);
418 EXPECT_EQ(out.i[2][0], 0x0A020901);
419 EXPECT_EQ(out.i[2][1], 0x0C040B03);
420 EXPECT_EQ(out.i[2][2], 0x00000000);
421 EXPECT_EQ(out.i[2][3], 0x00000000);
423 EXPECT_EQ(out.i[3][0], 0x0E060D05);
424 EXPECT_EQ(out.i[3][1], 0x10080F07);
425 EXPECT_EQ(out.i[3][2], 0x00000000);
426 EXPECT_EQ(out.i[3][3], 0x00000000);
428 for(int i = 0; i < 256; i++)
430 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] & 0xFFFF,
431 ((i >> 0) & 0x03) + 1);
432 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] >> 16,
433 ((i >> 2) & 0x03) + 1);
434 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] & 0xFFFF,
435 ((i >> 4) & 0x03) + 1);
436 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] >> 16,
437 ((i >> 6) & 0x03) + 1);
440 for(int i = 0; i < 256; i++)
442 EXPECT_EQ(out.i[132 + i][0], ((i >> 0) & 0x03) + 1);
443 EXPECT_EQ(out.i[132 + i][1], ((i >> 2) & 0x03) + 1);
444 EXPECT_EQ(out.i[132 + i][2], ((i >> 4) & 0x03) + 1);
445 EXPECT_EQ(out.i[132 + i][3], ((i >> 6) & 0x03) + 1);
453 TEST(ReactorUnitTests, Branching)
455 Routine *routine = nullptr;
458 Function<Int(Void)> function;
462 For(Int i = 0, i < 8, i++)
481 For(Int i = 0, i < 5, i++)
485 For(Int i = 0, i < 10, i++)
486 for(int i = 0; i < 10; i++)
487 For(Int i = 0, i < 10, i++)
492 For(Int i = 0, i < 2, i++)
504 routine = function("one");
508 int(*callable)() = (int(*)())routine->getEntry();
509 int result = callable();
511 EXPECT_EQ(result, 1000402222);
518 TEST(ReactorUnitTests, MinMax)
520 Routine *routine = nullptr;
523 Function<Int(Pointer<Byte>)> function;
525 Pointer<Byte> out = function.Arg<0>();
527 *Pointer<Float4>(out + 16 * 0) = Min(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
528 *Pointer<Float4>(out + 16 * 1) = Max(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
530 *Pointer<Int4>(out + 16 * 2) = Min(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
531 *Pointer<Int4>(out + 16 * 3) = Max(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
532 *Pointer<UInt4>(out + 16 * 4) = Min(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
533 *Pointer<UInt4>(out + 16 * 5) = Max(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
535 *Pointer<Short4>(out + 16 * 6) = Min(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
536 *Pointer<Short4>(out + 16 * 7) = Max(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
537 *Pointer<UShort4>(out + 16 * 8) = Min(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
538 *Pointer<UShort4>(out + 16 * 9) = Max(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
543 routine = function("one");
547 unsigned int out[10][4];
549 memset(&out, 0, sizeof(out));
551 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
554 EXPECT_EQ(out[0][0], 0x00000000u);
555 EXPECT_EQ(out[0][1], 0x00000000u);
556 EXPECT_EQ(out[0][2], 0x00000000u);
557 EXPECT_EQ(out[0][3], 0x80000000u);
559 EXPECT_EQ(out[1][0], 0x3F800000u);
560 EXPECT_EQ(out[1][1], 0x3F800000u);
561 EXPECT_EQ(out[1][2], 0x00000000u);
562 EXPECT_EQ(out[1][3], 0x80000000u);
564 EXPECT_EQ(out[2][0], 0x00000000u);
565 EXPECT_EQ(out[2][1], 0x00000000u);
566 EXPECT_EQ(out[2][2], 0xFFFFFFFFu);
567 EXPECT_EQ(out[2][3], 0x00000000u);
569 EXPECT_EQ(out[3][0], 0x00000001u);
570 EXPECT_EQ(out[3][1], 0x00000001u);
571 EXPECT_EQ(out[3][2], 0x00000000u);
572 EXPECT_EQ(out[3][3], 0x00000000u);
574 EXPECT_EQ(out[4][0], 0x00000000u);
575 EXPECT_EQ(out[4][1], 0x00000000u);
576 EXPECT_EQ(out[4][2], 0x00000000u);
577 EXPECT_EQ(out[4][3], 0x00000000u);
579 EXPECT_EQ(out[5][0], 0x00000001u);
580 EXPECT_EQ(out[5][1], 0x00000001u);
581 EXPECT_EQ(out[5][2], 0xFFFFFFFFu);
582 EXPECT_EQ(out[5][3], 0x00000000u);
584 EXPECT_EQ(out[6][0], 0x00000000u);
585 EXPECT_EQ(out[6][1], 0x0000FFFFu);
586 EXPECT_EQ(out[6][2], 0x00000000u);
587 EXPECT_EQ(out[6][3], 0x00000000u);
589 EXPECT_EQ(out[7][0], 0x00010001u);
590 EXPECT_EQ(out[7][1], 0x00000000u);
591 EXPECT_EQ(out[7][2], 0x00000000u);
592 EXPECT_EQ(out[7][3], 0x00000000u);
594 EXPECT_EQ(out[8][0], 0x00000000u);
595 EXPECT_EQ(out[8][1], 0x00000000u);
596 EXPECT_EQ(out[8][2], 0x00000000u);
597 EXPECT_EQ(out[8][3], 0x00000000u);
599 EXPECT_EQ(out[9][0], 0x00010001u);
600 EXPECT_EQ(out[9][1], 0x0000FFFFu);
601 EXPECT_EQ(out[9][2], 0x00000000u);
602 EXPECT_EQ(out[9][3], 0x00000000u);
609 TEST(ReactorUnitTests, NotNeg)
611 Routine *routine = nullptr;
614 Function<Int(Pointer<Byte>)> function;
616 Pointer<Byte> out = function.Arg<0>();
618 *Pointer<Int>(out + 16 * 0) = ~Int(0x55555555);
619 *Pointer<Short>(out + 16 * 1) = ~Short(0x5555);
620 *Pointer<Int4>(out + 16 * 2) = ~Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF);
621 *Pointer<Short4>(out + 16 * 3) = ~Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF);
623 *Pointer<Int>(out + 16 * 4) = -Int(0x55555555);
624 *Pointer<Short>(out + 16 * 5) = -Short(0x5555);
625 *Pointer<Int4>(out + 16 * 6) = -Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF);
626 *Pointer<Short4>(out + 16 * 7) = -Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF);
628 *Pointer<Float4>(out + 16 * 8) = -Float4(1.0f, -1.0f, 0.0f, -0.0f);
633 routine = function("one");
637 unsigned int out[10][4];
639 memset(&out, 0, sizeof(out));
641 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
644 EXPECT_EQ(out[0][0], 0xAAAAAAAAu);
645 EXPECT_EQ(out[0][1], 0x00000000u);
646 EXPECT_EQ(out[0][2], 0x00000000u);
647 EXPECT_EQ(out[0][3], 0x00000000u);
649 EXPECT_EQ(out[1][0], 0x0000AAAAu);
650 EXPECT_EQ(out[1][1], 0x00000000u);
651 EXPECT_EQ(out[1][2], 0x00000000u);
652 EXPECT_EQ(out[1][3], 0x00000000u);
654 EXPECT_EQ(out[2][0], 0xAAAAAAAAu);
655 EXPECT_EQ(out[2][1], 0x55555555u);
656 EXPECT_EQ(out[2][2], 0xFFFFFFFFu);
657 EXPECT_EQ(out[2][3], 0x00000000u);
659 EXPECT_EQ(out[3][0], 0x5555AAAAu);
660 EXPECT_EQ(out[3][1], 0x0000FFFFu);
661 EXPECT_EQ(out[3][2], 0x00000000u);
662 EXPECT_EQ(out[3][3], 0x00000000u);
664 EXPECT_EQ(out[4][0], 0xAAAAAAABu);
665 EXPECT_EQ(out[4][1], 0x00000000u);
666 EXPECT_EQ(out[4][2], 0x00000000u);
667 EXPECT_EQ(out[4][3], 0x00000000u);
669 EXPECT_EQ(out[5][0], 0x0000AAABu);
670 EXPECT_EQ(out[5][1], 0x00000000u);
671 EXPECT_EQ(out[5][2], 0x00000000u);
672 EXPECT_EQ(out[5][3], 0x00000000u);
674 EXPECT_EQ(out[6][0], 0xAAAAAAABu);
675 EXPECT_EQ(out[6][1], 0x55555556u);
676 EXPECT_EQ(out[6][2], 0x00000000u);
677 EXPECT_EQ(out[6][3], 0x00000001u);
679 EXPECT_EQ(out[7][0], 0x5556AAABu);
680 EXPECT_EQ(out[7][1], 0x00010000u);
681 EXPECT_EQ(out[7][2], 0x00000000u);
682 EXPECT_EQ(out[7][3], 0x00000000u);
684 EXPECT_EQ(out[8][0], 0xBF800000u);
685 EXPECT_EQ(out[8][1], 0x3F800000u);
686 EXPECT_EQ(out[8][2], 0x80000000u);
687 EXPECT_EQ(out[8][3], 0x00000000u);
694 TEST(ReactorUnitTests, VectorCompare)
696 Routine *routine = nullptr;
699 Function<Int(Pointer<Byte>)> function;
701 Pointer<Byte> out = function.Arg<0>();
703 *Pointer<Int4>(out + 16 * 0) = CmpEQ(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
704 *Pointer<Int4>(out + 16 * 1) = CmpEQ(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
705 *Pointer<Byte8>(out + 16 * 2) = CmpEQ(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0));
707 *Pointer<Int4>(out + 16 * 3) = CmpNLT(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
708 *Pointer<Int4>(out + 16 * 4) = CmpNLT(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
709 *Pointer<Byte8>(out + 16 * 5) = CmpGT(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0));
714 routine = function("one");
718 unsigned int out[6][4];
720 memset(&out, 0, sizeof(out));
722 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
725 EXPECT_EQ(out[0][0], 0x00000000u);
726 EXPECT_EQ(out[0][1], 0xFFFFFFFFu);
727 EXPECT_EQ(out[0][2], 0xFFFFFFFFu);
728 EXPECT_EQ(out[0][3], 0xFFFFFFFFu);
730 EXPECT_EQ(out[1][0], 0x00000000u);
731 EXPECT_EQ(out[1][1], 0x00000000u);
732 EXPECT_EQ(out[1][2], 0x00000000u);
733 EXPECT_EQ(out[1][3], 0xFFFFFFFFu);
735 EXPECT_EQ(out[2][0], 0xFF000000u);
736 EXPECT_EQ(out[2][1], 0x00000000u);
738 EXPECT_EQ(out[3][0], 0xFFFFFFFFu);
739 EXPECT_EQ(out[3][1], 0xFFFFFFFFu);
740 EXPECT_EQ(out[3][2], 0xFFFFFFFFu);
741 EXPECT_EQ(out[3][3], 0xFFFFFFFFu);
743 EXPECT_EQ(out[4][0], 0xFFFFFFFFu);
744 EXPECT_EQ(out[4][1], 0x00000000u);
745 EXPECT_EQ(out[4][2], 0x00000000u);
746 EXPECT_EQ(out[4][3], 0xFFFFFFFFu);
748 EXPECT_EQ(out[5][0], 0x00000000u);
749 EXPECT_EQ(out[5][1], 0xFFFFFFFFu);
756 TEST(ReactorUnitTests, SaturatedAddAndSubtract)
758 Routine *routine = nullptr;
761 Function<Int(Pointer<Byte>)> function;
763 Pointer<Byte> out = function.Arg<0>();
765 *Pointer<Byte8>(out + 8 * 0) =
766 AddSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8),
767 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
768 *Pointer<Byte8>(out + 8 * 1) =
769 AddSat(Byte8(0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE),
770 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
771 *Pointer<Byte8>(out + 8 * 2) =
772 SubSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8),
773 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
775 *Pointer<SByte8>(out + 8 * 3) =
776 AddSat(SByte8(1, 2, 3, 4, 5, 6, 7, 8),
777 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
778 *Pointer<SByte8>(out + 8 * 4) =
779 AddSat(SByte8(0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E),
780 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
781 *Pointer<SByte8>(out + 8 * 5) =
782 AddSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88),
783 SByte8(-7, -6, -5, -4, -3, -2, -1, -0));
784 *Pointer<SByte8>(out + 8 * 6) =
785 SubSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88),
786 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
788 *Pointer<Short4>(out + 8 * 7) =
789 AddSat(Short4(1, 2, 3, 4), Short4(3, 2, 1, 0));
790 *Pointer<Short4>(out + 8 * 8) =
791 AddSat(Short4(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE),
793 *Pointer<Short4>(out + 8 * 9) =
794 AddSat(Short4(0x8001, 0x8002, 0x8003, 0x8004),
795 Short4(-3, -2, -1, -0));
796 *Pointer<Short4>(out + 8 * 10) =
797 SubSat(Short4(0x8001, 0x8002, 0x8003, 0x8004),
800 *Pointer<UShort4>(out + 8 * 11) =
801 AddSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0));
802 *Pointer<UShort4>(out + 8 * 12) =
803 AddSat(UShort4(0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE),
804 UShort4(3, 2, 1, 0));
805 *Pointer<UShort4>(out + 8 * 13) =
806 SubSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0));
811 routine = function("one");
815 unsigned int out[14][2];
817 memset(&out, 0, sizeof(out));
819 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
822 EXPECT_EQ(out[0][0], 0x08080808u);
823 EXPECT_EQ(out[0][1], 0x08080808u);
825 EXPECT_EQ(out[1][0], 0xFFFFFFFFu);
826 EXPECT_EQ(out[1][1], 0xFEFFFFFFu);
828 EXPECT_EQ(out[2][0], 0x00000000u);
829 EXPECT_EQ(out[2][1], 0x08060402u);
831 EXPECT_EQ(out[3][0], 0x08080808u);
832 EXPECT_EQ(out[3][1], 0x08080808u);
834 EXPECT_EQ(out[4][0], 0x7F7F7F7Fu);
835 EXPECT_EQ(out[4][1], 0x7E7F7F7Fu);
837 EXPECT_EQ(out[5][0], 0x80808080u);
838 EXPECT_EQ(out[5][1], 0x88868482u);
840 EXPECT_EQ(out[6][0], 0x80808080u);
841 EXPECT_EQ(out[6][1], 0x88868482u);
843 EXPECT_EQ(out[7][0], 0x00040004u);
844 EXPECT_EQ(out[7][1], 0x00040004u);
846 EXPECT_EQ(out[8][0], 0x7FFF7FFFu);
847 EXPECT_EQ(out[8][1], 0x7FFE7FFFu);
849 EXPECT_EQ(out[9][0], 0x80008000u);
850 EXPECT_EQ(out[9][1], 0x80048002u);
852 EXPECT_EQ(out[10][0], 0x80008000u);
853 EXPECT_EQ(out[10][1], 0x80048002u);
855 EXPECT_EQ(out[11][0], 0x00040004u);
856 EXPECT_EQ(out[11][1], 0x00040004u);
858 EXPECT_EQ(out[12][0], 0xFFFFFFFFu);
859 EXPECT_EQ(out[12][1], 0xFFFEFFFFu);
861 EXPECT_EQ(out[13][0], 0x00000000u);
862 EXPECT_EQ(out[13][1], 0x00040002u);
869 TEST(ReactorUnitTests, Unpack)
871 Routine *routine = nullptr;
874 Function<Int(Pointer<Byte>,Pointer<Byte>)> function;
876 Pointer<Byte> in = function.Arg<0>();
877 Pointer<Byte> out = function.Arg<1>();
879 Byte4 test_byte_a = *Pointer<Byte4>(in + 4 * 0);
880 Byte4 test_byte_b = *Pointer<Byte4>(in + 4 * 1);
882 *Pointer<Short4>(out + 8 * 0) =
883 Unpack(test_byte_a, test_byte_b);
885 *Pointer<Short4>(out + 8 * 1) = Unpack(test_byte_a);
890 routine = function("one");
894 unsigned int in[1][2];
895 unsigned int out[2][2];
897 memset(&out, 0, sizeof(out));
899 in[0][0] = 0xABCDEF12u;
900 in[0][1] = 0x34567890u;
902 int(*callable)(void*,void*) = (int(*)(void*,void*))routine->getEntry();
905 EXPECT_EQ(out[0][0], 0x78EF9012u);
906 EXPECT_EQ(out[0][1], 0x34AB56CDu);
908 EXPECT_EQ(out[1][0], 0xEFEF1212u);
909 EXPECT_EQ(out[1][1], 0xABABCDCDu);
916 TEST(ReactorUnitTests, Pack)
918 Routine *routine = nullptr;
921 Function<Int(Pointer<Byte>)> function;
923 Pointer<Byte> out = function.Arg<0>();
925 *Pointer<SByte8>(out + 8 * 0) =
926 PackSigned(Short4(-1, -2, 1, 2),
927 Short4(3, 4, -3, -4));
929 *Pointer<Byte8>(out + 8 * 1) =
930 PackUnsigned(Short4(-1, -2, 1, 2),
931 Short4(3, 4, -3, -4));
933 *Pointer<Short8>(out + 8 * 2) =
934 PackSigned(Int4(-1, -2, 1, 2),
937 *Pointer<UShort8>(out + 8 * 4) =
938 PackUnsigned(Int4(-1, -2, 1, 2),
944 routine = function("one");
948 unsigned int out[6][2];
950 memset(&out, 0, sizeof(out));
952 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
955 EXPECT_EQ(out[0][0], 0x0201FEFFu);
956 EXPECT_EQ(out[0][1], 0xFCFD0403u);
958 EXPECT_EQ(out[1][0], 0x02010000u);
959 EXPECT_EQ(out[1][1], 0x00000403u);
961 EXPECT_EQ(out[2][0], 0xFFFEFFFFu);
962 EXPECT_EQ(out[2][1], 0x00020001u);
964 EXPECT_EQ(out[3][0], 0x00040003u);
965 EXPECT_EQ(out[3][1], 0xFFFCFFFDu);
967 EXPECT_EQ(out[4][0], 0x00000000u);
968 EXPECT_EQ(out[4][1], 0x00020001u);
970 EXPECT_EQ(out[5][0], 0x00040003u);
971 EXPECT_EQ(out[5][1], 0x00000000u);
978 TEST(ReactorUnitTests, MulHigh)
980 Routine *routine = nullptr;
983 Function<Int(Pointer<Byte>)> function;
985 Pointer<Byte> out = function.Arg<0>();
987 *Pointer<Short4>(out + 16 * 0) =
988 MulHigh(Short4(0x01AA, 0x02DD, 0x03EE, 0xF422),
989 Short4(0x01BB, 0x02CC, 0x03FF, 0xF411));
990 *Pointer<UShort4>(out + 16 * 1) =
991 MulHigh(UShort4(0x01AA, 0x02DD, 0x03EE, 0xF422),
992 UShort4(0x01BB, 0x02CC, 0x03FF, 0xF411));
994 *Pointer<Int4>(out + 16 * 2) =
995 MulHigh(Int4(0x000001AA, 0x000002DD, 0xC8000000, 0xF8000000),
996 Int4(0x000001BB, 0x84000000, 0x000003EE, 0xD7000000));
997 *Pointer<UInt4>(out + 16 * 3) =
998 MulHigh(UInt4(0x000001AAu, 0x000002DDu, 0xC8000000u, 0xD8000000u),
999 UInt4(0x000001BBu, 0x84000000u, 0x000003EEu, 0xD7000000u));
1001 *Pointer<Int4>(out + 16 * 4) =
1002 MulHigh(Int4(0x7FFFFFFF, 0x7FFFFFFF, 0x80008000, 0xFFFFFFFF),
1003 Int4(0x7FFFFFFF, 0x80000000, 0x80008000, 0xFFFFFFFF));
1004 *Pointer<UInt4>(out + 16 * 5) =
1005 MulHigh(UInt4(0x7FFFFFFFu, 0x7FFFFFFFu, 0x80008000u, 0xFFFFFFFFu),
1006 UInt4(0x7FFFFFFFu, 0x80000000u, 0x80008000u, 0xFFFFFFFFu));
1008 // (U)Short8 variants currently unimplemented.
1013 routine = function("one");
1017 unsigned int out[6][4];
1019 memset(&out, 0, sizeof(out));
1021 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
1024 EXPECT_EQ(out[0][0], 0x00080002u);
1025 EXPECT_EQ(out[0][1], 0x008D000Fu);
1027 EXPECT_EQ(out[1][0], 0x00080002u);
1028 EXPECT_EQ(out[1][1], 0xE8C0000Fu);
1030 EXPECT_EQ(out[2][0], 0x00000000u);
1031 EXPECT_EQ(out[2][1], 0xFFFFFE9Cu);
1032 EXPECT_EQ(out[2][2], 0xFFFFFF23u);
1033 EXPECT_EQ(out[2][3], 0x01480000u);
1035 EXPECT_EQ(out[3][0], 0x00000000u);
1036 EXPECT_EQ(out[3][1], 0x00000179u);
1037 EXPECT_EQ(out[3][2], 0x00000311u);
1038 EXPECT_EQ(out[3][3], 0xB5680000u);
1040 EXPECT_EQ(out[4][0], 0x3FFFFFFFu);
1041 EXPECT_EQ(out[4][1], 0xC0000000u);
1042 EXPECT_EQ(out[4][2], 0x3FFF8000u);
1043 EXPECT_EQ(out[4][3], 0x00000000u);
1045 EXPECT_EQ(out[5][0], 0x3FFFFFFFu);
1046 EXPECT_EQ(out[5][1], 0x3FFFFFFFu);
1047 EXPECT_EQ(out[5][2], 0x40008000u);
1048 EXPECT_EQ(out[5][3], 0xFFFFFFFEu);
1055 TEST(ReactorUnitTests, MulAdd)
1057 Routine *routine = nullptr;
1060 Function<Int(Pointer<Byte>)> function;
1062 Pointer<Byte> out = function.Arg<0>();
1064 *Pointer<Int2>(out + 8 * 0) =
1065 MulAdd(Short4(0x1aa, 0x2dd, 0x3ee, 0xF422),
1066 Short4(0x1bb, 0x2cc, 0x3ff, 0xF411));
1068 // (U)Short8 variant is mentioned but unimplemented
1072 routine = function("one");
1076 unsigned int out[1][2];
1078 memset(&out, 0, sizeof(out));
1080 int(*callable)(void*) = (int(*)(void*))routine->getEntry();
1083 EXPECT_EQ(out[0][0], 0x000AE34Au);
1084 EXPECT_EQ(out[0][1], 0x009D5254u);
1091 // Check that a complex generated function which utilizes all 8 or 16 XMM
1092 // registers computes the correct result.
1093 // (Note that due to MSC's lack of support for inline assembly in x64,
1094 // this test does not actually check that the register contents are
1095 // preserved, just that the generated function computes the correct value.
1096 // It's necessary to inspect the registers in a debugger to actually verify.)
1097 TEST(ReactorUnitTests, PreserveXMMRegisters)
1099 Routine *routine = nullptr;
1102 Function<Void(Pointer<Byte>, Pointer<Byte>)> function;
1104 Pointer<Byte> in = function.Arg<0>();
1105 Pointer<Byte> out = function.Arg<1>();
1107 Float4 a = *Pointer<Float4>(in + 16 * 0);
1108 Float4 b = *Pointer<Float4>(in + 16 * 1);
1109 Float4 c = *Pointer<Float4>(in + 16 * 2);
1110 Float4 d = *Pointer<Float4>(in + 16 * 3);
1111 Float4 e = *Pointer<Float4>(in + 16 * 4);
1112 Float4 f = *Pointer<Float4>(in + 16 * 5);
1113 Float4 g = *Pointer<Float4>(in + 16 * 6);
1114 Float4 h = *Pointer<Float4>(in + 16 * 7);
1115 Float4 i = *Pointer<Float4>(in + 16 * 8);
1116 Float4 j = *Pointer<Float4>(in + 16 * 9);
1117 Float4 k = *Pointer<Float4>(in + 16 * 10);
1118 Float4 l = *Pointer<Float4>(in + 16 * 11);
1119 Float4 m = *Pointer<Float4>(in + 16 * 12);
1120 Float4 n = *Pointer<Float4>(in + 16 * 13);
1121 Float4 o = *Pointer<Float4>(in + 16 * 14);
1122 Float4 p = *Pointer<Float4>(in + 16 * 15);
1133 Float4 abcd = ab + cd;
1134 Float4 efgh = ef + gh;
1135 Float4 ijkl = ij + kl;
1136 Float4 mnop = mn + op;
1138 Float4 abcdefgh = abcd + efgh;
1139 Float4 ijklmnop = ijkl + mnop;
1140 Float4 sum = abcdefgh + ijklmnop;
1141 *Pointer<Float4>(out) = sum;
1145 routine = function("one");
1148 float input[64] = { 1.0f, 0.0f, 0.0f, 0.0f,
1149 -1.0f, 1.0f, -1.0f, 0.0f,
1150 1.0f, 2.0f, -2.0f, 0.0f,
1151 -1.0f, 3.0f, -3.0f, 0.0f,
1152 1.0f, 4.0f, -4.0f, 0.0f,
1153 -1.0f, 5.0f, -5.0f, 0.0f,
1154 1.0f, 6.0f, -6.0f, 0.0f,
1155 -1.0f, 7.0f, -7.0f, 0.0f,
1156 1.0f, 8.0f, -8.0f, 0.0f,
1157 -1.0f, 9.0f, -9.0f, 0.0f,
1158 1.0f, 10.0f, -10.0f, 0.0f,
1159 -1.0f, 11.0f, -11.0f, 0.0f,
1160 1.0f, 12.0f, -12.0f, 0.0f,
1161 -1.0f, 13.0f, -13.0f, 0.0f,
1162 1.0f, 14.0f, -14.0f, 0.0f,
1163 -1.0f, 15.0f, -15.0f, 0.0f };
1166 void (*callable)(float*, float*) = (void(*)(float*,float*))routine->getEntry();
1168 callable(input, result);
1170 EXPECT_EQ(result[0], 0.0f);
1171 EXPECT_EQ(result[1], 120.0f);
1172 EXPECT_EQ(result[2], -120.0f);
1173 EXPECT_EQ(result[3], 0.0f);
1179 template <typename T>
1180 class CToReactorCastTest : public ::testing::Test
1183 using CType = typename std::tuple_element<0, T>::type;
1184 using ReactorType = typename std::tuple_element<1, T>::type;
1187 using CToReactorCastTestTypes = ::testing::Types
1188 < // Subset of types that can be used as arguments.
1189 // std::pair<bool, Bool>, FIXME(capn): Not supported as argument type by Subzero.
1190 // std::pair<uint8_t, Byte>, FIXME(capn): Not supported as argument type by Subzero.
1191 // std::pair<int8_t, SByte>, FIXME(capn): Not supported as argument type by Subzero.
1192 // std::pair<int16_t, Short>, FIXME(capn): Not supported as argument type by Subzero.
1193 // std::pair<uint16_t, UShort>, FIXME(capn): Not supported as argument type by Subzero.
1194 std::pair<int, Int>,
1195 std::pair<unsigned int, UInt>,
1196 std::pair<float, Float>
1199 TYPED_TEST_CASE(CToReactorCastTest, CToReactorCastTestTypes);
1201 TYPED_TEST(CToReactorCastTest, Casts)
1203 using CType = typename TestFixture::CType;
1204 using ReactorType = typename TestFixture::ReactorType;
1206 Routine *routine = nullptr;
1209 Function< Int(ReactorType) > function;
1211 ReactorType a = function.template Arg<0>();
1212 ReactorType b = CType{};
1213 RValue<ReactorType> c = RValue<ReactorType>(CType{});
1214 Bool same = (a == b) && (a == c);
1215 Return(IfThenElse(same, Int(1), Int(0))); // TODO: Ability to use Bools as return values.
1218 routine = function("one");
1222 auto callable = (int(*)(CType))routine->getEntry();
1224 EXPECT_EQ(callable(in), 1);
1231 template <typename T>
1232 class GEPTest : public ::testing::Test
1235 using CType = typename std::tuple_element<0, T>::type;
1236 using ReactorType = typename std::tuple_element<1, T>::type;
1239 using GEPTestTypes = ::testing::Types
1241 std::pair<bool, Bool>,
1242 std::pair<int8_t, Byte>,
1243 std::pair<int8_t, SByte>,
1244 std::pair<int8_t[4], Byte4>,
1245 std::pair<int8_t[4], SByte4>,
1246 std::pair<int8_t[8], Byte8>,
1247 std::pair<int8_t[8], SByte8>,
1248 std::pair<int8_t[16], Byte16>,
1249 std::pair<int8_t[16], SByte16>,
1250 std::pair<int16_t, Short>,
1251 std::pair<int16_t, UShort>,
1252 std::pair<int16_t[2], Short2>,
1253 std::pair<int16_t[2], UShort2>,
1254 std::pair<int16_t[4], Short4>,
1255 std::pair<int16_t[4], UShort4>,
1256 std::pair<int16_t[8], Short8>,
1257 std::pair<int16_t[8], UShort8>,
1258 std::pair<int, Int>,
1259 std::pair<int, UInt>,
1260 std::pair<int[2], Int2>,
1261 std::pair<int[2], UInt2>,
1262 std::pair<int[4], Int4>,
1263 std::pair<int[4], UInt4>,
1264 std::pair<int64_t, Long>,
1265 std::pair<int16_t, Half>,
1266 std::pair<float, Float>,
1267 std::pair<float[2], Float2>,
1268 std::pair<float[4], Float4>
1271 TYPED_TEST_CASE(GEPTest, GEPTestTypes);
1273 TYPED_TEST(GEPTest, PtrOffsets)
1275 using CType = typename TestFixture::CType;
1276 using ReactorType = typename TestFixture::ReactorType;
1278 Routine *routine = nullptr;
1281 Function< Pointer<ReactorType>(Pointer<ReactorType>, Int) > function;
1283 Pointer<ReactorType> pointer = function.template Arg<0>();
1284 Int index = function.template Arg<1>();
1285 Return(&pointer[index]);
1288 routine = function("one");
1292 auto callable = (CType*(*)(CType*, unsigned int))routine->getEntry();
1302 for (int i = 0; i < 5; i++)
1305 reference.p = &base.p[i];
1308 result.p = callable(base.p, i);
1310 auto expect = reference.i - base.i;
1311 auto got = result.i - base.i;
1313 EXPECT_EQ(got, expect) << "i:" << i;
1321 int main(int argc, char **argv)
1323 ::testing::InitGoogleTest(&argc, argv);
1324 return RUN_ALL_TESTS();