source: CLRX/CLRadeonExtender/trunk/tests/amdasm/AsmRegAlloc.cpp @ 3601

Last change on this file since 3601 was 3601, checked in by matszpk, 10 months ago

CLRadeonExtender: AsmRegAlloc?: Next createSSAData testcase.

File size: 58.5 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2018 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <algorithm>
22#include <iostream>
23#include <sstream>
24#include <string>
25#include <vector>
26#include <cstring>
27#include <CLRX/utils/Utilities.h>
28#include <CLRX/amdasm/Assembler.h>
29#include <CLRX/utils/Containers.h>
30#include "../TestUtils.h"
31
32using namespace CLRX;
33
34typedef AsmRegAllocator::CodeBlock CodeBlock;
35typedef AsmRegAllocator::NextBlock NextBlock;
36
37struct CCodeBlock
38{
39    size_t start, end; // place in code
40    Array<NextBlock> nexts; ///< nexts blocks
41    bool haveCalls;
42    bool haveReturn;
43    bool haveEnd;
44};
45
46struct AsmCodeStructCase
47{
48    const char* input;
49    Array<CCodeBlock> codeBlocks;
50    bool good;
51    const char* errorMessages;
52};
53
54static const AsmCodeStructCase codeStructTestCases1Tbl[] =
55{
56    {   // 0
57        "v_mov_b32 v1, v2\n"
58        "v_mov_b32 v1, v3\n",
59        {
60            { 0, 8, { }, false, false, true }
61        },
62        true, ""
63    },
64    {   // 1
65        "v_mov_b32 v1, v2\n"
66        "v_mov_b32 v1, v3\n"
67        ".cf_end\n"
68        ".cf_start\n"
69        "v_mov_b32 v4, v2\n"
70        "v_mov_b32 v8, v3\n"
71        "v_mov_b32 v8, v3\n"
72        ".cf_end\n",
73        {
74            { 0, 8, { }, false, false, true },
75            { 8, 20, { }, false, false, true }
76        },
77        true, ""
78    },
79    {   // 2 - ignore cf_start to cf_end (except first)
80        "v_mov_b32 v1, v2\n"
81        "v_mov_b32 v1, v3\n"
82        ".cf_start\n"
83        "v_mov_b32 v4, v2\n"
84        "v_mov_b32 v8, v3\n"
85        ".cf_start\n"
86        "v_mov_b32 v8, v3\n"
87        ".cf_end\n"
88        ".cf_start\n"
89        "v_and_b32 v6, v1, v2\n"
90        ".cf_start\n"
91        "v_and_b32 v9, v1, v3\n"
92        ".cf_end\n",
93        {
94            { 0, 20, { }, false, false, true },
95            { 20, 28, { }, false, false, true }
96        },
97        true, ""
98    },
99    {   // 3 - ignore cf_end
100        "v_mov_b32 v1, v2\n"
101        "v_mov_b32 v1, v3\n"
102        ".cf_end\n"
103        "v_mov_b32 v4, v2\n"
104        "v_mov_b32 v8, v3\n"
105        "v_mov_b32 v8, v3\n"
106        ".cf_end\n"
107        ".cf_start\n"
108        "v_and_b32 v9, v1, v3\n"
109        ".cf_end\n",
110        {
111            { 0, 8, { }, false, false, true },
112            { 20, 24, { }, false, false, true }
113        },
114        true, ""
115    },
116    {   /* 4 - cond jump */
117        "v_mov_b32 v1, v2\n"
118        "v_mov_b32 v1, v3\n"
119        "label2:\n"
120        "v_mov_b32 v1, v3\n"
121        "v_mov_b32 v1, v3\n"
122        "s_cbranch_vccz label2\n"
123        "s_xor_b32 s3, s5, s8\n"
124        "s_endpgm\n",
125        {
126            { 0, 8, { }, false, false, false },
127            { 8, 20,
128              { { 1, false }, { 2, false } },
129              false, false, false },
130            { 20, 28, { }, false, false, true }
131        },
132        true, ""
133    },
134    {   /* 5 - jump */
135        "v_mov_b32 v1, v2\n"
136        "v_mov_b32 v1, v3\n"
137        "label2:\n"
138        "v_mov_b32 v1, v3\n"
139        "v_mov_b32 v1, v3\n"
140        "s_branch label2\n"
141        "s_xor_b32 s3, s5, s8\n"
142        "s_endpgm\n",
143        {
144            { 0, 8, { }, false, false, false },
145            { 8, 20,
146              { { 1, false } },
147              false, false, true }
148        },
149        true, ""
150    },
151    {
152        /* 6 - jump */
153        "v_mov_b32 v1, v2\n"
154        "v_mov_b32 v1, v3\n"
155        "lstart:\n"
156        ".cf_jump l0, l1, l2\n"
157        "s_setpc_b64 s[0:1]\n"
158        "l0:\n"
159        "v_add_f32 v1, v2, v3\n"
160        "s_branch lend\n"
161        "l1:\n"
162        "v_add_f32 v1, v2, v3\n"
163        "s_branch lend\n"
164        "l2:\n"
165        "v_add_f32 v1, v2, v3\n"
166        "s_branch lend\n"
167        "lend:\n"
168        "s_cbranch_vccz lstart\n"
169        "s_endpgm\n",
170        {
171            { 0, 8, { }, false, false, false },
172            { 8, 12,
173              { { 2, false }, { 3, false }, { 4, false } },
174              false, false, true },
175            { 12, 20,
176              { { 5, false } },
177              false, false, true },
178            { 20, 28,
179              { { 5, false } },
180              false, false, true },
181            { 28, 36,
182              { { 5, false } },
183              false, false, true },
184            { 36, 40,
185              { { 1, false }, { 6, false } },
186              false, false, false },
187            { 40, 44, { }, false, false, true }
188        },
189        true, ""
190    },
191    {   /* 7 - subroutines */
192        R"ffDXD(
193        v_mov_b32 v1, v2
194        v_mov_b32 v1, v3
195        .cf_call l0, l1, l2
196        s_setpc_b64 s[0:1]
197        v_sub_f32 v1, v3, v6    # 12
198        s_branch j0
199b0:     v_add_u32 v4, vcc, v6, v11  # 20
200        v_mac_f32 v6, v6, v6
201        s_endpgm
202l0:     # 32
203        v_add_f32 v1, v2, v3
204        v_add_f32 v1, v2, v3
205        .cf_ret
206        s_swappc_b64 s[0:1], s[0:1]
207l1:     # 44
208        v_add_f32 v1, v2, v3
209        v_add_f32 v1, v2, v3
210        v_add_f32 v1, v2, v3
211        .cf_ret
212        s_swappc_b64 s[0:1], s[0:1]
213l2:     # 60
214        v_add_f32 v1, v2, v3
215        v_add_f32 v1, v2, v3
216        v_add_f32 v1, v2, v3
217        v_add_f32 v1, v2, v3
218        v_add_f32 v1, v2, v3
219        .cf_ret
220        s_swappc_b64 s[0:1], s[0:1]
221j0:     # 84
222        v_lshrrev_b32 v4, 3, v2
223        v_lshrrev_b32 v4, 3, v2
224        s_branch b0
225)ffDXD",
226        {
227            { 0, 12,
228                { { 1, false }, { 3, true }, { 4, true }, { 5, true } },
229                true, false, false },
230            { 12, 20, { { 6, false } }, false, false, true },
231            { 20, 32, { }, false, false, true },
232            { 32, 44, { }, false, true, true },
233            { 44, 60, { }, false, true, true },
234            { 60, 84, { }, false, true, true },
235            { 84, 96, { { 2, false } }, false, false, true }
236        },
237        true, ""
238    },
239    {   /* 8 - subroutines 2 - more complex */
240        R"ffDXD(
241        v_mov_b32 v1, v2    # 0
242        v_mov_b32 v1, v3
243loop:   s_mov_b32 s5, s0    # 8
244        .cf_call c1,c2,c3
245        s_swappc_b64 s[0:1], s[0:1]
246        v_and_b32 v4, v5, v4    # 16
247        v_and_b32 v4, v5, v3
248        v_and_b32 v4, v5, v4
249        .cf_call c5,c6
250        s_swappc_b64 s[0:1], s[0:1]
251        v_and_b32 v4, v5, v3    # 32
252        v_and_b32 v4, v5, v9
253        s_add_i32 s3, s3, s1
254        s_cbranch_vccnz loop
255        v_mac_f32 v4, v6, v7    # 48
256        s_endpgm
257.p2align 4
258c1:     v_xor_b32 v3, v4, v3    # 64
259        v_xor_b32 v3, v4, v7
260        v_xor_b32 v3, v4, v8
261        .cf_ret
262        s_swappc_b64 s[0:1], s[0:1]
263.p2align 4
264c2:     v_xor_b32 v3, v4, v3    # 80
265        v_xor_b32 v3, v4, v7
266c5:     v_xor_b32 v3, v4, v8    # 88
267        .cf_call c4
268        s_swappc_b64 s[0:1], s[0:1]
269        v_or_b32 v3, v11, v9    # 96
270        .cf_ret
271        s_swappc_b64 s[0:1], s[0:1]
272.p2align 4
273c3:     v_xor_b32 v3, v4, v3    # 112
274        v_xor_b32 v3, v4, v8
275        .cf_ret
276        s_swappc_b64 s[0:1], s[0:1]
277.p2align 4
278c4:     v_xor_b32 v3, v4, v3    # 128
279        v_xor_b32 v3, v9, v8
280c6: loop2:
281        v_xor_b32 v3, v9, v8    # 136
282        v_xor_b32 v3, v9, v8
283        s_add_i32 s4, 1, s34
284        s_cbranch_vccz loop2
285        v_lshlrev_b32 v3, 4, v2 # 152
286        .cf_ret
287        s_swappc_b64 s[0:1], s[0:1]
288)ffDXD",
289        {
290            { 0, 8, { }, false, false, false },
291            { 8, 16,
292                { { 2, false }, { 5, true }, { 6, true }, { 9, true } },
293                true, false, false },
294            // 2
295            { 16, 32,
296                { { 3, false }, { 7, true }, { 11, true } },
297                true, false, false },
298            { 32, 48,
299                { { 1, false }, { 4, false } },
300                false, false, false },
301            // 4
302            { 48, 56, { }, false, false, true },
303            // 5 - c1 subroutine
304            { 64, 80, { }, false, true, true },
305            // 6 - c2 subroutine
306            { 80, 88, { }, false, false, false },
307            { 88, 96, { { 8, false }, { 10, true } },
308                true, false, false },
309            { 96, 104, { }, false, true, true },
310            // 9 - c3 subroutine
311            { 112, 124, { }, false, true, true },
312            // 10 - c4 subroutine
313            { 128, 136, { }, false, false, false },
314            { 136, 152,
315                { { 11, false }, { 12, false } },
316                false, false, false },
317            { 152, 160, { }, false, true, true }
318        },
319        true, ""
320    },
321    {   // 9 - switch
322        R"ffDXD(
323            v_mac_f32 v6, v9, v8    # 0
324            v_xor_b32 v3, v9, v8
325            .cf_jump j1, j2, j3, j4
326            s_setpc_b64 s[0:1]
327           
328j1:         v_xor_b32 v3, v9, v8    # 12
329            v_xor_b32 v3, v9, v8
330            v_xor_b32 v3, v9, v8
331            s_branch b0
332
333j2:         v_xor_b32 v3, v9, v8    # 28
334            v_xor_b32 v1, v5, v8
335            v_and_b32 v2, v9, v8
336            v_xor_b32 v3, v9, v8
337            s_branch b0
338
339j3:         v_xor_b32 v3, v9, v8    # 48
340            v_xor_b32 v1, v5, v8
341            s_branch b0
342
343j4:         v_xor_b32 v3, v9, v8    # 60
344            v_xor_b32 v1, v5, v8
345            v_xor_b32 v1, v5, v8
346b0:         s_sub_u32 s0, s1, s2    # 72
347            s_endpgm
348)ffDXD",
349        {
350            { 0, 12,
351                { { 1, false }, { 2, false }, { 3, false }, { 4, false } },
352                false, false, true },
353            { 12, 28, { { 5, false } }, false, false, true },
354            { 28, 48, { { 5, false } }, false, false, true },
355            { 48, 60, { { 5, false } }, false, false, true },
356            { 60, 72, { }, false, false, false },
357            { 72, 80, { }, false, false, true }
358        },
359        true, ""
360    },
361    {   // 10 - multiple kernels
362        R"ffDXD(
363            .cf_start
364            v_mac_f32 v6, v9, v8    # 0
365            v_xor_b32 v3, v9, v8
366            .cf_end
367.p2align 6
368            .cf_start
369            v_xor_b32 v3, v9, v8
370            v_xor_b32 v1, v5, v8
371            v_xor_b32 v1, v5, v8
372            v_xor_b32 v1, v5, v8
373            s_endpgm
374.p2align 6
375            .cf_start       # empty block, ignored
376            .cf_end
377            .cf_start
378            v_xor_b32 v3, v9, v8
379            v_xor_b32 v1, v5, v8
380            v_xor_b32 v3, v9, v8
381            v_or_b32 v3, v9, v8
382            v_or_b32 v3, v9, v8
383            s_endpgm
384            .cf_end
385            .cf_start
386            v_or_b32 v3, v9, v8
387            .cf_end
388            .cf_start   # empty block, ignored
389            .cf_end
390)ffDXD",
391        {
392            { 0, 8, { }, false, false, true },
393            { 64, 84, { }, false, false, true },
394            { 128, 152, { }, false, false, true },
395            { 152, 156, { }, false, false, true }
396        },
397        true, ""
398    },
399    {   // 11 - different type of jumps
400        R"ffDXD(
401            v_mac_f32 v6, v9, v8    # 0
402            v_xor_b32 v3, v9, v8
403            .cf_jump j1, j4
404            .cf_cjump j2, j3
405            s_setpc_b64 s[0:1]
406           
407            v_mov_b32 v5, v3
408            .cf_jump j1, j4
409            .cf_cjump j2, j3
410            s_setpc_b64 s[0:1]
411            .cf_end
412           
413j1:         v_xor_b32 v3, v9, v8    # 20
414            v_xor_b32 v3, v9, v8
415            v_xor_b32 v3, v9, v8
416            s_branch b0
417
418j2:         v_xor_b32 v3, v9, v8    # 36
419            v_xor_b32 v1, v5, v8
420            v_and_b32 v2, v9, v8
421            v_xor_b32 v3, v9, v8
422            s_branch b0
423
424j3:         v_xor_b32 v3, v9, v8    # 56
425            v_xor_b32 v1, v5, v8
426            s_branch b0
427
428j4:         v_xor_b32 v3, v9, v8    # 68
429            v_xor_b32 v1, v5, v8
430            v_xor_b32 v1, v5, v8
431b0:         s_sub_u32 s0, s1, s2    # 80
432            s_endpgm
433)ffDXD",
434        {
435            { 0, 12,
436                { { 1, false }, { 2, false }, { 3, false },
437                  { 4, false }, { 5, false } },
438                false, false, false },
439            { 12, 20,
440                { { 2, false }, { 3, false }, { 4, false }, { 5, false } },
441                false, false, true }, // have cf_end, force haveEnd
442            { 20, 36, { { 6, false } }, false, false, true },
443            { 36, 56, { { 6, false } }, false, false, true },
444            { 56, 68, { { 6, false } }, false, false, true },
445            { 68, 80, { }, false, false, false },
446            { 80, 88, { }, false, false, true }
447        },
448        true, ""
449    },
450    {   // 12 - many jumps to same place
451        R"ffDXD(
452            v_mac_f32 v6, v9, v8    # 0
453            v_xor_b32 v3, v9, v8
454            s_cbranch_vccz j1
455            v_mov_b32 v4, v3        # 12
456            v_mov_b32 v4, v3
457            s_cbranch_execz j1
458            v_mov_b32 v4, v3        # 24
459            v_mov_b32 v4, v3
460            s_cbranch_execnz b0
461            s_branch j2             # 36
462b0:         v_mov_b32 v4, v3        # 40
463            v_mov_b32 v5, v3
464            v_mov_b32 v5, v4
465            s_branch j2
466j1:         v_max_u32 v4, v1, v6    # 56
467            s_endpgm
468j2:         v_min_i32 v4, v1, v6    # 64
469            v_min_i32 v3, v1, v6
470            .cf_call c1
471            s_swappc_b64 s[0:1], s[0:1]
472            v_min_i32 v3, v1, v6    # 76
473            .cf_call c1
474            s_swappc_b64 s[0:1], s[0:1]
475            v_min_i32 v3, v1, v6    # 84
476            s_endpgm
477c1:         v_add_f32 v6, v1, v4    # 92
478            v_add_f32 v6, v1, v4
479            .cf_ret
480            s_swappc_b64 s[0:1], s[0:1]
481)ffDXD",
482        {
483            { 0, 12,
484                { { 1, false }, { 5, false } },
485                false, false, false },
486            { 12, 24,
487                { { 2, false }, { 5, false } },
488                false, false, false },
489            { 24, 36,
490                { { 3, false }, { 4, false } },
491                false, false, false },
492            { 36, 40, { { 6, false } }, false, false, true },
493            { 40, 56, { { 6, false } }, false, false, true },
494            // 5
495            { 56, 64, { }, false, false, true },
496            { 64, 76,
497                { { 7, false }, { 9, true } },
498                true, false, false },
499            { 76, 84,
500                { { 8, false }, { 9, true } },
501                true, false, false },
502            { 84, 92, { }, false, false, true },
503            // 9 - subroutine
504            { 92, 104, { }, false, true, true }
505        },
506        true, ""
507    },
508    {   /* 13 - subroutines 2 (one is jump) */
509        R"ffDXD(
510        v_mov_b32 v1, v2
511        v_mov_b32 v1, v3
512        .cf_call l0, l1
513        .cf_jump l2
514        s_setpc_b64 s[0:1]
515        v_sub_f32 v1, v3, v6    # 12
516        s_branch j0
517b0:     v_add_u32 v4, vcc, v6, v11  # 20
518        v_mac_f32 v6, v6, v6
519        s_endpgm
520l0:     # 32
521        v_add_f32 v1, v2, v3
522        v_add_f32 v1, v2, v3
523        .cf_ret
524        s_swappc_b64 s[0:1], s[0:1]
525l1:     # 44
526        v_add_f32 v1, v2, v3
527        v_add_f32 v1, v2, v3
528        v_add_f32 v1, v2, v3
529        .cf_ret
530        s_swappc_b64 s[0:1], s[0:1]
531l2:     # 60
532        v_add_f32 v1, v2, v3
533        v_add_f32 v1, v2, v3
534        v_add_f32 v1, v2, v3
535        v_add_f32 v1, v2, v3
536        v_add_f32 v1, v2, v3
537        .cf_ret
538        s_swappc_b64 s[0:1], s[0:1]
539j0:     # 84
540        v_lshrrev_b32 v4, 3, v2
541        v_lshrrev_b32 v4, 3, v2
542        s_branch b0
543)ffDXD",
544        {
545            { 0, 12,
546                { { 1, false }, { 5, false }, { 3, true }, { 4, true } },
547                true, false, true },
548            { 12, 20, { { 6, false } }, false, false, true },
549            { 20, 32, { }, false, false, true },
550            { 32, 44, { }, false, true, true },
551            { 44, 60, { }, false, true, true },
552            { 60, 84, { }, false, true, true },
553            { 84, 96, { { 2, false } }, false, false, true }
554        },
555        true, ""
556    },
557    {   /* 14 - empty */
558        ".regvar sa:s:8, va:v:12, vb:v:10\n",
559        { },
560        true, ""
561    },
562    {   // 15 - switch (empty block at end)
563        R"ffDXD(
564            v_mac_f32 v6, v9, v8    # 0
565            v_xor_b32 v3, v9, v8
566            .cf_jump j1, j2, j3, j4
567            s_setpc_b64 s[0:1]
568           
569j1:         v_xor_b32 v3, v9, v8    # 12
570            v_xor_b32 v3, v9, v8
571            v_xor_b32 v3, v9, v8
572            s_branch b0
573
574j2:         v_xor_b32 v3, v9, v8    # 28
575            v_xor_b32 v1, v5, v8
576            v_and_b32 v2, v9, v8
577            v_xor_b32 v3, v9, v8
578            s_branch b0
579
580j3:         v_xor_b32 v3, v9, v8    # 48
581            v_xor_b32 v1, v5, v8
582            s_branch b0
583
584j4:         v_xor_b32 v3, v9, v8    # 60
585            v_xor_b32 v1, v5, v8
586            v_xor_b32 v1, v5, v8
587b0:         # 72
588)ffDXD",
589        {
590            { 0, 12,
591                { { 1, false }, { 2, false }, { 3, false }, { 4, false } },
592                false, false, true },
593            { 12, 28, { { 5, false } }, false, false, true },
594            { 28, 48, { { 5, false } }, false, false, true },
595            { 48, 60, { { 5, false } }, false, false, true },
596            { 60, 72, { }, false, false, false },
597            { 72, 72, { }, false, false, true }
598        },
599        true, ""
600    },
601};
602
603static void testCreateCodeStructure(cxuint i, const AsmCodeStructCase& testCase)
604{
605    std::istringstream input(testCase.input);
606    std::ostringstream errorStream;
607   
608    Assembler assembler("test.s", input, ASM_ALL&~ASM_ALTMACRO,
609                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
610    bool good = assembler.assemble();
611   
612    if (assembler.getSections().size()<1)
613    {
614        std::ostringstream oss;
615        oss << "FAILED for " << " testAsmCodeStructCase#" << i;
616        throw Exception(oss.str());
617    }
618    const AsmSection& section = assembler.getSections()[0];
619   
620    AsmRegAllocator regAlloc(assembler);
621   
622    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
623                            section.content.data());
624    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
625    std::ostringstream oss;
626    oss << " testAsmCodeStructCase#" << i;
627    const std::string testCaseName = oss.str();
628    assertValue<bool>("testAsmCodeStruct", testCaseName+".good",
629                      testCase.good, good);
630    assertString("testAsmCodeStruct", testCaseName+".errorMessages",
631              testCase.errorMessages, errorStream.str());
632   
633    assertValue("testAsmCodeStruct", testCaseName+".codeBlocks.size",
634                testCase.codeBlocks.size(), resCodeBlocks.size());
635   
636    for (size_t j = 0; j < resCodeBlocks.size(); j++)
637    {
638        const CCodeBlock& expCBlock = testCase.codeBlocks[j];
639        const CodeBlock& resCBlock = resCodeBlocks[j];
640        std::ostringstream codeBlockOss;
641        codeBlockOss << ".codeBlock#" << j << ".";
642        codeBlockOss.flush();
643        std::string cbname(codeBlockOss.str());
644        assertValue("testAsmCodeStruct", testCaseName + cbname + "start",
645                    expCBlock.start, resCBlock.start);
646        assertValue("testAsmCodeStruct", testCaseName + cbname + "end",
647                    expCBlock.end, resCBlock.end);
648        assertValue("testAsmCodeStruct", testCaseName + cbname + "nextsSize",
649                    expCBlock.nexts.size(), resCBlock.nexts.size());
650       
651        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
652        {
653            std::ostringstream nextOss;
654            nextOss << "next#" << k << ".";
655            nextOss.flush();
656            std::string nname(nextOss.str());
657           
658            assertValue("testAsmCodeStruct", testCaseName + cbname + nname + "block",
659                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
660            assertValue("testAsmCodeStruct", testCaseName + cbname + nname + "isCall",
661                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
662        }
663       
664        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveCalls",
665                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
666        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveReturn",
667                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
668        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveEnd",
669                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
670    }
671}
672
673typedef AsmRegAllocator::SSAInfo SSAInfo;
674typedef AsmRegAllocator::SSAReplace SSAReplace;
675typedef AsmRegAllocator::SSAReplacesMap SSAReplacesMap;
676
677struct TestSingleVReg
678{
679    CString name;
680    uint16_t index;
681   
682    bool operator==(const TestSingleVReg& b) const
683    { return name==b.name && index==b.index; }
684    bool operator!=(const TestSingleVReg& b) const
685    { return name!=b.name || index!=b.index; }
686    bool operator<(const TestSingleVReg& b) const
687    { return name<b.name || (name==b.name && index<b.index); }
688};
689
690std::ostream& operator<<(std::ostream& os, const TestSingleVReg& vreg)
691{
692    if (!vreg.name.empty())
693        os << vreg.name << "[" << vreg.index << "]";
694    else
695        os << "@REG[" << vreg.index << "]";
696    return os;
697}
698
699struct CCodeBlock2
700{
701    size_t start, end; // place in code
702    Array<NextBlock> nexts; ///< nexts blocks
703    Array<std::pair<TestSingleVReg, SSAInfo> > ssaInfos;
704    bool haveCalls;
705    bool haveReturn;
706    bool haveEnd;
707};
708
709struct AsmSSADataCase
710{
711    const char* input;
712    Array<CCodeBlock2> codeBlocks;
713    Array<std::pair<TestSingleVReg, Array<SSAReplace> > > ssaReplaces;
714    bool good;
715    const char* errorMessages;
716};
717
718static const AsmSSADataCase ssaDataTestCases1Tbl[] =
719{
720    {   /* 0 - simple */
721        ".regvar sa:s:8, va:v:10\n"
722        "s_mov_b32 sa[4], sa[2]\n"
723        "s_add_u32 sa[4], sa[2], s3\n"
724        "ds_read_b64 va[4:5], v0\n"
725        "v_add_f64 va[0:1], va[4:5], va[2:3]\n"
726        "v_mac_f32 va[0], va[4], va[5]\n"  // ignore this write, because also read
727        "v_mul_f32 va[1], va[4], va[5]\n"
728        "ds_read_b32 v10, v0\n"
729        "v_mul_lo_u32 v10, va[2], va[3]\n"
730        "v_mul_lo_u32 v10, va[2], va[3]\n",
731        {
732            { 0, 56, { },
733                {
734                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
735                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
736                    { { "", 266 }, SSAInfo(0, 0, 0, 0, 0, false) },
737                    { { "sa", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
738                    { { "sa", 4 }, SSAInfo(0, 1, 1, 2, 2, false) },
739                    { { "va", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
740                    { { "va", 1 }, SSAInfo(0, 1, 1, 2, 2, false) },
741                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
742                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
743                    { { "va", 4 }, SSAInfo(0, 1, 1, 1, 1, false) },
744                    { { "va", 5 }, SSAInfo(0, 1, 1, 1, 1, false) }
745                }, false, false, true }
746        },
747        { },
748        true, ""
749    },
750    {   /* 1 - tree */
751        R"ffDXD(.regvar sa:s:8, va:v:10
752        s_mov_b32 sa[4], sa[2]  # 0
753        s_add_u32 sa[4], sa[2], s3
754        ds_read_b64 va[4:5], v0
755        v_add_f64 va[0:1], va[4:5], va[2:3]
756        v_add_f64 va[0:1], va[4:5], va[2:3]
757        v_add_f64 va[0:1], va[4:5], va[2:3]
758        .cf_jump j1,j2,j3
759        s_setpc_b64 s[0:1]
760        # 44
761j1:     v_add_f32 va[5], va[2], va[3]
762        v_mov_b32 va[6], va[2]
763        s_endpgm
764j2:     v_add_f32 va[3], va[2], va[5]
765        v_add_f32 va[6], va[2], va[3]
766        s_endpgm
767j3:     v_add_f32 va[2], va[5], va[3]
768        s_endpgm
769)ffDXD",
770        {
771            { 0, 44,
772                { { 1, false }, { 2, false }, { 3, false } },
773                {
774                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
775                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
776                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
777                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
778                    { { "sa", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
779                    { { "sa", 4 }, SSAInfo(0, 1, 1, 2, 2, false) },
780                    { { "va", 0 }, SSAInfo(0, 1, 1, 3, 3, false) },
781                    { { "va", 1 }, SSAInfo(0, 1, 1, 3, 3, false) },
782                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
783                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
784                    { { "va", 4 }, SSAInfo(0, 1, 1, 1, 1, false) },
785                    { { "va", 5 }, SSAInfo(0, 1, 1, 1, 1, false) }
786                }, false, false, true },
787            { 44, 56, { },
788                {
789                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
790                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
791                    { { "va", 5 }, SSAInfo(1, 2, 2, 2, 1, false) },
792                    { { "va", 6 }, SSAInfo(0, 1, 1, 1, 1, false) }
793                }, false, false, true },
794            { 56, 68, { },
795                {
796                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
797                    { { "va", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
798                    { { "va", 5 }, SSAInfo(1, SIZE_MAX, 3, SIZE_MAX, 0, true) },
799                    { { "va", 6 }, SSAInfo(0, 2, 2, 2, 1, false) }
800                }, false, false, true },
801            { 68, 76, { },
802                {
803                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
804                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 2, SIZE_MAX, 0, true) },
805                    { { "va", 5 }, SSAInfo(1, SIZE_MAX, 3, SIZE_MAX, 0, true) }
806                }, false, false, true },
807        },
808        { },
809        true, ""
810    },
811    {   /* 2 - tree (align) */
812        R"ffDXD(.regvar sa:s:8, va:v:10
813        s_mov_b32 sa[4], sa[2]  # 0
814        s_add_u32 sa[4], sa[2], s3
815        ds_read_b64 va[4:5], v0
816        v_add_f64 va[0:1], va[4:5], va[2:3]
817        v_add_f64 va[0:1], va[4:5], va[2:3]
818        v_add_f64 va[0:1], va[4:5], va[2:3]
819        .cf_jump j1,j2,j3
820        s_setpc_b64 s[0:1]
821.p2align 6
822        # 64
823j1:     v_add_f32 va[5], va[2], va[3]
824        v_mov_b32 va[6], va[2]
825        s_endpgm
826j2:     v_add_f32 va[3], va[2], va[5]
827        v_add_f32 va[6], va[2], va[3]
828        s_endpgm
829j3:     v_add_f32 va[2], va[5], va[3]
830        s_endpgm
831)ffDXD",
832        {
833            { 0, 44,
834                { { 1, false }, { 2, false }, { 3, false } },
835                {
836                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
837                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
838                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
839                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
840                    { { "sa", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
841                    { { "sa", 4 }, SSAInfo(0, 1, 1, 2, 2, false) },
842                    { { "va", 0 }, SSAInfo(0, 1, 1, 3, 3, false) },
843                    { { "va", 1 }, SSAInfo(0, 1, 1, 3, 3, false) },
844                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
845                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
846                    { { "va", 4 }, SSAInfo(0, 1, 1, 1, 1, false) },
847                    { { "va", 5 }, SSAInfo(0, 1, 1, 1, 1, false) }
848                }, false, false, true },
849            { 64, 76, { },
850                {
851                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
852                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
853                    { { "va", 5 }, SSAInfo(1, 2, 2, 2, 1, false) },
854                    { { "va", 6 }, SSAInfo(0, 1, 1, 1, 1, false) }
855                }, false, false, true },
856            { 76, 88, { },
857                {
858                    { { "va", 2 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) },
859                    { { "va", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
860                    { { "va", 5 }, SSAInfo(1, SIZE_MAX, 3, SIZE_MAX, 0, true) },
861                    { { "va", 6 }, SSAInfo(0, 2, 2, 2, 1, false) }
862                }, false, false, true },
863            { 88, 96, { },
864                {
865                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
866                    { { "va", 3 }, SSAInfo(0, SIZE_MAX, 2, SIZE_MAX, 0, true) },
867                    { { "va", 5 }, SSAInfo(1, SIZE_MAX, 3, SIZE_MAX, 0, true) }
868                }, false, false, true },
869        },
870        { },
871        true, ""
872    },
873    {   /* 3 - longer tree (more blocks) */
874        R"ffDXD(.regvar sa:s:8, va:v:12, vb:v:10
875        # 0
876        ds_read_b64 v[2:3], v0
877        ds_read_b64 v[4:5], v0
878        v_mov_b32 va[0], v1
879        v_mul_f32 va[1], v0, v1
880        .cf_cjump tx1, tx2, tx3
881        s_setpc_b64 s[0:1]
882        # 28
883        v_mul_lo_u32 va[2], va[0], va[1]
884        v_mul_hi_u32 va[3], va[0], va[1]
885        v_lshrrev_b32 va[4], v2, va[5]
886        .cf_cjump ux1, ux2, ux3
887        s_setpc_b64 s[0:1]
888        # 52
889        v_mul_u32_u24 va[2], va[0], va[1]
890        v_mul_hi_u32_u24 va[3], va[0], va[1]
891        v_lshlrev_b32 va[5], v3, va[4]
892        .cf_cjump vx1, vx2, vx3
893        s_setpc_b64 s[0:1]
894        # 68
895        v_mul_lo_i32 va[2], va[0], va[1]
896        v_mul_hi_i32 va[3], va[0], va[1]
897        v_ashrrev_i32 va[6], v4, va[4]
898        .cf_jump wx1, wx2, wx3
899        s_setpc_b64 s[0:1]
900       
901.p2align 4
902        # 96
903tx1:    v_min_f32 vb[0], va[0], va[1]
904        v_madak_f32 vb[5], vb[0], va[1], 2.5
905        s_endpgm
906ux1:    v_nop
907        s_endpgm
908vx1:    v_add_f32 va[9], v11, vb[4]
909        s_endpgm
910wx1:    v_add_f32 va[10], v11, vb[4]
911        s_endpgm
912.p2align 4
913tx2:    v_max_f32 vb[1], va[0], va[1]
914        v_madak_f32 va[3], va[0], va[1], 2.5
915        s_endpgm
916ux2:    v_nop
917        s_nop 7
918        s_endpgm
919vx2:    v_nop
920        s_endpgm
921wx2:    v_add_f32 va[8], v19, vb[5]
922        s_endpgm
923.p2align 4
924tx3:    v_max_u32 vb[2], va[0], va[1]
925        v_madmk_f32 vb[3], va[0], 1.23, vb[1]
926        s_endpgm
927ux3:    v_add_f32 va[7], v11, vb[5]
928        s_endpgm
929vx3:    v_add_f32 va[6], v13, vb[5]
930        s_endpgm
931wx3:    v_nop
932        s_endpgm
933)ffDXD",
934        {
935            { 0, 28,
936                { { 1, false }, { 4, false }, { 8, false }, { 12, false } },
937                {
938                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
939                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
940                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
941                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
942                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, false) },
943                    { { "", 256+3 }, SSAInfo(0, 0, 0, 0, 0, false) },
944                    { { "", 256+4 }, SSAInfo(0, 0, 0, 0, 0, false) },
945                    { { "", 256+5 }, SSAInfo(0, 0, 0, 0, 0, false) },
946                    { { "va", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
947                    { { "va", 1 }, SSAInfo(0, 1, 1, 1, 1, false) }
948                }, false, false, false },
949            { 28, 52,
950                { { 2, false }, { 5, false }, { 9, false }, { 13, false } },
951                {
952                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
953                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
954                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, true) },
955                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
956                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
957                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
958                    { { "va", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
959                    { { "va", 4 }, SSAInfo(0, 1, 1, 1, 1, false) },
960                    { { "va", 5 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
961                }, false, false, false },
962            { 52, 68,
963                { { 3, false }, { 6, false }, { 10, false }, { 14, false } },
964                {
965                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
966                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
967                    { { "", 256+3, }, SSAInfo(0, 0, 0, 0, 0, true) },
968                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
969                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
970                    { { "va", 2 }, SSAInfo(1, 2, 2, 2, 1, false) },
971                    { { "va", 3 }, SSAInfo(1, 2, 2, 2, 1, false) },
972                    { { "va", 4 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
973                    { { "va", 5 }, SSAInfo(0, 1, 1, 1, 1, false) }
974                }, false, false, false },
975            { 68, 92,
976                { { 7, false }, { 11, false }, { 15, false } },
977                {
978                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
979                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
980                    { { "", 256+4 }, SSAInfo(0, 0, 0, 0, 0, true) },
981                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
982                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
983                    { { "va", 2 }, SSAInfo(2, 3, 3, 3, 1, false) },
984                    { { "va", 3 }, SSAInfo(2, 3, 3, 3, 1, false) },
985                    { { "va", 4 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
986                    { { "va", 6 }, SSAInfo(0, 1, 1, 1, 1, false) }
987                }, false, false, true },
988            // 4-7:
989            { 96, 112,
990                { },
991                {
992                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
993                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
994                    { { "vb", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
995                    { { "vb", 5 }, SSAInfo(0, 1, 1, 1, 1, false) }
996                }, false, false, true },
997            { 112, 120,
998                { },
999                { }, false, false, true },
1000            { 120, 128,
1001                { },
1002                {
1003                    { { "", 256+11 }, SSAInfo(0, 0, 0, 0, 0, true) },
1004                    { { "va", 9 }, SSAInfo(0, 1, 1, 1, 1, false) },
1005                    { { "vb", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
1006                }, false, false, true },
1007            { 128, 136,
1008                { },
1009                {
1010                    { { "", 256+11 }, SSAInfo(0, 0, 0, 0, 0, true) },
1011                    { { "va", 10 }, SSAInfo(0, 1, 1, 1, 1, false) },
1012                    { { "vb", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
1013                }, false, false, true },
1014            // 8-11
1015            { 144, 160,
1016                { },
1017                {
1018                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1019                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1020                    { { "va", 3 }, SSAInfo(0, 4, 4, 4, 1, false) },
1021                    { { "vb", 1 }, SSAInfo(0, 1, 1, 1, 1, false) }
1022                }, false, false, true },
1023            { 160, 172,
1024                { },
1025                { }, false, false, true },
1026            { 172, 180,
1027                { },
1028                { }, false, false, true },
1029            { 180, 188,
1030                { },
1031                {
1032                    { { "", 256+19 }, SSAInfo(0, 0, 0, 0, 0, true) },
1033                    { { "va", 8 }, SSAInfo(0, 1, 1, 1, 1, false) },
1034                    { { "vb", 5 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
1035                }, false, false, true },
1036            // 12-15
1037            { 192, 208,
1038                { },
1039                {
1040                    { { "va", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1041                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1042                    { { "vb", 1 }, SSAInfo(0, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1043                    { { "vb", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1044                    { { "vb", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1045                }, false, false, true },
1046            { 208, 216,
1047                { },
1048                {
1049                    { { "", 256+11 }, SSAInfo(0, 0, 0, 0, 0, true) },
1050                    { { "va", 7 }, SSAInfo(0, 1, 1, 1, 1, false) },
1051                    { { "vb", 5 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
1052                }, false, false, true },
1053            { 216, 224,
1054                { },
1055                {
1056                    { { "", 256+13 }, SSAInfo(0, 0, 0, 0, 0, true) },
1057                    { { "va", 6 }, SSAInfo(0, 2, 2, 2, 1, false) },
1058                    { { "vb", 5 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
1059                }, false, false, true },
1060            { 224, 232,
1061                { },
1062                { }, false, false, true }
1063        },
1064        { },
1065        true, ""
1066    },
1067    {   /* 4 - empty! */
1068        ".regvar sa:s:8, va:v:12, vb:v:10\n",
1069        { },
1070        { },
1071        true, ""
1072    },
1073    {   /* 5 - longer blocks (tree) */
1074        R"ffDXD(.regvar sa:s:8, va:v:12, vb:v:10
1075        # block 0, offset - 0
1076        s_mov_b32 s0, 0x11
1077        s_mov_b32 s1, 0x11
1078        s_mov_b64 s[2:3], 3344
1079        v_mov_b32 v1, v0
1080        v_add_f32 v2, v1, v0
1081        v_and_b32 v1, v1, v2
1082       
1083        s_mov_b32 sa[0], 1
1084        s_mov_b32 sa[1], 1
1085        s_mov_b32 sa[2], 1
1086        s_mov_b32 sa[3], 1
1087       
1088.rept 4
1089        s_xor_b32 sa[0], sa[1], sa[3]
1090        s_and_b32 sa[1], sa[2], sa[3]
1091        s_xor_b32 sa[3], sa[0], sa[2]
1092        s_xor_b32 sa[2], sa[1], sa[3]
1093.endr
1094        s_and_b32 sa[1], sa[2], sa[3]
1095        s_xor_b32 sa[2], sa[1], sa[3]
1096        s_xor_b32 sa[2], sa[1], sa[3]
1097       
1098        .cf_jump b1, b2
1099        s_setpc_b64 s[4:5]
1100       
1101        # block 1, offset - 124
1102b1:     s_add_u32 s4, s1, sa[2]
1103        s_add_u32 sa[4], s2, sa[3]
1104       
1105        s_mov_b32 sa[6], s[4]
1106.rept 3
1107        s_xor_b32 sa[0], sa[6], sa[3]
1108        s_and_b32 sa[5], sa[2], sa[3]
1109        s_and_b32 sa[6], sa[0], sa[5]
1110.endr
1111        .cf_jump b11, b12
1112        s_setpc_b64 s[6:7]
1113       
1114        # block 2, offset - 176
1115b2:     v_mul_lo_u32 va[1], va[1], va[4]
1116        v_mul_lo_u32 va[2], sa[1], va[1]
1117        v_mov_b32 va[3], 2343
1118.rept 3
1119        v_mul_lo_u32 va[3], sa[1], va[3]
1120        v_mul_lo_u32 va[1], sa[0], va[4]
1121        v_mul_lo_u32 va[2], sa[2], va[1]
1122.endr
1123.rept 4
1124        v_mul_lo_u32 va[1], sa[0], va[4]
1125.endr
1126.rept 2
1127        v_mul_lo_u32 va[2], v1, v4
1128.endr
1129        v_and_b32 v3, v3, v2
1130        s_endpgm
1131       
1132        # block 2, offset - xx
1133b11:    v_mov_b32 va[0], 122
1134        v_mov_b32 va[1], 122
1135        v_mov_b32 va[2], 122
1136.rept 4
1137        v_xor_b32 va[0], va[1], v2
1138        v_xor_b32 va[1], va[1], v1
1139        v_xor_b32 va[2], sa[2], va[1]
1140.endr
1141        v_xor_b32 va[1], sa[1], v0
1142        s_xor_b32 sa[1], sa[2], s3
1143        s_endpgm
1144       
1145        # block 3, offset - xx
1146b12:    v_mov_b32 va[4], 122
1147        v_xor_b32 va[1], 112, va[1]
1148        v_xor_b32 va[0], v2, va[0]
1149.rept 5
1150        v_xor_b32 va[0], va[1], v2
1151        v_xor_b32 va[1], va[0], v0
1152        v_xor_b32 va[4], sa[3], va[4]
1153.endr
1154        v_xor_b32 va[4], sa[2], v0
1155        s_xor_b32 sa[1], sa[3], s3
1156        s_endpgm
1157)ffDXD",
1158        {
1159            { 0, 124,
1160                { { 1, false }, { 2, false } },
1161                {
1162                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, false) },
1163                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, false) },
1164                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, false) },
1165                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, false) },
1166                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1167                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
1168                    { { "", 256+0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1169                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, false) },
1170                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, false) },
1171                    { { "sa", 0 }, SSAInfo(0, 1, 1, 5, 5, false) },
1172                    { { "sa", 1 }, SSAInfo(0, 1, 1, 6, 6, false) },
1173                    { { "sa", 2 }, SSAInfo(0, 1, 1, 7, 7, false) },
1174                    { { "sa", 3 }, SSAInfo(0, 1, 1, 5, 5, false) }
1175                }, false, false, true },
1176            // block 1
1177            { 124, 176,
1178                { { 3, false }, { 4, false } },
1179                {
1180                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1181                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1182                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, false) },
1183                    { { "", 6 }, SSAInfo(0, 0, 0, 0, 0, true) },
1184                    { { "", 7 }, SSAInfo(0, 0, 0, 0, 0, true) },
1185                    { { "sa", 0 }, SSAInfo(5, 6, 6, 8, 3, false) },
1186                    { { "sa", 2 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1187                    { { "sa", 3 }, SSAInfo(5, SIZE_MAX, 6, SIZE_MAX, 0, true) },
1188                    { { "sa", 4 }, SSAInfo(0, 1, 1, 1, 1, false) },
1189                    { { "sa", 5 }, SSAInfo(0, 1, 1, 3, 3, false) },
1190                    { { "sa", 6 }, SSAInfo(0, 1, 1, 4, 4, false) }
1191                }, false, false, true },
1192            // block 2
1193            { 176, 328,
1194                { },
1195                {
1196                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1197                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1198                    { { "", 256+3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1199                    { { "", 256+4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1200                    { { "sa", 0 }, SSAInfo(5, SIZE_MAX, 9, SIZE_MAX, 0, true) },
1201                    { { "sa", 1 }, SSAInfo(6, SIZE_MAX, 9, SIZE_MAX, 0, true) },
1202                    { { "sa", 2 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1203                    { { "va", 1 }, SSAInfo(0, 13, 13, 20, 8, true) },
1204                    { { "va", 2 }, SSAInfo(0, 6, 6, 11, 6, false) },
1205                    { { "va", 3 }, SSAInfo(0, 1, 1, 4, 4, false) },
1206                    { { "va", 4 }, SSAInfo(0, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1207                }, false, false, true },
1208            // block 3
1209            { 328, 412,
1210                { },
1211                {
1212                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1213                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
1214                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1215                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1216                    { { "sa", 1 }, SSAInfo(6, 7, 7, 7, 1, true) },
1217                    { { "sa", 2 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1218                    { { "va", 0 }, SSAInfo(0, 1, 1, 5, 5, false) },
1219                    { { "va", 1 }, SSAInfo(0, 1, 1, 6, 6, false) },
1220                    { { "va", 2 }, SSAInfo(0, 1, 1, 5, 5, false) }
1221                }, false, false, true },
1222            // block 4
1223            { 412, 504,
1224                { },
1225                {
1226                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1227                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
1228                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1229                    { { "sa", 1 }, SSAInfo(6, 8, 8, 8, 1, false) },
1230                    { { "sa", 2 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1231                    { { "sa", 3 }, SSAInfo(5, SIZE_MAX, 6, SIZE_MAX, 0, true) },
1232                    { { "va", 0 }, SSAInfo(0, 6, 6, 11, 6, true) },
1233                    { { "va", 1 }, SSAInfo(0, 7, 7, 12, 6, true) },
1234                    { { "va", 4 }, SSAInfo(0, 1, 1, 7, 7, false) }
1235                }, false, false, true }
1236        },
1237        { },
1238        true, ""
1239    },
1240    {   // 6: simple loop
1241        R"ffDXD(.regvar sa:s:8, va:v:8
1242        s_mov_b32 sa[0], 0
1243        s_mov_b32 sa[1], s10
1244        v_mov_b32 va[0], v0
1245        v_mov_b32 va[1], v1
1246        v_mov_b32 va[3], 0
1247loop:
1248        ds_read_b32 va[2], va[3]
1249        v_xor_b32 va[0], va[1], va[2]
1250        v_not_b32 va[0], va[0]
1251        v_xor_b32 va[0], 0xfff, va[0]
1252        v_add_u32 va[1], vcc, 1001, va[1]
1253       
1254        s_add_u32 sa[0], sa[0], 1
1255        s_cmp_lt_u32 sa[0], sa[1]
1256        s_cbranch_scc1 loop
1257       
1258        v_xor_b32 va[0], 33, va[0]
1259        s_add_u32 sa[0], 14, sa[0]
1260        s_endpgm
1261)ffDXD",
1262        {
1263            { 0, 20,
1264                { },
1265                {
1266                    { { "", 10 }, SSAInfo(0, 0, 0, 0, 0, true) },
1267                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
1268                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1269                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1270                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1271                    { { "va", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1272                    { { "va", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1273                    { { "va", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1274                }, false, false, false },
1275            { 20, 64,
1276                { { 1, false }, { 2, false } },
1277                {
1278                    { { "sa", 0 }, SSAInfo(1, 2, 2, 2, 1, true) },
1279                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1280                    { { "va", 0 }, SSAInfo(1, 2, 2, 4, 3, false) },
1281                    { { "va", 1 }, SSAInfo(1, 2, 2, 2, 1, true) },
1282                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1283                    { { "va", 3 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1284                }, false, false, false },
1285            { 64, 76,
1286                { },
1287                {
1288                    { { "sa", 0 }, SSAInfo(2, 3, 3, 3, 1, true) },
1289                    { { "va", 0 }, SSAInfo(4, 5, 5, 5, 1, true) }
1290                }, false, false, true, }
1291        },
1292        {   // SSA replaces
1293            { { "sa", 0 }, { { 2, 1 } } },
1294            { { "va", 0 }, { { 4, 2 } } },
1295            { { "va", 1 }, { { 2, 1 } } }
1296        },
1297        true, ""
1298    },
1299    {   // 7 - branches
1300        R"ffDXD(.regvar sa:s:8, va:v:8
1301        # block 0
1302        s_mov_b32 sa[0], s0
1303        s_mov_b32 sa[1], s1
1304        s_mov_b32 sa[2], s2
1305        s_add_u32 sa[0], sa[1], sa[2]
1306        s_mov_b32 sa[3], 31
1307        s_mov_b32 sa[4], 11
1308        s_cbranch_scc0 pp0
1309       
1310        # block 1
1311bb0:    s_xor_b32 sa[1], sa[1], sa[0]
1312        s_xor_b32 sa[1], 122, sa[1]
1313        s_xor_b32 sa[2], sa[1], sa[0]
1314        s_cbranch_scc0 pp1
1315       
1316        # block 2
1317        s_xor_b32 sa[0], 122, sa[0]
1318        s_xor_b32 sa[2], sa[0], sa[2]
1319        s_bfe_u32 sa[3], sa[2], sa[0]
1320        s_endpgm
1321       
1322        # block 3
1323pp1:    s_xor_b32 sa[1], sa[0], sa[1]
1324        s_and_b32 sa[0], sa[0], sa[1]
1325        s_xor_b32 sa[2], sa[0], sa[1]
1326        s_bfe_u32 sa[4], sa[4], sa[0]
1327        s_endpgm
1328       
1329        # block 4
1330pp0:    s_xor_b32 sa[1], sa[1], sa[0]
1331        s_sub_u32 sa[0], sa[1], sa[0]
1332        s_xor_b32 sa[1], sa[1], sa[0]
1333        s_xor_b32 sa[1], sa[1], sa[0]
1334        s_add_u32 sa[0], sa[1], sa[0]
1335        s_xor_b32 sa[2], sa[1], sa[2]
1336        s_add_u32 sa[2], sa[0], sa[0]
1337        s_cbranch_scc0 pp2
1338       
1339        # block 5
1340        s_xor_b32 sa[2], sa[1], sa[2]
1341        s_add_u32 sa[2], sa[0], sa[0]
1342        s_xor_b32 sa[2], sa[1], sa[2]
1343        s_sub_u32 sa[4], sa[4], sa[0]
1344        s_sub_u32 sa[4], sa[4], sa[2]
1345        s_branch bb0
1346       
1347        # block 6
1348pp2:    s_xor_b32 sa[1], sa[1], sa[0]
1349        s_xor_b32 sa[0], sa[1], sa[2]
1350        s_add_u32 sa[0], sa[1], sa[2]
1351        s_and_b32 sa[3], sa[3], sa[0]
1352        s_bfe_u32 sa[3], sa[3], sa[4]
1353        s_bfe_u32 sa[3], sa[3], sa[1]
1354        s_branch bb0
1355)ffDXD",
1356        {
1357            // block 0
1358            { 0, 28,
1359                { { 1, false }, { 4, false } },
1360                {
1361                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1362                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1363                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1364                    { { "sa", 0 }, SSAInfo(0, 1, 1, 2, 2, false) },
1365                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1366                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1367                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
1368                    { { "sa", 4 }, SSAInfo(0, 1, 1, 1, 1, false) }
1369                }, false, false, false },
1370            // block 1
1371            { 28, 48,
1372                { { 2, false }, { 3, false } },
1373                {
1374                    { { "sa", 0 }, SSAInfo(2, SIZE_MAX, 3, SIZE_MAX, 0, true) },
1375                    { { "sa", 1 }, SSAInfo(1, 2, 2, 3, 2, true) },
1376                    { { "sa", 2 }, SSAInfo(1, 2, 2, 2, 1, false) },
1377                }, false, false, false },
1378            // block 2
1379            { 48, 68,
1380                { },
1381                {
1382                    { { "sa", 0 }, SSAInfo(2, 3, 3, 3, 1, true) },
1383                    { { "sa", 2 }, SSAInfo(2, 3, 3, 3, 1, true) },
1384                    { { "sa", 3 }, SSAInfo(1, 2, 2, 2, 1, false) }
1385                }, false, false, true },
1386            // block 3
1387            { 68, 88,
1388                { },
1389                {
1390                    { { "sa", 0 }, SSAInfo(2, 4, 4, 4, 1, true) },
1391                    { { "sa", 1 }, SSAInfo(3, 4, 4, 4, 1, true) },
1392                    { { "sa", 2 }, SSAInfo(2, 4, 4, 4, 1, false) },
1393                    { { "sa", 4 }, SSAInfo(1, 2, 2, 2, 1, true) }
1394                }, false, false, true },
1395            // block 4
1396            { 88, 120,
1397                { { 5, false }, { 6, false } },
1398                {
1399                    { { "sa", 0 }, SSAInfo(2, 5, 5, 6, 2, true) },
1400                    { { "sa", 1 }, SSAInfo(1, 5, 5, 7, 3, true) },
1401                    { { "sa", 2 }, SSAInfo(1, 5, 5, 6, 2, true) }
1402                }, false, false, false },
1403            // block 5
1404            { 120, 144,
1405                { { 1, false } },
1406                {
1407                    { { "sa", 0 }, SSAInfo(6, SIZE_MAX, 7, SIZE_MAX, 0, true) },
1408                    { { "sa", 1 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1409                    { { "sa", 2 }, SSAInfo(6, 7, 7, 9, 3, true) },
1410                    { { "sa", 4 }, SSAInfo(1, 3, 3, 4, 2, true) }
1411                }, false, false, true },
1412            // block 6
1413            { 144, 172,
1414                { { 1, false } },
1415                {
1416                    { { "sa", 0 }, SSAInfo(6, 7, 7, 8, 2, true) },
1417                    { { "sa", 1 }, SSAInfo(7, 8, 8, 8, 1, true) },
1418                    { { "sa", 2 }, SSAInfo(6, SIZE_MAX, 10, SIZE_MAX, 0, true) },
1419                    { { "sa", 3 }, SSAInfo(1, 3, 3, 5, 3, true) },
1420                    { { "sa", 4 }, SSAInfo(1, SIZE_MAX, 5, SIZE_MAX, 0, true) }
1421                }, false, false, true }
1422        },
1423        {
1424            { { "sa", 0 }, { { 6, 2 }, { 8, 2 } } },
1425            { { "sa", 1 }, { { 7, 1 }, { 8, 1 } } },
1426            { { "sa", 2 }, { { 9, 2 }, { 6, 2 } } },
1427            { { "sa", 3 }, { { 5, 2 } } },
1428            { { "sa", 4 }, { { 4, 1 } } }
1429        },
1430        true, ""
1431    }
1432};
1433
1434static TestSingleVReg getTestSingleVReg(const AsmSingleVReg& vr,
1435        const std::unordered_map<const AsmRegVar*, CString>& rvMap)
1436{
1437    if (vr.regVar == nullptr)
1438        return { "", vr.index };
1439   
1440    auto it = rvMap.find(vr.regVar);
1441    if (it == rvMap.end())
1442        throw Exception("getTestSingleVReg: RegVar not found!!");
1443    return { it->second, vr.index };
1444}
1445
1446static void testCreateSSAData(cxuint i, const AsmSSADataCase& testCase)
1447{
1448    std::istringstream input(testCase.input);
1449    std::ostringstream errorStream;
1450   
1451    Assembler assembler("test.s", input,
1452                    (ASM_ALL&~ASM_ALTMACRO) | ASM_TESTRUN | ASM_TESTRESOLVE,
1453                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
1454    bool good = assembler.assemble();
1455    if (assembler.getSections().size()<1)
1456    {
1457        std::ostringstream oss;
1458        oss << "FAILED for " << " testAsmCodeStructCase#" << i;
1459        throw Exception(oss.str());
1460    }
1461    const AsmSection& section = assembler.getSections()[0];
1462   
1463    AsmRegAllocator regAlloc(assembler);
1464   
1465    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
1466                            section.content.data());
1467    regAlloc.createSSAData(*section.usageHandler);
1468    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
1469    std::ostringstream oss;
1470    oss << " testAsmSSADataCase#" << i;
1471    const std::string testCaseName = oss.str();
1472    assertValue<bool>("testAsmSSAData", testCaseName+".good",
1473                      testCase.good, good);
1474    assertString("testAsmSSAData", testCaseName+".errorMessages",
1475              testCase.errorMessages, errorStream.str());
1476   
1477    assertValue("testAsmSSAData", testCaseName+".codeBlocks.size",
1478                testCase.codeBlocks.size(), resCodeBlocks.size());
1479   
1480    std::unordered_map<const AsmRegVar*, CString> regVarNamesMap;
1481    for (const auto& rvEntry: assembler.getRegVarMap())
1482        regVarNamesMap.insert(std::make_pair(&rvEntry.second, rvEntry.first));
1483   
1484    for (size_t j = 0; j < resCodeBlocks.size(); j++)
1485    {
1486        const CCodeBlock2& expCBlock = testCase.codeBlocks[j];
1487        const CodeBlock& resCBlock = resCodeBlocks[j];
1488        std::ostringstream codeBlockOss;
1489        codeBlockOss << ".codeBlock#" << j << ".";
1490        codeBlockOss.flush();
1491        std::string cbname(codeBlockOss.str());
1492        assertValue("testAsmSSAData", testCaseName + cbname + "start",
1493                    expCBlock.start, resCBlock.start);
1494        assertValue("testAsmSSAData", testCaseName + cbname + "end",
1495                    expCBlock.end, resCBlock.end);
1496        assertValue("testAsmSSAData", testCaseName + cbname + "nextsSize",
1497                    expCBlock.nexts.size(), resCBlock.nexts.size());
1498       
1499        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
1500        {
1501            std::ostringstream nextOss;
1502            nextOss << "next#" << k << ".";
1503            nextOss.flush();
1504            std::string nname(nextOss.str());
1505           
1506            assertValue("testAsmSSAData", testCaseName + cbname + nname + "block",
1507                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
1508            assertValue("testAsmSSAData", testCaseName + cbname + nname + "isCall",
1509                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
1510        }
1511       
1512        assertValue("testAsmSSAData", testCaseName + cbname + "ssaInfoSize",
1513                    expCBlock.ssaInfos.size(), resCBlock.ssaInfoMap.size());
1514       
1515        Array<std::pair<TestSingleVReg, SSAInfo> > resSSAInfos(
1516                        resCBlock.ssaInfoMap.size());
1517        std::transform(resCBlock.ssaInfoMap.begin(), resCBlock.ssaInfoMap.end(),
1518            resSSAInfos.begin(),
1519            [&regVarNamesMap](const std::pair<AsmSingleVReg, SSAInfo>& a)
1520            -> std::pair<TestSingleVReg, SSAInfo>
1521            { return { getTestSingleVReg(a.first, regVarNamesMap), a.second }; });
1522        mapSort(resSSAInfos.begin(), resSSAInfos.end());
1523       
1524        for (size_t k = 0; k < expCBlock.ssaInfos.size(); k++)
1525        {
1526            std::ostringstream ssaOss;
1527            ssaOss << "ssaInfo#" << k << ".";
1528            ssaOss.flush();
1529            std::string ssaName(ssaOss.str());
1530           
1531            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "svreg",
1532                        expCBlock.ssaInfos[k].first, resSSAInfos[k].first);
1533            const SSAInfo& expSInfo = expCBlock.ssaInfos[k].second;
1534            const SSAInfo& resSInfo = resSSAInfos[k].second;
1535            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdBefore",
1536                        expSInfo.ssaIdBefore, resSInfo.ssaIdBefore);
1537            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaId",
1538                        expSInfo.ssaId, resSInfo.ssaId);
1539            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdChange",
1540                        expSInfo.ssaIdChange, resSInfo.ssaIdChange);
1541            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdFirst",
1542                        expSInfo.ssaIdFirst, resSInfo.ssaIdFirst);
1543            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdLast",
1544                        expSInfo.ssaIdLast, resSInfo.ssaIdLast);
1545            assertValue("testAsmSSAData", testCaseName + cbname + ssaName +
1546                        "readBeforeWrite", int(expSInfo.readBeforeWrite),
1547                        int(resSInfo.readBeforeWrite));
1548        }
1549       
1550        assertValue("testAsmSSAData", testCaseName + cbname + "haveCalls",
1551                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
1552        assertValue("testAsmSSAData", testCaseName + cbname + "haveReturn",
1553                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
1554        assertValue("testAsmSSAData", testCaseName + cbname + "haveEnd",
1555                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
1556    }
1557   
1558    const SSAReplacesMap& ssaReplacesMap = regAlloc.getSSAReplacesMap();
1559    assertValue("testAsmSSAData", testCaseName + "ssaReplacesSize",
1560                    testCase.ssaReplaces.size(), ssaReplacesMap.size());
1561    Array<std::pair<TestSingleVReg, Array<SSAReplace> > >
1562                        resSSAReplaces(ssaReplacesMap.size());
1563    std::transform(ssaReplacesMap.begin(), ssaReplacesMap.end(),
1564            resSSAReplaces.begin(),
1565            [&regVarNamesMap](const std::pair<AsmSingleVReg, std::vector<SSAReplace> >& a)
1566            -> std::pair<TestSingleVReg, Array<SSAReplace> >
1567            { return { getTestSingleVReg(a.first, regVarNamesMap), 
1568                Array<SSAReplace>(a.second.begin(), a.second.end()) }; });
1569    mapSort(resSSAReplaces.begin(), resSSAReplaces.end());
1570   
1571    for (size_t j = 0; j < testCase.ssaReplaces.size(); j++)
1572    {
1573        std::ostringstream ssaOss;
1574        ssaOss << "ssas" << j << ".";
1575        ssaOss.flush();
1576        std::string ssaName(ssaOss.str());
1577       
1578        const auto& expEntry = testCase.ssaReplaces[j];
1579        const auto& resEntry = resSSAReplaces[j];
1580       
1581        assertValue("testAsmSSAData", testCaseName + ssaName + "svreg",
1582                        expEntry.first, resEntry.first);
1583        assertValue("testAsmSSAData", testCaseName + ssaName + "replacesSize",
1584                        expEntry.second.size(), resEntry.second.size());
1585        for (size_t k = 0; k < expEntry.second.size(); k++)
1586        {
1587            std::ostringstream repOss;
1588            repOss << "replace#" << k << ".";
1589            repOss.flush();
1590            std::string repName(repOss.str());
1591           
1592            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "first",
1593                        expEntry.second[k].first, resEntry.second[k].first);
1594            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "second",
1595                        expEntry.second[k].second, resEntry.second[k].second);
1596        }
1597    }
1598}
1599
1600int main(int argc, const char** argv)
1601{
1602    int retVal = 0;
1603    for (size_t i = 0; i < sizeof(codeStructTestCases1Tbl)/sizeof(AsmCodeStructCase); i++)
1604        try
1605        { testCreateCodeStructure(i, codeStructTestCases1Tbl[i]); }
1606        catch(const std::exception& ex)
1607        {
1608            std::cerr << ex.what() << std::endl;
1609            retVal = 1;
1610        }
1611    for (size_t i = 0; i < sizeof(ssaDataTestCases1Tbl)/sizeof(AsmSSADataCase); i++)
1612        try
1613        { testCreateSSAData(i, ssaDataTestCases1Tbl[i]); }
1614        catch(const std::exception& ex)
1615        {
1616            std::cerr << ex.what() << std::endl;
1617            retVal = 1;
1618        }
1619    return retVal;
1620}
Note: See TracBrowser for help on using the repository browser.