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

Last change on this file since 4137 was 4137, checked in by linmengl, 5 years ago

move USE_UADD_OVERFLOW to llvm_gen.h: it doesn't work in icgrep.cpp; add abc_test in 'make check';

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