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

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

A change to the way unicode categories are handled. This version supports the unicode categlry 'Nd'.

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