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

Last change on this file since 3914 was 3914, checked in by cameron, 5 years ago

Updates for icgrep-0.9: re simplifications, re names, replimit mods, debugged while loops

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