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

Last change on this file since 3612 was 3612, checked in by matszpk, 3 years ago

CLRadeonExtender: AsmRegAlloc?: Do not add all blocks to routineMap. initialize replacedSSAIdMap while adding new routine ssaIds.
Add new testcase with routine with two branches.

File size: 82.9 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
1247        v_mov_b32 va[4], 11
1248loop:
1249        ds_read_b32 va[2], va[3]
1250        v_xor_b32 va[0], va[1], va[2]
1251        v_not_b32 va[0], va[0]
1252        v_xor_b32 va[0], 0xfff, va[0]
1253        v_xor_b32 va[4], va[4], va[2]
1254        v_not_b32 va[4], va[0]
1255        v_xor_b32 va[4], 0xfff, va[0]
1256        v_add_u32 va[1], vcc, 1001, va[1]
1257       
1258        s_add_u32 sa[0], sa[0], 1
1259        s_cmp_lt_u32 sa[0], sa[1]
1260        s_cbranch_scc1 loop
1261       
1262        v_xor_b32 va[0], 33, va[0]
1263        s_add_u32 sa[0], 14, sa[0]
1264        s_endpgm
1265)ffDXD",
1266        {
1267            { 0, 24,
1268                { },
1269                {
1270                    { { "", 10 }, SSAInfo(0, 0, 0, 0, 0, true) },
1271                    { { "", 256 }, SSAInfo(0, 0, 0, 0, 0, true) },
1272                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1273                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1274                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1275                    { { "va", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1276                    { { "va", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1277                    { { "va", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
1278                    { { "va", 4 }, SSAInfo(0, 1, 1, 1, 1, false) }
1279                }, false, false, false },
1280            { 24, 84,
1281                { { 1, false }, { 2, false } },
1282                {
1283                    { { "sa", 0 }, SSAInfo(1, 2, 2, 2, 1, true) },
1284                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1285                    { { "va", 0 }, SSAInfo(1, 2, 2, 4, 3, false) },
1286                    { { "va", 1 }, SSAInfo(1, 2, 2, 2, 1, true) },
1287                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1288                    { { "va", 3 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1289                    { { "va", 4 }, SSAInfo(1, 2, 2, 4, 3, true) }
1290                }, false, false, false },
1291            { 84, 96,
1292                { },
1293                {
1294                    { { "sa", 0 }, SSAInfo(2, 3, 3, 3, 1, true) },
1295                    { { "va", 0 }, SSAInfo(4, 5, 5, 5, 1, true) }
1296                }, false, false, true, }
1297        },
1298        {   // SSA replaces
1299            { { "sa", 0 }, { { 2, 1 } } },
1300            { { "va", 1 }, { { 2, 1 } } },
1301            { { "va", 4 }, { { 4, 1 } } }
1302        },
1303        true, ""
1304    },
1305    {   // 7 - branches
1306        R"ffDXD(.regvar sa:s:8, va:v:8
1307        # block 0
1308        s_mov_b32 sa[0], s0
1309        s_mov_b32 sa[1], s1
1310        s_mov_b32 sa[2], s2
1311        s_add_u32 sa[0], sa[1], sa[2]
1312        s_mov_b32 sa[3], 31
1313        s_mov_b32 sa[4], 11
1314        s_cbranch_scc0 pp0
1315       
1316        # block 1
1317bb0:    s_xor_b32 sa[1], sa[1], sa[0]
1318        s_xor_b32 sa[1], 122, sa[1]
1319        s_xor_b32 sa[2], sa[1], sa[0]
1320        s_cbranch_scc0 pp1
1321       
1322        # block 2
1323        s_xor_b32 sa[0], 122, sa[0]
1324        s_xor_b32 sa[2], sa[0], sa[2]
1325        s_bfe_u32 sa[3], sa[2], sa[0]
1326        s_endpgm
1327       
1328        # block 3
1329pp1:    s_xor_b32 sa[1], sa[0], sa[1]
1330        s_and_b32 sa[0], sa[0], sa[1]
1331        s_xor_b32 sa[2], sa[0], sa[1]
1332        s_bfe_u32 sa[4], sa[4], sa[0]
1333        s_endpgm
1334       
1335        # block 4
1336pp0:    s_xor_b32 sa[1], sa[1], sa[0]
1337        s_sub_u32 sa[0], sa[1], sa[0]
1338        s_xor_b32 sa[1], sa[1], sa[0]
1339        s_xor_b32 sa[1], sa[1], sa[0]
1340        s_add_u32 sa[0], sa[1], sa[0]
1341        s_xor_b32 sa[2], sa[1], sa[2]
1342        s_add_u32 sa[2], sa[0], sa[0]
1343        s_cbranch_scc0 pp2
1344       
1345        # block 5
1346        s_xor_b32 sa[2], sa[1], sa[2]
1347        s_add_u32 sa[2], sa[0], sa[0]
1348        s_xor_b32 sa[2], sa[1], sa[2]
1349        s_sub_u32 sa[4], sa[4], sa[0]
1350        s_sub_u32 sa[4], sa[4], sa[2]
1351        s_branch bb0
1352       
1353        # block 6
1354pp2:    s_xor_b32 sa[1], sa[1], sa[0]
1355        s_xor_b32 sa[0], sa[1], sa[2]
1356        s_add_u32 sa[0], sa[1], sa[2]
1357        s_and_b32 sa[3], sa[3], sa[0]
1358        s_bfe_u32 sa[3], sa[3], sa[4]
1359        s_bfe_u32 sa[3], sa[3], sa[1]
1360        s_branch bb0
1361)ffDXD",
1362        {
1363            // block 0
1364            { 0, 28,
1365                { { 1, false }, { 4, false } },
1366                {
1367                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1368                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1369                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1370                    { { "sa", 0 }, SSAInfo(0, 1, 1, 2, 2, false) },
1371                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1372                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1373                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
1374                    { { "sa", 4 }, SSAInfo(0, 1, 1, 1, 1, false) }
1375                }, false, false, false },
1376            // block 1
1377            { 28, 48,
1378                { { 2, false }, { 3, false } },
1379                {
1380                    { { "sa", 0 }, SSAInfo(2, SIZE_MAX, 3, SIZE_MAX, 0, true) },
1381                    { { "sa", 1 }, SSAInfo(1, 2, 2, 3, 2, true) },
1382                    { { "sa", 2 }, SSAInfo(1, 2, 2, 2, 1, false) },
1383                }, false, false, false },
1384            // block 2
1385            { 48, 68,
1386                { },
1387                {
1388                    { { "sa", 0 }, SSAInfo(2, 3, 3, 3, 1, true) },
1389                    { { "sa", 2 }, SSAInfo(2, 3, 3, 3, 1, true) },
1390                    { { "sa", 3 }, SSAInfo(1, 2, 2, 2, 1, false) }
1391                }, false, false, true },
1392            // block 3
1393            { 68, 88,
1394                { },
1395                {
1396                    { { "sa", 0 }, SSAInfo(2, 4, 4, 4, 1, true) },
1397                    { { "sa", 1 }, SSAInfo(3, 4, 4, 4, 1, true) },
1398                    { { "sa", 2 }, SSAInfo(2, 4, 4, 4, 1, false) },
1399                    { { "sa", 4 }, SSAInfo(1, 2, 2, 2, 1, true) }
1400                }, false, false, true },
1401            // block 4
1402            { 88, 120,
1403                { { 5, false }, { 6, false } },
1404                {
1405                    { { "sa", 0 }, SSAInfo(2, 5, 5, 6, 2, true) },
1406                    { { "sa", 1 }, SSAInfo(1, 5, 5, 7, 3, true) },
1407                    { { "sa", 2 }, SSAInfo(1, 5, 5, 6, 2, true) }
1408                }, false, false, false },
1409            // block 5
1410            { 120, 144,
1411                { { 1, false } },
1412                {
1413                    { { "sa", 0 }, SSAInfo(6, SIZE_MAX, 7, SIZE_MAX, 0, true) },
1414                    { { "sa", 1 }, SSAInfo(7, SIZE_MAX, 8, SIZE_MAX, 0, true) },
1415                    { { "sa", 2 }, SSAInfo(6, 7, 7, 9, 3, true) },
1416                    { { "sa", 4 }, SSAInfo(1, 3, 3, 4, 2, true) }
1417                }, false, false, true },
1418            // block 6
1419            { 144, 172,
1420                { { 1, false } },
1421                {
1422                    { { "sa", 0 }, SSAInfo(6, 7, 7, 8, 2, true) },
1423                    { { "sa", 1 }, SSAInfo(7, 8, 8, 8, 1, true) },
1424                    { { "sa", 2 }, SSAInfo(6, SIZE_MAX, 10, SIZE_MAX, 0, true) },
1425                    { { "sa", 3 }, SSAInfo(1, 3, 3, 5, 3, true) },
1426                    { { "sa", 4 }, SSAInfo(1, SIZE_MAX, 5, SIZE_MAX, 0, true) }
1427                }, false, false, true }
1428        },
1429        {
1430            { { "sa", 0 }, { { 6, 2 }, { 8, 2 } } },
1431            { { "sa", 1 }, { { 7, 1 }, { 8, 1 } } },
1432            { { "sa", 4 }, { { 4, 1 } } }
1433        },
1434        true, ""
1435    },
1436    {   // 8 - two loops, one nested
1437        R"ffDXD(.regvar sa:s:8, va:v:8
1438        s_mov_b64 sa[0:1], 0
1439        v_mov_b32 va[0], v1
1440        v_mov_b32 va[1], v2
1441        v_mov_b32 va[2], v3
1442       
1443loop0:  v_lshrrev_b32 va[0], va[2], va[0]
1444        v_xor_b32 va[0], va[1], va[0]
1445       
1446        s_xor_b32 sa[3], sa[0], 0x5
1447        s_cmp_eq_u32 sa[3], 9
1448        s_cbranch_scc1 bb0
1449       
1450        v_and_b32 va[0], -15, va[0]
1451        v_sub_u32 va[0], vcc, -13, va[0]
1452        s_branch loop1start
1453       
1454bb0:    v_xor_b32 va[0], 15, va[0]
1455        v_add_u32 va[0], vcc, 17, va[0]
1456loop1start:
1457        s_mov_b32 sa[1], sa[0]
1458       
1459loop1:  v_add_u32 va[2], vcc, va[2], va[1]
1460        v_xor_b32 va[2], 0xffaaaa, va[0]
1461       
1462        s_xor_b32 sa[2], sa[1], 0x5
1463        s_cmp_eq_u32 sa[2], 7
1464        s_cbranch_scc1 bb1
1465       
1466        v_sub_u32 va[1], vcc, 5, va[1]
1467        v_sub_u32 va[2], vcc, 7, va[2]
1468        s_branch loop1end
1469       
1470bb1:    v_xor_b32 va[1], 15, va[1]
1471        v_xor_b32 va[2], 17, va[2]
1472loop1end:
1473       
1474        s_add_u32 sa[1], sa[1], 1
1475        s_cmp_lt_u32 sa[1], 52
1476        s_cbranch_scc1 loop1
1477       
1478        v_xor_b32 va[0], va[1], va[0]
1479        v_xor_b32 va[0], va[2], va[0]
1480        v_xor_b32 va[0], sa[0], va[0]
1481       
1482        s_add_u32 sa[0], sa[0], 1
1483        s_cmp_lt_u32 sa[0], 33
1484        s_cbranch_scc1 loop0
1485       
1486        s_endpgm
1487)ffDXD",
1488        {
1489            // block 0
1490            { 0, 16,
1491                { },
1492                {
1493                    { { "", 256+1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1494                    { { "", 256+2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1495                    { { "", 256+3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1496                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1497                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1498                    { { "va", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1499                    { { "va", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1500                    { { "va", 2 }, SSAInfo(0, 1, 1, 1, 1, false) }
1501                }, false, false, false },
1502            // block 1 (loop0)
1503            { 16, 36,
1504                { { 2, false }, { 3, false } },
1505                {
1506                    { { "sa", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1507                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) },
1508                    { { "va", 0 }, SSAInfo(1, 2, 2, 3, 2, true) },
1509                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1510                    { { "va", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1511                }, false, false, false },
1512            // block 2 (to bb0)
1513            { 36, 48,
1514                { { 4, false } },
1515                {
1516                    { { "va", 0 }, SSAInfo(3, 4, 4, 5, 2, true) }
1517                }, false, false, true },
1518            // block 3 (bb0)
1519            { 48, 56,
1520                { },
1521                {
1522                    { { "va", 0 }, SSAInfo(3, 9, 9, 10, 2, true) }
1523                }, false, false, false },
1524            // block 4 (loop1start)
1525            { 56, 60,
1526                { },
1527                {
1528                    { { "sa", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1529                    { { "sa", 1 }, SSAInfo(1, 2, 2, 2, 1, false) }
1530                }, false, false, false },
1531            // block 5 (loop1)
1532            { 60, 84,
1533                { { 6, false }, { 7, false } },
1534                {
1535                    { { "sa", 1 }, SSAInfo(2, SIZE_MAX, 3, SIZE_MAX, 0, true) },
1536                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1537                    { { "va", 0 }, SSAInfo(5, SIZE_MAX, 6, SIZE_MAX, 0, true) },
1538                    { { "va", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1539                    { { "va", 2 }, SSAInfo(1, 2, 2, 3, 2, true) }
1540                }, false, false, false },
1541            // block 6 (to bb1)
1542            { 84, 96,
1543                { { 8, false } },
1544                {
1545                    { { "va", 1 }, SSAInfo(1, 2, 2, 2, 1, true) },
1546                    { { "va", 2 }, SSAInfo(3, 4, 4, 4, 1, true) }
1547                }, false, false, true },
1548            // block 7 (b11)
1549            { 96, 104,
1550                { },
1551                {
1552                    { { "va", 1 }, SSAInfo(1, 3, 3, 3, 1, true) },
1553                    { { "va", 2 }, SSAInfo(3, 5, 5, 5, 1, true) }
1554                }, false, false, false },
1555            // block 8 (loop1end)
1556            { 104, 116,
1557                { { 5, false }, { 9, false } },
1558                {
1559                    { { "sa", 1 }, SSAInfo(2, 3, 3, 3, 1, true) }
1560                }, false, false, false },
1561            // block 9 (loop0end)
1562            { 116, 140,
1563                { { 1, false }, { 10, false } },
1564                {
1565                    { { "sa", 0 }, SSAInfo(1, 2, 2, 2, 1, true) },
1566                    { { "va", 0 }, SSAInfo(5, 6, 6, 8, 3, true) },
1567                    { { "va", 1 }, SSAInfo(2, SIZE_MAX, 3, SIZE_MAX, 0, true) },
1568                    { { "va", 2 }, SSAInfo(4, SIZE_MAX, 5, SIZE_MAX, 0, true) }
1569                }, false, false, false },
1570            // block 10 (to bb0)
1571            { 140, 144,
1572                { },
1573                { }, false, false, true }
1574        },
1575        {   // SSA replaces
1576            { { "sa", 0 }, { { 2, 1 } } },
1577            { { "sa", 1 }, { { 3, 2 } } },
1578            { { "va", 0 }, { { 8, 1 }, { 10, 5 } } },
1579            { { "va", 1 }, { { 2, 1 }, { 2, 1 }, { 3, 1 }, { 3, 2 } } },
1580            { { "va", 2 }, { { 4, 1 }, { 4, 1 }, { 5, 1 }, { 5, 4 } } }
1581        },
1582        true, ""
1583    },
1584    {   // 9 - two branches
1585        R"ffDXD(.regvar sa:s:8, va:v:8
1586        # block 0
1587        s_mov_b64 sa[0:1], 321
1588        s_mov_b32 sa[2], s1
1589        s_mov_b32 sa[3], s2
1590        s_cmpk_eq_u32 s1, 321
1591        s_cbranch_scc1 bb10
1592       
1593        # block 1
1594        s_add_u32 sa[0], sa[0], sa[1]
1595        s_add_u32 sa[0], sa[0], sa[1]
1596        s_add_u32 sa[0], sa[0], sa[1]
1597        s_cbranch_scc1 bb01
1598       
1599        # block 2
1600        s_add_u32 sa[0], sa[0], sa[1]
1601        s_add_u32 sa[0], sa[0], sa[1]
1602        s_branch bb0e
1603       
1604        # block 3
1605bb01:   s_add_u32 sa[0], sa[0], sa[1]
1606        s_add_u32 sa[0], sa[0], sa[1]
1607       
1608        # block 4
1609bb0e:   s_add_u32 sa[0], sa[0], sa[2]
1610        s_endpgm
1611       
1612        # block 5
1613bb10:   s_add_u32 sa[0], sa[0], sa[1]
1614        s_add_u32 sa[0], sa[0], sa[1]
1615        s_add_u32 sa[0], sa[0], sa[1]
1616        s_add_u32 sa[0], sa[0], sa[1]
1617        s_add_u32 sa[0], sa[0], sa[1]
1618        s_cbranch_scc1 bb11
1619       
1620        # block 6
1621        s_add_u32 sa[0], sa[0], sa[2]
1622        s_add_u32 sa[0], sa[0], sa[2]
1623        s_branch bb1e
1624       
1625        # block 7
1626bb11:   s_add_u32 sa[0], sa[0], sa[3]
1627        s_add_u32 sa[0], sa[0], sa[3]
1628       
1629        # block 8
1630bb1e:   s_add_u32 sa[0], sa[0], sa[1]
1631        s_endpgm
1632)ffDXD",
1633        {
1634            // block 0 - start
1635            { 0, 24,
1636                { { 1, false }, { 5, false } },
1637                {
1638                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1639                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1640                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1641                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1642                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1643                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1644                }, false, false, false },
1645            // block 1 - bb00
1646            { 24, 40,
1647                { { 2, false }, { 3, false } },
1648                {
1649                    { { "sa", 0 }, SSAInfo(1, 2, 2, 4, 3, true) },
1650                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1651                }, false, false, false },
1652            // block 2 - bb00 second
1653            { 40, 52,
1654                { { 4, false } },
1655                {
1656                    { { "sa", 0 }, SSAInfo(4, 5, 5, 6, 2, true) },
1657                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1658                }, false, false, true },
1659            // block 3 - bb01
1660            { 52, 60,
1661                { },
1662                {
1663                    { { "sa", 0 }, SSAInfo(4, 8, 8, 9, 2, true) },
1664                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1665                }, false, false, false },
1666            // block 4 - bb0e
1667            { 60, 68,
1668                { },
1669                {
1670                    { { "sa", 0 }, SSAInfo(6, 7, 7, 7, 1, true) },
1671                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1672                }, false, false, true },
1673            // block 5 - bb10
1674            { 68, 92,
1675                { { 6, false }, { 7, false } },
1676                {
1677                    { { "sa", 0 }, SSAInfo(1, 10, 10, 14, 5, true) },
1678                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1679                }, false, false, false },
1680            // block 6 - bb10 (second)
1681            { 92, 104,
1682                { { 8, false } },
1683                {
1684                    { { "sa", 0 }, SSAInfo(14, 15, 15, 16, 2, true) },
1685                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1686                }, false, false, true },
1687            // block 7 - bb11
1688            { 104, 112,
1689                { },
1690                {
1691                    { { "sa", 0 }, SSAInfo(14, 18, 18, 19, 2, true) },
1692                    { { "sa", 3 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1693                }, false, false, false },
1694            // block 8 - bb1e
1695            { 112, 120,
1696                { },
1697                {
1698                    { { "sa", 0 }, SSAInfo(16, 17, 17, 17, 1, true) },
1699                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) }
1700                }, false, false, true }
1701        },
1702        {   // SSA replaces
1703            { { "sa", 0 }, { { 9, 6 }, { 19, 16 } } }
1704        },
1705        true, ""
1706    },
1707    {   // 10 - two branches with various SSAIds
1708        R"ffDXD(.regvar sa:s:8, va:v:8
1709        # block 0
1710        s_mov_b32 sa[0], s2
1711        s_mov_b32 sa[1], s3
1712        s_mov_b32 sa[2], s4
1713        s_mov_b32 sa[3], s5
1714       
1715        s_cmp_lt_u32 s0, s1
1716        s_cbranch_scc1 bb1
1717       
1718        # block 1, bb0
1719bb0:    s_add_u32 sa[3], sa[3], s1   # replace from this
1720        s_add_u32 sa[3], sa[3], s2
1721        s_cbranch_scc1 bb01
1722       
1723        # block 2, bb00
1724        s_add_u32 sa[2], sa[2], sa[1]   # replace from this
1725        s_add_u32 sa[3], sa[3], sa[2]
1726        s_endpgm
1727
1728bb01:   s_add_u32 sa[2], sa[2], sa[1]
1729        s_add_u32 sa[2], sa[2], sa[0]
1730        s_add_u32 sa[3], sa[3], sa[2]
1731        s_endpgm
1732       
1733bb1:    s_xor_b32 sa[2], sa[2], sa[0]
1734        s_xor_b32 sa[3], sa[3], sa[1]
1735        s_branch bb0
1736)ffDXD",
1737        {
1738            // block 0 - start
1739            { 0, 24,
1740                { { 1, false }, { 4, false } },
1741                {
1742                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1743                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1744                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1745                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1746                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1747                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
1748                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1749                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1750                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1751                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1752                }, false, false, false },
1753            // block 1 - bb0
1754            { 24, 36,
1755                { { 2, false }, { 3, false } },
1756                {
1757                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1758                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1759                    { { "sa", 3 }, SSAInfo(1, 2, 2, 3, 2, true) }
1760                }, false, false, false },
1761            // block 2 - bb00
1762            { 36, 48,
1763                { },
1764                {
1765                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1766                    { { "sa", 2 }, SSAInfo(1, 2, 2, 2, 1, true) },
1767                    { { "sa", 3 }, SSAInfo(3, 4, 4, 4, 1, true) }
1768                }, false, false, true },
1769            // block 3 - bb01
1770            { 48, 64,
1771                { },
1772                {
1773                    { { "sa", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1774                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1775                    { { "sa", 2 }, SSAInfo(1, 3, 3, 4, 2, true) },
1776                    { { "sa", 3 }, SSAInfo(3, 5, 5, 5, 1, true) }
1777                }, false, false, true },
1778            // block 4 - bb1
1779            { 64, 76,
1780                { { 1, false } },
1781                {
1782                    { { "sa", 0 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1783                    { { "sa", 1 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1784                    { { "sa", 2 }, SSAInfo(1, 5, 5, 5, 1, true) },
1785                    { { "sa", 3 }, SSAInfo(1, 6, 6, 6, 1, true) }
1786                }, false, false, true }
1787        },
1788        {   // SSA replaces
1789            { { "sa", 2 }, { { 5, 1 }, { 5, 1 } } },
1790            { { "sa", 3 }, { { 6, 1 } } }
1791        },
1792        true, ""
1793    },
1794    {   // 11 - with trap: first branch have unhandled SSA replace
1795        R"ffDXD(.regvar sa:s:8, va:v:8
1796        # block 0
1797        s_mov_b32 sa[0], s2
1798        s_mov_b32 sa[1], s3
1799        s_mov_b32 sa[2], s4
1800        s_mov_b32 sa[3], s5
1801        s_cmp_lt_u32 s0, s1
1802        s_cbranch_scc1 bb1
1803       
1804        # bb0
1805bb0:    s_add_u32 sa[3], sa[3], s1      # SSAID replace
1806        s_add_u32 sa[3], sa[3], s2
1807        s_endpgm
1808       
1809bb3:    s_add_u32 sa[3], sa[3], s2      # no SSAID replace (this same SSAID)
1810        s_endpgm
1811       
1812bb1:    s_add_u32 sa[3], sa[3], s2
1813bb1x:   .cf_jump bb3, bb2, bb4
1814        s_setpc_b64 s[0:1]
1815
1816bb2:    s_branch bb0
1817       
1818bb4:    s_branch bb1x       # jump to point to resolve conflict (bb1x)
1819)ffDXD",
1820        {
1821            // block 0
1822            { 0, 24,
1823                { { 1, false }, { 3, false } },
1824                {
1825                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1826                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1827                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1828                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1829                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1830                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
1831                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1832                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1833                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1834                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1835                }, false, false, false },
1836            // block 1
1837            { 24, 36,
1838                { },
1839                {
1840                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1841                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1842                    { { "sa", 3 }, SSAInfo(1, 2, 2, 3, 2, true) }
1843                }, false, false, true },
1844            // block 2
1845            { 36, 44,
1846                { },
1847                {
1848                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1849                    { { "sa", 3 }, SSAInfo(4, 5, 5, 5, 1, true) }
1850                }, false, false, true },
1851            // block 3 - bb1 - main part
1852            { 44, 48,
1853                { },
1854                {
1855                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1856                    { { "sa", 3 }, SSAInfo(1, 4, 4, 4, 1, true) }
1857                }, false, false, false },
1858            // block 4 - bb1x - jmp part
1859            { 48, 52,
1860                { { 2, false }, { 5, false }, { 6, false } },
1861                {
1862                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1863                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) }
1864                }, false, false, true },
1865            // block 5
1866            { 52, 56,
1867                { { 1, false } },
1868                { }, false, false, true },
1869            // block 6
1870            { 56, 60,
1871                { { 4, false } },
1872                { }, false, false, true }
1873        },
1874        {
1875            { { "sa", 3 }, { { 4, 1 }, { 4, 1 } } }
1876        },
1877        true, ""
1878    },
1879    {   // 12 - with trap: first branch have higher SSAId
1880        R"ffDXD(.regvar sa:s:8, va:v:8
1881        # block 0
1882        s_mov_b32 sa[0], s2
1883        s_mov_b32 sa[1], s3
1884        s_mov_b32 sa[2], s4
1885        s_mov_b32 sa[3], s5
1886        s_cmp_lt_u32 s0, s1
1887        .cf_jump bb1, bbx, bb3, bb2
1888        s_setpc_b64 s[0:1]
1889       
1890bb1:    s_add_u32 sa[3], sa[3], sa[2]
1891        s_endpgm
1892       
1893bbx:    s_add_u32 sa[3], sa[3], sa[2]
1894        s_cbranch_scc1 bb1_
1895
1896bb0:    s_add_u32 sa[3], sa[3], sa[2]
1897        s_endpgm
1898       
1899bb1_:   s_branch bb1
1900
1901bb3:    .cf_jump bb0, bb1_
1902        s_setpc_b64 s[0:1]
1903               
1904bb2:    s_add_u32 sa[3], sa[3], sa[2]
1905        s_branch bb3
1906)ffDXD",
1907        {
1908            // block 0
1909            { 0, 24,
1910                { { 1, false }, { 2, false }, { 5, false }, { 6, false } },
1911                {
1912                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1913                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
1914                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, true) },
1915                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, true) },
1916                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1917                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
1918                    { { "sa", 0 }, SSAInfo(0, 1, 1, 1, 1, false) },
1919                    { { "sa", 1 }, SSAInfo(0, 1, 1, 1, 1, false) },
1920                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
1921                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
1922                }, false, false, true },
1923            // block 1 - bb1
1924            { 24, 32,
1925                { },
1926                {
1927                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1928                    { { "sa", 3 }, SSAInfo(1, 2, 2, 2, 1, true) }
1929                }, false, false, true },
1930            // block 2 - bbx
1931            { 32, 40,
1932                { { 3, false }, { 4, false } },
1933                {
1934                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1935                    { { "sa", 3 }, SSAInfo(1, 3, 3, 3, 1, true) }
1936                }, false, false, false },
1937            // block 3 - bb0
1938            { 40, 48,
1939                { },
1940                {
1941                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1942                    { { "sa", 3 }, SSAInfo(3, 4, 4, 4, 1, true) }
1943                }, false, false, true },
1944            // block 4 - bb1_
1945            { 48, 52,
1946                { { 1, false } },
1947                { }, false, false, true },
1948            // block 5
1949            { 52, 56,
1950                { { 3, false }, { 4, false } },
1951                {
1952                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
1953                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) }
1954                }, false, false, true },
1955            // block 5
1956            { 56, 64,
1957                { { 5, false } },
1958                {
1959                    { { "sa", 2 }, SSAInfo(1, SIZE_MAX, 2, SIZE_MAX, 0, true) },
1960                    { { "sa", 3 }, SSAInfo(1, 5, 5, 5, 1, true) }
1961                }, false, false, true }
1962        },
1963        {
1964            { { "sa", 3 }, { { 3, 1 }, { 5, 3 }, { 5, 1 } } }
1965        },
1966        true, ""
1967    },
1968    {   // 13 - simple call
1969        R"ffDXD(.regvar sa:s:8, va:v:8
1970        s_mov_b32 sa[2], s4
1971        s_mov_b32 sa[3], s5
1972       
1973        s_getpc_b64 s[2:3]
1974        s_add_u32 s2, s2, routine-.
1975        s_add_u32 s3, s3, routine-.+4
1976        .cf_call routine
1977        s_swappc_b64 s[0:1], s[2:3]
1978       
1979        s_lshl_b32 sa[2], sa[2], 3
1980        s_lshl_b32 sa[3], sa[3], 4
1981        s_endpgm
1982       
1983routine:
1984        s_xor_b32 sa[2], sa[2], sa[4]
1985        s_xor_b32 sa[3], sa[3], sa[4]
1986        .cf_ret
1987        s_setpc_b64 s[0:1]
1988)ffDXD",
1989        {
1990            { 0, 32,
1991                { { 1, false }, { 2, true } },
1992                {
1993                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, false) },
1994                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, false) },
1995                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, false) },
1996                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, false) },
1997                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
1998                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
1999                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
2000                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
2001                }, true, false, false },
2002            { 32, 44,
2003                { },
2004                {
2005                    { { "sa", 2 }, SSAInfo(1, 2, 2, 2, 1, true) },
2006                    { { "sa", 3 }, SSAInfo(1, 2, 2, 2, 1, true) }
2007                }, false, false, true },
2008            { 44, 56,
2009                { },
2010                {
2011                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
2012                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
2013                    { { "sa", 2 }, SSAInfo(1, 3, 3, 3, 1, true) },
2014                    { { "sa", 3 }, SSAInfo(1, 3, 3, 3, 1, true) },
2015                    { { "sa", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
2016                }, false, true, true }
2017        },
2018        {
2019            { { "sa", 2 }, { { 3, 1 } } },
2020            { { "sa", 3 }, { { 3, 1 } } }
2021        },
2022        true, ""
2023    },
2024    {   // 14 - simple call, more complex routine
2025        R"ffDXD(.regvar sa:s:8, va:v:8
2026        s_mov_b32 sa[2], s4
2027        s_mov_b32 sa[3], s5
2028       
2029        s_getpc_b64 s[2:3]
2030        s_add_u32 s2, s2, routine-.
2031        s_add_u32 s3, s3, routine-.+4
2032        .cf_call routine
2033        s_swappc_b64 s[0:1], s[2:3]
2034       
2035        s_lshl_b32 sa[2], sa[2], 3
2036        s_lshl_b32 sa[3], sa[3], 4
2037        s_endpgm
2038       
2039routine:
2040        s_xor_b32 sa[2], sa[2], sa[4]
2041        s_xor_b32 sa[3], sa[3], sa[4]
2042        s_cbranch_scc1 bb1
2043       
2044        s_min_u32 sa[2], sa[2], sa[4]
2045        s_min_u32 sa[3], sa[3], sa[4]
2046        .cf_ret
2047        s_setpc_b64 s[0:1]
2048       
2049bb1:    s_and_b32 sa[2], sa[2], sa[4]
2050        s_and_b32 sa[3], sa[3], sa[4]
2051        .cf_ret
2052        s_setpc_b64 s[0:1]
2053)ffDXD",
2054        {
2055            { 0, 32,
2056                { {1, false }, { 2, true } },
2057                {
2058                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, false) },
2059                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, false) },
2060                    { { "", 2 }, SSAInfo(0, 0, 0, 0, 0, false) },
2061                    { { "", 3 }, SSAInfo(0, 0, 0, 0, 0, false) },
2062                    { { "", 4 }, SSAInfo(0, 0, 0, 0, 0, true) },
2063                    { { "", 5 }, SSAInfo(0, 0, 0, 0, 0, true) },
2064                    { { "sa", 2 }, SSAInfo(0, 1, 1, 1, 1, false) },
2065                    { { "sa", 3 }, SSAInfo(0, 1, 1, 1, 1, false) }
2066                }, true, false, false },
2067            // block 1 - after call
2068            { 32, 44,
2069                { },
2070                {
2071                    { { "sa", 2 }, SSAInfo(1, 2, 2, 2, 1, true) },
2072                    { { "sa", 3 }, SSAInfo(1, 2, 2, 2, 1, true) }
2073                }, false, false, true },
2074            // block 2 - routine
2075            { 44, 56,
2076                { { 3, false }, { 4, false } },
2077                {
2078                    { { "sa", 2 }, SSAInfo(1, 3, 3, 3, 1, true) },
2079                    { { "sa", 3 }, SSAInfo(1, 3, 3, 3, 1, true) },
2080                    { { "sa", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
2081                }, false, false, false },
2082            // block 3 - first return
2083            { 56, 68,
2084                { },
2085                {
2086                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
2087                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
2088                    { { "sa", 2 }, SSAInfo(3, 4, 4, 4, 1, true) },
2089                    { { "sa", 3 }, SSAInfo(3, 4, 4, 4, 1, true) },
2090                    { { "sa", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
2091                }, false, true, true },
2092            // block 4 - second return
2093            { 68, 80,
2094                { },
2095                {
2096                    { { "", 0 }, SSAInfo(0, 0, 0, 0, 0, true) },
2097                    { { "", 1 }, SSAInfo(0, 0, 0, 0, 0, true) },
2098                    { { "sa", 2 }, SSAInfo(3, 5, 5, 5, 1, true) },
2099                    { { "sa", 3 }, SSAInfo(3, 5, 5, 5, 1, true) },
2100                    { { "sa", 4 }, SSAInfo(0, SIZE_MAX, 1, SIZE_MAX, 0, true) }
2101                }, false, true, true }
2102        },
2103        {
2104            { { "sa", 2 }, { { 4, 1 }, { 5, 1 } } },
2105            { { "sa", 3 }, { { 4, 1 }, { 5, 1 } } }
2106        },
2107        true, ""
2108    }
2109};
2110
2111static TestSingleVReg getTestSingleVReg(const AsmSingleVReg& vr,
2112        const std::unordered_map<const AsmRegVar*, CString>& rvMap)
2113{
2114    if (vr.regVar == nullptr)
2115        return { "", vr.index };
2116   
2117    auto it = rvMap.find(vr.regVar);
2118    if (it == rvMap.end())
2119        throw Exception("getTestSingleVReg: RegVar not found!!");
2120    return { it->second, vr.index };
2121}
2122
2123static void testCreateSSAData(cxuint i, const AsmSSADataCase& testCase)
2124{
2125    std::istringstream input(testCase.input);
2126    std::ostringstream errorStream;
2127   
2128    Assembler assembler("test.s", input,
2129                    (ASM_ALL&~ASM_ALTMACRO) | ASM_TESTRUN | ASM_TESTRESOLVE,
2130                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
2131    bool good = assembler.assemble();
2132    if (assembler.getSections().size()<1)
2133    {
2134        std::ostringstream oss;
2135        oss << "FAILED for " << " testAsmCodeStructCase#" << i;
2136        throw Exception(oss.str());
2137    }
2138    const AsmSection& section = assembler.getSections()[0];
2139   
2140    AsmRegAllocator regAlloc(assembler);
2141   
2142    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
2143                            section.content.data());
2144    regAlloc.createSSAData(*section.usageHandler);
2145    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
2146    std::ostringstream oss;
2147    oss << " testAsmSSADataCase#" << i;
2148    const std::string testCaseName = oss.str();
2149    assertValue<bool>("testAsmSSAData", testCaseName+".good",
2150                      testCase.good, good);
2151    assertString("testAsmSSAData", testCaseName+".errorMessages",
2152              testCase.errorMessages, errorStream.str());
2153   
2154    assertValue("testAsmSSAData", testCaseName+".codeBlocks.size",
2155                testCase.codeBlocks.size(), resCodeBlocks.size());
2156   
2157    std::unordered_map<const AsmRegVar*, CString> regVarNamesMap;
2158    for (const auto& rvEntry: assembler.getRegVarMap())
2159        regVarNamesMap.insert(std::make_pair(&rvEntry.second, rvEntry.first));
2160   
2161    for (size_t j = 0; j < resCodeBlocks.size(); j++)
2162    {
2163        const CCodeBlock2& expCBlock = testCase.codeBlocks[j];
2164        const CodeBlock& resCBlock = resCodeBlocks[j];
2165        std::ostringstream codeBlockOss;
2166        codeBlockOss << ".codeBlock#" << j << ".";
2167        codeBlockOss.flush();
2168        std::string cbname(codeBlockOss.str());
2169        assertValue("testAsmSSAData", testCaseName + cbname + "start",
2170                    expCBlock.start, resCBlock.start);
2171        assertValue("testAsmSSAData", testCaseName + cbname + "end",
2172                    expCBlock.end, resCBlock.end);
2173        assertValue("testAsmSSAData", testCaseName + cbname + "nextsSize",
2174                    expCBlock.nexts.size(), resCBlock.nexts.size());
2175       
2176        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
2177        {
2178            std::ostringstream nextOss;
2179            nextOss << "next#" << k << ".";
2180            nextOss.flush();
2181            std::string nname(nextOss.str());
2182           
2183            assertValue("testAsmSSAData", testCaseName + cbname + nname + "block",
2184                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
2185            assertValue("testAsmSSAData", testCaseName + cbname + nname + "isCall",
2186                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
2187        }
2188       
2189        assertValue("testAsmSSAData", testCaseName + cbname + "ssaInfoSize",
2190                    expCBlock.ssaInfos.size(), resCBlock.ssaInfoMap.size());
2191       
2192        Array<std::pair<TestSingleVReg, SSAInfo> > resSSAInfos(
2193                        resCBlock.ssaInfoMap.size());
2194        std::transform(resCBlock.ssaInfoMap.begin(), resCBlock.ssaInfoMap.end(),
2195            resSSAInfos.begin(),
2196            [&regVarNamesMap](const std::pair<AsmSingleVReg, SSAInfo>& a)
2197            -> std::pair<TestSingleVReg, SSAInfo>
2198            { return { getTestSingleVReg(a.first, regVarNamesMap), a.second }; });
2199        mapSort(resSSAInfos.begin(), resSSAInfos.end());
2200       
2201        for (size_t k = 0; k < expCBlock.ssaInfos.size(); k++)
2202        {
2203            std::ostringstream ssaOss;
2204            ssaOss << "ssaInfo#" << k << ".";
2205            ssaOss.flush();
2206            std::string ssaName(ssaOss.str());
2207           
2208            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "svreg",
2209                        expCBlock.ssaInfos[k].first, resSSAInfos[k].first);
2210            const SSAInfo& expSInfo = expCBlock.ssaInfos[k].second;
2211            const SSAInfo& resSInfo = resSSAInfos[k].second;
2212            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdBefore",
2213                        expSInfo.ssaIdBefore, resSInfo.ssaIdBefore);
2214            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaId",
2215                        expSInfo.ssaId, resSInfo.ssaId);
2216            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdChange",
2217                        expSInfo.ssaIdChange, resSInfo.ssaIdChange);
2218            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdFirst",
2219                        expSInfo.ssaIdFirst, resSInfo.ssaIdFirst);
2220            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdLast",
2221                        expSInfo.ssaIdLast, resSInfo.ssaIdLast);
2222            assertValue("testAsmSSAData", testCaseName + cbname + ssaName +
2223                        "readBeforeWrite", int(expSInfo.readBeforeWrite),
2224                        int(resSInfo.readBeforeWrite));
2225        }
2226       
2227        assertValue("testAsmSSAData", testCaseName + cbname + "haveCalls",
2228                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
2229        assertValue("testAsmSSAData", testCaseName + cbname + "haveReturn",
2230                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
2231        assertValue("testAsmSSAData", testCaseName + cbname + "haveEnd",
2232                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
2233    }
2234   
2235    const SSAReplacesMap& ssaReplacesMap = regAlloc.getSSAReplacesMap();
2236    assertValue("testAsmSSAData", testCaseName + "ssaReplacesSize",
2237                    testCase.ssaReplaces.size(), ssaReplacesMap.size());
2238    Array<std::pair<TestSingleVReg, Array<SSAReplace> > >
2239                        resSSAReplaces(ssaReplacesMap.size());
2240    std::transform(ssaReplacesMap.begin(), ssaReplacesMap.end(),
2241            resSSAReplaces.begin(),
2242            [&regVarNamesMap](const std::pair<AsmSingleVReg, std::vector<SSAReplace> >& a)
2243            -> std::pair<TestSingleVReg, Array<SSAReplace> >
2244            { return { getTestSingleVReg(a.first, regVarNamesMap), 
2245                Array<SSAReplace>(a.second.begin(), a.second.end()) }; });
2246    mapSort(resSSAReplaces.begin(), resSSAReplaces.end());
2247   
2248    for (size_t j = 0; j < testCase.ssaReplaces.size(); j++)
2249    {
2250        std::ostringstream ssaOss;
2251        ssaOss << "ssas" << j << ".";
2252        ssaOss.flush();
2253        std::string ssaName(ssaOss.str());
2254       
2255        const auto& expEntry = testCase.ssaReplaces[j];
2256        const auto& resEntry = resSSAReplaces[j];
2257       
2258        assertValue("testAsmSSAData", testCaseName + ssaName + "svreg",
2259                        expEntry.first, resEntry.first);
2260        assertValue("testAsmSSAData", testCaseName + ssaName + "replacesSize",
2261                        expEntry.second.size(), resEntry.second.size());
2262        for (size_t k = 0; k < expEntry.second.size(); k++)
2263        {
2264            std::ostringstream repOss;
2265            repOss << "replace#" << k << ".";
2266            repOss.flush();
2267            std::string repName(repOss.str());
2268           
2269            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "first",
2270                        expEntry.second[k].first, resEntry.second[k].first);
2271            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "second",
2272                        expEntry.second[k].second, resEntry.second[k].second);
2273        }
2274    }
2275}
2276
2277int main(int argc, const char** argv)
2278{
2279    int retVal = 0;
2280    for (size_t i = 0; i < sizeof(codeStructTestCases1Tbl)/sizeof(AsmCodeStructCase); i++)
2281        try
2282        { testCreateCodeStructure(i, codeStructTestCases1Tbl[i]); }
2283        catch(const std::exception& ex)
2284        {
2285            std::cerr << ex.what() << std::endl;
2286            retVal = 1;
2287        }
2288    for (size_t i = 0; i < sizeof(ssaDataTestCases1Tbl)/sizeof(AsmSSADataCase); i++)
2289        try
2290        { testCreateSSAData(i, ssaDataTestCases1Tbl[i]); }
2291        catch(const std::exception& ex)
2292        {
2293            std::cerr << ex.what() << std::endl;
2294            retVal = 1;
2295        }
2296    return retVal;
2297}
Note: See TracBrowser for help on using the repository browser.