Changeset 3566 in CLRX


Ignore:
Timestamp:
Dec 28, 2017, 6:39:25 PM (9 months ago)
Author:
matszpk
Message:

CLRadeonExtender: Asm: Speeding up evaluating simple expressions with literals and addition and subtraction.
AmdCL2Bin: Fixing GPU code tables in AmdBinaries?.

Location:
CLRadeonExtender/trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • CLRadeonExtender/trunk/CLRX/amdasm/AsmDefs.h

    r3479 r3566  
    424424    static bool makeSymbolSnapshot(Assembler& assembler, const AsmSymbolEntry& symEntry,
    425425               AsmSymbolEntry*& outSymEntry, const AsmSourcePos* parentExprSourcePos);
     426   
     427    /// fast expression parse and evaluate
     428    static bool fastExprEvaluate(Assembler& assembler, const char*& linePtr,
     429                uint64_t& value);
     430    static bool fastExprEvaluate(Assembler& assembler, size_t& linePos,
     431                uint64_t& value);
    426432};
    427433
  • CLRadeonExtender/trunk/CLRX/amdasm/Assembler.h

    r3547 r3566  
    513513   
    514514    bool parseLiteral(uint64_t& value, const char*& linePtr);
     515    bool parseLiteralNoError(uint64_t& value, const char*& linePtr);
    515516    bool parseString(std::string& outString, const char*& linePtr);
    516517   
  • CLRadeonExtender/trunk/amdasm/AsmExpression.cpp

    r3457 r3566  
    15771577    return opIndex;
    15781578}
     1579
     1580static const uint32_t acceptedCharsAfterFastExpr =
     1581    (1U<<('!'-32)) | (1U<<('%'-32)) | (1U<<('&'-32)) | (1U<<('*'-32)) | (1U<<('!'-32)) |
     1582        (1U<<('+'-32)) | (1U<<('-'-32)) | (1U<<('/'-32)) | (1U<<('<'-32)) |
     1583        (1U<<('='-32)) | (1U<<('>'-32)) | (1U<<('?'-32));
     1584
     1585bool AsmExpression::fastExprEvaluate(Assembler& assembler, const char*& linePtr,
     1586                        uint64_t& value)
     1587{
     1588    const char* end = assembler.line + assembler.lineSize;
     1589    uint64_t sum = 0;
     1590    bool addition = true;
     1591    const char* tmpLinePtr = linePtr;
     1592    skipSpacesToEnd(tmpLinePtr, end);
     1593    // check first operator '+' or '-'
     1594    if (tmpLinePtr!=end)
     1595    {
     1596        if (*tmpLinePtr=='+' || *tmpLinePtr=='-')
     1597        {
     1598            addition = (*tmpLinePtr=='+');
     1599            skipCharAndSpacesToEnd(tmpLinePtr, end);
     1600        }
     1601    }
     1602    else
     1603        return false;
     1604   
     1605    // main loop
     1606    while (true)
     1607    {
     1608        uint64_t tmp = 0;
     1609        if (!isDigit(*tmpLinePtr) && *tmpLinePtr!='\'')
     1610            return false;
     1611        if (!assembler.parseLiteralNoError(tmp, tmpLinePtr))
     1612            return false;
     1613        if (tmpLinePtr!=end && (*tmpLinePtr=='f' || *tmpLinePtr=='b'))
     1614        {   // if local label
     1615            const char* t = tmpLinePtr-1;
     1616            while (t!=linePtr-1 && isDigit(*t)) t--;
     1617            if (t==linePtr-1 || isSpace(*t)) // if local label
     1618                return false;
     1619        }
     1620        // add or subtract
     1621        sum += addition ? tmp : -tmp;
     1622        // skip to next '+' or '-'
     1623        skipSpacesToEnd(tmpLinePtr, end);
     1624        if (tmpLinePtr==end || (*tmpLinePtr!='+' && *tmpLinePtr!='-'))
     1625            break; // end
     1626        // otherwise we continue
     1627        addition = (*tmpLinePtr=='+');
     1628        skipCharAndSpacesToEnd(tmpLinePtr, end);
     1629    }
     1630    if (tmpLinePtr==end ||
     1631        // check whether is not other operator
     1632        (*tmpLinePtr!='~' && *tmpLinePtr!='^' && *tmpLinePtr!='|' &&
     1633        (*tmpLinePtr<32 || *tmpLinePtr>=64 ||
     1634        // check whether is not other operator (by checking rest of characters)
     1635        ((1U<<(*tmpLinePtr-32)) & acceptedCharsAfterFastExpr)==0)))
     1636    {
     1637        value = sum;
     1638        linePtr = tmpLinePtr;
     1639        return true;
     1640    }
     1641    return false;
     1642}
     1643
     1644bool AsmExpression::fastExprEvaluate(Assembler& assembler, size_t& linePos,
     1645                        uint64_t& value)
     1646{
     1647    const char* linePtr = assembler.line + linePos;
     1648    bool res = fastExprEvaluate(assembler, linePtr, value);
     1649    linePos = linePtr - assembler.line;
     1650    return res;
     1651}
  • CLRadeonExtender/trunk/amdasm/AsmPseudoOps.cpp

    r3564 r3566  
    679679        const char* exprPlace = linePtr;
    680680        // try parse expression for this integer
     681        uint64_t value;
     682        if (AsmExpression::fastExprEvaluate(asmr, linePtr, value))
     683        {   // fast path (expression)
     684            if (sizeof(T) < 8)
     685                asmr.printWarningForRange(sizeof(T)<<3, value,
     686                                asmr.getSourcePos(exprPlace));
     687            T out;
     688            SLEV(out, value); // store in little-endian
     689            asmr.putData(sizeof(T), reinterpret_cast<const cxbyte*>(&out));
     690            continue;
     691        }
    681692        std::unique_ptr<AsmExpression> expr(AsmExpression::parse(asmr, linePtr));
    682693        if (expr)
     
    688699            {
    689700                // put directly to section
    690                 uint64_t value;
    691701                cxuint sectionId;
    692702                if (expr->evaluate(asmr, value, sectionId))
  • CLRadeonExtender/trunk/amdasm/Assembler.cpp

    r3564 r3566  
    261261    skipSpacesToEnd(linePtr, end);
    262262    const char* exprPlace = linePtr;
     263    if (AsmExpression::fastExprEvaluate(asmr, linePtr, value))
     264        return true;
    263265    std::unique_ptr<AsmExpression> expr(AsmExpression::parse(asmr, linePtr, false, true));
    264266    if (expr == nullptr)
     
    284286    skipSpacesToEnd(linePtr, end);
    285287    const char* exprPlace = linePtr;
     288    if (AsmExpression::fastExprEvaluate(asmr, linePtr, value))
     289    {
     290        sectionId = ASMSECT_ABS;
     291        return true;
     292    }
    286293    std::unique_ptr<AsmExpression> expr(AsmExpression::parse(asmr, linePtr, false, true));
    287294    if (expr == nullptr)
     
    986993        return false;
    987994    }
     995    return true;
     996}
     997
     998bool Assembler::parseLiteralNoError(uint64_t& value, const char*& linePtr)
     999{
     1000    const char* startPlace = linePtr;
     1001    const char* end = line+lineSize;
     1002    // if literal begins '
     1003    if (linePtr != end && *linePtr == '\'')
     1004    {
     1005        linePtr++;
     1006        if (linePtr == end || *linePtr == '\'')
     1007            return false;
     1008       
     1009        if (*linePtr != '\\')
     1010        {
     1011            value = *linePtr++;
     1012            if (linePtr == end || *linePtr != '\'')
     1013                return false;
     1014            linePtr++;
     1015            return true;
     1016        }
     1017        else // escapes
     1018        {
     1019            linePtr++;
     1020            if (linePtr == end)
     1021                return false;
     1022            if (*linePtr == 'x')
     1023            {
     1024                // hex literal
     1025                linePtr++;
     1026                if (linePtr == end)
     1027                    return false;
     1028                value = 0;
     1029                if (isXDigit(*linePtr))
     1030                    for (; linePtr != end; linePtr++)
     1031                    {
     1032                        cxuint digit;
     1033                        if (*linePtr >= '0' && *linePtr <= '9')
     1034                            digit = *linePtr-'0';
     1035                        else if (*linePtr >= 'a' && *linePtr <= 'f')
     1036                            digit = *linePtr-'a'+10;
     1037                        else if (*linePtr >= 'A' && *linePtr <= 'F')
     1038                            digit = *linePtr-'A'+10;
     1039                        else
     1040                            break; // end of literal
     1041                        value = (value<<4) + digit;
     1042                    }
     1043                else
     1044                    return false;
     1045                value &= 0xff;
     1046            }
     1047            else if (isODigit(*linePtr))
     1048            {
     1049                // octal literal
     1050                value = 0;
     1051                for (cxuint i = 0; linePtr != end && i < 3 && *linePtr != '\'';
     1052                     i++, linePtr++)
     1053                {
     1054                    if (!isODigit(*linePtr))
     1055                        return false;
     1056                    value = (value<<3) + uint64_t(*linePtr-'0');
     1057                    // checking range
     1058                    if (value > 255)
     1059                        return false;
     1060                }
     1061            }
     1062            else
     1063            {
     1064                // normal escapes
     1065                const char c = *linePtr++;
     1066                switch (c)
     1067                {
     1068                    case 'a':
     1069                        value = '\a';
     1070                        break;
     1071                    case 'b':
     1072                        value = '\b';
     1073                        break;
     1074                    case 'r':
     1075                        value = '\r';
     1076                        break;
     1077                    case 'n':
     1078                        value = '\n';
     1079                        break;
     1080                    case 'f':
     1081                        value = '\f';
     1082                        break;
     1083                    case 'v':
     1084                        value = '\v';
     1085                        break;
     1086                    case 't':
     1087                        value = '\t';
     1088                        break;
     1089                    case '\\':
     1090                        value = '\\';
     1091                        break;
     1092                    case '\'':
     1093                        value = '\'';
     1094                        break;
     1095                    case '\"':
     1096                        value = '\"';
     1097                        break;
     1098                    default:
     1099                        value = c;
     1100                }
     1101            }
     1102            if (linePtr == end || *linePtr != '\'')
     1103                return false;
     1104            linePtr++;
     1105            return true;
     1106        }
     1107    }
     1108    // try to parse integer value
     1109    try
     1110    { value = cstrtovCStyle<uint64_t>(startPlace, line+lineSize, linePtr); }
     1111    catch(const ParseException& ex)
     1112    { return false; }
    9881113    return true;
    9891114}
     
    14131538    // make base expr if baseExpr=true and symbolName is not output counter
    14141539    bool makeBaseExpr = (baseExpr && symbolName != ".");
    1415     std::unique_ptr<AsmExpression> expr(AsmExpression::parse(*this, linePtr, makeBaseExpr));
    1416     if (!expr) // no expression, errors
    1417         return false;
     1540   
     1541    std::unique_ptr<AsmExpression> expr;
     1542    uint64_t value;
     1543    cxuint sectionId = ASMSECT_ABS;
     1544    if (makeBaseExpr || !AsmExpression::fastExprEvaluate(*this, linePtr, value))
     1545    {
     1546        expr.reset(AsmExpression::parse(*this, linePtr, makeBaseExpr));
     1547        if (!expr) // no expression, errors
     1548            return false;
     1549    }
    14181550   
    14191551    if (linePtr != line+lineSize)
    14201552        THIS_FAIL_BY_ERROR(linePtr, "Garbages at end of expression")
    1421     if (expr->isEmpty()) // empty expression, we treat as error
     1553    if (expr && expr->isEmpty()) // empty expression, we treat as error
    14221554        THIS_FAIL_BY_ERROR(exprPlace, "Expected assignment expression")
    14231555   
     
    14251557    {
    14261558        // assigning '.'
    1427         uint64_t value;
    1428         cxuint sectionId;
     1559        if (!expr) // if fast path
     1560            return assignOutputCounter(symbolPlace, value, sectionId);
    14291561        if (!expr->evaluate(*this, value, sectionId))
    14301562            return false;
     
    14461578    AsmSymbolEntry& symEntry = *res.first;
    14471579   
    1448     if (expr->getSymOccursNum()==0)
     1580    if (!expr)
     1581    {
     1582        setSymbol(symEntry, value, sectionId);
     1583        symEntry.second.onceDefined = !reassign;
     1584    }
     1585    else if (expr->getSymOccursNum()==0)
    14491586    {
    14501587        // can evalute, assign now
  • CLRadeonExtender/trunk/amdasm/GCNAsmHelpers.cpp

    r3537 r3566  
    729729        outTargetExpr->reset();
    730730    skipSpacesToEnd(linePtr, end);
     731   
     732    uint64_t value;
    731733    const char* exprPlace = linePtr;
     734    // if fast expression
     735    if (AsmExpression::fastExprEvaluate(asmr, linePtr, value))
     736    {
     737        if (bits != UINT_MAX && bits < 64)
     738        {
     739            asmr.printWarningForRange(bits, value,
     740                            asmr.getSourcePos(exprPlace), signess);
     741            outValue = value & ((1ULL<<bits)-1ULL);
     742        }
     743        else // just copy
     744            outValue = value;
     745        return true;
     746    }
     747   
    732748    std::unique_ptr<AsmExpression> expr(AsmExpression::parse(asmr, linePtr));
    733749    if (expr==nullptr) // error
     
    739755        // resolved now
    740756        cxuint sectionId; // for getting
    741         uint64_t value;
    742757        if (!expr->evaluate(asmr, value, sectionId)) // failed evaluation!
    743758            return false;
     
    14321447        else
    14331448        {
     1449            if (!AsmExpression::fastExprEvaluate(asmr, linePtr, value))
     1450            {
    14341451            // if expression
    14351452            std::unique_ptr<AsmExpression> expr(AsmExpression::parse(asmr, linePtr));
     
    14671484                operand.range = { 255, 0 };
    14681485                exprToResolve = true;
     1486            }
    14691487            }
    14701488           
  • CLRadeonExtender/trunk/amdbin/AmdCL2Binaries.cpp

    r3555 r3566  
    753753// tables with GPU device codes for specific driver version
    754754// for almost cases are matches.
     755// IMPORTANT: gpu device code tables must be sorted by elfflag
    755756
    756757/* 1912.05 driver device table list */
     
    893894    { 14, GPUDeviceType::STONEY },
    894895    { 15, GPUDeviceType::BAFFIN },
    895     { 18, GPUDeviceType::ELLESMERE },
     896    { 16, GPUDeviceType::ELLESMERE },
     897    { 17, GPUDeviceType::GFX900 },
    896898    { 18, GPUDeviceType::GFX804 },
    897     { 17, GPUDeviceType::GFX900 },
    898899    { 19, GPUDeviceType::GFX901 }
    899900};
     
    914915    { 16, GPUDeviceType::BAFFIN },
    915916    { 18, GPUDeviceType::ELLESMERE },
     917    { 19, GPUDeviceType::GFX900 },
    916918    { 20, GPUDeviceType::GFX804 },
    917     { 19, GPUDeviceType::GFX900 },
    918919    { 21, GPUDeviceType::GFX901 }
    919920};
     
    934935    { 16, GPUDeviceType::BAFFIN },
    935936    { 18, GPUDeviceType::ELLESMERE },
     937    { 20, GPUDeviceType::GFX900 },
    936938    { 21, GPUDeviceType::GFX804 },
    937     { 20, GPUDeviceType::GFX900 },
    938939    { 23, GPUDeviceType::GFX901 },
    939940    { 24, GPUDeviceType::GFX902 },
  • CLRadeonExtender/trunk/tests/amdasm/AsmExprParse.cpp

    r3436 r3566  
    2424#include <sstream>
    2525#include <CLRX/amdasm/Assembler.h>
     26#include "../TestUtils.h"
    2627
    2728using namespace CLRX;
     
    409410};
    410411
     412/* fast expression evaluation test cases */
     413struct FastExprEvalCase
     414{
     415    const char* expression;
     416    uint64_t evaluated;
     417    const char* extra;
     418    bool good;
     419};
     420
     421static const FastExprEvalCase fastExprEvalCases[] =
     422{
     423    { "1324 + 2", 1326, "", true },
     424    { "  1324+ 2  ", 1326, "", true },
     425    { "1324 + 2xxx", 1326, "xxx", true },
     426    { "-1324 + 2", -1322ULL, "", true },
     427    { " - 1324+2  ", -1322ULL, "", true },
     428    { "+ 1324 + 2", 1326, "", true },
     429    { " 0xffa -0xe  ", 0xfec, "", true },
     430    { " 'g' - 'a'", 6, "", true },
     431    { " 4 - 7 + 11-54", -46ULL, "", true },
     432    { " -1 +7+8 + 1 + 124 + 7", 146, "", true },
     433    { " 15 + 12;", 27, ";", true },
     434    { " 15 + 12 ( ", 27, "( ", true },
     435    { " 15 + 12 : ", 27, ": ", true },
     436    { " 15 + 12 [ ", 27, "[ ", true },
     437    { " 15 + 12 } ", 27, "} ", true },
     438    { " 15 + 12 { ", 27, "{ ", true },
     439    { " 15 + 12 } ", 27, "} ", true },
     440    { " 15 + 12 \" ", 27, "\" ", true },
     441    { " 15 + 12 @ ", 27, "@ ", true },
     442    { " 15 + 12 _ ", 27, "_ ", true },
     443    { " 15 + 12 ' ", 27, "' ", true },
     444    { " 15 + 12 $ ", 27, "$ ", true },
     445    { " 15 + 12 \\ ", 27, "\\ ", true },
     446    { " 15 + 12 ` ", 27, "` ", true },
     447    /* failed (if can be complex expression */
     448    { " 15 + 12 * ", 0, " 15 + 12 * ", false },
     449    { " 15 + 12 / ", 0, " 15 + 12 / ", false },
     450    { " 15 + 12 & ", 0, " 15 + 12 & ", false },
     451    { " 15 + 12 | ", 0, " 15 + 12 | ", false },
     452    { " 15 + 12 ^ ", 0, " 15 + 12 ^ ", false },
     453    { " 15 + 12 % ", 0, " 15 + 12 % ", false },
     454    { " 15 + 12 ? ", 0, " 15 + 12 ? ", false },
     455    { " 15 + 12 ! ", 0, " 15 + 12 ! ", false },
     456    { " 15 + 12 ~ ", 0, " 15 + 12 ~ ", false },
     457    { " 15 + 12 == ", 0, " 15 + 12 == ", false },
     458    { " 15 + 12 <= ", 0, " 15 + 12 <= ", false },
     459    { " 15 + 12 >= ", 0, " 15 + 12 >= ", false },
     460    { " 15 + sym ", 0, " 15 + sym ", false },
     461    { " 15 + ::sym ", 0, " 15 + ::sym ", false },
     462    { " 15 + $$$ ", 0, " 15 + $$$ ", false },
     463    { " 15 + . ", 0, " 15 + . ", false },
     464    { "b", 0, "b", false },
     465    { "$a", 0, "$a", false },
     466    { "  $a", 0, "  $a", false },
     467    { "2b", 0, "2b", false },
     468    // local labels
     469    { "   21b", 0, "   21b", false },
     470    { "   21f", 0, "   21f", false },
     471    // not local labels
     472    { "   0x21b", 0x21b, "", true },
     473    { "   0x21f", 0x21f, "", true }
     474};
     475
    411476// generate expression string from AsmExpression (to verify)
    412477static std::string rpnExpression(const AsmExpression* expr)
     
    589654}
    590655
     656static void testFastExprEval(cxuint i, const FastExprEvalCase& testCase)
     657{
     658    std::istringstream iss(testCase.expression);
     659    std::ostringstream resultErrorsOut;
     660    MyAssembler assembler(iss, resultErrorsOut);
     661    size_t linePos = 0;
     662    uint64_t resValue = 0;
     663    const bool resGood = AsmExpression::fastExprEvaluate(assembler, linePos, resValue);
     664   
     665    const char* resExtra = testCase.expression + linePos;
     666   
     667    char testName[40];
     668    snprintf(testName, 40, "FastExprEvalTest #%u", i);
     669    assertValue(testName, "value", testCase.evaluated, resValue);
     670    assertValue(testName, "good", cxuint(testCase.good), cxuint(resGood));
     671    assertString(testName, "extra", testCase.extra, resExtra);
     672}
     673
    591674int main(int argc, const char** argv)
    592675{
     
    609692        }
    610693    }
     694   
     695    for (cxuint i = 0; i < sizeof(fastExprEvalCases)/sizeof(FastExprEvalCase); i++)
     696        try
     697        { testFastExprEval(i, fastExprEvalCases[i]); }
     698        catch(const std::exception& ex)
     699        {
     700            std::cerr << ex.what() << std::endl;
     701            retVal = 1;
     702        }
     703   
    611704    return retVal;
    612705}
Note: See TracChangeset for help on using the changeset viewer.