Changeset 6052


Ignore:
Timestamp:
May 20, 2018, 3:38:31 PM (4 weeks ago)
Author:
cameron
Message:

IDISA test checking, more test operations, IDISA fixes

Location:
icGREP/icgrep-devel/icgrep
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/IR_Gen/idisa_builder.cpp

    r6051 r6052  
    141141
    142142Value * IDISA_Builder::simd_ule(unsigned fw, Value * a, Value * b) {
    143     if (fw < 8) report_fatal_error("Unsupported field width: ult " + std::to_string(fw));
     143    if (fw == 1) return simd_or(simd_not(a), b);
     144    if (fw < 8) {
     145        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_ule(2*fw, simd_and(simd_himask(2*fw), a), b));
     146        Value * lo_rslt = simd_and(simd_lomask(2*fw), simd_ule(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b)));
     147        return simd_or(hi_rslt, lo_rslt);
     148    }
    144149    return CreateSExt(CreateICmpULE(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
    145150}
    146151
    147152Value * IDISA_Builder::simd_uge(unsigned fw, Value * a, Value * b) {
     153    if (fw == 1) return simd_or(a, simd_not(b));
     154    if (fw < 8) {
     155        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_uge(2*fw, a, simd_and(simd_himask(2*fw), b)));
     156        Value * lo_rslt = simd_and(simd_lomask(2*fw), simd_uge(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b)));
     157        return simd_or(hi_rslt, lo_rslt);
     158    }
    148159    if (fw < 8) report_fatal_error("Unsupported field width: ult " + std::to_string(fw));
    149160    return CreateSExt(CreateICmpUGE(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
     
    158169
    159170Value * IDISA_Builder::simd_umax(unsigned fw, Value * a, Value * b) {
    160     if (fw < 8) report_fatal_error("Unsupported field width: umax " + std::to_string(fw));
     171    if (fw == 1) return simd_or(a, b);
     172    if (fw < 8) {
     173        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_umax(2*fw, a, b));
     174        Value * lo_rslt = simd_umax(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b));
     175        return simd_or(hi_rslt, lo_rslt);
     176    }
    161177    Value * aVec = fwCast(fw, a);
    162178    Value * bVec = fwCast(fw, b);
     
    172188
    173189Value * IDISA_Builder::simd_umin(unsigned fw, Value * a, Value * b) {
    174     if (fw < 8) report_fatal_error("Unsupported field width: umin " + std::to_string(fw));
     190    if (fw == 1) return simd_and(a, b);
     191    if (fw < 8) {
     192        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_umin(2*fw, a, b));
     193        Value * lo_rslt = simd_umin(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b));
     194        return simd_or(hi_rslt, lo_rslt);
     195    }
    175196    Value * aVec = fwCast(fw, a);
    176197    Value * bVec = fwCast(fw, b);
     
    308329    Value * pext_shift_back_amts = simd_and(simd_lomask(fieldwidth), delcounts.back());
    309330    Value * w = simd_sllv(fieldwidth, v, pext_shift_back_amts);
    310    
    311331    //
    312332    // No work through the smaller field widths.
     
    321341                    simd_sllv(fw, simd_and(w, pext_shift_back_field_mask), pext_shift_back_amts));
    322342    }
    323     return w;
     343    return CreateAnd(w, deposit_mask);
    324344}
    325345
     
    517537
    518538Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
    519     if (fw < 8) report_fatal_error("Unsupported field width: mvmd_extract " + std::to_string(fw));
     539    if (fw < 8) {
     540        unsigned byte_no = (fieldIndex * fw) / 8;
     541        unsigned intrabyte_shift = (fieldIndex * fw) % 8;
     542        Value * byte = CreateExtractElement(fwCast(8, a), getInt32(byte_no));
     543        return CreateTrunc(CreateLShr(byte, getInt8(intrabyte_shift)), getIntNTy(fw));
     544    }
    520545    return CreateExtractElement(fwCast(fw, a), getInt32(fieldIndex));
    521546}
    522547
    523 Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * blk, Value * elt, unsigned fieldIndex) {
    524     if (fw < 8) report_fatal_error("Unsupported field width: mvmd_insert " + std::to_string(fw));
    525     return CreateInsertElement(fwCast(fw, blk), elt, getInt32(fieldIndex));
     548Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * a, Value * elt, unsigned fieldIndex) {
     549    if (fw < 8) {
     550        unsigned byte_no = (fieldIndex * fw) / 8;
     551        unsigned intrabyte_shift = (fieldIndex * fw) % 8;
     552        unsigned field_mask = ((1 << fw) - 1) << intrabyte_shift;
     553        Value * byte = CreateAnd(CreateExtractElement(fwCast(8, a), getInt32(byte_no)), getInt8(0xFF &~ field_mask));
     554        byte = CreateOr(byte, CreateShl(CreateZExtOrTrunc(elt, getInt8Ty()), getInt8(intrabyte_shift)));
     555        return CreateInsertElement(fwCast(8, a), byte, getInt32(byte_no));
     556    }
     557    return CreateInsertElement(fwCast(fw, a), elt, getInt32(fieldIndex));
    526558}
    527559
  • icGREP/icgrep-devel/icgrep/idisa_test.cpp

    r6051 r6052  
    3636
    3737static cl::opt<std::string> Operand1TestFile(cl::Positional, cl::desc("Operand 1 data file."), cl::Required, cl::cat(testFlags));
    38 static cl::opt<std::string> Operand2TestFile(cl::Positional, cl::desc("Operand 1 data file."), cl::Required, cl::cat(testFlags));
    39 static cl::opt<std::string> TestOutputFile(cl::Positional, cl::desc("Test output file."), cl::cat(testFlags));
     38static cl::opt<std::string> Operand2TestFile(cl::Positional, cl::desc("Operand 2 data file."), cl::Required, cl::cat(testFlags));
     39static cl::opt<std::string> TestOutputFile("o", cl::desc("Test output file."), cl::cat(testFlags));
     40
     41static cl::opt<int> ShiftLimit("ShiftLimit", cl::desc("Upper limit for the shift operand (2nd operand) of sllv, srlv, srav."), cl::init(0));
     42
     43class ShiftLimitKernel : public kernel::BlockOrientedKernel {
     44public:
     45    ShiftLimitKernel(const std::unique_ptr<kernel::KernelBuilder> & b, unsigned fw, unsigned limit);
     46    bool isCachable() const override { return true; }
     47    bool hasSignature() const override { return false; }
     48protected:
     49    void generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
     50private:
     51    const unsigned mTestFw;
     52    const unsigned mShiftLimit;
     53};
     54
     55ShiftLimitKernel::ShiftLimitKernel(const std::unique_ptr<kernel::KernelBuilder> & b, unsigned fw, unsigned limit)
     56: kernel::BlockOrientedKernel("shiftLimit" + std::to_string(fw) + "_" + std::to_string(limit),
     57                              {kernel::Binding{b->getStreamSetTy(1, fw), "shiftOperand"}},
     58                              {kernel::Binding{b->getStreamSetTy(1, fw), "limitedShift"}},
     59                              {}, {}, {}),
     60mTestFw(fw), mShiftLimit(limit) {}
     61
     62void ShiftLimitKernel::generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> & kb) {
     63    Type * fwTy = kb->getIntNTy(mTestFw);
     64    Constant * const ZeroConst = kb->getSize(0);
     65    Value * shiftOperand = kb->loadInputStreamBlock("shiftOperand", ZeroConst);
     66    unsigned fieldCount = kb->getBitBlockWidth()/mTestFw;
     67    Value * limited = kb->simd_umin(mTestFw, shiftOperand, ConstantVector::getSplat(fieldCount, ConstantInt::get(fwTy, mShiftLimit)));
     68    kb->storeOutputStreamBlock("limitedShift", ZeroConst, limited);
     69}
    4070
    4171class IdisaBinaryOpTestKernel : public kernel::MultiBlockKernel {
     
    6797    PHINode * blockOffsetPhi = kb->CreatePHI(kb->getSizeTy(), 2);
    6898    blockOffsetPhi->addIncoming(ZeroConst, entry);
    69     Value * operand1 = kb->fwCast(mTestFw, kb->loadInputStreamBlock("operand1", ZeroConst, blockOffsetPhi));
    70     Value * operand2 = kb->fwCast(mTestFw, kb->loadInputStreamBlock("operand2", ZeroConst, blockOffsetPhi));
     99    Value * operand1 = kb->loadInputStreamBlock("operand1", ZeroConst, blockOffsetPhi);
     100    Value * operand2 = kb->loadInputStreamBlock("operand2", ZeroConst, blockOffsetPhi);
    71101    Value * result = nullptr;
    72102    if (mIdisaOperation == "simd_add") {
     
    82112    } else if (mIdisaOperation == "simd_ugt") {
    83113        result = kb->simd_ugt(mTestFw, operand1, operand2);
     114    } else if (mIdisaOperation == "simd_uge") {
     115        result = kb->simd_uge(mTestFw, operand1, operand2);
    84116    } else if (mIdisaOperation == "simd_lt") {
    85117        result = kb->simd_lt(mTestFw, operand1, operand2);
    86118    } else if (mIdisaOperation == "simd_ult") {
    87119        result = kb->simd_ult(mTestFw, operand1, operand2);
     120    } else if (mIdisaOperation == "simd_ule") {
     121        result = kb->simd_ule(mTestFw, operand1, operand2);
    88122    } else if (mIdisaOperation == "simd_max") {
    89123        result = kb->simd_max(mTestFw, operand1, operand2);
     
    125159}
    126160
     161class IdisaBinaryOpCheckKernel : public kernel::BlockOrientedKernel {
     162public:
     163    IdisaBinaryOpCheckKernel(const std::unique_ptr<kernel::KernelBuilder> & b, std::string idisa_op, unsigned fw);
     164    bool isCachable() const override { return true; }
     165    bool hasSignature() const override { return false; }
     166protected:
     167    void generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> & kb) override;
     168private:
     169    const std::string mIdisaOperation;
     170    const unsigned mTestFw;
     171};
     172
     173IdisaBinaryOpCheckKernel::IdisaBinaryOpCheckKernel(const std::unique_ptr<kernel::KernelBuilder> & b, std::string idisa_op, unsigned fw)
     174: kernel::BlockOrientedKernel(idisa_op + std::to_string(fw) + "_check",
     175                           {kernel::Binding{b->getStreamSetTy(1, 1), "operand1"},
     176                            kernel::Binding{b->getStreamSetTy(1, 1), "operand2"},
     177                            kernel::Binding{b->getStreamSetTy(1, 1), "test_result"}},
     178                           {kernel::Binding{b->getStreamSetTy(1, 1), "expected_result"}},
     179                           {}, {}, {}),
     180mIdisaOperation(idisa_op), mTestFw(fw) {}
     181
     182void IdisaBinaryOpCheckKernel::generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> & kb) {
     183    Type * fwTy = kb->getIntNTy(mTestFw);
     184    BasicBlock * reportFailure = kb->CreateBasicBlock("reportFailure");
     185    BasicBlock * continueTest = kb->CreateBasicBlock("continueTest");
     186    Constant * const ZeroConst = kb->getSize(0);
     187    Value * operand1Block = kb->loadInputStreamBlock("operand1", ZeroConst);
     188    Value * operand2Block = kb->loadInputStreamBlock("operand2", ZeroConst);
     189    Value * resultBlock = kb->loadInputStreamBlock("test_result", ZeroConst);
     190    unsigned fieldCount = kb->getBitBlockWidth()/mTestFw;
     191    Value * expectedBlock = kb->allZeroes();
     192    for (unsigned i = 0; i < fieldCount; i++) {
     193        Value * operand1 = kb->mvmd_extract(mTestFw, operand1Block, i);
     194        Value * operand2 = kb->mvmd_extract(mTestFw, operand2Block, i);
     195        Value * expected = nullptr;
     196        if (mIdisaOperation.substr(0,5) == "simd_") {
     197            if (mIdisaOperation == "simd_add") {
     198                expected = kb->CreateAdd(operand1, operand2);
     199            } else if (mIdisaOperation == "simd_sub") {
     200                expected = kb->CreateSub(operand1, operand2);
     201            } else if (mIdisaOperation == "simd_mult") {
     202                expected = kb->CreateMul(operand1, operand2);
     203            } else if (mIdisaOperation == "simd_eq") {
     204                expected = kb->CreateSExt(kb->CreateICmpEQ(operand1, operand2), fwTy);
     205            } else if (mIdisaOperation == "simd_gt") {
     206                expected = kb->CreateSExt(kb->CreateICmpSGT(operand1, operand2), fwTy);
     207            } else if (mIdisaOperation == "simd_ugt") {
     208                expected = kb->CreateSExt(kb->CreateICmpUGT(operand1, operand2), fwTy);
     209            } else if (mIdisaOperation == "simd_uge") {
     210                expected = kb->CreateSExt(kb->CreateICmpUGE(operand1, operand2), fwTy);
     211            } else if (mIdisaOperation == "simd_lt") {
     212                expected = kb->CreateSExt(kb->CreateICmpSLT(operand1, operand2), fwTy);
     213            } else if (mIdisaOperation == "simd_ult") {
     214                expected = kb->CreateSExt(kb->CreateICmpULT(operand1, operand2), fwTy);
     215            } else if (mIdisaOperation == "simd_ule") {
     216                expected = kb->CreateSExt(kb->CreateICmpULE(operand1, operand2), fwTy);
     217            } else if (mIdisaOperation == "simd_max") {
     218                expected = kb->CreateSelect(kb->CreateICmpSGT(operand1, operand2), operand1, operand2);
     219            } else if (mIdisaOperation == "simd_min") {
     220                expected = kb->CreateSelect(kb->CreateICmpSLT(operand1, operand2), operand1, operand2);
     221            } else if (mIdisaOperation == "simd_umax") {
     222                expected = kb->CreateSelect(kb->CreateICmpUGT(operand1, operand2), operand1, operand2);
     223            } else if (mIdisaOperation == "simd_umin") {
     224                expected = kb->CreateSelect(kb->CreateICmpULT(operand1, operand2), operand1, operand2);
     225            } else if (mIdisaOperation == "simd_sllv") {
     226                expected = kb->CreateShl(operand1, operand2);
     227            } else if (mIdisaOperation == "simd_srlv") {
     228                expected = kb->CreateLShr(operand1, operand2);
     229            } else if (mIdisaOperation == "simd_pext") {
     230                Constant * zeroConst = ConstantInt::getNullValue(fwTy);
     231                Constant * oneConst = ConstantInt::get(fwTy, 1);
     232                expected = zeroConst;
     233                Value * out_bit = oneConst;
     234                for (unsigned i = 0; i < mTestFw; i++) {
     235                    Value * i_bit = Constant::getIntegerValue(fwTy, APInt::getOneBitSet(mTestFw, i));
     236                    Value * operand_i_isSet = kb->CreateICmpEQ(kb->CreateAnd(operand1, i_bit), i_bit);
     237                    Value * mask_i_isSet = kb->CreateICmpEQ(kb->CreateAnd(operand2, i_bit), i_bit);
     238                    expected = kb->CreateSelect(kb->CreateAnd(operand_i_isSet, mask_i_isSet), kb->CreateOr(expected, out_bit), expected);
     239                    out_bit = kb->CreateSelect(mask_i_isSet, kb->CreateAdd(out_bit, out_bit), out_bit);
     240                }
     241            } else if (mIdisaOperation == "simd_pdep") {
     242                Constant * zeroConst = ConstantInt::getNullValue(fwTy);
     243                Constant * oneConst = ConstantInt::get(fwTy, 1);
     244                expected = zeroConst;
     245                Value * shft = zeroConst;
     246                Value * select_bit = oneConst;
     247                for (unsigned i = 0; i < mTestFw; i++) {
     248                    expected = kb->CreateOr(kb->CreateAnd(operand2, kb->CreateShl(kb->CreateAnd(operand1, select_bit), shft)), expected);
     249                    Value * i_bit = Constant::getIntegerValue(fwTy, APInt::getOneBitSet(mTestFw, i));
     250                    Value * mask_i_isSet = kb->CreateICmpEQ(kb->CreateAnd(operand2, i_bit), i_bit);
     251                    select_bit = kb->CreateSelect(mask_i_isSet, kb->CreateAdd(select_bit, select_bit), select_bit);
     252                    shft = kb->CreateSelect(mask_i_isSet, shft, kb->CreateAdd(shft, oneConst));
     253                }
     254            } else {
     255                llvm::report_fatal_error("Unknown SIMD vertical operation: " + mIdisaOperation);
     256            }
     257            expectedBlock = kb->bitCast(kb->mvmd_insert(mTestFw, expectedBlock, expected, i));
     258        } else if (mIdisaOperation == "hsimd_packh") {
     259            operand1 = kb->CreateTrunc(kb->CreateLShr(operand1, mTestFw/2), kb->getIntNTy(mTestFw/2));
     260            operand2 = kb->CreateTrunc(kb->CreateLShr(operand2, mTestFw/2), kb->getIntNTy(mTestFw/2));
     261            expectedBlock = kb->mvmd_insert(mTestFw/2, expectedBlock, operand1, i);
     262            expectedBlock = kb->bitCast(kb->mvmd_insert(mTestFw/2, expectedBlock, operand2, fieldCount + i));
     263        } else if (mIdisaOperation == "hsimd_packl") {
     264            operand1 = kb->CreateTrunc(operand1, kb->getIntNTy(mTestFw/2));
     265            operand2 = kb->CreateTrunc(operand2, kb->getIntNTy(mTestFw/2));
     266            expectedBlock = kb->mvmd_insert(mTestFw/2, expectedBlock, operand1, i);
     267            expectedBlock = kb->bitCast(kb->mvmd_insert(mTestFw/2, expectedBlock, operand2, fieldCount + i));
     268        } else if (mIdisaOperation == "esimd_mergeh") {
     269            if (i >= fieldCount/2) {
     270                expectedBlock = kb->mvmd_insert(mTestFw, expectedBlock, operand1, 2*(i - fieldCount/2));
     271                expectedBlock = kb->bitCast(kb->mvmd_insert(mTestFw, expectedBlock, operand2, 2*(i - fieldCount/2) + 1));
     272            }
     273        } else if (mIdisaOperation == "esimd_mergel") {
     274            if (i < fieldCount/2) {
     275                expectedBlock = kb->mvmd_insert(mTestFw, expectedBlock, operand1, 2*i);
     276                expectedBlock = kb->bitCast(kb->mvmd_insert(mTestFw, expectedBlock, operand2, 2*i + 1));
     277            }
     278        }
     279    }
     280    kb->storeOutputStreamBlock("expected_result", ZeroConst, expectedBlock);
     281    Value * failure = kb->bitblock_any(kb->CreateXor(resultBlock, expectedBlock));
     282    kb->CreateCondBr(failure, reportFailure, continueTest);
     283    kb->SetInsertPoint(reportFailure);
     284    kb->CallPrintRegister("operand1", kb->bitCast(operand1Block));
     285    kb->CallPrintRegister("operand2", kb->bitCast(operand2Block));
     286    kb->CallPrintRegister(mIdisaOperation + "(" + std::to_string(mTestFw) + ", operand1, operand2)", resultBlock);
     287    kb->CallPrintRegister("expecting", expectedBlock);
     288    kb->CreateBr(continueTest);
     289    kb->SetInsertPoint(continueTest);
     290}
     291
    127292// Open a file and return its file desciptor.
    128293int32_t openFile(const std::string & fileName, llvm::raw_ostream & msgstrm) {
     
    196361    kernel::Kernel * hexbinK2 = pxDriver.addKernelInstance<kernel::HexToBinary>(idb);
    197362    pxDriver.makeKernelCall(hexbinK2, {Operand2HexStream}, {Operand2BitStream});
     363   
     364    if (ShiftLimit > 0) {
     365        StreamSetBuffer * PreLimitBitStream = Operand2BitStream;
     366        Operand2BitStream = pxDriver.addBuffer<StaticBuffer>(idb, idb->getStreamSetTy(1, 1), bufferSize);
     367        kernel::Kernel * limitK = pxDriver.addKernelInstance<ShiftLimitKernel>(idb, TestFieldWidth, ShiftLimit);
     368        pxDriver.makeKernelCall(limitK, {PreLimitBitStream}, {Operand2BitStream});
     369    }
    198370
    199371    StreamSetBuffer * ResultBitStream = pxDriver.addBuffer<StaticBuffer>(idb, idb->getStreamSetTy(1, 1), bufferSize);
     
    201373    pxDriver.makeKernelCall(testK, {Operand1BitStream, Operand2BitStream}, {ResultBitStream});
    202374   
    203     StreamSetBuffer * ResultHexStream = pxDriver.addBuffer<StaticBuffer>(idb, idb->getStreamSetTy(1, 8), bufferSize);
    204     kernel::Kernel * binhexK = pxDriver.addKernelInstance<kernel::BinaryToHex>(idb);
    205     pxDriver.makeKernelCall(binhexK, {ResultBitStream}, {ResultHexStream});
    206    
    207     kernel::Kernel * outK = nullptr;
    208     if (TestOutputFile.empty()) {
    209         outK = pxDriver.addKernelInstance<kernel::StdOutKernel>(idb, 8);
    210     } else {
    211         outK = pxDriver.addKernelInstance<kernel::FileSink>(idb, 8);
     375    StreamSetBuffer * ExpectedResultBitStream = pxDriver.addBuffer<StaticBuffer>(idb, idb->getStreamSetTy(1, 1), bufferSize);
     376    kernel::Kernel * checkK = pxDriver.addKernelInstance<IdisaBinaryOpCheckKernel>(idb, TestOperation, TestFieldWidth);
     377    pxDriver.makeKernelCall(checkK, {Operand1BitStream, Operand2BitStream, ResultBitStream}, {ExpectedResultBitStream});
     378
     379    if (!TestOutputFile.empty()) {
     380        StreamSetBuffer * ResultHexStream = pxDriver.addBuffer<StaticBuffer>(idb, idb->getStreamSetTy(1, 8), bufferSize);
     381        kernel::Kernel * binhexK = pxDriver.addKernelInstance<kernel::BinaryToHex>(idb);
     382        pxDriver.makeKernelCall(binhexK, {ResultBitStream}, {ResultHexStream});
     383        kernel::Kernel * outK = pxDriver.addKernelInstance<kernel::FileSink>(idb, 8);
    212384        Value * fName = idb->CreatePointerCast(idb->GetString(TestOutputFile.c_str()), idb->getInt8PtrTy());
    213385        outK->setInitialArguments({fName});
    214     }
    215     pxDriver.makeKernelCall(outK, {ResultHexStream}, {});
     386        pxDriver.makeKernelCall(outK, {ResultHexStream}, {});
     387   }
    216388   
    217389    pxDriver.generatePipelineIR();
Note: See TracChangeset for help on using the changeset viewer.