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

Last change on this file since 4172 was 4172, checked in by matszpk, 11 months ago

CLRadeonExtender: AsmRegAlloc?: Unfinished integration LinearDepHandler? with AsmRegAllocator?.

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 " << testSuiteId << " " << 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 " << " testAsmCodeSSAData#" << 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, *section.linearDepHandler);
151   
152    const std::vector<CodeBlock>& resCodeBlocks = regAlloc.getCodeBlocks();
153    std::ostringstream oss;
154    oss << " testAsmSSAData" << testSuiteId << " case#" << i;
155    const std::string testCaseName = oss.str();
156   
157    assertValue<bool>("testAsmSSAData", testCaseName+".good",
158                      testCase.good, good);
159    assertString("testAsmSSAData", testCaseName+".errorMessages",
160              testCase.errorMessages, errorStream.str());
161   
162    assertValue("testAsmSSAData", testCaseName+".codeBlocks.size",
163                testCase.codeBlocks.size(), resCodeBlocks.size());
164   
165    std::unordered_map<const AsmRegVar*, CString> regVarNamesMap;
166    for (const auto& rvEntry: assembler.getRegVarMap())
167        regVarNamesMap.insert(std::make_pair(&rvEntry.second, rvEntry.first));
168   
169    for (size_t j = 0; j < resCodeBlocks.size(); j++)
170    {
171        const CCodeBlock2& expCBlock = testCase.codeBlocks[j];
172        const CodeBlock& resCBlock = resCodeBlocks[j];
173        std::ostringstream codeBlockOss;
174        codeBlockOss << ".codeBlock#" << j << ".";
175        codeBlockOss.flush();
176        std::string cbname(codeBlockOss.str());
177        assertValue("testAsmSSAData", testCaseName + cbname + "start",
178                    expCBlock.start, resCBlock.start);
179        assertValue("testAsmSSAData", testCaseName + cbname + "end",
180                    expCBlock.end, resCBlock.end);
181        assertValue("testAsmSSAData", testCaseName + cbname + "nextsSize",
182                    expCBlock.nexts.size(), resCBlock.nexts.size());
183       
184        for (size_t k = 0; k < expCBlock.nexts.size(); k++)
185        {
186            std::ostringstream nextOss;
187            nextOss << "next#" << k << ".";
188            nextOss.flush();
189            std::string nname(nextOss.str());
190           
191            assertValue("testAsmSSAData", testCaseName + cbname + nname + "block",
192                    expCBlock.nexts[k].block, resCBlock.nexts[k].block);
193            assertValue("testAsmSSAData", testCaseName + cbname + nname + "isCall",
194                    int(expCBlock.nexts[k].isCall), int(resCBlock.nexts[k].isCall));
195        }
196       
197        assertValue("testAsmSSAData", testCaseName + cbname + "ssaInfoSize",
198                    expCBlock.ssaInfos.size(), resCBlock.ssaInfoMap.size());
199       
200        Array<std::pair<TestSingleVReg, SSAInfo> > resSSAInfos(
201                        resCBlock.ssaInfoMap.size());
202        std::transform(resCBlock.ssaInfoMap.begin(), resCBlock.ssaInfoMap.end(),
203            resSSAInfos.begin(),
204            [&regVarNamesMap](const std::pair<AsmSingleVReg, SSAInfo>& a)
205            -> std::pair<TestSingleVReg, SSAInfo>
206            { return { getTestSingleVReg(a.first, regVarNamesMap), a.second }; });
207        mapSort(resSSAInfos.begin(), resSSAInfos.end());
208       
209        for (size_t k = 0; k < expCBlock.ssaInfos.size(); k++)
210        {
211            std::ostringstream ssaOss;
212            ssaOss << "ssaInfo#" << k << ".";
213            ssaOss.flush();
214            std::string ssaName(ssaOss.str());
215           
216            const TestSingleVReg expVReg = { expCBlock.ssaInfos[k].first.name,
217                    expCBlock.ssaInfos[k].first.index };
218           
219            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "svreg",
220                        expVReg, resSSAInfos[k].first);
221            const SSAInfo& expSInfo = expCBlock.ssaInfos[k].second;
222            const SSAInfo& resSInfo = resSSAInfos[k].second;
223            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdBefore",
224                        expSInfo.ssaIdBefore, resSInfo.ssaIdBefore);
225            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaId",
226                        expSInfo.ssaId, resSInfo.ssaId);
227            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdChange",
228                        expSInfo.ssaIdChange, resSInfo.ssaIdChange);
229            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdFirst",
230                        expSInfo.ssaIdFirst, resSInfo.ssaIdFirst);
231            assertValue("testAsmSSAData", testCaseName + cbname + ssaName + "ssaIdLast",
232                        expSInfo.ssaIdLast, resSInfo.ssaIdLast);
233            assertValue("testAsmSSAData", testCaseName + cbname + ssaName +
234                        "readBeforeWrite", int(expSInfo.readBeforeWrite),
235                        int(resSInfo.readBeforeWrite));
236        }
237       
238        assertValue("testAsmSSAData", testCaseName + cbname + "haveCalls",
239                    int(expCBlock.haveCalls), int(resCBlock.haveCalls));
240        assertValue("testAsmSSAData", testCaseName + cbname + "haveReturn",
241                    int(expCBlock.haveReturn), int(resCBlock.haveReturn));
242        assertValue("testAsmSSAData", testCaseName + cbname + "haveEnd",
243                    int(expCBlock.haveEnd), int(resCBlock.haveEnd));
244    }
245   
246    const SSAReplacesMap& ssaReplacesMap = regAlloc.getSSAReplacesMap();
247    assertValue("testAsmSSAData", testCaseName + "ssaReplacesSize",
248                    testCase.ssaReplaces.size(), ssaReplacesMap.size());
249    Array<std::pair<TestSingleVReg, Array<SSAReplace> > >
250                        resSSAReplaces(ssaReplacesMap.size());
251    std::transform(ssaReplacesMap.begin(), ssaReplacesMap.end(),
252            resSSAReplaces.begin(),
253            [&regVarNamesMap](const std::pair<AsmSingleVReg, std::vector<SSAReplace> >& a)
254            -> std::pair<TestSingleVReg, Array<SSAReplace> >
255            { return { getTestSingleVReg(a.first, regVarNamesMap), 
256                Array<SSAReplace>(a.second.begin(), a.second.end()) }; });
257    mapSort(resSSAReplaces.begin(), resSSAReplaces.end());
258   
259    for (size_t j = 0; j < testCase.ssaReplaces.size(); j++)
260    {
261        std::ostringstream ssaOss;
262        ssaOss << "ssas" << j << ".";
263        ssaOss.flush();
264        std::string ssaName(ssaOss.str());
265       
266        const auto& expEntry = testCase.ssaReplaces[j];
267        const auto& resEntry = resSSAReplaces[j];
268       
269        const TestSingleVReg expVReg = { expEntry.first.name, expEntry.first.index };
270       
271        assertValue("testAsmSSAData", testCaseName + ssaName + "svreg",
272                        expVReg, resEntry.first);
273        assertValue("testAsmSSAData", testCaseName + ssaName + "replacesSize",
274                        expEntry.second.size(), resEntry.second.size());
275        for (size_t k = 0; k < expEntry.second.size(); k++)
276        {
277            std::ostringstream repOss;
278            repOss << "replace#" << k << ".";
279            repOss.flush();
280            std::string repName(repOss.str());
281           
282            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "first",
283                        expEntry.second[k].first, resEntry.second[k].first);
284            assertValue("testAsmSSAData", testCaseName + ssaName + repName + "second",
285                        expEntry.second[k].second, resEntry.second[k].second);
286        }
287    }
288}
289
290int main(int argc, const char** argv)
291{
292    int retVal = 0;
293    for (size_t i = 0; codeStructTestCases1Tbl[i].input!=nullptr; i++)
294        try
295        { testCreateCodeStructure(i, codeStructTestCases1Tbl[i]); }
296        catch(const std::exception& ex)
297        {
298            std::cerr << ex.what() << std::endl;
299            retVal = 1;
300        }
301    for (size_t i = 0; ssaDataTestCases1Tbl[i].input!=nullptr; i++)
302        try
303        { testCreateSSAData(0, i, ssaDataTestCases1Tbl[i]); }
304        catch(const std::exception& ex)
305        {
306            std::cerr << ex.what() << std::endl;
307            retVal = 1;
308        }
309    for (size_t i = 0; ssaDataTestCases2Tbl[i].input!=nullptr; i++)
310        try
311        { testCreateSSAData(1, i, ssaDataTestCases2Tbl[i]); }
312        catch(const std::exception& ex)
313        {
314            std::cerr << ex.what() << std::endl;
315            retVal = 1;
316        }
317    for (size_t i = 0; ssaDataTestCases3Tbl[i].input!=nullptr; i++)
318        try
319        { testCreateSSAData(2, i, ssaDataTestCases3Tbl[i]); }
320        catch(const std::exception& ex)
321        {
322            std::cerr << ex.what() << std::endl;
323            retVal = 1;
324        }
325    return retVal;
326}
Note: See TracBrowser for help on using the repository browser.