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

Last change on this file since 3916 was 3916, checked in by matszpk, 13 months ago

CLRadeonExtender: AsmRegAlloc?: Add new testsuite. Do not put already cached subroutine.

File size: 13.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#include "AsmRegAlloc.h"
32
33using namespace CLRX;
34
35std::ostream& operator<<(std::ostream& os, const TestSingleVReg& vreg)
36{
37    if (!vreg.name.empty())
38        os << vreg.name << "[" << vreg.index << "]";
39    else
40        os << "@REG[" << vreg.index << "]";
41    return os;
42}
43
44static void testCreateCodeStructure(cxuint i, const AsmCodeStructCase& testCase)
45{
46    std::istringstream input(testCase.input);
47    std::ostringstream errorStream;
48   
49    Assembler assembler("test.s", input, ASM_ALL&~ASM_ALTMACRO,
50                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
51    bool good = assembler.assemble();
52   
53    if (assembler.getSections().size()<1)
54    {
55        std::ostringstream oss;
56        oss << "FAILED for " << " testAsmCodeStructCase#" << i;
57        throw Exception(oss.str());
58    }
59    const AsmSection& section = assembler.getSections()[0];
60   
61    AsmRegAllocator regAlloc(assembler);
62   
63    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
64                            section.content.data());
65    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
66    std::ostringstream oss;
67    oss << " testAsmCodeStructCase#" << i;
68    const std::string testCaseName = oss.str();
69    assertValue<bool>("testAsmCodeStruct", testCaseName+".good",
70                      testCase.good, good);
71    assertString("testAsmCodeStruct", testCaseName+".errorMessages",
72              testCase.errorMessages, errorStream.str());
73   
74    assertValue("testAsmCodeStruct", testCaseName+".codeBlocks.size",
75                testCase.codeBlocks.size(), resCodeBlocks.size());
76   
77    for (size_t j = 0; j < resCodeBlocks.size(); j++)
78    {
79        const CCodeBlock& expCBlock = testCase.codeBlocks[j];
80        const CodeBlock& resCBlock = resCodeBlocks[j];
81        std::ostringstream codeBlockOss;
82        codeBlockOss << ".codeBlock#" << j << ".";
83        codeBlockOss.flush();
84        std::string cbname(codeBlockOss.str());
85        assertValue("testAsmCodeStruct", testCaseName + cbname + "start",
86                    expCBlock.start, resCBlock.start);
87        assertValue("testAsmCodeStruct", testCaseName + cbname + "end",
88                    expCBlock.end, resCBlock.end);
89        assertValue("testAsmCodeStruct", testCaseName + cbname + "nextsSize",
90                    expCBlock.nexts.size(), resCBlock.nexts.size());
91       
92        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
93        {
94            std::ostringstream nextOss;
95            nextOss << "next#" << k << ".";
96            nextOss.flush();
97            std::string nname(nextOss.str());
98           
99            assertValue("testAsmCodeStruct", testCaseName + cbname + nname + "block",
100                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
101            assertValue("testAsmCodeStruct", testCaseName + cbname + nname + "isCall",
102                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
103        }
104       
105        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveCalls",
106                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
107        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveReturn",
108                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
109        assertValue("testAsmCodeStruct", testCaseName + cbname + "haveEnd",
110                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
111    }
112}
113
114static TestSingleVReg getTestSingleVReg(const AsmSingleVReg& vr,
115        const std::unordered_map<const AsmRegVar*, CString>& rvMap)
116{
117    if (vr.regVar == nullptr)
118        return { "", vr.index };
119   
120    auto it = rvMap.find(vr.regVar);
121    if (it == rvMap.end())
122        throw Exception("getTestSingleVReg: RegVar not found!!");
123    return { it->second, vr.index };
124}
125
126static void testCreateSSAData(cxuint testSuiteId, cxuint i, const AsmSSADataCase& testCase)
127{
128    std::cout << "-----------------------------------------------\n"
129    "           Test " << i << "\n"
130                "------------------------------------------------\n";
131    std::istringstream input(testCase.input);
132    std::ostringstream errorStream;
133   
134    Assembler assembler("test.s", input,
135                    (ASM_ALL&~ASM_ALTMACRO) | ASM_TESTRUN | ASM_TESTRESOLVE,
136                    BinaryFormat::RAWCODE, GPUDeviceType::CAPE_VERDE, errorStream);
137    bool good = assembler.assemble();
138    if (assembler.getSections().size()<1)
139    {
140        std::ostringstream oss;
141        oss << "FAILED for " << " testAsmCodeStructCase#" << i;
142        throw Exception(oss.str());
143    }
144    const AsmSection& section = assembler.getSections()[0];
145   
146    AsmRegAllocator regAlloc(assembler);
147   
148    regAlloc.createCodeStructure(section.codeFlow, section.getSize(),
149                            section.content.data());
150    regAlloc.createSSAData(*section.usageHandler);
151    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
152    std::ostringstream oss;
153    oss << " testAsmSSAData" << testSuiteId << " case#" << i;
154    const std::string testCaseName = oss.str();
155    assertValue<bool>("testAsmSSAData", testCaseName+".good",
156                      testCase.good, good);
157    assertString("testAsmSSAData", testCaseName+".errorMessages",
158              testCase.errorMessages, errorStream.str());
159   
160    assertValue("testAsmSSAData", testCaseName+".codeBlocks.size",
161                testCase.codeBlocks.size(), resCodeBlocks.size());
162   
163    std::unordered_map<const AsmRegVar*, CString> regVarNamesMap;
164    for (const auto& rvEntry: assembler.getRegVarMap())
165        regVarNamesMap.insert(std::make_pair(&rvEntry.second, rvEntry.first));
166   
167    for (size_t j = 0; j < resCodeBlocks.size(); j++)
168    {
169        const CCodeBlock2& expCBlock = testCase.codeBlocks[j];
170        const CodeBlock& resCBlock = resCodeBlocks[j];
171        std::ostringstream codeBlockOss;
172        codeBlockOss << ".codeBlock#" << j << ".";
173        codeBlockOss.flush();
174        std::string cbname(codeBlockOss.str());
175        assertValue("testAsmSSAData", testCaseName + cbname + "start",
176                    expCBlock.start, resCBlock.start);
177        assertValue("testAsmSSAData", testCaseName + cbname + "end",
178                    expCBlock.end, resCBlock.end);
179        assertValue("testAsmSSAData", testCaseName + cbname + "nextsSize",
180                    expCBlock.nexts.size(), resCBlock.nexts.size());
181       
182        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
183        {
184            std::ostringstream nextOss;
185            nextOss << "next#" << k << ".";
186            nextOss.flush();
187            std::string nname(nextOss.str());
188           
189            assertValue("testAsmSSAData", testCaseName + cbname + nname + "block",
190                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
191            assertValue("testAsmSSAData", testCaseName + cbname + nname + "isCall",
192                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
193        }
194       
195        assertValue("testAsmSSAData", testCaseName + cbname + "ssaInfoSize",
196                    expCBlock.ssaInfos.size(), resCBlock.ssaInfoMap.size());
197       
198        Array<std::pair<TestSingleVReg, SSAInfo> > resSSAInfos(
199                        resCBlock.ssaInfoMap.size());
200        std::transform(resCBlock.ssaInfoMap.begin(), resCBlock.ssaInfoMap.end(),
201            resSSAInfos.begin(),
202            [&regVarNamesMap](const std::pair<AsmSingleVReg, SSAInfo>& a)
203            -> std::pair<TestSingleVReg, SSAInfo>
204            { return { getTestSingleVReg(a.first, regVarNamesMap), a.second }; });
205        mapSort(resSSAInfos.begin(), resSSAInfos.end());
206       
207        for (size_t k = 0; k < expCBlock.ssaInfos.size(); k++)
208        {
209            std::ostringstream ssaOss;
210            ssaOss << "ssaInfo#" << k << ".";
211            ssaOss.flush();
212            std::string ssaName(ssaOss.str());
213           
214            const TestSingleVReg expVReg = { expCBlock.ssaInfos[k].first.name,
215                    expCBlock.ssaInfos[k].first.index };
216           
217            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "svreg",
218                        expVReg, resSSAInfos[k].first);
219            const SSAInfo& expSInfo = expCBlock.ssaInfos[k].second;
220            const SSAInfo& resSInfo = resSSAInfos[k].second;
221            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdBefore",
222                        expSInfo.ssaIdBefore, resSInfo.ssaIdBefore);
223            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaId",
224                        expSInfo.ssaId, resSInfo.ssaId);
225            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdChange",
226                        expSInfo.ssaIdChange, resSInfo.ssaIdChange);
227            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdFirst",
228                        expSInfo.ssaIdFirst, resSInfo.ssaIdFirst);
229            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdLast",
230                        expSInfo.ssaIdLast, resSInfo.ssaIdLast);
231            assertValue("testAsmSSAData", testCaseName + cbname + ssaName +
232                        "readBeforeWrite", int(expSInfo.readBeforeWrite),
233                        int(resSInfo.readBeforeWrite));
234        }
235       
236        assertValue("testAsmSSAData", testCaseName + cbname + "haveCalls",
237                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
238        assertValue("testAsmSSAData", testCaseName + cbname + "haveReturn",
239                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
240        assertValue("testAsmSSAData", testCaseName + cbname + "haveEnd",
241                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
242    }
243   
244    const SSAReplacesMap& ssaReplacesMap = regAlloc.getSSAReplacesMap();
245    assertValue("testAsmSSAData", testCaseName + "ssaReplacesSize",
246                    testCase.ssaReplaces.size(), ssaReplacesMap.size());
247    Array<std::pair<TestSingleVReg, Array<SSAReplace> > >
248                        resSSAReplaces(ssaReplacesMap.size());
249    std::transform(ssaReplacesMap.begin(), ssaReplacesMap.end(),
250            resSSAReplaces.begin(),
251            [&regVarNamesMap](const std::pair<AsmSingleVReg, std::vector<SSAReplace> >& a)
252            -> std::pair<TestSingleVReg, Array<SSAReplace> >
253            { return { getTestSingleVReg(a.first, regVarNamesMap), 
254                Array<SSAReplace>(a.second.begin(), a.second.end()) }; });
255    mapSort(resSSAReplaces.begin(), resSSAReplaces.end());
256   
257    for (size_t j = 0; j < testCase.ssaReplaces.size(); j++)
258    {
259        std::ostringstream ssaOss;
260        ssaOss << "ssas" << j << ".";
261        ssaOss.flush();
262        std::string ssaName(ssaOss.str());
263       
264        const auto& expEntry = testCase.ssaReplaces[j];
265        const auto& resEntry = resSSAReplaces[j];
266       
267        const TestSingleVReg expVReg = { expEntry.first.name, expEntry.first.index };
268       
269        assertValue("testAsmSSAData", testCaseName + ssaName + "svreg",
270                        expVReg, resEntry.first);
271        assertValue("testAsmSSAData", testCaseName + ssaName + "replacesSize",
272                        expEntry.second.size(), resEntry.second.size());
273        for (size_t k = 0; k < expEntry.second.size(); k++)
274        {
275            std::ostringstream repOss;
276            repOss << "replace#" << k << ".";
277            repOss.flush();
278            std::string repName(repOss.str());
279           
280            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "first",
281                        expEntry.second[k].first, resEntry.second[k].first);
282            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "second",
283                        expEntry.second[k].second, resEntry.second[k].second);
284        }
285    }
286}
287
288int main(int argc, const char** argv)
289{
290    int retVal = 0;
291    for (size_t i = 0; codeStructTestCases1Tbl[i].input!=nullptr; i++)
292        try
293        { testCreateCodeStructure(i, codeStructTestCases1Tbl[i]); }
294        catch(const std::exception& ex)
295        {
296            std::cerr << ex.what() << std::endl;
297            retVal = 1;
298        }
299    for (size_t i = 0; ssaDataTestCases1Tbl[i].input!=nullptr; i++)
300        try
301        { testCreateSSAData(0, i, ssaDataTestCases1Tbl[i]); }
302        catch(const std::exception& ex)
303        {
304            std::cerr << ex.what() << std::endl;
305            retVal = 1;
306        }
307    for (size_t i = 0; ssaDataTestCases2Tbl[i].input!=nullptr; i++)
308        try
309        { testCreateSSAData(1, i, ssaDataTestCases2Tbl[i]); }
310        catch(const std::exception& ex)
311        {
312            std::cerr << ex.what() << std::endl;
313            retVal = 1;
314        }
315    for (size_t i = 0; ssaDataTestCases3Tbl[i].input!=nullptr; i++)
316        try
317        { testCreateSSAData(2, i, ssaDataTestCases3Tbl[i]); }
318        catch(const std::exception& ex)
319        {
320            std::cerr << ex.what() << std::endl;
321            retVal = 1;
322        }
323    return retVal;
324}
Note: See TracBrowser for help on using the repository browser.