Changeset 6080


Ignore:
Timestamp:
Jun 11, 2018, 3:58:54 PM (9 days ago)
Author:
xwa163
Message:

Use AVX512 gather and scatter intrinsic for literal copy in LZ4ParallelByteSteamAIOKernel

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

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_parallel_bytestream_aio.cpp

    r6077 r6080  
    778778
    779779    void LZ4ParallelByteStreamAioKernel::handleSimdLiteralCopy(const std::unique_ptr<KernelBuilder> &b, llvm::Value* literalStartVec, llvm::Value* literalLengthVec, llvm::Value* outputPosVec) {
    780         this->generateSimdSequentialLiteralCopy(b, literalStartVec, literalLengthVec, outputPosVec);
     780        this->generateSimdLiteralCopyByScatter(b, literalStartVec, literalLengthVec, outputPosVec);
     781//        this->generateSimdSequentialLiteralCopy(b, literalStartVec, literalLengthVec, outputPosVec);
    781782//        this->generateSequentialLiteralCopyWithSimdCalculation(b, literalStartVec, literalLengthVec, outputPosVec);
    782783//        this->generateLiteralCopyByMemcpy(b, literalStartVec, literalLengthVec, outputPosVec);
     
    858859        }
    859860    }
     861
    860862    void LZ4ParallelByteStreamAioKernel::generateOverwritingMemcpy(const std::unique_ptr<KernelBuilder> &b, llvm::Value *inputBasePtr,
    861863                                   llvm::Value *outputBasePtr, llvm::Value *copyBytes, llvm::PointerType *targetPtrTy,
    862864                                   llvm::Value* stepSize) {
    863         unsigned targetPtrBitWidth = targetPtrTy->getElementType()->getIntegerBitWidth();
     865//        unsigned targetPtrBitWidth = targetPtrTy->getElementType()->getIntegerBitWidth();
    864866
    865867        Constant * SIZE_0 = b->getSize(0);
    866         Constant * SIZE_1 = b->getSize(1);
     868//        Constant * SIZE_1 = b->getSize(1);
    867869        PointerType* i8PtrTy = b->getInt8PtrTy();
    868870
     
    982984                                                                          llvm::Value *literalLengthVec,
    983985                                                                          llvm::Value *outputPosVec) {
    984         // TODO
    985     }
    986 
    987     void LZ4ParallelByteStreamAioKernel::generateSimdSequentialLiteralCopyWithSimdCalculation(
    988             const std::unique_ptr<KernelBuilder> &b, llvm::Value *literalStartVec, llvm::Value *literalLengthVec,
    989             llvm::Value *outputPosVec) {
    990         // TODO Incomplete
    991 
    992         /*
     986        // ---- EntryBlock
     987        BasicBlock* entryBlock = b->GetInsertBlock();
     988        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
     989        BasicBlock* i64LiteralCopyBlock = b->CreateBasicBlock("i64LiteralCopyBlock");
     990        BasicBlock* i8LiteralCopyBlock = b->CreateBasicBlock("i8LiteralCopyBlock");
     991
     992
     993
     994
     995
     996        llvm::Value* initCopiedLength = ConstantVector::getNullValue(literalLengthVec->getType());
     997
     998        Value* inputBasePtr = b->CreatePointerCast(b->getRawInputPointer("byteStream", b->getSize(0)), b->getInt8PtrTy());
     999        Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream", b->getSize(0)), b->getInt8PtrTy());
     1000
    9931001        Value* outputCapacity = b->getCapacity("outputStream");
    9941002        Value* outputPosRemVec = b->simd_and(outputPosVec, b->simd_fill(SIMD_WIDTH, b->CreateNot(b->CreateNeg(outputCapacity))));
    995         Value* outputPosRemOutputBlockSize = b->simd_and(outputPosVec, b->simd_fill(SIMD_WIDTH, b->CreateNot(b->CreateNeg(b->getIntN(SIMD_WIDTH, mOutputBlockSize)))));
    996 
    997 
    998 
    999         Value* inputBasePtr = b->CreatePointerCast(b->getRawInputPointer("byteStream", b->getSize(0)), b->getInt8PtrTy());
    1000         Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream", b->getSize(0)), b->getInt8PtrTy());
    1001 
    1002         ////
    1003         // ---- i64LiteralCopy
    1004         BasicBlock* i64LiteralCopyCon = b->CreateBasicBlock("literalCopyCon");
    1005         BasicBlock* i64LiteralCopyBody = b->CreateBasicBlock("literalCopyBody");
    1006         BasicBlock* i64LiteralCopyExit = b->CreateBasicBlock("literalCopyExit");
    1007 
    1008         b->CreateBr(i64LiteralCopyCon);
    1009 
    1010         // ---- i64LiteralCopyCon
    1011         b->SetInsertPoint(i64LiteralCopyCon);
    1012 
    1013 
    1014         // ---- literalCopyBody
    1015         b->SetInsertPoint(i64LiteralCopyBody);
    1016 
    1017         // ---- literalCopyExit
    1018         b->SetInsertPoint(i64LiteralCopyExit);
    1019 
    1020 
    1021         //// ---- i8LiteralCopyCon
    1022          */
    1023     }
     1003        Value* outputPosRemBlockSizeVec = b->simd_and(outputPosVec, b->simd_fill(SIMD_WIDTH, b->CreateNot(b->CreateNeg(b->getIntN(SIMD_WIDTH, mOutputBlockSize)))));
     1004        Value* remainingBlockSizeVec = b->simd_sub(SIMD_WIDTH, b->simd_fill(SIMD_WIDTH, b->getIntN(SIMD_WIDTH, mOutputBlockSize)), outputPosRemBlockSizeVec);
     1005
     1006        Value* possibleExceedBuffer = b->simd_uge(SIMD_WIDTH, b->simd_add(SIMD_WIDTH, literalLengthVec, b->simd_fill(SIMD_WIDTH, b->getIntN(SIMD_WIDTH, 8))), remainingBlockSizeVec);
     1007        // true ffff, false 0000
     1008
     1009        // TODO handle literalLengthVec == 0
     1010
     1011        b->CreateUnlikelyCondBr(
     1012                b->CreateICmpNE(b->CreateBitCast(possibleExceedBuffer, b->getIntNTy(b->getBitBlockWidth())), b->getIntN(b->getBitBlockWidth(), 0)),
     1013                i8LiteralCopyBlock,
     1014                i64LiteralCopyBlock
     1015        );
     1016
     1017        // ---- i8LiteralCopyBlock
     1018        b->SetInsertPoint(i8LiteralCopyBlock);
     1019        this->generateSimdSequentialLiteralCopy(b, literalStartVec, literalLengthVec, outputPosVec);
     1020        b->CreateBr(exitBlock);
     1021
     1022        // ---- i64LiteralCopyBlock
     1023        b->SetInsertPoint(i64LiteralCopyBlock);
     1024
     1025        BasicBlock* i64LiteralCopyConBlock = b->CreateBasicBlock("i64LiteralCopyConBlock");
     1026        BasicBlock* i64LiteralCopyBodyBlock = b->CreateBasicBlock("i64LiteralCopyBodyBlock");
     1027
     1028
     1029        b->CreateBr(i64LiteralCopyConBlock);
     1030
     1031        // ---- i64LiteralCopyConBlock
     1032        b->SetInsertPoint(i64LiteralCopyConBlock);
     1033        PHINode* phiCopiedLength = b->CreatePHI(initCopiedLength->getType(), 2);
     1034        phiCopiedLength->addIncoming(initCopiedLength, i64LiteralCopyBlock);
     1035
     1036        Value* shouldCopiedBitBlock = b->simd_ult(SIMD_WIDTH, phiCopiedLength, literalLengthVec);
     1037//        b->CallPrintRegister("phiCopiedLength", phiCopiedLength);
     1038//        b->CallPrintRegister("literalLengthVec", literalLengthVec);
     1039//        b->CallPrintRegister("shouldCopiedBitBlock", shouldCopiedBitBlock);
     1040        Value* shouldCopiedI1 = b->CreateICmpNE(
     1041                b->CreateBitCast(shouldCopiedBitBlock, b->getIntNTy(b->getBitBlockWidth())),
     1042                b->getIntN(b->getBitBlockWidth(), 0)
     1043        );
     1044
     1045
     1046        b->CreateCondBr(shouldCopiedI1, i64LiteralCopyBodyBlock, exitBlock);
     1047
     1048
     1049        // ---- i64LiteralCopyBodyBlock
     1050        b->SetInsertPoint(i64LiteralCopyBodyBlock);
     1051        Value* literalData = this->simdFetchI64DataByGather(b, inputBasePtr, b->simd_add(SIMD_WIDTH, literalStartVec, phiCopiedLength), shouldCopiedBitBlock);
     1052
     1053        this->simdPutData(
     1054                b,
     1055                outputBasePtr,
     1056                b->simd_add(SIMD_WIDTH, outputPosRemVec, phiCopiedLength),
     1057                literalData,
     1058                shouldCopiedBitBlock
     1059        );
     1060//        b->CallPrintRegister("phiCopiedLength", phiCopiedLength);
     1061        phiCopiedLength->addIncoming(
     1062                b->simd_add(
     1063                        SIMD_WIDTH,
     1064                        phiCopiedLength,
     1065                        b->simd_and(
     1066                                b->simd_fill(
     1067                                        SIMD_WIDTH,
     1068                                        b->getIntN(SIMD_WIDTH, 8)
     1069                                ),
     1070                                shouldCopiedBitBlock
     1071                        )
     1072
     1073                ),
     1074                b->GetInsertBlock()
     1075        );
     1076
     1077        b->CreateBr(i64LiteralCopyConBlock);
     1078
     1079        b->SetInsertPoint(exitBlock);
     1080    }
     1081
    10241082
    10251083    void LZ4ParallelByteStreamAioKernel::handleLiteralCopy(const std::unique_ptr<KernelBuilder> &b, llvm::Value *literalStart,
     
    11191177//        return this->simdFetchDataByLoop(b, basePtr, offsetVec, mask);
    11201178        if (AVX2_available()) {
    1121             return this->simdFetchDataByGather(b, basePtr, offsetVec, mask);
     1179            return this->simdFetchI32DataByGather(b, basePtr, offsetVec, mask);
    11221180        } else {
    11231181            return this->simdFetchDataByLoop(b, basePtr, offsetVec, mask);
    11241182        }
    11251183    }
     1184
     1185
     1186
    11261187    llvm::Value* LZ4ParallelByteStreamAioKernel::simdFetchByteData(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec, llvm::Value* mask) {
    11271188        return b->CreateAnd(
     
    11311192    }
    11321193
    1133     llvm::Value* LZ4ParallelByteStreamAioKernel::simdFetchDataByGather(const std::unique_ptr<KernelBuilder> &b,
    1134                                                                        llvm::Value *basePtr, llvm::Value *offsetVec,
    1135                                                                        llvm::Value *mask) {
    1136 
    1137 //        Function *gatherFnc = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx2_gather_d_q_256);
     1194    llvm::Value* LZ4ParallelByteStreamAioKernel::simdFetchI32DataByGather(const std::unique_ptr<KernelBuilder> &b,
     1195                                                                          llvm::Value *basePtr, llvm::Value *offsetVec,
     1196                                                                          llvm::Value *mask) {
     1197
    11381198        Function *gatherFunc2 = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx2_gather_d_d);
    11391199        Function *gatherFunc3 = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx2_gather_d_d_256);
    11401200
    1141 //        gatherFunc2->dump();
    1142 //        gatherFunc3->dump();
    1143 //        Function *gatherFunc4 = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx512_gather_qpi_512);
    1144 
    11451201        Function *gatherFunc = AVX512BW_available() ? gatherFunc3 : gatherFunc2;
    11461202
    1147         Value* firstOffset = b->CreateExtractElement(offsetVec, (uint64_t)0);
    1148 
    11491203        Type* i32BitBlockTy = VectorType::get(b->getInt32Ty(), b->getBitBlockWidth() / SIMD_WIDTH);
    11501204
    1151 //        Value* tokenValuesVec =  b->CreateCall(
    1152 //                gatherFunc,
    1153 //                {
    1154 //                        UndefValue::get(b->getBitBlockType()),
    1155 //                        b->CreateGEP(basePtr, firstOffset),
    1156 //                        b->CreateTrunc(b->CreateSub(offsetVec, b->simd_fill(SIMD_WIDTH, firstOffset)), VectorType::get(b->getInt32Ty(), 4)),
    1157 //                        mask,
    1158 //                        b->getInt8(1)
    1159 //                }
    1160 //        );
    1161 
    1162         ////
     1205
    11631206        Value* tokenValuesVec =  b->CreateCall(
    11641207                gatherFunc,
    11651208                {
    11661209                        UndefValue::get(i32BitBlockTy),
    1167                         b->CreateGEP(basePtr, firstOffset),
    1168                         b->CreateTrunc(b->CreateSub(offsetVec, b->simd_fill(SIMD_WIDTH, firstOffset)), i32BitBlockTy),
     1210                        basePtr,
     1211                        b->CreateTrunc(offsetVec, i32BitBlockTy),
    11691212                        b->CreateTrunc(mask, i32BitBlockTy),
    11701213                        b->getInt8(1)
     
    11751218
    11761219        return tokenValuesVec;
     1220    }
     1221
     1222    llvm::Value* LZ4ParallelByteStreamAioKernel::simdFetchI64DataByGather(const std::unique_ptr<KernelBuilder> &b,
     1223                                                                          llvm::Value *basePtr, llvm::Value *offsetVec,
     1224                                                                          llvm::Value *mask) {
     1225        Type* i32BitBlockTy = VectorType::get(b->getInt32Ty(), b->getBitBlockWidth() / SIMD_WIDTH);
     1226        if (AVX512BW_available()) {
     1227            // AVX512 gather use i8 mask
     1228            //declare <8 x double> @llvm.x86.avx512.gather.dpd.512(<8 x double>, i8*, <8 x i32>, i8, i32) #1
     1229            Function *gatherFunc512 = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx512_gather_dpd_512);
     1230            return b->CreateCall(
     1231                    gatherFunc512,
     1232                    {
     1233                            UndefValue::get(b->getBitBlockType()),
     1234                            basePtr,
     1235                            b->CreateTrunc(offsetVec, i32BitBlockTy),
     1236                            b->CreateTruncOrBitCast(b->hsimd_signmask(SIMD_WIDTH, mask), b->getInt8Ty()),
     1237                            b->getInt32(1)
     1238                    });
     1239            // return result & i512Mask ?
     1240        } else {
     1241            // AVX2 gather use i256 mask
     1242            Function *gatherFunc = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx2_gather_d_q_256);
     1243            Value* tokenValuesVec =  b->CreateCall(
     1244                    gatherFunc,
     1245                    {
     1246                            UndefValue::get(b->getBitBlockType()),
     1247                            basePtr,
     1248                            b->CreateTrunc(offsetVec, VectorType::get(b->getInt32Ty(), 4)),
     1249                            mask,
     1250                            b->getInt8(1)
     1251                    }
     1252            );
     1253            tokenValuesVec = b->CreateAnd(tokenValuesVec, mask);
     1254            return tokenValuesVec;
     1255        }
    11771256    }
    11781257
     
    11941273    }
    11951274
     1275    void LZ4ParallelByteStreamAioKernel::simdPutData(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask) {
     1276        if (AVX512BW_available()) {
     1277            this->simdPutDataByScatter(b, basePtr, offsetVec, values, mask);
     1278        } else {
     1279            this->simdPutDataByLoop(b, basePtr, offsetVec, values, mask);
     1280        }
     1281
     1282
     1283    }
     1284
     1285    void LZ4ParallelByteStreamAioKernel::simdPutDataByLoop(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask) {
     1286
     1287        Value* shouldStoreVec = b->CreateICmpNE(mask, b->simd_fill(SIMD_WIDTH, b->getIntN(SIMD_WIDTH, 0)));
     1288
     1289        for (unsigned i = 0 ; i < b->getBitBlockWidth() / SIMD_WIDTH; i++) {
     1290            BasicBlock* conBlock = b->CreateBasicBlock("simdPutDataByLoopCon");
     1291            BasicBlock* bodyBlock = b->CreateBasicBlock("simdPutDataByLoopBody");
     1292            BasicBlock* exitBlock = b->CreateBasicBlock("simdPutDataByLoopExit");
     1293
     1294            b->CreateBr(conBlock);
     1295
     1296            // ---- ConBlock
     1297            b->SetInsertPoint(conBlock);
     1298            Value* shouldStore = b->CreateExtractElement(shouldStoreVec, i);
     1299            b->CreateCondBr(shouldStore, bodyBlock, exitBlock);
     1300
     1301            // ---- BodyBlock
     1302            b->SetInsertPoint(bodyBlock);
     1303            b->CreateStore(
     1304                    b->CreateExtractElement(values, i),
     1305                    b->CreatePointerCast(b->CreateGEP(basePtr, b->CreateExtractElement(offsetVec, i)), b->getIntNTy(SIMD_WIDTH)->getPointerTo())
     1306            );
     1307
     1308            b->CreateBr(exitBlock);
     1309
     1310            // ---- ExitBlock
     1311            b->SetInsertPoint(exitBlock);
     1312
     1313        }
     1314    }
     1315    void LZ4ParallelByteStreamAioKernel::simdPutDataByScatter(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask) {
     1316        Function *scatterFunc = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_avx512_scatter_dpq_512);
     1317        //declare void @llvm.x86.avx512.scatter.dpq.512(i8*, i8, <8 x i32>, <8 x i64>, i32)
     1318
     1319        Value* i8Mask = b->CreateTruncOrBitCast(b->hsimd_signmask(SIMD_WIDTH, mask), b->getIntNTy(b->getBitBlockWidth() / SIMD_WIDTH));
     1320
     1321        b->CreateCall(scatterFunc, {
     1322                basePtr,
     1323                i8Mask,
     1324                b->CreateTrunc(offsetVec, VectorType::get(b->getInt32Ty(), b->getBitBlockWidth() / SIMD_WIDTH)),
     1325                values,
     1326                b->getInt32(1)
     1327        });
     1328
     1329    }
     1330
    11961331}
  • icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_parallel_bytestream_aio.h

    r6077 r6080  
    5959                                               llvm::Value *literalLengthVec, llvm::Value *outputPosVec);
    6060
    61         void generateSimdSequentialLiteralCopyWithSimdCalculation(const std::unique_ptr<KernelBuilder> &b,
    62                                                                   llvm::Value *literalStartVec,
    63                                                                   llvm::Value *literalLengthVec,
    64                                                                   llvm::Value *outputPosVec);
    6561        void generateSimdLiteralCopyByScatter(const std::unique_ptr<KernelBuilder> &b, llvm::Value *literalStartVec,
    6662                                              llvm::Value *literalLengthVec, llvm::Value *outputPosVec);
     
    8783        llvm::Value* simdFetchData(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec, llvm::Value* mask);
    8884        llvm::Value* simdFetchByteData(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec, llvm::Value* mask);
    89         llvm::Value* simdFetchDataByGather(const std::unique_ptr<KernelBuilder> &b, llvm::Value *basePtr,
    90                                            llvm::Value *offsetVec, llvm::Value *mask);
     85        llvm::Value* simdFetchI64DataByGather(const std::unique_ptr<KernelBuilder> &b, llvm::Value *basePtr,
     86                                              llvm::Value *offsetVec, llvm::Value *mask);
     87        llvm::Value* simdFetchI32DataByGather(const std::unique_ptr<KernelBuilder> &b, llvm::Value *basePtr,
     88                                              llvm::Value *offsetVec, llvm::Value *mask);
    9189        llvm::Value* simdFetchDataByLoop(const std::unique_ptr<KernelBuilder> &b, llvm::Value *basePtr,
    9290                                         llvm::Value *offsetVec, llvm::Value *mask);
     91
     92        void simdPutData(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask /*i256*/);
     93        void simdPutDataByLoop(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask /*i256*/);
     94        void simdPutDataByScatter(const std::unique_ptr<KernelBuilder> &b, llvm::Value* basePtr, llvm::Value* offsetVec,llvm::Value* values, llvm::Value* mask /*i256*/);
    9395
    9496        size_t mOutputBlockSize;
  • icGREP/icgrep-devel/icgrep/lz4/LZ4GrepGenerator.cpp

    r6070 r6080  
    628628//    Kernel * outK = mPxDriver.addKernelInstance<FileSink>(iBuilder, 8);
    629629//    outK->setInitialArguments({iBuilder->GetString("/Users/wxy325/developer/LZ4-sample-files/workspace/lz4d-normal/8k_.txt")});
    630 //    mPxDriver.makeKernelCall(outK, {decompressedStream}, {});
     630//    mPxDriver.makeKernelCall(outK, {decompressedByteStream}, {});
    631631
    632632    kernel::Kernel * matchCountK = mPxDriver.addKernelInstance<kernel::PopcountKernel>(iBuilder);
Note: See TracChangeset for help on using the changeset viewer.