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

Last change on this file since 3956 was 3956, checked in by daled, 5 years ago

Matchstar for utf-8 character classes works. Needs refactoring.

File size: 23.2 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#include "printer_pablos.h"
9
10extern "C" {
11  void wrapped_print_register(BitBlock bit_block) {
12      print_register<BitBlock>("", bit_block);
13  }
14}
15
16extern "C" {
17    BitBlock wrapped_get_unicode_category(const char* name){
18        return Unicode_Categories::getCategory(name);
19    }
20}
21
22BitBlock LLVM_Generator::Get_UnicodeCategory(const char *name)
23{
24    return Unicode_Categories::getCategory(name);
25}
26
27void LLVM_Generator::Print_Register(char *name, BitBlock bit_block)
28{
29    print_register<BitBlock>(name, bit_block);
30}
31
32LLVM_Generator::LLVM_Generator(std::map<std::string, std::string> name_map, std::string basis_pattern, int bits)
33{
34    m_name_map = name_map;
35    mBasis_Pattern = basis_pattern;
36    mBits = bits;
37}
38
39LLVM_Generator::~LLVM_Generator()
40{
41    delete mMod;
42}
43
44LLVM_Gen_RetVal LLVM_Generator::Generate_LLVMIR(CodeGenState cg_state, CodeGenState subexpression_cg_state, std::list<PabloS*> cc_cgo_stmtsl)
45{
46    //Create the module.
47    MakeLLVMModule();
48
49    //Create the jit execution engine.up
50    InitializeNativeTarget();
51    std::string ErrStr;
52
53    mExecutionEngine = EngineBuilder(mMod).setUseMCJIT(true).setErrorStr(&ErrStr).setOptLevel(CodeGenOpt::Level::Less).create();
54    if (!mExecutionEngine)
55    {
56        std::cout << "\nCould not create ExecutionEngine: " + ErrStr << std::endl;
57        exit(1);
58    }
59
60    InitializeNativeTargetAsmPrinter();
61    InitializeNativeTargetAsmParser();
62
63    DefineTypes();
64    DeclareFunctions();
65
66    Function::arg_iterator args = mFunc_process_block->arg_begin();
67    Value* ptr_basis_bits = args++;
68    ptr_basis_bits->setName("basis_bits");
69    mptr_carry_q = args++;
70    mptr_carry_q->setName("carry_q");
71    Value* ptr_output = args++;
72    ptr_output->setName("output");
73
74    //Create the carry queue.
75    mCarryQueueIdx = 0;
76    mCarryQueueSize = LLVM_Generator_Helper::CarryCount_PabloStatements(subexpression_cg_state.stmtsl);
77    mCarryQueueSize += LLVM_Generator_Helper::CarryCount_PabloStatements(cg_state.stmtsl);
78
79    mBasicBlock = BasicBlock::Create(mMod->getContext(), "parabix_entry", mFunc_process_block,0);
80
81    //The basis bits structure
82    mPtr_basis_bits_addr = new AllocaInst(mStruct_Basis_Bits_Ptr1, "basis_bits.addr", mBasicBlock);
83    StoreInst* void_14 = new StoreInst(ptr_basis_bits, mPtr_basis_bits_addr, false, mBasicBlock);
84
85    for (int i = 0; i < mBits; i++)
86    {
87        StoreBitBlockMarkerPtr(mBasis_Pattern + INT2STRING(i), i);
88    }
89
90    //The output structure.
91    mPtr_output_addr = new AllocaInst(mStruct_Output_Ptr1, "output.addr", mBasicBlock);
92    StoreInst* void_16 = new StoreInst(ptr_output, mPtr_output_addr, false, mBasicBlock);
93
94    //Generate the IR instructions for the function.
95
96    Generate_PabloStatements(cc_cgo_stmtsl);
97    Generate_PabloStatements(subexpression_cg_state.stmtsl);
98    Generate_PabloStatements(cg_state.stmtsl);
99    SetReturnMarker(cg_state.newsym, 0);
100    SetReturnMarker(m_name_map.find("LineFeed")->second, 1);
101
102    //Terminate the block
103    ReturnInst::Create(mMod->getContext(), mBasicBlock);
104
105    //Create a verifier.  The verifier will print an error message if our module is malformed in any way.
106    verifyModule(*mMod, PrintMessageAction);
107
108    //Un-comment this line in order to display the IR that has been generated by this module.
109    //mMod->dump();
110
111    //Use the pass manager to run optimizations on the function.
112    FunctionPassManager fpm(mMod);
113
114    // Set up the optimizer pipeline.  Start with registering info about how the target lays out data structures.
115    fpm.add(new DataLayout(*mExecutionEngine->getDataLayout()));
116
117    fpm.add(createPromoteMemoryToRegisterPass()); //Transform to SSA form.
118
119    fpm.add(createBasicAliasAnalysisPass());      //Provide basic AliasAnalysis support for GVN. (Global Value Numbering)
120    fpm.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
121    fpm.add(createCFGSimplificationPass());       //Simplify the control flow graph (deleting unreachable blocks, etc).
122    fpm.add(createReassociatePass());             //Reassociate expressions.
123    fpm.add(createGVNPass());                     //Eliminate common subexpressions.
124
125    fpm.doInitialization();
126
127    fpm.run(*mFunc_process_block);
128
129    //mMod->dump();
130
131    mExecutionEngine->finalizeObject();
132
133    LLVM_Gen_RetVal retVal;
134    //Return the required size of the carry queue and a pointer to the process_block function.
135    retVal.carry_q_size = mCarryQueueSize;
136    retVal.process_block_fptr = mExecutionEngine->getPointerToFunction(mFunc_process_block);
137
138    return retVal;
139}
140
141void LLVM_Generator::DefineTypes()
142{
143    //The BitBlock vector.
144    m64x2Vect = VectorType::get(IntegerType::get(mMod->getContext(), 64), 2);
145    m128x1Vect = VectorType::get(IntegerType::get(mMod->getContext(), 128), 1);
146    //A pointer to the BitBlock vector.
147    m64x2Vect_Ptr1 = PointerType::get(m64x2Vect, 0);
148
149    //Constant definitions.
150    mConst_int64_neg1 = ConstantInt::get(mMod->getContext(), APInt(64, StringRef("-1"), 10));
151
152    mConst_Aggregate_64x2_0 = ConstantAggregateZero::get(m64x2Vect);
153    std::vector<Constant*> const_packed_27_elems;
154    const_packed_27_elems.push_back(mConst_int64_neg1);
155    const_packed_27_elems.push_back(mConst_int64_neg1);
156    mConst_Aggregate_64x2_neg1 = ConstantVector::get(const_packed_27_elems);
157
158
159    StructType *StructTy_struct_Basis_bits = mMod->getTypeByName("struct.Basis_bits");
160    if (!StructTy_struct_Basis_bits) {
161        StructTy_struct_Basis_bits = StructType::create(mMod->getContext(), "struct.Basis_bits");
162    }
163    std::vector<Type*>StructTy_struct_Basis_bits_fields;
164    for (int i = 0; i < mBits; i++)
165    {
166        StructTy_struct_Basis_bits_fields.push_back(m64x2Vect);
167    }
168    if (StructTy_struct_Basis_bits->isOpaque()) {
169        StructTy_struct_Basis_bits->setBody(StructTy_struct_Basis_bits_fields, /*isPacked=*/false);
170    }
171
172    mStruct_Basis_Bits_Ptr1 = PointerType::get(StructTy_struct_Basis_bits, 0);
173
174    std::vector<Type*>FuncTy_0_args;
175    FuncTy_0_args.push_back(mStruct_Basis_Bits_Ptr1);
176
177    //The carry q array.
178    FuncTy_0_args.push_back(m64x2Vect_Ptr1);
179
180    //The output structure.
181    StructType *StructTy_struct_Output = mMod->getTypeByName("struct.Output");
182    if (!StructTy_struct_Output) {
183        StructTy_struct_Output = StructType::create(mMod->getContext(), "struct.Output");
184    }
185    std::vector<Type*>StructTy_struct_Output_fields;
186    StructTy_struct_Output_fields.push_back(m64x2Vect);
187    StructTy_struct_Output_fields.push_back(m64x2Vect);
188    if (StructTy_struct_Output->isOpaque()) {
189        StructTy_struct_Output->setBody(StructTy_struct_Output_fields, /*isPacked=*/false);
190    }
191    mStruct_Output_Ptr1 = PointerType::get(StructTy_struct_Output, 0);
192
193    //The &output parameter.
194    FuncTy_0_args.push_back(mStruct_Output_Ptr1);
195
196    mFuncTy_0 = FunctionType::get(
197     /*Result=*/Type::getVoidTy(mMod->getContext()),
198     /*Params=*/FuncTy_0_args,
199     /*isVarArg=*/false);
200}
201
202void LLVM_Generator::DeclareFunctions()
203{
204    mFunc_get_unicode_category = mMod->getOrInsertFunction("wrapped_get_unicode_category", m64x2Vect, Type::getInt8PtrTy(mMod->getContext()), NULL);
205    mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mFunc_get_unicode_category), (void *)&wrapped_get_unicode_category);
206
207    //This function can be used for testing to print the contents of a register from JIT'd code to the terminal window.
208    mFunc_print_register = mMod->getOrInsertFunction("wrapped_print_register", Type::getVoidTy(getGlobalContext()), m64x2Vect, NULL);
209
210    mExecutionEngine->addGlobalMapping(cast<GlobalValue>(mFunc_print_register), (void *)&wrapped_print_register);
211    // to call->  b.CreateCall(mFunc_print_register, unicode_category);
212
213    SmallVector<AttributeSet, 4> Attrs;
214    AttributeSet PAS;
215    {
216        AttrBuilder B;
217        B.addAttribute(Attribute::ReadOnly);
218        B.addAttribute(Attribute::NoCapture);
219        PAS = AttributeSet::get(mMod->getContext(), 1U, B);
220    }
221    Attrs.push_back(PAS);
222    {
223        AttrBuilder B;
224        B.addAttribute(Attribute::NoCapture);
225        PAS = AttributeSet::get(mMod->getContext(), 2U, B);
226    }
227    Attrs.push_back(PAS);
228    {
229        AttrBuilder B;
230        B.addAttribute(Attribute::NoCapture);
231        PAS = AttributeSet::get(mMod->getContext(), 3U, B);
232    }
233    Attrs.push_back(PAS);
234    {
235        AttrBuilder B;
236        B.addAttribute(Attribute::NoUnwind);
237        B.addAttribute(Attribute::UWTable);
238        PAS = AttributeSet::get(mMod->getContext(), ~0U, B);
239    }
240    AttributeSet AttrSet = AttributeSet::get(mMod->getContext(), Attrs);
241
242    //Create the function that will be generated.
243    mFunc_process_block = mMod->getFunction("process_block");
244    if (!mFunc_process_block) {
245        mFunc_process_block = Function::Create(
246            /*Type=*/mFuncTy_0,
247            /*Linkage=*/GlobalValue::ExternalLinkage,
248            /*Name=*/"process_block", mMod);
249        mFunc_process_block->setCallingConv(CallingConv::C);
250    }
251    mFunc_process_block->setAttributes(AttrSet);
252}
253
254void LLVM_Generator::MakeLLVMModule()
255{
256    mMod = new Module("icgrep", getGlobalContext());
257    mMod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
258    mMod->setTargetTriple("x86_64-unknown-linux-gnu");
259}
260
261void LLVM_Generator::StoreBitBlockMarkerPtr(std::string name, int index)
262{
263    IRBuilder<> b(mBasicBlock);
264
265    Value* basis_bits_struct = b.CreateLoad(mPtr_basis_bits_addr);
266    Value* struct_indices[] = {b.getInt64(0), b.getInt32(index)};
267    Value* basis_bits_struct_GEP = b.CreateGEP(basis_bits_struct, struct_indices, name);
268    mMarkerMap.insert(make_pair(name, basis_bits_struct_GEP));
269}
270
271Value* LLVM_Generator::GetMarker(std::string name)
272{
273    IRBuilder<> b(mBasicBlock);
274
275    if (mMarkerMap.find(name) == mMarkerMap.end())
276    {       
277        Value* ptr = b.CreateAlloca(m64x2Vect);
278        Value* void_1 = b.CreateStore(mConst_Aggregate_64x2_0, ptr);
279        mMarkerMap.insert(make_pair(name, ptr));
280    }
281    std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(name);
282
283    return itGet->second;
284}
285
286void LLVM_Generator::SetReturnMarker(std::string marker, int output_idx)
287{
288    IRBuilder<> b(mBasicBlock);
289
290    Value* marker_bitblock = b.CreateLoad(GetMarker(marker));
291    Value* output_struct = b.CreateLoad(mPtr_output_addr);
292    Value* output_indices[] = {b.getInt64(0), b.getInt32(output_idx)};
293    Value* output_struct_GEP = b.CreateGEP(output_struct, output_indices, "return" + marker);
294    Value* store_marker = b.CreateStore(marker_bitblock, output_struct_GEP);
295}
296
297std::string LLVM_Generator::Generate_PabloStatements(std::list<PabloS*> stmts)
298{
299    std::string retVal = "";
300
301    std::list<PabloS*>::iterator it;
302    for (it = stmts.begin(); it != stmts.end(); ++it)
303    {
304        retVal = Generate_PabloS(*it);
305    }
306
307    return retVal;
308}
309
310std::string LLVM_Generator::Generate_PabloS(PabloS *stmt)
311{
312    std::string retVal = "";
313
314    if (Assign* assign = dynamic_cast<Assign*>(stmt))
315    {
316        IRBuilder<> b(mBasicBlock);
317
318        b.CreateStore(Generate_PabloE(assign->getExpr()), GetMarker(assign->getM()));
319
320        retVal = assign->getM();
321    }
322    else if (While* whl = dynamic_cast<While*>(stmt))
323    {
324        int idx = mCarryQueueIdx;
325
326        //With this call to the while body we will account for all of the carry in values.
327        std::string returnMarker = Generate_PabloStatements(whl->getPSList());
328
329        BasicBlock*  whileCondBlock = BasicBlock::Create(mMod->getContext(), "while.cond", mFunc_process_block, 0);
330        BasicBlock*  whileBodyBlock = BasicBlock::Create(mMod->getContext(), "while.body",mFunc_process_block, 0);
331        BasicBlock*  whileEndBlock = BasicBlock::Create(mMod->getContext(), "while.end",mFunc_process_block, 0);
332
333        IRBuilder<> b(mBasicBlock);
334        b.CreateBr(whileCondBlock);
335        mBasicBlock = whileCondBlock;
336        IRBuilder<> b_cond(whileCondBlock);
337
338        Value* expression_marker_value = Generate_PabloE(whl->getExpr());
339        // Use an i128 compare for simplicity and speed.
340        Value* cast_marker_value_1 = b_cond.CreateBitCast(expression_marker_value, IntegerType::get(mMod->getContext(), 128));
341        Value* int_tobool1 = b_cond.CreateICmpEQ(cast_marker_value_1, ConstantInt::get(IntegerType::get(mMod->getContext(), 128), 0));
342        b_cond.CreateCondBr(int_tobool1, whileEndBlock, whileBodyBlock);
343
344        mBasicBlock = whileBodyBlock;
345        mCarryQueueIdx = 0;
346        //Store the current carry queue.
347        Value* ptr_last_carry_q = mptr_carry_q;
348
349        IRBuilder<> b_wb1(mBasicBlock);
350        //Create and initialize a new carry queue.
351        Value* ptr_while_carry_q = b_wb1.CreateAlloca(m64x2Vect, b_wb1.getInt64(mCarryQueueSize - idx));
352        for (int i=0; i<(mCarryQueueSize-idx); i++)
353        {
354            Value* carryq_idx1 = b_wb1.getInt64(i);
355            Value* carryq_GEP1 = b_wb1.CreateGEP(ptr_while_carry_q, carryq_idx1);
356            Value* void_1 = b_wb1.CreateStore(mConst_Aggregate_64x2_0, carryq_GEP1);
357        }
358
359        //Point mptr_carry_q to the new local carry queue.
360        mptr_carry_q = ptr_while_carry_q;
361
362        returnMarker = Generate_PabloStatements(whl->getPSList());
363
364        IRBuilder<> b_wb2(mBasicBlock);
365        //Copy back to the last carry queue the carries from the execution of the while statement list.
366        for (int c=0; c<(mCarryQueueSize-idx); c++)
367        {
368            Value* carryq_idx = b_wb2.getInt64(c);
369            Value* carryq_GEP = b_wb2.CreateGEP(mptr_carry_q, carryq_idx);
370            Value* carryq_value = b_wb2.CreateLoad(carryq_GEP);
371
372            Value* last_carryq_idx = b_wb2.getInt64(idx + c);
373            Value* last_carryq_GEP = b_wb2.CreateGEP(ptr_last_carry_q, last_carryq_idx);
374            Value* last_carryq_value = b_wb2.CreateLoad(last_carryq_GEP);
375
376            Value* new_carryq_value = b_wb2.CreateOr(carryq_value, last_carryq_value);
377            Value* void_1 = b_wb2.CreateStore(new_carryq_value, last_carryq_GEP);
378        }
379
380        b_wb2.CreateBr(whileCondBlock);
381
382        mBasicBlock = whileEndBlock;
383        mptr_carry_q = ptr_last_carry_q;
384        mCarryQueueIdx += idx;
385
386        retVal = returnMarker;
387    }
388
389    return retVal;
390}
391
392Value* LLVM_Generator::Generate_PabloE(PabloE *expr)
393{
394    Value* retVal = 0;
395
396    if (All* all = dynamic_cast<All*>(expr))
397    {
398        IRBuilder<> b(mBasicBlock);
399
400        if ((all->getNum() != 0) && (all->getNum() != 1))
401            std::cout << "\nErr: 'All' can only be set to 1 or 0.\n" << std::endl;
402        Value* ptr_all = b.CreateAlloca(m64x2Vect);
403        Value* void_1 = b.CreateStore((all->getNum() == 0 ? mConst_Aggregate_64x2_0 : mConst_Aggregate_64x2_neg1), ptr_all);
404        Value* all_value = b.CreateLoad(ptr_all);
405
406        retVal = all_value;
407    }
408    else if (Call* call = dynamic_cast<Call*>(expr))
409    {
410        IRBuilder<> b(mBasicBlock);
411
412        //Call the callee once and store the result in the marker map.
413        if (mMarkerMap.find(call->getCallee()) == mMarkerMap.end())
414        {
415            Value* unicode_category = b.CreateCall(mFunc_get_unicode_category, b.CreateGlobalStringPtr(call->getCallee()));
416            Value* ptr = b.CreateAlloca(m64x2Vect);
417            Value* void_1 = b.CreateStore(unicode_category, ptr);
418
419            mMarkerMap.insert(make_pair(call->getCallee(), ptr));
420        }
421        std::map<std::string, Value*>::iterator itGet = mMarkerMap.find(call->getCallee());
422        Value * var_value = b.CreateLoad(itGet->second);
423
424        retVal = var_value;
425    }
426    else if (Var* var = dynamic_cast<Var*>(expr))
427    {
428        IRBuilder<> b(mBasicBlock);
429
430        Value* var_value = b.CreateLoad(GetMarker(var->getVar()), false, var->getVar());
431
432        retVal = var_value;
433    }
434    else if (And* pablo_and = dynamic_cast<And*>(expr))
435    {
436        IRBuilder<> b(mBasicBlock);
437
438        Value* and_result = b.CreateAnd(Generate_PabloE(pablo_and->getExpr1()), Generate_PabloE(pablo_and->getExpr2()), "and_inst");
439
440        retVal = and_result;
441    }
442    else if (Or* pablo_or = dynamic_cast<Or*>(expr))
443    {
444        IRBuilder<> b(mBasicBlock);
445
446        Value* or_result = b.CreateOr(Generate_PabloE(pablo_or->getExpr1()), Generate_PabloE(pablo_or->getExpr2()), "or_inst");
447
448        retVal = or_result;
449    }
450    else if (Sel* pablo_sel = dynamic_cast<Sel*>(expr))
451    {
452        IRBuilder<>b(mBasicBlock);
453
454        Value* and_if_true_result = b.CreateAnd(Generate_PabloE(pablo_sel->getIf_expr()), Generate_PabloE(pablo_sel->getT_expr()));
455        Constant* const_packed_elems [] = {b.getInt64(-1), b.getInt64(-1)};
456        Constant* const_packed = ConstantVector::get(const_packed_elems);
457        Value* not_if_result = b.CreateXor(Generate_PabloE(pablo_sel->getIf_expr()), const_packed);
458        Value* and_if_false_result = b.CreateAnd(not_if_result, Generate_PabloE(pablo_sel->getF_expr()));
459        Value* or_result = b.CreateOr(and_if_true_result, and_if_false_result);
460
461        retVal = or_result;
462    }
463    else if (Not* pablo_not = dynamic_cast<Not*>(expr))
464    {
465        IRBuilder<> b(mBasicBlock);
466
467        Constant* const_packed_elems [] = {b.getInt64(-1), b.getInt64(-1)};
468        Constant* const_packed = ConstantVector::get(const_packed_elems);
469        Value* expr_value = Generate_PabloE(pablo_not->getExpr());
470        Value* xor_rslt = b.CreateXor(expr_value, const_packed, "xor_inst");
471
472        retVal = xor_rslt;
473    }
474    else if (CharClass* cc = dynamic_cast<CharClass*>(expr))
475    {
476        IRBuilder<> b(mBasicBlock);
477
478        Value* character_class = b.CreateLoad(GetMarker(cc->getCharClass()));
479
480        retVal = character_class;
481    }
482    else if (Advance* adv = dynamic_cast<Advance*>(expr))
483    {
484        IRBuilder<> b(mBasicBlock);
485
486        //CarryQ - carry in.
487        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
488        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
489        Value* carryq_value = b.CreateLoad(carryq_GEP);
490
491        Value* strm_value = Generate_PabloE(adv->getExpr());
492        Value* srli_1_value = b.CreateLShr(strm_value, 63);
493
494        Value* packed_shuffle;
495        Constant* const_packed_1_elems [] = {b.getInt32(0), b.getInt32(2)};
496        Constant* const_packed_1 = ConstantVector::get(const_packed_1_elems);
497        packed_shuffle = b.CreateShuffleVector(carryq_value, srli_1_value, const_packed_1, "packed_shuffle nw");
498
499        Constant* const_packed_2_elems[] = {b.getInt64(1), b.getInt64(1)};
500        Constant* const_packed_2 = ConstantVector::get(const_packed_2_elems);
501
502        Value* shl_value = b.CreateShl(strm_value, const_packed_2, "shl_value");
503        Value* result_value = b.CreateOr(shl_value, packed_shuffle, "or.result_value");
504
505        //CarryQ - carry out.
506        Value* cast_marker_value_1 = b.CreateBitCast(strm_value, IntegerType::get(mMod->getContext(), 128));
507        Value* srli_2_value = b.CreateLShr(cast_marker_value_1, 127);
508        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
509        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
510
511        //Increment the idx for the next advance or scan through.
512        mCarryQueueIdx++;
513
514        retVal = result_value;
515    }
516    else if (MatchStar* mstar = dynamic_cast<MatchStar*>(expr))
517    {
518        IRBuilder<> b(mBasicBlock);
519
520        //CarryQ - carry in.
521        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
522        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
523        Value* carryq_value = b.CreateLoad(carryq_GEP);
524        //Get the input stream.
525        Value* strm_value = Generate_PabloE(mstar->getExpr1());
526        //Get the character that is to be matched.
527        Value* cc_value = Generate_PabloE(mstar->getExpr2());
528
529        Value* and_value_1 = b.CreateAnd(cc_value, strm_value, "match_star_and_value_1");
530        Value* add_value_1 = b.CreateAdd(and_value_1, cc_value, "match_star_add_value_1");
531        Value* add_value_2 = b.CreateAdd(add_value_1, carryq_value, "match_star_add_value_2");
532        Value* xor_value_1 = b.CreateXor(add_value_2, mConst_Aggregate_64x2_neg1, "match_star_xor_value_1");
533        Value* and_value_2 = b.CreateAnd(cc_value, xor_value_1, "match_star_and_value_2");
534        Value* or_value_1 = b.CreateOr(and_value_1, and_value_2, "match_star_or_value_1");
535
536        Value* srli_instr_1 = b.CreateLShr(or_value_1, 63);
537
538        Value* cast_marker_value_1 = b.CreateBitCast(srli_instr_1, IntegerType::get(mMod->getContext(), 128));
539        Value* sll_1_value = b.CreateShl(cast_marker_value_1, 64);
540        Value* cast_marker_value_2 = b.CreateBitCast(sll_1_value, m64x2Vect);
541
542
543        Value* add_value_3 = b.CreateAdd(cast_marker_value_2, add_value_2, "match_star_add_value_3");
544        Value* xor_value_2 = b.CreateXor(add_value_3, mConst_Aggregate_64x2_neg1, "match_star_xor_value_2");
545        Value* and_value_3 = b.CreateAnd(cc_value, xor_value_2, "match_star_and_value_3");
546        Value* or_value_2  = b.CreateOr(and_value_1, and_value_3, "match_star_or_value_2 ");
547        Value* xor_value_3 = b.CreateXor(add_value_3, cc_value, "match_star_xor_value_3");
548        Value* result_value = b.CreateOr(xor_value_3, strm_value, "match_star_result_value");
549
550        //CarryQ - carry out:
551        Value* cast_marker_value_3 = b.CreateBitCast(or_value_2, IntegerType::get(mMod->getContext(), 128));
552        Value* srli_2_value = b.CreateLShr(cast_marker_value_3, 127);
553        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
554
555        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
556
557        mCarryQueueIdx++;
558
559        retVal = result_value;
560    }
561    else if (ScanThru* sthru = dynamic_cast<ScanThru*>(expr))
562    {
563        IRBuilder<> b(mBasicBlock);
564
565        //CarryQ - carry in.
566        Value* carryq_idx = b.getInt64(mCarryQueueIdx);
567        Value* carryq_GEP = b.CreateGEP(mptr_carry_q, carryq_idx);
568        Value* carryq_value = b.CreateLoad(carryq_GEP);
569        //Get the input stream.
570        Value* strm_value = Generate_PabloE(sthru->getScanFrom());
571        //Get the scanthru bit stream.
572        Value* scanthru_value = Generate_PabloE(sthru->getScanThru());
573
574        Value* and_value_1 = b.CreateAnd(scanthru_value, strm_value, "scanthru_and_value_1");
575        Value* add_value_1 = b.CreateAdd(and_value_1, carryq_value, "scanthru_add_value_1");
576        Value* add_value_2 = b.CreateAdd(add_value_1, scanthru_value, "scanthru_add_value_2");
577
578        Value* srli_instr_1 = b.CreateLShr(and_value_1, 63);
579
580        Value* cast_marker_value_1 = b.CreateBitCast(srli_instr_1, IntegerType::get(mMod->getContext(), 128));
581        Value* sll_1_value = b.CreateShl(cast_marker_value_1, 64);
582        Value* cast_marker_value_2 = b.CreateBitCast(sll_1_value, m64x2Vect);
583
584        Value* add_value_3 = b.CreateAdd(cast_marker_value_2, add_value_2, "scanthru_add_value_3");
585        Value* xor_value_1  = b.CreateXor(scanthru_value, mConst_Aggregate_64x2_neg1, "scanthru_xor_value_1");
586        Value* result_value = b.CreateAnd(add_value_3, xor_value_1, "scanthru_result_value");
587
588        //CarryQ - carry out:
589        Value* cast_marker_value_3 = b.CreateBitCast(add_value_3, IntegerType::get(mMod->getContext(), 128));
590        Value* srli_2_value = b.CreateLShr(cast_marker_value_3, 127);
591        Value* carryout_2_carry = b.CreateBitCast(srli_2_value, m64x2Vect);
592
593        Value* void_1 = b.CreateStore(carryout_2_carry, carryq_GEP);
594
595        mCarryQueueIdx++;
596
597        retVal = result_value;
598    }
599
600    return retVal;
601}
602
Note: See TracBrowser for help on using the repository browser.