source: icGREP/icgrep-devel/icgrep/llvm_gen.cpp @ 4200

Last change on this file since 4200 was 4200, checked in by nmedfort, 5 years ago

Replaced dynamic_cast with llvm::dyn_cast in pablo code; implemented make functions for pablo constructors. Disabled RTTI.

File size: 41.9 KB
RevLine 
[3850]1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "llvm_gen.h"
[4194]8//Pablo Expressions
[4199]9#include <pablo/pe_advance.h>
10#include <pablo/pe_all.h>
11#include <pablo/pe_and.h>
12#include <pablo/pe_call.h>
13#include <pablo/pe_charclass.h>
14#include <pablo/pe_matchstar.h>
15#include <pablo/pe_not.h>
16#include <pablo/pe_or.h>
17#include <pablo/pe_pabloe.h>
18#include <pablo/pe_scanthru.h>
19#include <pablo/pe_sel.h>
20#include <pablo/pe_var.h>
21#include <pablo/pe_xor.h>
22#include <pablo/ps_pablos.h>
23#include <pablo/ps_assign.h>
24#include <pablo/ps_if.h>
25#include <pablo/ps_while.h>
[3850]26
[4199]27using namespace pablo;
[4194]28
[4198]29Ps* fPs = NULL; Nl* fNl = NULL; No* fNo = NULL; Lo* fLo = NULL; Ll* fLl = NULL; Lm* fLm = NULL; Nd* fNd = NULL;
30Pc* fPc = NULL; Lt* fLt = NULL; Lu* fLu = NULL; Pf* fPf = NULL; Pd* fPd = NULL; Pe* fPe = NULL; Pi* fPi = NULL;
31Po* fPo = NULL; Me* fMe = NULL; Mc* fMc = NULL; Mn* fMn = NULL; Sk* fSk = NULL; So* fSo = NULL; Sm* fSm = NULL;
32Sc* fSc = NULL; Zl* fZl = NULL; Co* fCo = NULL; Cn* fCn = NULL; Cc* fCc = NULL; Cf* fCf = NULL; Cs* fCs = NULL;
33Zp* fZp = NULL; Zs* fZs = NULL;
[3969]34
[3850]35extern "C" {
36  void wrapped_print_register(BitBlock bit_block) {
37      print_register<BitBlock>("", bit_block);
38  }
39}
40
[3940]41extern "C" {
[3982]42    BitBlock wrapped_get_category_Ps(Basis_bits &basis_bits){
[4198]43        if (fPs == nullptr) fPs = new Ps();
[3982]44        Struct_Ps ps_output;
[4198]45        fPs->do_block(basis_bits, ps_output);
[3940]46
[3982]47        return ps_output.cc;
48    }
49}
50
51extern "C" {
52    BitBlock wrapped_get_category_Nl(Basis_bits &basis_bits){
[4198]53        if (fNl == nullptr) fNl = new Nl();
[3982]54        Struct_Nl nl_output;
[4198]55        fNl->do_block(basis_bits, nl_output);
[3982]56
57        return nl_output.cc;
58    }
59}
60
61extern "C" {
62    BitBlock wrapped_get_category_No(Basis_bits &basis_bits){
[4198]63        if (fNo == nullptr) fNo = new No();
[3982]64        Struct_No no_output;
[4198]65        fNo->do_block(basis_bits, no_output);
[3982]66
67        return no_output.cc;
68    }
69}
70
71extern "C" {
72    BitBlock wrapped_get_category_Lo(Basis_bits &basis_bits){
[4198]73        if (fLo == nullptr) fLo = new Lo();
[3982]74        Struct_Lo lo_output;
[4198]75        fLo->do_block(basis_bits, lo_output);
[3982]76
77        return lo_output.cc;
78    }
79}
80
81extern "C" {
82    BitBlock wrapped_get_category_Ll(Basis_bits &basis_bits){
[4198]83        if (fLl == nullptr) fLl = new Ll();
[3982]84        Struct_Ll ll_output;
[4198]85        fLl->do_block(basis_bits, ll_output);
[3982]86
87        return ll_output.cc;
88    }
89}
90
91extern "C" {
92    BitBlock wrapped_get_category_Lm(Basis_bits &basis_bits){
[4198]93        if (fLm == nullptr) fLm = new Lm();
[3982]94        Struct_Lm lm_output;
[4198]95        fLm->do_block(basis_bits, lm_output);
[3982]96
97        return lm_output.cc;
98    }
99}
100
101extern "C" {
102    BitBlock wrapped_get_category_Nd(Basis_bits &basis_bits){
[4198]103        if (fNd == nullptr) fNd = new Nd();
[3969]104        Struct_Nd nd_output;
[4198]105        fNd->do_block(basis_bits, nd_output);
[3940]106
[3969]107        return nd_output.cc;
108    }
[3850]109}
110
[3982]111extern "C" {
112    BitBlock wrapped_get_category_Pc(Basis_bits &basis_bits){
[4198]113        if (fPc == nullptr) fPc = new Pc();
[3982]114        Struct_Pc pc_output;
[4198]115        fPc->do_block(basis_bits, pc_output);
[3982]116
117        return pc_output.cc;
118    }
119}
120
121extern "C" {
122    BitBlock wrapped_get_category_Lt(Basis_bits &basis_bits){
[4198]123        if (fLt == nullptr) fLt = new Lt();
[3982]124        Struct_Lt lt_output;
[4198]125        fLt->do_block(basis_bits, lt_output);
[3982]126
127        return lt_output.cc;
128    }
129}
130
131extern "C" {
132    BitBlock wrapped_get_category_Lu(Basis_bits &basis_bits){
[4198]133        if (fLu == nullptr) fLu = new Lu();
[3982]134        Struct_Lu lu_output;
[4198]135        fLu->do_block(basis_bits, lu_output);
[3982]136
137        return lu_output.cc;
138    }
139}
140
141extern "C" {
142    BitBlock wrapped_get_category_Pf(Basis_bits &basis_bits){
[4198]143        if (fPf == nullptr) fPf = new Pf();
[3982]144        Struct_Pf pf_output;
[4198]145        fPf->do_block(basis_bits, pf_output);
[3982]146
147        return pf_output.cc;
148    }
149}
150
151extern "C" {
152    BitBlock wrapped_get_category_Pd(Basis_bits &basis_bits){
[4198]153        if (fPd == nullptr) fPd = new Pd();
[3982]154        Struct_Pd pd_output;
[4198]155        fPd->do_block(basis_bits, pd_output);
[3982]156
157        return pd_output.cc;
158    }
159}
160
161extern "C" {
162    BitBlock wrapped_get_category_Pe(Basis_bits &basis_bits){
[4198]163        if (fPe == nullptr) fPe = new Pe();
[3982]164        Struct_Pe pe_output;
[4198]165        fPe->do_block(basis_bits, pe_output);
[3982]166
167        return pe_output.cc;
168    }
169}
170
171extern "C" {
172    BitBlock wrapped_get_category_Pi(Basis_bits &basis_bits){
[4198]173        if (fPi == nullptr) fPi = new Pi();
[3982]174        Struct_Pi pi_output;
[4198]175        fPi->do_block(basis_bits, pi_output);
[3982]176
177        return pi_output.cc;
178    }
179}
180
181extern "C" {
182    BitBlock wrapped_get_category_Po(Basis_bits &basis_bits){
[4198]183        if (fPo == nullptr) fPo = new Po();
[3982]184        Struct_Po po_output;
[4198]185        fPo->do_block(basis_bits, po_output);
[3982]186
187        return po_output.cc;
188    }
189}
190
191extern "C" {
192    BitBlock wrapped_get_category_Me(Basis_bits &basis_bits){
[4198]193        if (fMe == nullptr) fMe = new Me();
[3982]194        Struct_Me me_output;
[4198]195        fMe->do_block(basis_bits, me_output);
[3982]196
197        return me_output.cc;
198    }
199}
200
201extern "C" {
202    BitBlock wrapped_get_category_Mc(Basis_bits &basis_bits){
[4198]203        if (fMc == nullptr) fMc = new Mc();
[3982]204        Struct_Mc mc_output;
[4198]205        fMc->do_block(basis_bits, mc_output);
[3982]206
207        return mc_output.cc;
208    }
209}
210
211extern "C" {
212    BitBlock wrapped_get_category_Mn(Basis_bits &basis_bits){
[4198]213        if (fMn == nullptr) fMn = new Mn();
[3982]214        Struct_Mn mn_output;
[4198]215        fMn->do_block(basis_bits, mn_output);
[3982]216
217        return mn_output.cc;
218    }
219}
220
221extern "C" {
222    BitBlock wrapped_get_category_Sk(Basis_bits &basis_bits){
[4198]223        if (fSk == nullptr) fSk = new Sk();
[3982]224        Struct_Sk sk_output;
[4198]225        fSk->do_block(basis_bits, sk_output);
[3982]226
227        return sk_output.cc;
228    }
229}
230
231extern "C" {
232    BitBlock wrapped_get_category_So(Basis_bits &basis_bits){
[4198]233        if (fSo == nullptr) fSo = new So();
[3982]234        Struct_So so_output;
[4198]235        fSo->do_block(basis_bits, so_output);
[3982]236
237        return so_output.cc;
238    }
239}
240
241extern "C" {
242    BitBlock wrapped_get_category_Sm(Basis_bits &basis_bits){
[4198]243        if (fSm == nullptr) fSm = new Sm();
[3982]244        Struct_Sm sm_output;
[4198]245        fSm->do_block(basis_bits, sm_output);
[3982]246
247        return sm_output.cc;
248    }
249}
250
251extern "C" {
252    BitBlock wrapped_get_category_Sc(Basis_bits &basis_bits){
[4198]253        if (fSc == nullptr) fSc = new Sc();
[3982]254        Struct_Sc sc_output;
[4198]255        fSc->do_block(basis_bits, sc_output);
[3982]256
257        return sc_output.cc;
258    }
259}
260
261extern "C" {
262    BitBlock wrapped_get_category_Zl(Basis_bits &basis_bits){
[4198]263        if (fZl == nullptr) fZl = new Zl();
[3982]264        Struct_Zl zl_output;
[4198]265        fZl->do_block(basis_bits, zl_output);
[3982]266
267        return zl_output.cc;
268    }
269}
270
271extern "C" {
272    BitBlock wrapped_get_category_Co(Basis_bits &basis_bits){
[4198]273        if (fCo == nullptr) fCo = new Co();
[3982]274        Struct_Co co_output;
[4198]275        fCo->do_block(basis_bits, co_output);
[3982]276
277        return co_output.cc;
278    }
279}
280
281extern "C" {
282    BitBlock wrapped_get_category_Cn(Basis_bits &basis_bits){
[4198]283        if (fCn == nullptr) fCn = new Cn();
[3982]284        Struct_Cn cn_output;
[4198]285        fCn->do_block(basis_bits, cn_output);
[3982]286
287        return cn_output.cc;
288    }
289}
290
291extern "C" {
292    BitBlock wrapped_get_category_Cc(Basis_bits &basis_bits){
[4198]293        if (fCc == nullptr) fCc = new Cc();
[3982]294        Struct_Cc cc_output;
[4198]295        fCc->do_block(basis_bits, cc_output);
[3982]296
297        return cc_output.cc;
298    }
299}
300
301extern "C" {
302    BitBlock wrapped_get_category_Cf(Basis_bits &basis_bits){
[4198]303        if (fCf == nullptr) fCf = new Cf();
[3982]304        Struct_Cf cf_output;
[4198]305        fCf->do_block(basis_bits, cf_output);
[3982]306
307        return cf_output.cc;
308    }
309}
310
311extern "C" {
312    BitBlock wrapped_get_category_Cs(Basis_bits &basis_bits){
[4198]313        if (fCs == nullptr) fCs = new Cs();
[3982]314        Struct_Cs cs_output;
[4198]315        fCs->do_block(basis_bits, cs_output);
[3982]316
317        return cs_output.cc;
318    }
319}
320
321extern "C" {
322    BitBlock wrapped_get_category_Zp(Basis_bits &basis_bits){
[4198]323        if (fZp == nullptr) fZp = new Zp();
[3982]324        Struct_Zp zp_output;
[4198]325        fZp->do_block(basis_bits, zp_output);
[3982]326
327        return zp_output.cc;
328    }
329}
330
331extern "C" {
332    BitBlock wrapped_get_category_Zs(Basis_bits &basis_bits){
[4198]333        if (fZs == nullptr) fZs = new Zs();
[3982]334        Struct_Zs zs_output;
[4198]335        fZs->do_block(basis_bits, zs_output);
[3982]336
337        return zs_output.cc;
338    }
339}
340
[3955]341LLVM_Generator::LLVM_Generator(std::map<std::string, std::string> name_map, std::string basis_pattern, int bits)
[3850]342{
[3955]343    m_name_map = name_map;
[3850]344    mBasis_Pattern = basis_pattern;
345    mBits = bits;
346}
347
348LLVM_Generator::~LLVM_Generator()
349{
350    delete mMod;
[3982]351
[4198]352    delete fPs;
353    delete fNl;
354    delete fNo;
355    delete fLo;
356    delete fLl;
357    delete fLm;
358    delete fNd;
359    delete fPc;
360    delete fLt;
361    delete fLu;
362    delete fPf;
363    delete fPd;
364    delete fPe;
365    delete fPi;
366    delete fPo;
367    delete fMe;
368    delete fMc;
369    delete fMn;
370    delete fSk;
371    delete fSo;
372    delete fSm;
373    delete fSc;
374    delete fZl;
375    delete fCo;
376    delete fCn;
377    delete fCc;
378    delete fCf;
379    delete fCs;
380    delete fZp;
381    delete fZs;
[3982]382
[3850]383}
384
[4199]385LLVM_Gen_RetVal LLVM_Generator::Generate_LLVMIR(CodeGenState cg_state, CodeGenState subexpression_cg_state, List cc_cgo_stmtsl)
[3850]386{
387    //Create the module.
388    MakeLLVMModule();
389
[3854]390    //Create the jit execution engine.up
[3850]391    InitializeNativeTarget();
392    std::string ErrStr;
[3914]393
394    mExecutionEngine = EngineBuilder(mMod).setUseMCJIT(true).setErrorStr(&ErrStr).setOptLevel(CodeGenOpt::Level::Less).create();
[3850]395    if (!mExecutionEngine)
396    {
397        std::cout << "\nCould not create ExecutionEngine: " + ErrStr << std::endl;
398        exit(1);
399    }
400
401    InitializeNativeTargetAsmPrinter();
402    InitializeNativeTargetAsmParser();
403
404    DefineTypes();
405    DeclareFunctions();
[3982]406    DeclareCallFunctions(cg_state.stmtsl);
[3850]407
408    Function::arg_iterator args = mFunc_process_block->arg_begin();
409    Value* ptr_basis_bits = args++;
410    ptr_basis_bits->setName("basis_bits");
411    mptr_carry_q = args++;
412    mptr_carry_q->setName("carry_q");
413    Value* ptr_output = args++;
414    ptr_output->setName("output");
415
416    //Create the carry queue.
417    mCarryQueueIdx = 0;
[3955]418    mCarryQueueSize = LLVM_Generator_Helper::CarryCount_PabloStatements(subexpression_cg_state.stmtsl);
419    mCarryQueueSize += LLVM_Generator_Helper::CarryCount_PabloStatements(cg_state.stmtsl);
[4002]420    /* The following may be needed if carry-generating operations are ever inserted
421       by the character class compiler.
422    mCarryQueueSize += LLVM_Generator_Helper::CarryCount_PabloStatements(cc_cgo_stmtsl);
423    */
[3850]424
425    mBasicBlock = BasicBlock::Create(mMod->getContext(), "parabix_entry", mFunc_process_block,0);
426
427    //The basis bits structure
428    mPtr_basis_bits_addr = new AllocaInst(mStruct_Basis_Bits_Ptr1, "basis_bits.addr", mBasicBlock);
429    StoreInst* void_14 = new StoreInst(ptr_basis_bits, mPtr_basis_bits_addr, false, mBasicBlock);
430
431    for (int i = 0; i < mBits; i++)
432    {
[3984]433        StoreBitBlockMarkerPtr(mBasis_Pattern + std::to_string(i), i);
[3850]434    }
435
436    //The output structure.
437    mPtr_output_addr = new AllocaInst(mStruct_Output_Ptr1, "output.addr", mBasicBlock);
438    StoreInst* void_16 = new StoreInst(ptr_output, mPtr_output_addr, false, mBasicBlock);
439
440    //Generate the IR instructions for the function.
[3940]441
[3850]442    Generate_PabloStatements(cc_cgo_stmtsl);
[3955]443    Generate_PabloStatements(subexpression_cg_state.stmtsl);
[3850]444    Generate_PabloStatements(cg_state.stmtsl);
445    SetReturnMarker(cg_state.newsym, 0);
[4129]446    SetReturnMarker(m_name_map.find("LineFeed")->second, 1);
[3850]447
448    //Terminate the block
449    ReturnInst::Create(mMod->getContext(), mBasicBlock);
450
451    //Create a verifier.  The verifier will print an error message if our module is malformed in any way.
[4088]452#ifdef USE_LLVM_3_5
453    verifyModule(*mMod, &dbgs());
454#endif
455
456#ifdef USE_LLVM_3_4
[3850]457    verifyModule(*mMod, PrintMessageAction);
[4088]458#endif
[3850]459
460    //Un-comment this line in order to display the IR that has been generated by this module.
[4002]461#ifdef DUMP_GENERATED_IR
462    mMod->dump();
463#endif
[3850]464
465    //Use the pass manager to run optimizations on the function.
466    FunctionPassManager fpm(mMod);
467
[4088]468#ifdef USE_LLVM_3_5
469    mMod->setDataLayout(mExecutionEngine->getDataLayout());
[3850]470    // Set up the optimizer pipeline.  Start with registering info about how the target lays out data structures.
[4088]471    fpm.add(new DataLayoutPass(mMod));
472#endif
473
474#ifdef USE_LLVM_3_4
[3850]475    fpm.add(new DataLayout(*mExecutionEngine->getDataLayout()));
[4088]476#endif
[3850]477
[3914]478    fpm.add(createPromoteMemoryToRegisterPass()); //Transform to SSA form.
[3854]479
[3914]480    fpm.add(createBasicAliasAnalysisPass());      //Provide basic AliasAnalysis support for GVN. (Global Value Numbering)
[3991]481    fpm.add(createCFGSimplificationPass());       //Simplify the control flow graph.
[3914]482    fpm.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
483    fpm.add(createReassociatePass());             //Reassociate expressions.
484    fpm.add(createGVNPass());                     //Eliminate common subexpressions.
485
[3850]486    fpm.doInitialization();
487
488    fpm.run(*mFunc_process_block);
489
[4002]490#ifdef DUMP_OPTIMIZED_IR
491    mMod->dump();
492#endif
[3850]493    mExecutionEngine->finalizeObject();
494
495    LLVM_Gen_RetVal retVal;
496    //Return the required size of the carry queue and a pointer to the process_block function.
[3914]497    retVal.carry_q_size = mCarryQueueSize;
[3850]498    retVal.process_block_fptr = mExecutionEngine->getPointerToFunction(mFunc_process_block);
499
500    return retVal;
501}
502
[4151]503#define bitBlockExprType mXi64Vect
[4002]504
[3850]505void LLVM_Generator::DefineTypes()
506{
507    //The BitBlock vector.
[4151]508    mXi64Vect = VectorType::get(IntegerType::get(mMod->getContext(), 64), BLOCK_SIZE / 64);
509    mXi128Vect = VectorType::get(IntegerType::get(mMod->getContext(), 128), BLOCK_SIZE / 128);
[3850]510    //A pointer to the BitBlock vector.
[4151]511    mXi64Vect_Ptr1 = PointerType::get(mXi64Vect, 0);
[3850]512
513    //Constant definitions.
514    mConst_int64_neg1 = ConstantInt::get(mMod->getContext(), APInt(64, StringRef("-1"), 10));
515
[4151]516    mConst_Aggregate_Xi64_0 = ConstantAggregateZero::get(mXi64Vect);
[3850]517    std::vector<Constant*> const_packed_27_elems;
[4151]518    for (int i = 0; i < BLOCK_SIZE / 64; ++i)
519      const_packed_27_elems.push_back(mConst_int64_neg1);
520    mConst_Aggregate_Xi64_neg1 = ConstantVector::get(const_packed_27_elems);
[3850]521
522
523    StructType *StructTy_struct_Basis_bits = mMod->getTypeByName("struct.Basis_bits");
524    if (!StructTy_struct_Basis_bits) {
525        StructTy_struct_Basis_bits = StructType::create(mMod->getContext(), "struct.Basis_bits");
526    }
527    std::vector<Type*>StructTy_struct_Basis_bits_fields;
528    for (int i = 0; i < mBits; i++)
529    {
[4151]530        StructTy_struct_Basis_bits_fields.push_back(mXi64Vect);
[3850]531    }
532    if (StructTy_struct_Basis_bits->isOpaque()) {
533        StructTy_struct_Basis_bits->setBody(StructTy_struct_Basis_bits_fields, /*isPacked=*/false);
534    }
535
536    mStruct_Basis_Bits_Ptr1 = PointerType::get(StructTy_struct_Basis_bits, 0);
537
538    std::vector<Type*>FuncTy_0_args;
539    FuncTy_0_args.push_back(mStruct_Basis_Bits_Ptr1);
540
541    //The carry q array.
[4151]542    FuncTy_0_args.push_back(mXi64Vect_Ptr1);
[3850]543
544    //The output structure.
545    StructType *StructTy_struct_Output = mMod->getTypeByName("struct.Output");
546    if (!StructTy_struct_Output) {
547        StructTy_struct_Output = StructType::create(mMod->getContext(), "struct.Output");
548    }
549    std::vector<Type*>StructTy_struct_Output_fields;
[4151]550    StructTy_struct_Output_fields.push_back(mXi64Vect);
551    StructTy_struct_Output_fields.push_back(mXi64Vect);
[3850]552    if (StructTy_struct_Output->isOpaque()) {
553        StructTy_struct_Output->setBody(StructTy_struct_Output_fields, /*isPacked=*/false);
554    }
555    mStruct_Output_Ptr1 = PointerType::get(StructTy_struct_Output, 0);
556
557    //The &output parameter.
558    FuncTy_0_args.push_back(mStruct_Output_Ptr1);
559
560    mFuncTy_0 = FunctionType::get(
561     /*Result=*/Type::getVoidTy(mMod->getContext()),
562     /*Params=*/FuncTy_0_args,
563     /*isVarArg=*/false);
564}
565
566void LLVM_Generator::DeclareFunctions()
567{
568    //This function can be used for testing to print the contents of a register from JIT'd code to the terminal window.
[4151]569    //mFunc_print_register = mMod->getOrInsertFunction("wrapped_print_register", Type::getVoidTy(getGlobalContext()), mXi64Vect, NULL);
[3983]570    //mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mFunc_print_register), (void *)&wrapped_print_register);
[3940]571    // to call->  b.CreateCall(mFunc_print_register, unicode_category);
572
[4118]573#ifdef USE_UADD_OVERFLOW
[4151]574    // Type Definitions for llvm.uadd.with.overflow.i128 or .i256
[4096]575    std::vector<Type*>StructTy_0_fields;
[4151]576    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
[4096]577    StructTy_0_fields.push_back(IntegerType::get(mMod->getContext(), 1));
578    StructType *StructTy_0 = StructType::get(mMod->getContext(), StructTy_0_fields, /*isPacked=*/false);
579
580    std::vector<Type*>FuncTy_1_args;
[4151]581    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
582    FuncTy_1_args.push_back(IntegerType::get(mMod->getContext(), BLOCK_SIZE));
[4096]583    FunctionType* FuncTy_1 = FunctionType::get(
584                                              /*Result=*/StructTy_0,
585                                              /*Params=*/FuncTy_1_args,
586                                              /*isVarArg=*/false);
587
[4151]588    mFunc_llvm_uadd_with_overflow = mMod->getFunction("llvm.uadd.with.overflow.i" + std::to_string(BLOCK_SIZE));
589    if (!mFunc_llvm_uadd_with_overflow) {
590        mFunc_llvm_uadd_with_overflow = Function::Create(
[4096]591          /*Type=*/FuncTy_1,
592          /*Linkage=*/GlobalValue::ExternalLinkage,
[4151]593          /*Name=*/"llvm.uadd.with.overflow.i" + std::to_string(BLOCK_SIZE), mMod); // (external, no body)
594        mFunc_llvm_uadd_with_overflow->setCallingConv(CallingConv::C);
[4096]595    }
[4151]596    AttributeSet mFunc_llvm_uadd_with_overflow_PAL;
[4096]597    {
598        SmallVector<AttributeSet, 4> Attrs;
599        AttributeSet PAS;
600        {
601          AttrBuilder B;
602          B.addAttribute(Attribute::NoUnwind);
603          B.addAttribute(Attribute::ReadNone);
604          PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
605        }
606
607        Attrs.push_back(PAS);
[4151]608        mFunc_llvm_uadd_with_overflow_PAL = AttributeSet::get(mMod->getContext(), Attrs);
[4096]609    }
[4151]610    mFunc_llvm_uadd_with_overflow->setAttributes(mFunc_llvm_uadd_with_overflow_PAL);
[4118]611#endif
[4096]612
613    //Starts on process_block
[3850]614    SmallVector<AttributeSet, 4> Attrs;
615    AttributeSet PAS;
616    {
617        AttrBuilder B;
618        B.addAttribute(Attribute::ReadOnly);
619        B.addAttribute(Attribute::NoCapture);
620        PAS = AttributeSet::get(mMod->getContext(), 1U, B);
621    }
622    Attrs.push_back(PAS);
623    {
624        AttrBuilder B;
625        B.addAttribute(Attribute::NoCapture);
626        PAS = AttributeSet::get(mMod->getContext(), 2U, B);
627    }
628    Attrs.push_back(PAS);
629    {
630        AttrBuilder B;
631        B.addAttribute(Attribute::NoCapture);
632        PAS = AttributeSet::get(mMod->getContext(), 3U, B);
633    }
634    Attrs.push_back(PAS);
635    {
636        AttrBuilder B;
637        B.addAttribute(Attribute::NoUnwind);
638        B.addAttribute(Attribute::UWTable);
639        PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
640    }
641    AttributeSet AttrSet = AttributeSet::get(mMod->getContext(), Attrs);
642
643    //Create the function that will be generated.
644    mFunc_process_block = mMod->getFunction("process_block");
645    if (!mFunc_process_block) {
646        mFunc_process_block = Function::Create(
647            /*Type=*/mFuncTy_0,
648            /*Linkage=*/GlobalValue::ExternalLinkage,
649            /*Name=*/"process_block", mMod);
650        mFunc_process_block->setCallingConv(CallingConv::C);
651    }
652    mFunc_process_block->setAttributes(AttrSet);
653}
654
[4199]655void LLVM_Generator::DeclareCallFunctions(List stmts) {
656    for (auto it = stmts.begin(); it != stmts.end(); ++it) {
[3982]657        DeclareCallFunctions_PabloS(*it);
658    }
659}
660
[4199]661void LLVM_Generator::DeclareCallFunctions_PabloS(PabloE *stmt)
[3982]662{
[4200]663    if (Assign * an = dyn_cast<Assign>(stmt))
[3982]664    {
665        DeclareCallFunctions_PabloE(an->getExpr());
666    }
[4200]667    else if (If * ifstmt = dyn_cast<If>(stmt))
[3982]668    {
[4124]669        DeclareCallFunctions_PabloE(ifstmt->getExpr());
670        DeclareCallFunctions(ifstmt->getPSList());
671    }
[4200]672    else if (While * whl = dyn_cast<While>(stmt))
[4124]673    {
[3982]674        DeclareCallFunctions_PabloE(whl->getExpr());
675        DeclareCallFunctions(whl->getPSList());
676    }
677}
678
679void LLVM_Generator::DeclareCallFunctions_PabloE(PabloE* expr)
680{
[4200]681    if (Call * pablo_call = dyn_cast<Call>(expr))
[3982]682    {
683        std::string callee = "wrapped_get_category_" + pablo_call->getCallee();
684        if (mMarkerMap.find(callee) == mMarkerMap.end())
685        {
[4151]686            Value* func_get_unicode_category = mMod->getOrInsertFunction(callee, mXi64Vect, mStruct_Basis_Bits_Ptr1, NULL);
[3982]687            void* addr;
688            if (pablo_call->getCallee() == "Ps")
689            {
690                addr = (void *)&wrapped_get_category_Ps;
691            }
692            else if (pablo_call->getCallee() == "Nl")
693            {
694                addr = (void *)&wrapped_get_category_Nl;
695            }
696            else if (pablo_call->getCallee() == "No")
697            {
698                addr = (void *)&wrapped_get_category_No;
699            }
700            else if (pablo_call->getCallee() == "Lo")
701            {
702                addr = (void *)&wrapped_get_category_Lo;
703            }
704            else if (pablo_call->getCallee() == "Ll")
705            {
706                addr = (void *)&wrapped_get_category_Ll;
707            }
708            else if (pablo_call->getCallee() == "Lm")
709            {
710                addr = (void *)&wrapped_get_category_Lm;
711            }
712            else if (pablo_call->getCallee() == "Nd")
713            {
714                addr = (void *)&wrapped_get_category_Nd;
715            }
716            else if (pablo_call->getCallee() == "Pc")
717            {
718                addr = (void *)&wrapped_get_category_Pc;
719            }
720            else if (pablo_call->getCallee() == "Lt")
721            {
722                addr = (void *)&wrapped_get_category_Lt;
723            }
724            else if (pablo_call->getCallee() == "Lu")
725            {
726                addr = (void *)&wrapped_get_category_Lu;
727            }
728            else if (pablo_call->getCallee() == "Pf")
729            {
730                addr = (void *)&wrapped_get_category_Pf;
731            }
732            else if (pablo_call->getCallee() == "Pd")
733            {
734                addr = (void *)&wrapped_get_category_Pd;
735            }
736            else if (pablo_call->getCallee() == "Pe")
737            {
738                addr = (void *)&wrapped_get_category_Pe;
739            }
740            else if (pablo_call->getCallee() == "Pi")
741            {
742                addr = (void *)&wrapped_get_category_Pi;
743            }
744            else if (pablo_call->getCallee() == "Po")
745            {
746                addr = (void *)&wrapped_get_category_Po;
747            }
748            else if (pablo_call->getCallee() == "Me")
749            {
750                addr = (void *)&wrapped_get_category_Me;
751            }
752            else if (pablo_call->getCallee() == "Mc")
753            {
754                addr = (void *)&wrapped_get_category_Mc;
755            }
756            else if (pablo_call->getCallee() == "Mn")
757            {
758                addr = (void *)&wrapped_get_category_Mn;
759            }
760            else if (pablo_call->getCallee() == "Sk")
761            {
762                addr = (void *)&wrapped_get_category_Sk;
763            }
764            else if (pablo_call->getCallee() == "So")
765            {
766                addr = (void *)&wrapped_get_category_So;
767            }
768            else if (pablo_call->getCallee() == "Sm")
769            {
770                addr = (void *)&wrapped_get_category_Sm;
771            }
772            else if (pablo_call->getCallee() == "Sc")
773            {
774                addr = (void *)&wrapped_get_category_Sc;
775            }
776            else if (pablo_call->getCallee() == "Zl")
777            {
778                addr = (void *)&wrapped_get_category_Zl;
779            }
780            else if (pablo_call->getCallee() == "Co")
781            {
782                addr = (void *)&wrapped_get_category_Co;
783            }
784            else if (pablo_call->getCallee() == "Cn")
785            {
786                addr = (void *)&wrapped_get_category_Cn;
787            }
788            else if (pablo_call->getCallee() == "Cc")
789            {
790                addr = (void *)&wrapped_get_category_Cc;
791            }
792            else if (pablo_call->getCallee() == "Cf")
793            {
794                addr = (void *)&wrapped_get_category_Cf;
795            }
796            else if (pablo_call->getCallee() == "Cs")
797            {
798                addr = (void *)&wrapped_get_category_Cs;
799            }
800            else if (pablo_call->getCallee() == "Zp")
801            {
802                addr = (void *)&wrapped_get_category_Zp;
803            }
804            else if (pablo_call->getCallee() == "Zs")
805            {
806                addr = (void *)&wrapped_get_category_Zs;
807            }
808
809            mExecutionEngine->addGlobalMapping(cast<GlobalValue>(func_get_unicode_category), addr);
810            mMarkerMap.insert(make_pair(callee, func_get_unicode_category));
811        }
812    }
[4200]813    else if (And * pablo_and = dyn_cast<And>(expr))
[3982]814    {
815        DeclareCallFunctions_PabloE(pablo_and->getExpr1());
816        DeclareCallFunctions_PabloE(pablo_and->getExpr2());
817    }
[4200]818    else if (Or * pablo_or = dyn_cast<Or>(expr))
[3982]819    {
820        DeclareCallFunctions_PabloE(pablo_or->getExpr1());
821        DeclareCallFunctions_PabloE(pablo_or->getExpr2());
822    }
[4200]823    else if (Sel * pablo_sel = dyn_cast<Sel>(expr))
[3982]824    {
825        DeclareCallFunctions_PabloE(pablo_sel->getIf_expr());
826        DeclareCallFunctions_PabloE(pablo_sel->getT_expr());
827        DeclareCallFunctions_PabloE(pablo_sel->getF_expr());
828    }
[4200]829    else if (Not * pablo_not = dyn_cast<Not>(expr))
[3982]830    {
831        DeclareCallFunctions_PabloE(pablo_not->getExpr());
832    }
[4200]833    else if (Advance * adv = dyn_cast<Advance>(expr))
[3982]834    {
835        DeclareCallFunctions_PabloE(adv->getExpr());
836    }
[4200]837    else if (MatchStar * mstar = dyn_cast<MatchStar>(expr))
[3982]838    {
839        DeclareCallFunctions_PabloE(mstar->getExpr1());
840        DeclareCallFunctions_PabloE(mstar->getExpr2());
841    }
[4200]842    else if (ScanThru * sthru = dyn_cast<ScanThru>(expr))
[3982]843    {
844        DeclareCallFunctions_PabloE(sthru->getScanFrom());
845        DeclareCallFunctions_PabloE(sthru->getScanThru());
846    }
847}
848
[3850]849void LLVM_Generator::MakeLLVMModule()
850{
851    mMod = new Module("icgrep", getGlobalContext());
[4088]852
[3850]853}
854
855void LLVM_Generator::StoreBitBlockMarkerPtr(std::string name, int index)
856{
857    IRBuilder<> b(mBasicBlock);
858
859    Value* basis_bits_struct = b.CreateLoad(mPtr_basis_bits_addr);
860    Value* struct_indices[] = {b.getInt64(0), b.getInt32(index)};
861    Value* basis_bits_struct_GEP = b.CreateGEP(basis_bits_struct, struct_indices, name);
862    mMarkerMap.insert(make_pair(name, basis_bits_struct_GEP));
863}
864
865Value* LLVM_Generator::GetMarker(std::string name)
866{
867    IRBuilder<> b(mBasicBlock);
868
869    if (mMarkerMap.find(name) == mMarkerMap.end())
[4088]870    {
[4151]871        Value* ptr = b.CreateAlloca(mXi64Vect);
872        Value* void_1 = b.CreateStore(mConst_Aggregate_Xi64_0, ptr);
[3850]873        mMarkerMap.insert(make_pair(name, ptr));
874    }
875    std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(name);
876
877    return itGet->second;
878}
879
880void LLVM_Generator::SetReturnMarker(std::string marker, int output_idx)
881{
882    IRBuilder<> b(mBasicBlock);
883
884    Value* marker_bitblock = b.CreateLoad(GetMarker(marker));
885    Value* output_struct = b.CreateLoad(mPtr_output_addr);
886    Value* output_indices[] = {b.getInt64(0), b.getInt32(output_idx)};
887    Value* output_struct_GEP = b.CreateGEP(output_struct, output_indices, "return" + marker);
888    Value* store_marker = b.CreateStore(marker_bitblock, output_struct_GEP);
889}
890
[4199]891std::string LLVM_Generator::Generate_PabloStatements(List stmts) {
[3850]892    std::string retVal = "";
[4199]893    for (auto it = stmts.begin(); it != stmts.end(); ++it) {
[3850]894        retVal = Generate_PabloS(*it);
895    }
896    return retVal;
897}
898
[4199]899std::string LLVM_Generator::Generate_PabloS(PabloE *stmt)
[3850]900{
901    std::string retVal = "";
902
[4200]903    if (Assign * assign = dyn_cast<Assign>(stmt))
[3850]904    {
905        IRBuilder<> b(mBasicBlock);
[4088]906
[3850]907        b.CreateStore(Generate_PabloE(assign->getExpr()), GetMarker(assign->getM()));
[4088]908
[3850]909        retVal = assign->getM();
910    }
[4200]911    else if (If * ifstmt = dyn_cast<If>(stmt))
[4086]912    {
913        BasicBlock*  ifEntryBlock = mBasicBlock;
914        BasicBlock*  ifBodyBlock = BasicBlock::Create(mMod->getContext(), "if.body",mFunc_process_block, 0);
915        BasicBlock*  ifEndBlock = BasicBlock::Create(mMod->getContext(), "if.end",mFunc_process_block, 0);
[4088]916
[4086]917        int if_start_idx = mCarryQueueIdx;
[4088]918
[4086]919        Value* if_test_value = Generate_PabloE(ifstmt->getExpr());
920
921        /* Generate the statements into the if body block, and also determine the
922           final carry index.  */
[4088]923
[4086]924        IRBuilder<> b_ifbody(ifBodyBlock);
925        mBasicBlock = ifBodyBlock;
926        std::string returnMarker = Generate_PabloStatements(ifstmt->getPSList());
927        int if_end_idx = mCarryQueueIdx;
[4088]928
[4086]929        if (if_start_idx < if_end_idx + 1) {
930            // Have at least two internal carries.   Accumulate and store.
931            int if_accum_idx = mCarryQueueIdx;
932            mCarryQueueIdx++;
[4088]933
[4086]934            Value* if_carry_accum_value = genCarryInLoad(mptr_carry_q, if_start_idx);
[4088]935
[4086]936            for (int c = if_start_idx+1; c < if_end_idx; c++)
937            {
938                Value* carryq_value = genCarryInLoad(mptr_carry_q, c);
939                if_carry_accum_value = b_ifbody.CreateOr(carryq_value, if_carry_accum_value);
940            }
[4200]941            genCarryOutStore(if_carry_accum_value, mptr_carry_q, if_accum_idx);
[4088]942
[4086]943        }
944        b_ifbody.CreateBr(ifEndBlock);
[4088]945
[4086]946        IRBuilder<> b_entry(ifEntryBlock);
947        mBasicBlock = ifEntryBlock;
948        if (if_start_idx < if_end_idx) {
949            // Have at least one internal carry.
950            int if_accum_idx = mCarryQueueIdx - 1;
951            Value* last_if_pending_carries = genCarryInLoad(mptr_carry_q, if_accum_idx);
952            if_test_value = b_entry.CreateOr(if_test_value, last_if_pending_carries);
953        }
954        b_entry.CreateCondBr(genBitBlockAny(if_test_value), ifEndBlock, ifBodyBlock);
[4088]955
[4086]956        mBasicBlock = ifEndBlock;
957
958        retVal = returnMarker;
959    }
[4200]960    else if (While* whl = dyn_cast<While>(stmt))
[3850]961    {
962        int idx = mCarryQueueIdx;
963
[3914]964        //With this call to the while body we will account for all of the carry in values.
[3850]965        std::string returnMarker = Generate_PabloStatements(whl->getPSList());
966
[3914]967        BasicBlock*  whileCondBlock = BasicBlock::Create(mMod->getContext(), "while.cond", mFunc_process_block, 0);
968        BasicBlock*  whileBodyBlock = BasicBlock::Create(mMod->getContext(), "while.body",mFunc_process_block, 0);
969        BasicBlock*  whileEndBlock = BasicBlock::Create(mMod->getContext(), "while.end",mFunc_process_block, 0);
[3850]970
[3914]971        IRBuilder<> b(mBasicBlock);
972        b.CreateBr(whileCondBlock);
973        mBasicBlock = whileCondBlock;
974        IRBuilder<> b_cond(whileCondBlock);
975
[3850]976        Value* expression_marker_value = Generate_PabloE(whl->getExpr());
[4151]977        Value* int_tobool1 = genBitBlockAny(expression_marker_value);
978
[3914]979        b_cond.CreateCondBr(int_tobool1, whileEndBlock, whileBodyBlock);
[3850]980
[3914]981        mBasicBlock = whileBodyBlock;
982        mCarryQueueIdx = 0;
983        //Store the current carry queue.
984        Value* ptr_last_carry_q = mptr_carry_q;
[3850]985
[3914]986        IRBuilder<> b_wb1(mBasicBlock);
987        //Create and initialize a new carry queue.
[4151]988        Value* ptr_while_carry_q = b_wb1.CreateAlloca(mXi64Vect, b_wb1.getInt64(mCarryQueueSize - idx));
[4200]989        for (int i=0; i < (mCarryQueueSize - idx); i++)
[3914]990        {
[4200]991            genCarryOutStore(mConst_Aggregate_Xi64_0, ptr_while_carry_q, i);
[3914]992        }
993
994        //Point mptr_carry_q to the new local carry queue.
995        mptr_carry_q = ptr_while_carry_q;
996
[3850]997        returnMarker = Generate_PabloStatements(whl->getPSList());
998
[3914]999        IRBuilder<> b_wb2(mBasicBlock);
1000        //Copy back to the last carry queue the carries from the execution of the while statement list.
[4200]1001        for (int c = 0; c < (mCarryQueueSize - idx); c++)
[3914]1002        {
[4085]1003            Value* new_carryq_value = b_wb2.CreateOr(genCarryInLoad(mptr_carry_q, c), genCarryInLoad(ptr_last_carry_q, idx + c));
[4200]1004            genCarryOutStore(new_carryq_value, ptr_last_carry_q, idx + c);
[3914]1005        }
1006
1007        b_wb2.CreateBr(whileCondBlock);
1008
1009        mBasicBlock = whileEndBlock;
1010        mptr_carry_q = ptr_last_carry_q;
1011        mCarryQueueIdx += idx;
1012
[3850]1013        retVal = returnMarker;
1014    }
1015
1016    return retVal;
1017}
1018
1019Value* LLVM_Generator::Generate_PabloE(PabloE *expr)
1020{
1021    Value* retVal = 0;
1022
[4200]1023    if (All* all = dyn_cast<All>(expr))
[3850]1024    {
1025        IRBuilder<> b(mBasicBlock);
[4151]1026        Value* ptr_all = b.CreateAlloca(mXi64Vect);
[4200]1027        b.CreateStore((all->getValue() == 0 ? mConst_Aggregate_Xi64_0 : mConst_Aggregate_Xi64_neg1), ptr_all);
[3850]1028        Value* all_value = b.CreateLoad(ptr_all);
1029        retVal = all_value;
1030    }
[4200]1031    else if (Call* call = dyn_cast<Call>(expr))
[3940]1032    {
1033        IRBuilder<> b(mBasicBlock);
1034
[3941]1035        //Call the callee once and store the result in the marker map.
[3940]1036        if (mMarkerMap.find(call->getCallee()) == mMarkerMap.end())
1037        {
[3982]1038            std::map<std::string, Value*>::iterator itFuncGet = mMarkerMap.find("wrapped_get_category_" + call->getCallee());
[3965]1039            Value* basis_bits_struct = b.CreateLoad(mPtr_basis_bits_addr);
[3982]1040            Value* unicode_category = b.CreateCall(itFuncGet->second, basis_bits_struct);
[4151]1041            Value* ptr = b.CreateAlloca(mXi64Vect);
[3940]1042            Value* void_1 = b.CreateStore(unicode_category, ptr);
1043
1044            mMarkerMap.insert(make_pair(call->getCallee(), ptr));
1045        }
1046        std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(call->getCallee());
1047        Value * var_value = b.CreateLoad(itGet->second);
1048
[3969]1049
[3940]1050        retVal = var_value;
1051    }
[4200]1052    else if (Var * var = dyn_cast<Var>(expr))
[3850]1053    {
1054        IRBuilder<> b(mBasicBlock);
1055
1056        Value* var_value = b.CreateLoad(GetMarker(var->getVar()), false, var->getVar());
1057
1058        retVal = var_value;
1059    }
[4200]1060    else if (And * pablo_and = dyn_cast<And>(expr))
[3850]1061    {
1062        IRBuilder<> b(mBasicBlock);
1063
1064        Value* and_result = b.CreateAnd(Generate_PabloE(pablo_and->getExpr1()), Generate_PabloE(pablo_and->getExpr2()), "and_inst");
1065
1066        retVal = and_result;
1067    }
[4200]1068    else if (Or * pablo_or = dyn_cast<Or>(expr))
[3850]1069    {
1070        IRBuilder<> b(mBasicBlock);
1071
1072        Value* or_result = b.CreateOr(Generate_PabloE(pablo_or->getExpr1()), Generate_PabloE(pablo_or->getExpr2()), "or_inst");
1073
1074        retVal = or_result;
1075    }
[4200]1076    else if (Sel * pablo_sel = dyn_cast<Sel>(expr))
[3850]1077    {
1078        IRBuilder<>b(mBasicBlock);
[4002]1079        Value* ifMask = Generate_PabloE(pablo_sel->getIf_expr());
1080        Value* and_if_true_result = b.CreateAnd(ifMask, Generate_PabloE(pablo_sel->getT_expr()));
1081        Value* and_if_false_result = b.CreateAnd(genNot(ifMask), Generate_PabloE(pablo_sel->getF_expr()));
[3850]1082        Value* or_result = b.CreateOr(and_if_true_result, and_if_false_result);
1083
1084        retVal = or_result;
1085    }
[4200]1086    else if (Not * pablo_not = dyn_cast<Not>(expr))
[3850]1087    {
1088        IRBuilder<> b(mBasicBlock);
1089
1090        Value* expr_value = Generate_PabloE(pablo_not->getExpr());
[4151]1091        Value* xor_rslt = b.CreateXor(expr_value, mConst_Aggregate_Xi64_neg1, "xor_inst");
[3850]1092
1093        retVal = xor_rslt;
1094    }
[4200]1095    else if (CharClass * cc = dyn_cast<CharClass>(expr))
[3850]1096    {
1097        IRBuilder<> b(mBasicBlock);
1098
1099        Value* character_class = b.CreateLoad(GetMarker(cc->getCharClass()));
1100
1101        retVal = character_class;
1102    }
[4200]1103    else if (Advance * adv = dyn_cast<Advance>(expr))
[3850]1104    {
1105        IRBuilder<> b(mBasicBlock);
1106        Value* strm_value = Generate_PabloE(adv->getExpr());
[4151]1107        retVal = genAdvanceWithCarry(strm_value);
[3850]1108    }
[4200]1109    else if (MatchStar * mstar = dyn_cast<MatchStar>(expr))
[3850]1110    {
1111        IRBuilder<> b(mBasicBlock);
1112        Value* strm_value = Generate_PabloE(mstar->getExpr1());
[3999]1113        Value* cc_value = Generate_PabloE(mstar->getExpr2());
1114        retVal = genMatchStar(strm_value, cc_value);
[3850]1115    }
[4200]1116    else if (ScanThru * sthru = dyn_cast<ScanThru>(expr))
[3955]1117    {
1118        IRBuilder<> b(mBasicBlock);
1119        Value* strm_value = Generate_PabloE(sthru->getScanFrom());
1120        Value* scanthru_value = Generate_PabloE(sthru->getScanThru());
[3999]1121        retVal = genScanThru(strm_value, scanthru_value);
[3955]1122    }
1123
[3850]1124    return retVal;
1125}
1126
[3999]1127
1128Value* LLVM_Generator::genMatchStar(Value* marker_expr, Value* cc_expr) {
1129    IRBuilder<> b(mBasicBlock);
1130    Value* marker_and_cc = b.CreateAnd(marker_expr, cc_expr);
1131    return b.CreateOr(b.CreateXor(genAddWithCarry(marker_and_cc, cc_expr), cc_expr), marker_expr, "matchstar_rslt");
1132}
1133
1134Value* LLVM_Generator::genScanThru(Value* marker_expr, Value* cc_expr) {
1135    IRBuilder<> b(mBasicBlock);
1136    return b.CreateAnd(genAddWithCarry(marker_expr, cc_expr), genNot(cc_expr), "scanthru_rslt");
1137}
1138
[4117]1139#ifdef USE_UADD_OVERFLOW
[4151]1140SumWithOverflowPack LLVM_Generator::callUaddOverflow(Value* int128_e1, Value* int128_e2) {
[4096]1141    std::vector<Value*> struct_res_params;
1142    struct_res_params.push_back(int128_e1);
1143    struct_res_params.push_back(int128_e2);
[4151]1144    CallInst* struct_res = CallInst::Create(mFunc_llvm_uadd_with_overflow, struct_res_params, "uadd_overflow_res", mBasicBlock);
[4096]1145    struct_res->setCallingConv(CallingConv::C);
1146    struct_res->setTailCall(false);
1147    AttributeSet struct_res_PAL;
1148    struct_res->setAttributes(struct_res_PAL);
1149
1150    SumWithOverflowPack ret;
1151
1152    std::vector<unsigned> int128_sum_indices;
1153    int128_sum_indices.push_back(0);
1154    ret.sum = ExtractValueInst::Create(struct_res, int128_sum_indices, "sum", mBasicBlock);
1155
1156    std::vector<unsigned> int1_obit_indices;
1157    int1_obit_indices.push_back(1);
1158    ret.obit = ExtractValueInst::Create(struct_res, int1_obit_indices, "obit", mBasicBlock);
1159
1160    return ret;
1161}
[4117]1162#endif
[4096]1163
[3999]1164Value* LLVM_Generator::genAddWithCarry(Value* e1, Value* e2) {
1165    IRBuilder<> b(mBasicBlock);
[4088]1166
[3999]1167    //CarryQ - carry in.
[4085]1168    int this_carry_idx = mCarryQueueIdx;
1169    mCarryQueueIdx++;
[4088]1170
[4085]1171    Value* carryq_value = genCarryInLoad(mptr_carry_q, this_carry_idx);
[3999]1172
[4117]1173#ifdef USE_UADD_OVERFLOW
[4151]1174    //use llvm.uadd.with.overflow.i128 or i256
[4137]1175
[4151]1176    CastInst* int128_e1 = new BitCastInst(e1, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e1_128", mBasicBlock);
1177    CastInst* int128_e2 = new BitCastInst(e2, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "e2_128", mBasicBlock);
1178    CastInst* int128_carryq_value = new BitCastInst(carryq_value, IntegerType::get(mMod->getContext(), BLOCK_SIZE), "carryq_128", mBasicBlock);
[3999]1179
[4096]1180    SumWithOverflowPack sumpack0, sumpack1;
[4088]1181
[4151]1182    sumpack0 = callUaddOverflow(int128_e1, int128_e2);
1183    sumpack1 = callUaddOverflow(sumpack0.sum, int128_carryq_value);
[4096]1184
1185    Value* obit = b.CreateOr(sumpack0.obit, sumpack1.obit, "carry_bit");
[4151]1186    Value* ret_sum = b.CreateBitCast(sumpack1.sum, mXi64Vect, "ret_sum");
[4096]1187
[4151]1188    /*obit is the i1 carryout, zero extend and insert it into a v2i64 or v4i64 vector.*/
1189    ConstantAggregateZero* const_packed_5 = ConstantAggregateZero::get(mXi64Vect);
[4096]1190    ConstantInt* const_int32_6 = ConstantInt::get(mMod->getContext(), APInt(32, StringRef("0"), 10));
1191    CastInst* int64_o0 = new ZExtInst(obit, IntegerType::get(mMod->getContext(), 64), "o0", mBasicBlock);
1192    InsertElementInst* carry_out = InsertElementInst::Create(const_packed_5, int64_o0, const_int32_6, "carry_out", mBasicBlock);
1193
[4085]1194    Value* void_1 = genCarryOutStore(carry_out, mptr_carry_q, this_carry_idx);
[4096]1195    return ret_sum;
[4118]1196#else
1197    //calculate carry through logical ops
[4117]1198    Value* carrygen = b.CreateAnd(e1, e2, "carrygen");
1199    Value* carryprop = b.CreateOr(e1, e2, "carryprop");
1200    Value* digitsum = b.CreateAdd(e1, e2, "digitsum");
1201    Value* partial = b.CreateAdd(digitsum, carryq_value, "partial");
1202    Value* digitcarry = b.CreateOr(carrygen, b.CreateAnd(carryprop, genNot(partial)));
1203    Value* mid_carry_in = genShiftLeft64(b.CreateLShr(digitcarry, 63), "mid_carry_in");
[4096]1204
[4117]1205    Value* sum = b.CreateAdd(partial, mid_carry_in, "sum");
[4151]1206    Value* carry_out = genShiftHighbitToLow(b.CreateOr(carrygen, b.CreateAnd(carryprop, genNot(sum))), "carry_out");
[4117]1207    Value* void_1 = genCarryOutStore(carry_out, mptr_carry_q, this_carry_idx);
[4096]1208
[4117]1209    return sum;
1210#endif
[3999]1211}
1212
[4085]1213Value* LLVM_Generator::genCarryInLoad(Value* ptr_carry_q, int n) {
[4003]1214    IRBuilder<> b(mBasicBlock);
[4085]1215    Value* carryq_idx = b.getInt64(n);
1216    Value* carryq_GEP = b.CreateGEP(ptr_carry_q, carryq_idx);
1217    return b.CreateLoad(carryq_GEP);
[4003]1218}
[3999]1219
[4085]1220Value* LLVM_Generator::genCarryOutStore(Value* carryout, Value* ptr_carry_q, int n ) {
1221    IRBuilder<> b(mBasicBlock);
1222    Value* carryq_idx = b.getInt64(n);
1223    Value* carryq_GEP = b.CreateGEP(ptr_carry_q, carryq_idx);
1224    return b.CreateStore(carryout, carryq_GEP);
1225}
[4002]1226
[4085]1227Value* LLVM_Generator::genBitBlockAny(Value* e) {
1228    IRBuilder<> b(mBasicBlock);
[4151]1229    Value* cast_marker_value_1 = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
1230    return b.CreateICmpEQ(cast_marker_value_1, ConstantInt::get(IntegerType::get(mMod->getContext(), BLOCK_SIZE), 0));
[4085]1231}
[4003]1232
[4151]1233Value* LLVM_Generator::genShiftHighbitToLow(Value* e, const Twine &namehint) {
[3999]1234    IRBuilder<> b(mBasicBlock);
[4151]1235    Value* i128_val = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
1236    return b.CreateBitCast(b.CreateLShr(i128_val, BLOCK_SIZE - 1, namehint), bitBlockExprType);
[3999]1237}
1238
1239Value* LLVM_Generator::genShiftLeft64(Value* e, const Twine &namehint) {
1240    IRBuilder<> b(mBasicBlock);
[4151]1241    Value* i128_val = b.CreateBitCast(e, IntegerType::get(mMod->getContext(), BLOCK_SIZE));
[3999]1242    return b.CreateBitCast(b.CreateShl(i128_val, 64, namehint), bitBlockExprType);
1243}
1244
1245Value* LLVM_Generator::genNot(Value* e, const Twine &namehint) {
1246    IRBuilder<> b(mBasicBlock);
[4151]1247    return b.CreateXor(e, mConst_Aggregate_Xi64_neg1, namehint);
[3999]1248}
1249
[4151]1250Value* LLVM_Generator::genAdvanceWithCarry(Value* strm_value) {
1251    IRBuilder<> b(mBasicBlock);
[3999]1252
[4151]1253#if (BLOCK_SIZE == 128)
1254    int this_carry_idx = mCarryQueueIdx;
1255    mCarryQueueIdx++;
[3999]1256
[4151]1257    Value* carryq_value = genCarryInLoad(mptr_carry_q, this_carry_idx);
[3999]1258
[4151]1259    Value* srli_1_value = b.CreateLShr(strm_value, 63);
1260
1261    Value* packed_shuffle;
1262    Constant* const_packed_1_elems [] = {b.getInt32(0), b.getInt32(2)};
1263    Constant* const_packed_1 = ConstantVector::get(const_packed_1_elems);
1264    packed_shuffle = b.CreateShuffleVector(carryq_value, srli_1_value, const_packed_1, "packed_shuffle nw");
1265
1266    Constant* const_packed_2_elems[] = {b.getInt64(1), b.getInt64(1)};
1267    Constant* const_packed_2 = ConstantVector::get(const_packed_2_elems);
1268
1269    Value* shl_value = b.CreateShl(strm_value, const_packed_2, "shl_value");
1270    Value* result_value = b.CreateOr(shl_value, packed_shuffle, "or.result_value");
1271
1272    Value* carry_out = genShiftHighbitToLow(strm_value, "carry_out");
1273    //CarryQ - carry out:
1274    Value* void_1 = genCarryOutStore(carry_out, mptr_carry_q, this_carry_idx);
1275
1276    return result_value;
1277#endif
1278
1279#if (BLOCK_SIZE == 256)
1280    return genAddWithCarry(strm_value, strm_value);
1281#endif
1282}
1283
1284
Note: See TracBrowser for help on using the repository browser.