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

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

Minor changes; moved printers to re and pablo folders.

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