source: CLRX/CLRadeonExtender/trunk/tests/amdasm/AsmRegAlloc3.cpp @ 4043

Last change on this file since 4043 was 4043, checked in by matszpk, 4 months ago

CLRadeonExtender: AsmRegAlloc3: Enable the rest of testcases.

File size: 16.6 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#include "AsmRegAlloc.h"
32
33using namespace CLRX;
34
35typedef AsmRegAllocator::OutLiveness OutLiveness;
36typedef AsmRegAllocator::LinearDep LinearDep;
37typedef AsmRegAllocator::VarIndexMap VarIndexMap;
38
39struct LinearDep2
40{
41    cxbyte align;
42    Array<size_t> prevVidxes;
43    Array<size_t> nextVidxes;
44};
45
46struct AsmLivenessesCase
47{
48    const char* input;
49    Array<OutLiveness> livenesses[MAX_REGTYPES_NUM];
50    Array<std::pair<size_t, LinearDep2> > linearDepMaps[MAX_REGTYPES_NUM];
51    bool good;
52    const char* errorMessages;
53};
54
55static const AsmLivenessesCase createLivenessesCasesTbl[] =
56{
57    {   // 0 - simple case
58        R"ffDXD(.regvar sa:s:8, va:v:10
59        s_mov_b32 sa[4], sa[2]  # 0
60        s_add_u32 sa[4], sa[4], s3
61        v_xor_b32 va[4], va[2], v3
62)ffDXD",
63        {   // livenesses
64            {   // for SGPRs
65                { { 0, 5 } }, // S3
66                { { 0, 1 } }, // sa[2]'0
67                { { 1, 5 } }, // sa[4]'0
68                { { 5, 6 } }  // sa[4]'1
69            },
70            {   // for VGPRs
71                { { 0, 9 } }, // V3
72                { { 0, 9 } }, // va[2]'0
73                { { 9, 10 } } // va[4]'0 : out of range code block
74            },
75            { },
76            { }
77        },
78        { },  // linearDepMaps
79        true, ""
80    },
81    {   // 1 - simple case 2
82        R"ffDXD(.regvar sa:s:8, va:v:10
83        s_mov_b32 sa[4], sa[2]  # 0
84        s_add_u32 sa[4], sa[4], s3
85        v_xor_b32 va[4], va[2], v3
86        s_endpgm
87)ffDXD",
88        {   // livenesses
89            {   // for SGPRs
90                { { 0, 5 } }, // S3
91                { { 0, 1 } }, // sa[2]'0
92                { { 1, 5 } }, // sa[4]'0
93                { { 5, 6 } }  // sa[4]'1
94            },
95            {   // for VGPRs
96                { { 0, 9 } }, // V3
97                { { 0, 9 } }, // va[2]'0
98                { { 9, 10 } } // va[4]'0 : out of range code block
99            },
100            { },
101            { }
102        },
103        { },  // linearDepMaps
104        true, ""
105    },
106    {   // 2 - simple case (linear dep)
107        R"ffDXD(.regvar sa:s:8, va:v:10
108        .regvar sbuf:s:4, rbx4:v:6
109        s_mov_b64 sa[4:5], sa[2:3]  # 0
110        s_and_b64 sa[4:5], sa[4:5], s[4:5]
111        v_add_f64 va[4:5], va[2:3], v[3:4]
112        buffer_load_dwordx4 rbx4[1:5], va[6], sbuf[0:3], sa[7] idxen offset:603 tfe
113)ffDXD",
114        {   // livenesses
115            {   // for SGPRs
116                { { 0, 5 } }, // S4
117                { { 0, 5 } }, // S5
118                { { 0, 1 } }, // sa[2]'0
119                { { 0, 1 } }, // sa[3]'0
120                { { 1, 5 } }, // sa[4]'0
121                { { 5, 6 } }, // sa[4]'1
122                { { 1, 5 } }, // sa[5]'0
123                { { 5, 6 } }, // sa[5]'1
124                { { 0, 17 } }, // sa[7]'0
125                { { 0, 17 } }, // sbuf[0]'0
126                { { 0, 17 } }, // sbuf[1]'0
127                { { 0, 17 } }, // sbuf[2]'0
128                { { 0, 17 } }, // sbuf[3]'0
129            },
130            {   // for VGPRs
131                { { 0, 9 } }, // V3
132                { { 0, 9 } }, // V4
133                { { 17, 18 } }, // rbx4[1]'0
134                { { 17, 18 } }, // rbx4[2]'0
135                { { 17, 18 } }, // rbx4[3]'0
136                { { 17, 18 } }, // rbx4[4]'0
137                { { 0, 17 } }, // rbx4[5]'0: tfe - read before write
138                { { 0, 9 } }, // va[2]'0
139                { { 0, 9 } }, // va[3]'0
140                { { 9, 10 } }, // va[4]'0 : out of range code block
141                { { 9, 10 } }, // va[5]'0 : out of range code block
142                { { 0, 17 } } // va[6]'0
143            },
144            { },
145            { }
146        },
147        {   // linearDepMaps
148            {   // for SGPRs
149                { 0, { 0, { }, { 1 } } },  // S4
150                { 1, { 0, { 0 }, { } } },  // S5
151                { 2, { 2, { }, { 3 } } },  // sa[2]'0
152                { 3, { 0, { 2 }, { } } },  // sa[3]'0
153                { 4, { 2, { }, { 6 } } },  // sa[4]'0
154                { 5, { 2, { }, { 7, 7 } } },  // sa[4]'1
155                { 6, { 0, { 4 }, { } } },  // sa[5]'0
156                { 7, { 0, { 5, 5 }, { } } },   // sa[5]'1
157                { 9, { 4, { }, { 10 } } }, // sbuf[0]'0
158                { 10, { 0, { 9 }, { 11 } } }, // sbuf[1]'0
159                { 11, { 0, { 10 }, { 12 } } }, // sbuf[2]'0
160                { 12, { 0, { 11 }, { } } }  // sbuf[3]'0
161            },
162            {   // for VGPRs
163                { 0, { 0, { }, { 1 } } },  // V3
164                { 1, { 0, { 0 }, { } } },  // V4
165                { 2, { 1, { }, { 3 } } }, // rbx4[1]'0
166                { 3, { 0, { 2 }, { 4 } } }, // rbx4[2]'0
167                { 4, { 0, { 3 }, { 5 } } }, // rbx4[3]'0
168                { 5, { 0, { 4 }, { 6 } } }, // rbx4[4]'0
169                { 6, { 0, { 5 }, { } } }, // rbx4[5]'0
170                { 7, { 1, { }, { 8 } } },  // va[2]'0
171                { 8, { 0, { 7 }, { } } },  // va[3]'0
172                { 9, { 1, { }, { 10 } } },  // va[4]'0
173                { 10, { 0, { 9 }, { } } }  // va[5]'0
174            },
175            { },
176            { }
177        },
178        true, ""
179    },
180    {   // 3 - next simple case
181        R"ffDXD(.regvar sa:s:8, va:v:10
182        s_mov_b32 sa[4], sa[2]  # 0
183        s_add_u32 sa[4], sa[4], s3
184        v_xor_b32 va[4], va[2], v3
185        v_mov_b32 va[3], 1.45s
186        v_mov_b32 va[6], -7.45s
187        v_lshlrev_b32 va[5], sa[4], va[4]
188        v_mac_f32 va[3], va[6], v0
189        s_mul_i32 sa[7], sa[2], sa[3]
190        v_mac_f32 va[3], va[7], v0
191        s_endpgm
192)ffDXD",
193        {   // livenesses
194            {   // for SGPRs
195                { { 0, 5 } }, // 0: S3
196                { { 0, 37 } }, // 1: sa[2]'0
197                { { 0, 37 } }, // 2: sa[3]'0
198                { { 1, 5 } }, // 3: sa[4]'0
199                { { 5, 29 } }, // 4: sa[4]'1
200                { { 37, 38 } }  // 5: sa[7]'0
201            },
202            {   // for VGPRs
203                { { 0, 41 } }, // 0: v0
204                { { 0, 9 } }, // 1: v3
205                { { 0, 9 } }, // 2: va[2]'0
206                { { 13, 41 } }, // 3: va[3]'0
207                { { 9, 29 } }, // 4: va[4]'0
208                { { 29, 30 } }, // 5: va[5]'0
209                { { 21, 33 } }, // 6: va[6]'0
210                { { 0, 41 } }  // 7: va[7]'0
211            },
212            { },
213            { }
214        },
215        { }, // linearDepMaps
216        true, ""
217    },
218    {   // 4 - next test case
219        R"ffDXD(.regvar sa:s:8, va:v:10
220        s_mov_b32 sa[4], sa[2]  # 0
221        s_add_u32 sa[4], sa[4], s3  # 4
222       
223        v_xor_b32 v4, va[2], v3         # 8
224        v_xor_b32 va[5], v4, va[5]      # 12
225       
226        s_sub_u32 sa[4], sa[4], sa[3]   # 16
227       
228        v_xor_b32 v4, va[5], v3         # 20
229        v_xor_b32 va[6], v4, va[6]      # 24
230       
231        s_mul_i32 sa[4], sa[4], sa[1]   # 28
232        s_mul_i32 sa[4], sa[4], sa[0]   # 32
233       
234        v_xor_b32 v4, va[6], v3         # 36
235        v_xor_b32 va[7], v4, va[7]      # 40
236)ffDXD",
237        {   // livenesses
238            {   // for SGPRs
239                { { 0, 5 } },   // 0: S3
240                { { 0, 33 } },  // 1: sa[0]'0
241                { { 0, 29 } },  // 2: sa[1]'0
242                { { 0, 1 } },   // 3: sa[2]'0
243                { { 0, 17 } },  // 4: sa[3]'0
244                { { 1, 5 } },   // 5: sa[4]'0
245                { { 5, 17 } },  // 6: sa[4]'1
246                { { 17, 29 } }, // 7: sa[4]'2
247                { { 29, 33 } }, // 8: sa[4]'3
248                { { 33, 34 } }  // 9: sa[4]'4
249            },
250            {   // for VGPRs
251                { { 0, 37 } },   // 0: v3
252                { { 9, 13 }, { 21, 25 }, { 37, 41 } }, // 1: v4
253                { { 0, 9 } },    // 2: va[2]'0
254                { { 0, 13 } },   // 3: va[5]'0
255                { { 13, 21 } },  // 4: va[5]'1
256                { { 0, 25 } },   // 5: va[6]'0
257                { { 25, 37 } },  // 6: va[6]'1
258                { { 0, 41 } },   // 7: va[7]'0
259                { { 41, 42 } }   // 8: va[7]'1
260            },
261            { },
262            { }
263        },
264        { }, // linearDepMaps
265        true, ""
266    }
267};
268
269static TestSingleVReg getTestSingleVReg(const AsmSingleVReg& vr,
270        const std::unordered_map<const AsmRegVar*, CString>& rvMap)
271{
272    if (vr.regVar == nullptr)
273        return { "", vr.index };
274   
275    auto it = rvMap.find(vr.regVar);
276    if (it == rvMap.end())
277        throw Exception("getTestSingleVReg: RegVar not found!!");
278    return { it->second, vr.index };
279}
280
281static void testCreateLivenessesCase(cxuint i, const AsmLivenessesCase& testCase)
282{
283    std::istringstream input(testCase.input);
284    std::ostringstream errorStream;
285   
286    Assembler assembler("test.s", input,
287                    (ASM_ALL&~ASM_ALTMACRO) | ASM_TESTRUN | ASM_TESTRESOLVE,
288                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
289    bool good = assembler.assemble();
290    if (assembler.getSections().size()<1)
291    {
292        std::ostringstream oss;
293        oss << "FAILED for " << " testAsmLivenesses#" << i;
294        throw Exception(oss.str());
295    }
296    const AsmSection& section = assembler.getSections()[0];
297   
298    AsmRegAllocator regAlloc(assembler);
299   
300    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
301                            section.content.data());
302    regAlloc.createSSAData(*section.usageHandler);
303    regAlloc.applySSAReplaces();
304    regAlloc.createLivenesses(*section.usageHandler);
305   
306    std::ostringstream oss;
307    oss << " testAsmLivenesses case#" << i;
308    const std::string testCaseName = oss.str();
309   
310    assertValue<bool>("testAsmLivenesses", testCaseName+".good",
311                      testCase.good, good);
312    assertString("testAsmLivenesses", testCaseName+".errorMessages",
313              testCase.errorMessages, errorStream.str());
314   
315    std::unordered_map<const AsmRegVar*, CString> regVarNamesMap;
316    for (const auto& rvEntry: assembler.getRegVarMap())
317        regVarNamesMap.insert(std::make_pair(&rvEntry.second, rvEntry.first));
318   
319    // generate livenesses indices conversion table
320    const VarIndexMap* vregIndexMaps = regAlloc.getVregIndexMaps();
321   
322    std::vector<size_t> lvIndexCvtTables[MAX_REGTYPES_NUM];
323    std::vector<size_t> revLvIndexCvtTables[MAX_REGTYPES_NUM];
324    for (size_t r = 0; r < MAX_REGTYPES_NUM; r++)
325    {
326        const VarIndexMap& vregIndexMap = vregIndexMaps[r];
327        Array<std::pair<TestSingleVReg, const std::vector<size_t>*> > outVregIdxMap(
328                    vregIndexMap.size());
329       
330        size_t j = 0;
331        for (const auto& entry: vregIndexMap)
332        {
333            TestSingleVReg vreg = getTestSingleVReg(entry.first, regVarNamesMap);
334            outVregIdxMap[j++] = std::make_pair(vreg, &entry.second);
335        }
336        mapSort(outVregIdxMap.begin(), outVregIdxMap.end());
337       
338        std::vector<size_t>& lvIndexCvtTable = lvIndexCvtTables[r];
339        std::vector<size_t>& revLvIndexCvtTable = revLvIndexCvtTables[r];
340        // generate livenessCvt table
341        for (const auto& entry: outVregIdxMap)
342            for (size_t v: *entry.second)
343                if (v != SIZE_MAX)
344                {
345                    /*std::cout << "lvidx: " << v << ": " << entry.first.name << ":" <<
346                            entry.first.index << std::endl;*/
347                    size_t j = lvIndexCvtTable.size();
348                    lvIndexCvtTable.push_back(v);
349                    if (v+1 > revLvIndexCvtTable.size())
350                        revLvIndexCvtTable.resize(v+1);
351                    revLvIndexCvtTable[v] = j;
352                }
353    }
354   
355    const Array<OutLiveness>* resLivenesses = regAlloc.getOutLivenesses();
356    for (size_t r = 0; r < MAX_REGTYPES_NUM; r++)
357    {
358        std::ostringstream rOss;
359        rOss << "live.regtype#" << r;
360        rOss.flush();
361        std::string rtname(rOss.str());
362       
363        assertValue("testAsmLivenesses", testCaseName + rtname + ".size",
364                    testCase.livenesses[r].size(), resLivenesses[r].size());
365       
366        for (size_t li = 0; li < resLivenesses[r].size(); li++)
367        {
368            std::ostringstream lOss;
369            lOss << ".liveness#" << li;
370            lOss.flush();
371            std::string lvname(rtname + lOss.str());
372            const OutLiveness& expLv = testCase.livenesses[r][li];
373            const OutLiveness& resLv = resLivenesses[r][lvIndexCvtTables[r][li]];
374           
375            // checking liveness
376            assertValue("testAsmLivenesses", testCaseName + lvname + ".size",
377                    expLv.size(), resLv.size());
378            for (size_t k = 0; k < resLv.size(); k++)
379            {
380                std::ostringstream regOss;
381                regOss << ".reg#" << k;
382                regOss.flush();
383                std::string regname(lvname + regOss.str());
384                assertValue("testAsmLivenesses", testCaseName + regname + ".first",
385                    expLv[k].first, resLv[k].first);
386                assertValue("testAsmLivenesses", testCaseName + regname + ".second",
387                    expLv[k].second, resLv[k].second);
388            }
389        }
390    }
391   
392    const std::unordered_map<size_t, LinearDep>* resLinearDepMaps =
393                regAlloc.getLinearDepMaps();
394    for (size_t r = 0; r < MAX_REGTYPES_NUM; r++)
395    {
396        std::ostringstream rOss;
397        rOss << "lndep.regtype#" << r;
398        rOss.flush();
399        std::string rtname(rOss.str());
400       
401        assertValue("testAsmLivenesses", testCaseName + rtname + ".size",
402                    testCase.linearDepMaps[r].size(), resLinearDepMaps[r].size());
403       
404        for (size_t di = 0; di < testCase.linearDepMaps[r].size(); di++)
405        {
406            std::ostringstream lOss;
407            lOss << ".lndep#" << di;
408            lOss.flush();
409            std::string ldname(rtname + lOss.str());
410            const auto& expLinearDepEntry = testCase.linearDepMaps[r][di];
411            auto rlit = resLinearDepMaps[r].find(
412                            lvIndexCvtTables[r][expLinearDepEntry.first]);
413           
414            std::ostringstream vOss;
415            vOss << expLinearDepEntry.first;
416            vOss.flush();
417            assertTrue("testAsmLivenesses", testCaseName + ldname + ".key=" + vOss.str(),
418                        rlit != resLinearDepMaps[r].end());
419            const LinearDep2& expLinearDep = expLinearDepEntry.second;
420            const LinearDep& resLinearDep = rlit->second;
421           
422            assertValue("testAsmLivenesses", testCaseName + ldname + ".align",
423                        cxuint(expLinearDep.align), cxuint(resLinearDep.align));
424           
425            Array<size_t> resPrevVidxes(resLinearDep.prevVidxes.size());
426            // convert to res ssaIdIndices
427            for (size_t k = 0; k < resLinearDep.prevVidxes.size(); k++)
428                resPrevVidxes[k] = revLvIndexCvtTables[r][resLinearDep.prevVidxes[k]];
429           
430            assertArray("testAsmLivenesses", testCaseName + ldname + ".prevVidxes",
431                        expLinearDep.prevVidxes, resPrevVidxes);
432           
433            Array<size_t> resNextVidxes(resLinearDep.nextVidxes.size());
434            // convert to res ssaIdIndices
435            for (size_t k = 0; k < resLinearDep.nextVidxes.size(); k++)
436                resNextVidxes[k] = revLvIndexCvtTables[r][resLinearDep.nextVidxes[k]];
437           
438            assertArray("testAsmLivenesses", testCaseName + ldname + ".nextVidxes",
439                        expLinearDep.nextVidxes, resNextVidxes);
440        }
441    }
442}
443
444int main(int argc, const char** argv)
445{
446    int retVal = 0;
447    for (size_t i = 0; i < sizeof(createLivenessesCasesTbl)/sizeof(AsmLivenessesCase); i++)
448        try
449        { testCreateLivenessesCase(i, createLivenessesCasesTbl[i]); }
450        catch(const std::exception& ex)
451        {
452            std::cerr << ex.what() << std::endl;
453            retVal = 1;
454        }
455    return retVal;
456}
Note: See TracBrowser for help on using the repository browser.