Changeset 4749


Ignore:
Timestamp:
Aug 25, 2015, 8:15:38 PM (4 years ago)
Author:
cameron
Message:

Pull long stream add logic out of pablo compiler.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.cpp

    r4741 r4749  
    180180    FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()), {{mInputType, outputType}}, false);
    181181
    182 #ifdef USE_UADD_OVERFLOW
    183 #ifdef USE_TWO_UADD_OVERFLOW
    184     // Type Definitions for llvm.uadd.with.overflow.carryin.i128 or .i256
    185     std::vector<Type*>StructTy_0_fields;
    186     StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    187     StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), 1));
    188     StructType *StructTy_0 = StructType::get(mMod->getContext(), StructTy_0_fields, /*isPacked=*/false);
    189 
    190     std::vector<Type*>FuncTy_1_args;
    191     FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    192     FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    193     FunctionType* FuncTy_1 = FunctionType::get(
    194                                               /*Result=*/StructTy_0,
    195                                               /*Params=*/FuncTy_1_args,
    196                                               /*isVarArg=*/false);
    197 
    198     mFunctionUaddOverflow = mMod->getFunction("llvm.uadd.with.overflow.i" +
    199                                               std::to_string(BLOCK_SIZE));
    200     if (!mFunctionUaddOverflow) {
    201         mFunctionUaddOverflow= Function::Create(
    202           /*Type=*/ FuncTy_1,
    203           /*Linkage=*/ GlobalValue::ExternalLinkage,
    204           /*Name=*/ "llvm.uadd.with.overflow.i" + std::to_string(BLOCK_SIZE), mMod); // (external, no body)
    205         mFunctionUaddOverflow->setCallingConv(CallingConv::C);
    206     }
    207     AttributeSet mFunctionUaddOverflowPAL;
    208     {
    209         SmallVector<AttributeSet, 4> Attrs;
    210         AttributeSet PAS;
    211         {
    212           AttrBuilder B;
    213           B.addAttribute(Attribute::NoUnwind);
    214           B.addAttribute(Attribute::ReadNone);
    215           PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
    216         }
    217 
    218         Attrs.push_back(PAS);
    219         mFunctionUaddOverflowPAL = AttributeSet::get(mMod->getContext(), Attrs);
    220     }
    221     mFunctionUaddOverflow->setAttributes(mFunctionUaddOverflowPAL);
    222 #else
    223     // Type Definitions for llvm.uadd.with.overflow.carryin.i128 or .i256
    224     std::vector<Type*>StructTy_0_fields;
    225     StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    226     StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), 1));
    227     StructType *StructTy_0 = StructType::get(mMod->getContext(), StructTy_0_fields, /*isPacked=*/false);
    228 
    229     std::vector<Type*>FuncTy_1_args;
    230     FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    231     FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
    232     FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), 1));
    233     FunctionType* FuncTy_1 = FunctionType::get(
    234                                               /*Result=*/StructTy_0,
    235                                               /*Params=*/FuncTy_1_args,
    236                                               /*isVarArg=*/false);
    237 
    238     mFunctionUaddOverflowCarryin = mMod->getFunction("llvm.uadd.with.overflow.carryin.i" +
    239                                               std::to_string(BLOCK_SIZE));
    240     if (!mFunctionUaddOverflowCarryin) {
    241         mFunctionUaddOverflowCarryin = Function::Create(
    242           /*Type=*/ FuncTy_1,
    243           /*Linkage=*/ GlobalValue::ExternalLinkage,
    244           /*Name=*/ "llvm.uadd.with.overflow.carryin.i" + std::to_string(BLOCK_SIZE), mMod); // (external, no body)
    245         mFunctionUaddOverflowCarryin->setCallingConv(CallingConv::C);
    246     }
    247     AttributeSet mFunctionUaddOverflowCarryinPAL;
    248     {
    249         SmallVector<AttributeSet, 4> Attrs;
    250         AttributeSet PAS;
    251         {
    252           AttrBuilder B;
    253           B.addAttribute(Attribute::NoUnwind);
    254           B.addAttribute(Attribute::ReadNone);
    255           PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
    256         }
    257 
    258         Attrs.push_back(PAS);
    259         mFunctionUaddOverflowCarryinPAL = AttributeSet::get(mMod->getContext(), Attrs);
    260     }
    261     mFunctionUaddOverflowCarryin->setAttributes(mFunctionUaddOverflowCarryinPAL);
    262 #endif
    263 #endif
    264182
    265183    //Starts on process_block
     
    618536}
    619537
    620 
    621 #ifdef USE_UADD_OVERFLOW
    622 #ifdef USE_TWO_UADD_OVERFLOW
    623 PabloCompiler::SumWithOverflowPack PabloCompiler::callUaddOverflow(Value* int128_e1, Value* int128_e2) {
    624     std::vector<Value*> struct_res_params;
    625     struct_res_params.push_back(int128_e1);
    626     struct_res_params.push_back(int128_e2);
    627     CallInst* struct_res = CallInst::Create(mFunctionUaddOverflow, struct_res_params, "uadd_overflow_res", mBasicBlock);
    628     struct_res->setCallingConv(CallingConv::C);
    629     struct_res->setTailCall(false);
    630     AttributeSet struct_res_PAL;
    631     struct_res->setAttributes(struct_res_PAL);
    632 
    633     SumWithOverflowPack ret;
    634 
    635     std::vector<unsigned> int128_sum_indices;
    636     int128_sum_indices.push_back(0);
    637     ret.sum = ExtractValueInst::Create(struct_res, int128_sum_indices, "sum", mBasicBlock);
    638 
    639     std::vector<unsigned> int1_obit_indices;
    640     int1_obit_indices.push_back(1);
    641     ret.obit = ExtractValueInst::Create(struct_res, int1_obit_indices, "obit", mBasicBlock);
    642 
    643     return ret;
    644 }
    645 #else
    646 PabloCompiler::SumWithOverflowPack PabloCompiler::callUaddOverflow(Value* int128_e1, Value* int128_e2, Value* int1_cin) {
    647     std::vector<Value*> struct_res_params;
    648     struct_res_params.push_back(int128_e1);
    649     struct_res_params.push_back(int128_e2);
    650     struct_res_params.push_back(int1_cin);
    651     CallInst* struct_res = CallInst::Create(mFunctionUaddOverflowCarryin, struct_res_params, "uadd_overflow_res", mBasicBlock);
    652     struct_res->setCallingConv(CallingConv::C);
    653     struct_res->setTailCall(false);
    654     AttributeSet struct_res_PAL;
    655     struct_res->setAttributes(struct_res_PAL);
    656 
    657     SumWithOverflowPack ret;
    658 
    659     std::vector<unsigned> int128_sum_indices;
    660     int128_sum_indices.push_back(0);
    661     ret.sum = ExtractValueInst::Create(struct_res, int128_sum_indices, "sum", mBasicBlock);
    662 
    663     std::vector<unsigned> int1_obit_indices;
    664     int1_obit_indices.push_back(1);
    665     ret.obit = ExtractValueInst::Create(struct_res, int1_obit_indices, "obit", mBasicBlock);
    666 
    667     return ret;
    668 }
    669 #endif
    670 #endif
    671 
    672 
    673 Value* PabloCompiler::genAddWithCarry(Value* e1, Value* e2, unsigned localIndex) {
    674     Value * carryq_value = mCarryManager->getCarryOpCarryIn(localIndex);
    675 #ifdef USE_TWO_UADD_OVERFLOW
    676     //This is the ideal implementation, which uses two uadd.with.overflow
    677     //The back end should be able to recognize this pattern and combine it into uadd.with.overflow.carryin
    678     CastInst* int128_e1 = new BitCastInst(e1, mBuilder->getIntNTy(BLOCK_SIZE), "e1_128", mBasicBlock);
    679     CastInst* int128_e2 = new BitCastInst(e2, mBuilder->getIntNTy(BLOCK_SIZE), "e2_128", mBasicBlock);
    680     CastInst* int128_carryq_value = new BitCastInst(carryq_value, mBuilder->getIntNTy(BLOCK_SIZE), "carryq_128", mBasicBlock);
    681 
    682     SumWithOverflowPack sumpack0, sumpack1;
    683 
    684     sumpack0 = callUaddOverflow(int128_e1, int128_e2);
    685     sumpack1 = callUaddOverflow(sumpack0.sum, int128_carryq_value);
    686 
    687     Value* obit = mBuilder->CreateOr(sumpack0.obit, sumpack1.obit, "carry_bit");
    688     Value* sum = mBuilder->CreateBitCast(sumpack1.sum, mBitBlockType, "ret_sum");
    689 
    690     /*obit is the i1 carryout, zero extend and insert it into a v2i64 or v4i64 vector.*/
    691     ConstantAggregateZero* const_packed_5 = ConstantAggregateZero::get(mBitBlockType);
    692     ConstantInt* const_int32_6 = ConstantInt::get(mMod->getContext(), APInt(32, StringRef("0"), 10));
    693     CastInst* int64_o0 = new ZExtInst(obit, IntegerType::get(mMod->getContext(), 64), "o0", mBasicBlock);
    694     InsertElementInst* carry_out = InsertElementInst::Create(const_packed_5, int64_o0, const_int32_6, "carry_out", mBasicBlock);
    695 
    696 #elif defined USE_UADD_OVERFLOW
    697     //use llvm.uadd.with.overflow.i128 or i256
    698     CastInst* int128_e1 = new BitCastInst(e1, mBuilder->getIntNTy(BLOCK_SIZE), "e1_128", mBasicBlock);
    699     CastInst* int128_e2 = new BitCastInst(e2, mBuilder->getIntNTy(BLOCK_SIZE), "e2_128", mBasicBlock);
    700 
    701     //get i1 carryin from iBLOCK_SIZE
    702     ConstantInt* const_int32_6 = ConstantInt::get(mMod->getContext(), APInt(32, StringRef("0"), 10));
    703     ExtractElementInst * int64_carryq_value = ExtractElementInst::Create(carryq_value, const_int32_6, "carryq_64", mBasicBlock);
    704     CastInst* int1_carryq_value = new TruncInst(int64_carryq_value, IntegerType::get(mMod->getContext(), 1), "carryq_1", mBasicBlock);
    705 
    706     SumWithOverflowPack sumpack0;
    707     sumpack0 = callUaddOverflow(int128_e1, int128_e2, int1_carryq_value);
    708     Value* obit = sumpack0.obit;
    709     Value* sum = mBuilder->CreateBitCast(sumpack0.sum, mBitBlockType, "sum");
    710 
    711     /*obit is the i1 carryout, zero extend and insert it into a v2i64 or v4i64 vector.*/
    712     ConstantAggregateZero* const_packed_5 = ConstantAggregateZero::get(mBitBlockType);
    713     CastInst* int64_o0 = new ZExtInst(obit, IntegerType::get(mMod->getContext(), 64), "o0", mBasicBlock);
    714     InsertElementInst* carry_out = InsertElementInst::Create(const_packed_5, int64_o0, const_int32_6, "carry_out", mBasicBlock);
    715 #elif (BLOCK_SIZE == 128)
    716     //calculate carry through logical ops
    717     Value* carrygen = mBuilder->CreateAnd(e1, e2, "carrygen");
    718     Value* carryprop = mBuilder->CreateOr(e1, e2, "carryprop");
    719     Value* digitsum = mBuilder->CreateAdd(e1, e2, "digitsum");
    720     Value* partial = mBuilder->CreateAdd(digitsum, carryq_value, "partial");
    721     Value* digitcarry = mBuilder->CreateOr(carrygen, mBuilder->CreateAnd(carryprop, genNot(partial)));
    722     Value* mid_carry_in = genShiftLeft64(mBuilder->CreateLShr(digitcarry, 63), "mid_carry_in");
    723 
    724     Value* sum = mBuilder->CreateAdd(partial, mid_carry_in, "sum");
    725     Value* carry_out = genShiftHighbitToLow(BLOCK_SIZE, mBuilder->CreateOr(carrygen, mBuilder->CreateAnd(carryprop, genNot(sum))));
    726 #else
    727     //BLOCK_SIZE == 256, there is no other implementation
    728     static_assert(false, "Add with carry for 256-bit bitblock requires USE_UADD_OVERFLOW");
    729 #endif //USE_TWO_UADD_OVERFLOW
    730 
    731     mCarryManager->setCarryOpCarryOut(localIndex, carry_out);
    732     return sum;
    733 }
    734 
    735 Value * PabloCompiler::genShiftHighbitToLow(unsigned FieldWidth, Value * op) {
    736     unsigned FieldCount = BLOCK_SIZE/FieldWidth;
    737     VectorType * vType = VectorType::get(IntegerType::get(mMod->getContext(), FieldWidth), FieldCount);
    738     Value * v = mBuilder->CreateBitCast(op, vType);
    739     return mBuilder->CreateBitCast(mBuilder->CreateLShr(v, FieldWidth - 1), mBitBlockType);
    740 }
    741 
    742538Value* PabloCompiler::genShiftLeft64(Value* e, const Twine &namehint) {
    743539    Value* i128_val = mBuilder->CreateBitCast(e, mBuilder->getIntNTy(BLOCK_SIZE));
Note: See TracChangeset for help on using the changeset viewer.