OSDN Git Service

Elide single basic block variable materialization
[android-x86/external-swiftshader.git] / src / Reactor / ReactorUnitTests.cpp
1 // Copyright 2016 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 "Reactor.hpp"
16
17 #include "gtest/gtest.h"
18
19 #include <tuple>
20
21 using namespace rr;
22
23 int reference(int *p, int y)
24 {
25         int x = p[-1];
26         int z = 4;
27
28         for(int i = 0; i < 10; i++)
29         {
30                 z += (2 << i) - (i / 3);
31         }
32
33         int sum = x + y + z;
34
35         return sum;
36 }
37
38 TEST(ReactorUnitTests, Sample)
39 {
40         Routine *routine = nullptr;
41
42         {
43                 Function<Int(Pointer<Int>, Int)> function;
44                 {
45                         Pointer<Int> p = function.Arg<0>();
46                         Int x = p[-1];
47                         Int y = function.Arg<1>();
48                         Int z = 4;
49
50                         For(Int i = 0, i < 10, i++)
51                         {
52                                 z += (2 << i) - (i / 3);
53                         }
54
55                         Float4 v;
56                         v.z = As<Float>(z);
57                         z = As<Int>(Float(Float4(v.xzxx).y));
58
59                         Int sum = x + y + z;
60
61                         Return(sum);
62                 }
63
64                 routine = function("one");
65
66                 if(routine)
67                 {
68                         int (*callable)(int*, int) = (int(*)(int*,int))routine->getEntry();
69                         int one[2] = {1, 0};
70                         int result = callable(&one[1], 2);
71                         EXPECT_EQ(result, reference(&one[1], 2));
72                 }
73         }
74
75         delete routine;
76 }
77
78 TEST(ReactorUnitTests, Uninitialized)
79 {
80         Routine *routine = nullptr;
81
82         {
83                 Function<Int()> function;
84                 {
85                         Int a;
86                         Int z = 4;
87                         Int q;
88                         Int c;
89                         Int p;
90                         Bool b;
91
92                         q += q;
93
94                         If(b)
95                         {
96                                 c = p;
97                         }
98
99                         Return(a + z + q + c);
100                 }
101
102                 routine = function("one");
103
104                 if(routine)
105                 {
106                         int (*callable)() = (int(*)())routine->getEntry();
107                         int result = callable();
108                         EXPECT_EQ(result, result);   // Anything is fine, just don't crash
109                 }
110         }
111
112         delete routine;
113 }
114
115 TEST(ReactorUnitTests, Unreachable)
116 {
117         Routine *routine = nullptr;
118
119         {
120                 Function<Int(Int)> function;
121                 {
122                         Int a = function.Arg<0>();
123                         Int z = 4;
124
125                         Return(a + z);
126
127                         // Code beyond this point is unreachable but should not cause any
128                         // compilation issues.
129
130                         z += a;
131                 }
132
133                 routine = function("one");
134
135                 if(routine)
136                 {
137                         int (*callable)(int) = (int(*)(int))routine->getEntry();
138                         int result = callable(16);
139                         EXPECT_EQ(result, 20);
140                 }
141         }
142
143         delete routine;
144 }
145
146 TEST(ReactorUnitTests, VariableAddress)
147 {
148         Routine *routine = nullptr;
149
150         {
151                 Function<Int(Int)> function;
152                 {
153                         Int a = function.Arg<0>();
154                         Int z = 0;
155                         Pointer<Int> p = &z;
156                         *p = 4;
157
158                         Return(a + z);
159                 }
160
161                 routine = function("one");
162
163                 if(routine)
164                 {
165                         int (*callable)(int) = (int(*)(int))routine->getEntry();
166                         int result = callable(16);
167                         EXPECT_EQ(result, 20);
168                 }
169         }
170
171         delete routine;
172 }
173
174 TEST(ReactorUnitTests, SubVectorLoadStore)
175 {
176         Routine *routine = nullptr;
177
178         {
179                 Function<Int(Pointer<Byte>, Pointer<Byte>)> function;
180                 {
181                         Pointer<Byte> in = function.Arg<0>();
182                         Pointer<Byte> out = function.Arg<1>();
183
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);
189
190                         Return(0);
191                 }
192
193                 routine = function("one");
194
195                 if(routine)
196                 {
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};
202
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};
208
209                         int (*callable)(void*, void*) = (int(*)(void*,void*))routine->getEntry();
210                         callable(in, out);
211
212                         for(int row = 0; row < 5; row++)
213                         {
214                                 for(int col = 0; col < 16; col++)
215                                 {
216                                         int i = row * 16 + col;
217
218                                         if(in[i] ==  0)
219                                         {
220                                                 EXPECT_EQ(out[i], -1) << "Row " << row << " column " << col <<  " not left untouched.";
221                                         }
222                                         else
223                                         {
224                                                 EXPECT_EQ(out[i], in[i]) << "Row " << row << " column " << col << " not equal to input.";
225                                         }
226                                 }
227                         }
228                 }
229         }
230
231         delete routine;
232 }
233
234 TEST(ReactorUnitTests, VectorConstant)
235 {
236         Routine *routine = nullptr;
237
238         {
239                 Function<Int(Pointer<Byte>)> function;
240                 {
241                         Pointer<Byte> out = function.Arg<0>();
242
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);
247
248                         Return(0);
249                 }
250
251                 routine = function("one");
252
253                 if(routine)
254                 {
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};
259
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};
264
265                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
266                         callable(out);
267
268                         for(int row = 0; row < 4; row++)
269                         {
270                                 for(int col = 0; col < 16; col++)
271                                 {
272                                         int i = row * 16 + col;
273
274                                         EXPECT_EQ(out[i], exp[i]);
275                                 }
276                         }
277                 }
278         }
279
280         delete routine;
281 }
282
283 TEST(ReactorUnitTests, Concatenate)
284 {
285         Routine *routine = nullptr;
286
287         {
288                 Function<Int(Pointer<Byte>)> function;
289                 {
290                         Pointer<Byte> out = function.Arg<0>();
291
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));
294
295                         Return(0);
296                 }
297
298                 routine = function("one");
299
300                 if(routine)
301                 {
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};
304
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};
307
308                         int (*callable)(void*) = (int(*)(void*))routine->getEntry();
309                         callable(out);
310
311                         for(int row = 0; row < 2; row++)
312                         {
313                                 for(int col = 0; col < 16; col++)
314                                 {
315                                         int i = row * 16 + col;
316
317                                         EXPECT_EQ(out[i], ref[i]) << "Row " << row << " column " << col << " not equal to reference.";
318                                 }
319                         }
320                 }
321         }
322
323         delete routine;
324 }
325
326 TEST(ReactorUnitTests, Swizzle)
327 {
328         Routine *routine = nullptr;
329
330         {
331                 Function<Int(Pointer<Byte>)> function;
332                 {
333                         Pointer<Byte> out = function.Arg<0>();
334
335                         for(int i = 0; i < 256; i++)
336                         {
337                                 *Pointer<Float4>(out + 16 * i) = Swizzle(Float4(1.0f, 2.0f, 3.0f, 4.0f), i);
338                         }
339
340                         for(int i = 0; i < 256; i++)
341                         {
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);
343                         }
344
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));
351
352                         for(int i = 0; i < 256; i++)
353                         {
354                                 *Pointer<Short4>(out + 16 * (512 + 6) + (8 * i)) =
355                                     Swizzle(Short4(1, 2, 3, 4), i);
356                         }
357
358                         for(int i = 0; i < 256; i++)
359                         {
360                                 *Pointer<Int4>(out + 16 * (512 + 6 + i) + (8 * 256)) =
361                                     Swizzle(Int4(1, 2, 3, 4), i);
362                         }
363
364                         Return(0);
365                 }
366
367                 routine = function("one");
368
369                 if(routine)
370                 {
371                         struct
372                         {
373                                 float f[256 + 256 + 2][4];
374                                 int i[388][4];
375                         } out;
376
377                         memset(&out, 0, sizeof(out));
378
379                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
380                         callable(&out);
381
382                         for(int i = 0; i < 256; i++)
383                         {
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);
388                         }
389
390                         for(int i = 0; i < 256; i++)
391                         {
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);
396                         }
397
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);
402
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);
407
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);
412
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);
417
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);
422
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);
427
428                         for(int i = 0; i < 256; i++)
429                         {
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);
438                         }
439
440                         for(int i = 0; i < 256; i++)
441                         {
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);
446                         }
447                 }
448         }
449
450         delete routine;
451 }
452
453 TEST(ReactorUnitTests, Branching)
454 {
455         Routine *routine = nullptr;
456
457         {
458                 Function<Int(Void)> function;
459                 {
460                         Int x = 0;
461
462                         For(Int i = 0, i < 8, i++)
463                         {
464                                 If(i < 2)
465                                 {
466                                         x += 1;
467                                 }
468                                 Else If(i < 4)
469                                 {
470                                         x += 10;
471                                 }
472                                 Else If(i < 6)
473                                 {
474                                         x += 100;
475                                 }
476                                 Else
477                                 {
478                                         x += 1000;
479                                 }
480
481                                 For(Int i = 0, i < 5, i++)
482                                         x += 10000;
483                         }
484
485                         For(Int i = 0, i < 10, i++)
486                                 for(int i = 0; i < 10; i++)
487                                         For(Int i = 0, i < 10, i++)
488                                         {
489                                                 x += 1000000;
490                                         }
491
492                         For(Int i = 0, i < 2, i++)
493                                 If(x == 1000402222)
494                                 {
495                                         If(x != 1000402222)
496                                                 x += 1000000000;
497                                 }
498                                 Else
499                                         x = -5;
500
501                         Return(x);
502                 }
503
504                 routine = function("one");
505
506                 if(routine)
507                 {
508                         int(*callable)() = (int(*)())routine->getEntry();
509                         int result = callable();
510
511                         EXPECT_EQ(result, 1000402222);
512                 }
513         }
514
515         delete routine;
516 }
517
518 TEST(ReactorUnitTests, MinMax)
519 {
520         Routine *routine = nullptr;
521
522         {
523                 Function<Int(Pointer<Byte>)> function;
524                 {
525                         Pointer<Byte> out = function.Arg<0>();
526
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));
529
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));
534
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));
539
540                         Return(0);
541                 }
542
543                 routine = function("one");
544
545                 if(routine)
546                 {
547                         unsigned int out[10][4];
548
549                         memset(&out, 0, sizeof(out));
550
551                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
552                         callable(&out);
553
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);
558
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);
563
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);
568
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);
573
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);
578
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);
583
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);
588
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);
593
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);
598
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);
603                 }
604         }
605
606         delete routine;
607 }
608
609 TEST(ReactorUnitTests, NotNeg)
610 {
611         Routine *routine = nullptr;
612
613         {
614                 Function<Int(Pointer<Byte>)> function;
615                 {
616                         Pointer<Byte> out = function.Arg<0>();
617
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);
622
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);
627
628                         *Pointer<Float4>(out + 16 * 8) = -Float4(1.0f, -1.0f, 0.0f, -0.0f);
629
630                         Return(0);
631                 }
632
633                 routine = function("one");
634
635                 if(routine)
636                 {
637                         unsigned int out[10][4];
638
639                         memset(&out, 0, sizeof(out));
640
641                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
642                         callable(&out);
643
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);
648
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);
653
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);
658
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);
663
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);
668
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);
673
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);
678
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);
683
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);
688                 }
689         }
690
691         delete routine;
692 }
693
694 TEST(ReactorUnitTests, VectorCompare)
695 {
696         Routine *routine = nullptr;
697
698         {
699                 Function<Int(Pointer<Byte>)> function;
700                 {
701                         Pointer<Byte> out = function.Arg<0>();
702
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));
706
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));
710
711                         Return(0);
712                 }
713
714                 routine = function("one");
715
716                 if(routine)
717                 {
718                         unsigned int out[6][4];
719
720                         memset(&out, 0, sizeof(out));
721
722                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
723                         callable(&out);
724
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);
729
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);
734
735                         EXPECT_EQ(out[2][0], 0xFF000000u);
736                         EXPECT_EQ(out[2][1], 0x00000000u);
737
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);
742
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);
747
748                         EXPECT_EQ(out[5][0], 0x00000000u);
749                         EXPECT_EQ(out[5][1], 0xFFFFFFFFu);
750                 }
751         }
752
753         delete routine;
754 }
755
756 TEST(ReactorUnitTests, SaturatedAddAndSubtract)
757 {
758         Routine *routine = nullptr;
759
760         {
761                 Function<Int(Pointer<Byte>)> function;
762                 {
763                         Pointer<Byte> out = function.Arg<0>();
764
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));
774
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));
787
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),
792                                        Short4(3, 2, 1, 0));
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),
798                                        Short4(3, 2, 1, 0));
799
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));
807
808                         Return(0);
809                 }
810
811                 routine = function("one");
812
813                 if(routine)
814                 {
815                         unsigned int out[14][2];
816
817                         memset(&out, 0, sizeof(out));
818
819                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
820                         callable(&out);
821
822                         EXPECT_EQ(out[0][0], 0x08080808u);
823                         EXPECT_EQ(out[0][1], 0x08080808u);
824
825                         EXPECT_EQ(out[1][0], 0xFFFFFFFFu);
826                         EXPECT_EQ(out[1][1], 0xFEFFFFFFu);
827
828                         EXPECT_EQ(out[2][0], 0x00000000u);
829                         EXPECT_EQ(out[2][1], 0x08060402u);
830
831                         EXPECT_EQ(out[3][0], 0x08080808u);
832                         EXPECT_EQ(out[3][1], 0x08080808u);
833
834                         EXPECT_EQ(out[4][0], 0x7F7F7F7Fu);
835                         EXPECT_EQ(out[4][1], 0x7E7F7F7Fu);
836
837                         EXPECT_EQ(out[5][0], 0x80808080u);
838                         EXPECT_EQ(out[5][1], 0x88868482u);
839
840                         EXPECT_EQ(out[6][0], 0x80808080u);
841                         EXPECT_EQ(out[6][1], 0x88868482u);
842
843                         EXPECT_EQ(out[7][0], 0x00040004u);
844                         EXPECT_EQ(out[7][1], 0x00040004u);
845
846                         EXPECT_EQ(out[8][0], 0x7FFF7FFFu);
847                         EXPECT_EQ(out[8][1], 0x7FFE7FFFu);
848
849                         EXPECT_EQ(out[9][0], 0x80008000u);
850                         EXPECT_EQ(out[9][1], 0x80048002u);
851
852                         EXPECT_EQ(out[10][0], 0x80008000u);
853                         EXPECT_EQ(out[10][1], 0x80048002u);
854
855                         EXPECT_EQ(out[11][0], 0x00040004u);
856                         EXPECT_EQ(out[11][1], 0x00040004u);
857
858                         EXPECT_EQ(out[12][0], 0xFFFFFFFFu);
859                         EXPECT_EQ(out[12][1], 0xFFFEFFFFu);
860
861                         EXPECT_EQ(out[13][0], 0x00000000u);
862                         EXPECT_EQ(out[13][1], 0x00040002u);
863                 }
864         }
865
866         delete routine;
867 }
868
869 TEST(ReactorUnitTests, Unpack)
870 {
871         Routine *routine = nullptr;
872
873         {
874                 Function<Int(Pointer<Byte>,Pointer<Byte>)> function;
875                 {
876                         Pointer<Byte> in = function.Arg<0>();
877                         Pointer<Byte> out = function.Arg<1>();
878
879                         Byte4 test_byte_a = *Pointer<Byte4>(in + 4 * 0);
880                         Byte4 test_byte_b = *Pointer<Byte4>(in + 4 * 1);
881
882                         *Pointer<Short4>(out + 8 * 0) =
883                                 Unpack(test_byte_a, test_byte_b);
884
885                         *Pointer<Short4>(out + 8 * 1) = Unpack(test_byte_a);
886
887                         Return(0);
888                 }
889
890                 routine = function("one");
891
892                 if(routine)
893                 {
894                         unsigned int in[1][2];
895                         unsigned int out[2][2];
896
897                         memset(&out, 0, sizeof(out));
898
899                         in[0][0] = 0xABCDEF12u;
900                         in[0][1] = 0x34567890u;
901
902                         int(*callable)(void*,void*) = (int(*)(void*,void*))routine->getEntry();
903                         callable(&in, &out);
904
905                         EXPECT_EQ(out[0][0], 0x78EF9012u);
906                         EXPECT_EQ(out[0][1], 0x34AB56CDu);
907
908                         EXPECT_EQ(out[1][0], 0xEFEF1212u);
909                         EXPECT_EQ(out[1][1], 0xABABCDCDu);
910                 }
911         }
912
913         delete routine;
914 }
915
916 TEST(ReactorUnitTests, Pack)
917 {
918         Routine *routine = nullptr;
919
920         {
921                 Function<Int(Pointer<Byte>)> function;
922                 {
923                         Pointer<Byte> out = function.Arg<0>();
924
925                         *Pointer<SByte8>(out + 8 * 0) =
926                                 PackSigned(Short4(-1, -2, 1, 2),
927                                            Short4(3, 4, -3, -4));
928
929                         *Pointer<Byte8>(out + 8 * 1) =
930                                 PackUnsigned(Short4(-1, -2, 1, 2),
931                                              Short4(3, 4, -3, -4));
932
933                         *Pointer<Short8>(out + 8 * 2) =
934                                 PackSigned(Int4(-1, -2, 1, 2),
935                                            Int4(3, 4, -3, -4));
936
937                         *Pointer<UShort8>(out + 8 * 4) =
938                                 PackUnsigned(Int4(-1, -2, 1, 2),
939                                              Int4(3, 4, -3, -4));
940
941                         Return(0);
942                 }
943
944                 routine = function("one");
945
946                 if(routine)
947                 {
948                         unsigned int out[6][2];
949
950                         memset(&out, 0, sizeof(out));
951
952                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
953                         callable(&out);
954
955                         EXPECT_EQ(out[0][0], 0x0201FEFFu);
956                         EXPECT_EQ(out[0][1], 0xFCFD0403u);
957
958                         EXPECT_EQ(out[1][0], 0x02010000u);
959                         EXPECT_EQ(out[1][1], 0x00000403u);
960
961                         EXPECT_EQ(out[2][0], 0xFFFEFFFFu);
962                         EXPECT_EQ(out[2][1], 0x00020001u);
963
964                         EXPECT_EQ(out[3][0], 0x00040003u);
965                         EXPECT_EQ(out[3][1], 0xFFFCFFFDu);
966
967                         EXPECT_EQ(out[4][0], 0x00000000u);
968                         EXPECT_EQ(out[4][1], 0x00020001u);
969
970                         EXPECT_EQ(out[5][0], 0x00040003u);
971                         EXPECT_EQ(out[5][1], 0x00000000u);
972                 }
973         }
974
975         delete routine;
976 }
977
978 TEST(ReactorUnitTests, MulHigh)
979 {
980         Routine *routine = nullptr;
981
982         {
983                 Function<Int(Pointer<Byte>)> function;
984                 {
985                         Pointer<Byte> out = function.Arg<0>();
986
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));
993
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));
1000
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));
1007
1008                         // (U)Short8 variants currently unimplemented.
1009
1010                         Return(0);
1011                 }
1012
1013                 routine = function("one");
1014
1015                 if(routine)
1016                 {
1017                         unsigned int out[6][4];
1018
1019                         memset(&out, 0, sizeof(out));
1020
1021                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
1022                         callable(&out);
1023
1024                         EXPECT_EQ(out[0][0], 0x00080002u);
1025                         EXPECT_EQ(out[0][1], 0x008D000Fu);
1026
1027                         EXPECT_EQ(out[1][0], 0x00080002u);
1028                         EXPECT_EQ(out[1][1], 0xE8C0000Fu);
1029
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);
1034
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);
1039
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);
1044
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);
1049                 }
1050         }
1051
1052         delete routine;
1053 }
1054
1055 TEST(ReactorUnitTests, MulAdd)
1056 {
1057         Routine *routine = nullptr;
1058
1059         {
1060                 Function<Int(Pointer<Byte>)> function;
1061                 {
1062                         Pointer<Byte> out = function.Arg<0>();
1063
1064                         *Pointer<Int2>(out + 8 * 0) =
1065                                 MulAdd(Short4(0x1aa, 0x2dd, 0x3ee, 0xF422),
1066                                        Short4(0x1bb, 0x2cc, 0x3ff, 0xF411));
1067
1068                         // (U)Short8 variant is mentioned but unimplemented
1069                         Return(0);
1070                 }
1071
1072                 routine = function("one");
1073
1074                 if(routine)
1075                 {
1076                         unsigned int out[1][2];
1077
1078                         memset(&out, 0, sizeof(out));
1079
1080                         int(*callable)(void*) = (int(*)(void*))routine->getEntry();
1081                         callable(&out);
1082
1083                         EXPECT_EQ(out[0][0], 0x000AE34Au);
1084                         EXPECT_EQ(out[0][1], 0x009D5254u);
1085                 }
1086         }
1087
1088         delete routine;
1089 }
1090
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)
1098 {
1099     Routine *routine = nullptr;
1100
1101     {
1102         Function<Void(Pointer<Byte>, Pointer<Byte>)> function;
1103         {
1104             Pointer<Byte> in = function.Arg<0>();
1105             Pointer<Byte> out = function.Arg<1>();
1106
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);
1123
1124             Float4 ab = a + b;
1125             Float4 cd = c + d;
1126             Float4 ef = e + f;
1127             Float4 gh = g + h;
1128             Float4 ij = i + j;
1129             Float4 kl = k + l;
1130             Float4 mn = m + n;
1131             Float4 op = o + p;
1132
1133             Float4 abcd = ab + cd;
1134             Float4 efgh = ef + gh;
1135             Float4 ijkl = ij + kl;
1136             Float4 mnop = mn + op;
1137
1138             Float4 abcdefgh = abcd + efgh;
1139             Float4 ijklmnop = ijkl + mnop;
1140             Float4 sum = abcdefgh + ijklmnop;
1141             *Pointer<Float4>(out) = sum;
1142             Return();
1143         }
1144
1145         routine = function("one");
1146         assert(routine);
1147
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 };
1164
1165         float result[4];
1166         void (*callable)(float*, float*) = (void(*)(float*,float*))routine->getEntry();
1167
1168         callable(input, result);
1169
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);
1174     }
1175
1176     delete routine;
1177 }
1178
1179 template <typename T>
1180 class CToReactorCastTest : public ::testing::Test
1181 {
1182 public:
1183         using CType = typename std::tuple_element<0, T>::type;
1184         using ReactorType = typename std::tuple_element<1, T>::type;
1185 };
1186
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>
1197         >;
1198
1199 TYPED_TEST_CASE(CToReactorCastTest, CToReactorCastTestTypes);
1200
1201 TYPED_TEST(CToReactorCastTest, Casts)
1202 {
1203         using CType = typename TestFixture::CType;
1204         using ReactorType = typename TestFixture::ReactorType;
1205
1206         Routine *routine = nullptr;
1207
1208         {
1209                 Function< Int(ReactorType) > function;
1210                 {
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.
1216                 }
1217
1218                 routine = function("one");
1219
1220                 if(routine)
1221                 {
1222                         auto callable = (int(*)(CType))routine->getEntry();
1223                         CType in = {};
1224                         EXPECT_EQ(callable(in), 1);
1225                 }
1226         }
1227
1228         delete routine;
1229 }
1230
1231 template <typename T>
1232 class GEPTest : public ::testing::Test
1233 {
1234 public:
1235         using CType = typename std::tuple_element<0, T>::type;
1236         using ReactorType = typename std::tuple_element<1, T>::type;
1237 };
1238
1239 using GEPTestTypes = ::testing::Types
1240         <
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>
1269         >;
1270
1271 TYPED_TEST_CASE(GEPTest, GEPTestTypes);
1272
1273 TYPED_TEST(GEPTest, PtrOffsets)
1274 {
1275         using CType = typename TestFixture::CType;
1276         using ReactorType = typename TestFixture::ReactorType;
1277
1278         Routine *routine = nullptr;
1279
1280         {
1281                 Function< Pointer<ReactorType>(Pointer<ReactorType>, Int) > function;
1282                 {
1283                         Pointer<ReactorType> pointer = function.template Arg<0>();
1284                         Int index = function.template Arg<1>();
1285                         Return(&pointer[index]);
1286                 }
1287
1288                 routine = function("one");
1289
1290                 if(routine)
1291                 {
1292                         auto callable = (CType*(*)(CType*, unsigned int))routine->getEntry();
1293
1294                         union PtrInt {
1295                                 CType* p;
1296                                 size_t i;
1297                         };
1298
1299                         PtrInt base;
1300                         base.i = 0x10000;
1301
1302                         for (int i = 0; i < 5; i++)
1303                         {
1304                                 PtrInt reference;
1305                                 reference.p = &base.p[i];
1306
1307                                 PtrInt result;
1308                                 result.p = callable(base.p, i);
1309
1310                                 auto expect = reference.i - base.i;
1311                                 auto got = result.i - base.i;
1312
1313                                 EXPECT_EQ(got, expect) << "i:" << i;
1314                         }
1315                 }
1316         }
1317
1318         delete routine;
1319 }
1320
1321 int main(int argc, char **argv)
1322 {
1323         ::testing::InitGoogleTest(&argc, argv);
1324         return RUN_ALL_TESTS();
1325 }