source: icGREP/icgrep-devel/icgrep/IR_Gen/idisa_builder.cpp @ 6063

Last change on this file since 6063 was 6063, checked in by cameron, 12 months ago

bit interleave (esimd_merge<1>) for AVX2

File size: 37.5 KB
RevLine 
[4651]1/*
[5117]2 *  Copyright (c) 2016 International Characters.
[4651]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 "idisa_builder.h"
8#include <llvm/IR/IRBuilder.h>
9#include <llvm/IR/Constants.h>
10#include <llvm/IR/Intrinsics.h>
11#include <llvm/IR/Function.h>
[5260]12#include <llvm/IR/Module.h>
[4974]13#include <llvm/Support/raw_ostream.h>
[5227]14#include <llvm/IR/TypeBuilder.h>
[5425]15#include <toolchain/toolchain.h>
[4651]16
[5260]17using namespace llvm;
18
[4665]19namespace IDISA {
[4651]20
[5377]21VectorType * IDISA_Builder::fwVectorType(const unsigned fw) {
22    return VectorType::get(getIntNTy(fw), mBitBlockWidth / fw);
[4651]23}
24
[5377]25Value * IDISA_Builder::fwCast(const unsigned fw, Value * const a) {
26    VectorType * const ty = fwVectorType(fw);
[5378]27    assert (a->getType()->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits());
[5377]28    return CreateBitCast(a, ty);
[4651]29}
30
[6059]31void IDISA_Builder::CallPrintRegisterCond(const std::string & regName, llvm::Value * const value, llvm::Value * const cond) {
32    BasicBlock* callBlock = this->CreateBasicBlock("callBlock");
33    BasicBlock* exitBlock = this->CreateBasicBlock("exitBlock");
34    this->CreateCondBr(cond, callBlock, exitBlock);
35
36    this->SetInsertPoint(callBlock);
37    this->CallPrintRegister(regName, value);
38
39    this->CreateBr(exitBlock);
40    this->SetInsertPoint(exitBlock);
41}
42
[4974]43void IDISA_Builder::CallPrintRegister(const std::string & name, Value * const value) {
[5440]44    Module * const m = getModule();
45    Constant * printRegister = m->getFunction("PrintRegister");
[4974]46    if (LLVM_UNLIKELY(printRegister == nullptr)) {
[5245]47        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), getBitBlockType() }, false);
[5440]48        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintRegister", m);
[4974]49        auto arg = function->arg_begin();
50        std::string tmp;
51        raw_string_ostream out(tmp);
52        out << "%-40s =";
53        for(unsigned i = 0; i < (mBitBlockWidth / 8); ++i) {
54            out << " %02x";
55        }
56        out << '\n';
[5440]57        BasicBlock * entry = BasicBlock::Create(m->getContext(), "entry", function);
[4974]58        IRBuilder<> builder(entry);
59        std::vector<Value *> args;
[5398]60        args.push_back(GetString(out.str().c_str()));
[5014]61        Value * const name = &*(arg++);
[4974]62        name->setName("name");
63        args.push_back(name);
[5014]64        Value * value = &*arg;
[4974]65        value->setName("value");
66        Type * const byteVectorType = VectorType::get(getInt8Ty(), (mBitBlockWidth / 8));
67        value = builder.CreateBitCast(value, byteVectorType);
68        for(unsigned i = (mBitBlockWidth / 8); i != 0; --i) {
[5774]69            args.push_back(builder.CreateZExt(builder.CreateExtractElement(value, builder.getInt32(i - 1)), builder.getInt32Ty()));
[4974]70        }
[5239]71        builder.CreateCall(GetPrintf(), args);
[4974]72        builder.CreateRetVoid();
[4942]73
[4974]74        printRegister = function;
75    }
[5398]76    CreateCall(printRegister, {GetString(name.c_str()), CreateBitCast(value, mBitBlockType)});
[4942]77}
78
79Constant * IDISA_Builder::simd_himask(unsigned fw) {
80    return Constant::getIntegerValue(getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw/2)));
[4651]81}
82
[4942]83Constant * IDISA_Builder::simd_lomask(unsigned fw) {
84    return Constant::getIntegerValue(getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getLowBitsSet(fw, fw/2)));
85}
86
[5140]87Value * IDISA_Builder::simd_fill(unsigned fw, Value * a) {
[5729]88    if (fw < 8) report_fatal_error("Unsupported field width: simd_fill " + std::to_string(fw));
[5828]89    const unsigned field_count = mBitBlockWidth/fw;
[5140]90    Type * singleFieldVecTy = VectorType::get(getIntNTy(fw), 1);
91    Value * aVec = CreateBitCast(a, singleFieldVecTy);
92    return CreateShuffleVector(aVec, UndefValue::get(singleFieldVecTy), Constant::getNullValue(VectorType::get(getInt32Ty(), field_count)));
93}
94
[4942]95Value * IDISA_Builder::simd_add(unsigned fw, Value * a, Value * b) {
[5828]96    if (fw == 1) {
97        return simd_xor(a, b);
98    } else if (fw < 8) {
[5729]99        Constant * hi_bit_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
100                                                           APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, 1)));
101        Constant * lo_bit_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
102                                                           APInt::getSplat(mBitBlockWidth, APInt::getLowBitsSet(fw, fw-1)));
103        Value * hi_xor = simd_xor(simd_and(a, hi_bit_mask), simd_and(b, hi_bit_mask));
104        Value * part_sum = simd_add(32, simd_and(a, lo_bit_mask), simd_and(b, lo_bit_mask));
105        return simd_xor(part_sum, hi_xor);
106    }
[5140]107    return CreateAdd(fwCast(fw, a), fwCast(fw, b));
[4942]108}
109
[4651]110Value * IDISA_Builder::simd_sub(unsigned fw, Value * a, Value * b) {
[5729]111    if (fw < 8) report_fatal_error("Unsupported field width: sub " + std::to_string(fw));
[4898]112    return CreateSub(fwCast(fw, a), fwCast(fw, b));
[4651]113}
114
115Value * IDISA_Builder::simd_mult(unsigned fw, Value * a, Value * b) {
[5729]116    if (fw < 8) report_fatal_error("Unsupported field width: mult " + std::to_string(fw));
[4898]117    return CreateMul(fwCast(fw, a), fwCast(fw, b));
[4651]118}
119
120Value * IDISA_Builder::simd_eq(unsigned fw, Value * a, Value * b) {
[5729]121    if (fw < 8) {
122        Value * eq_bits = simd_not(simd_xor(a, b));
123        if (fw == 1) return eq_bits;
124        eq_bits = simd_or(simd_and(simd_srli(32, simd_and(simd_himask(2), eq_bits), 1), eq_bits),
125                          simd_and(simd_slli(32, simd_and(simd_lomask(2), eq_bits), 1), eq_bits));
126        if (fw == 2) return eq_bits;
127        eq_bits = simd_or(simd_and(simd_srli(32, simd_and(simd_himask(4), eq_bits), 2), eq_bits),
128                          simd_and(simd_slli(32, simd_and(simd_lomask(4), eq_bits), 2), eq_bits));
129        return eq_bits;
130    }
[4898]131    return CreateSExt(CreateICmpEQ(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
[4651]132}
133
134Value * IDISA_Builder::simd_gt(unsigned fw, Value * a, Value * b) {
[5729]135    if (fw < 8) report_fatal_error("Unsupported field width: gt " + std::to_string(fw));
[4898]136    return CreateSExt(CreateICmpSGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
[4651]137}
138
139Value * IDISA_Builder::simd_ugt(unsigned fw, Value * a, Value * b) {
[6063]140    if (fw == 1) return simd_and(a, simd_not(b));
[5729]141    if (fw < 8) report_fatal_error("Unsupported field width: ugt " + std::to_string(fw));
[4898]142    return CreateSExt(CreateICmpUGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
[4651]143}
144
145Value * IDISA_Builder::simd_lt(unsigned fw, Value * a, Value * b) {
[5729]146    if (fw < 8) report_fatal_error("Unsupported field width: lt " + std::to_string(fw));
[4898]147    return CreateSExt(CreateICmpSLT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
[4651]148}
149
150Value * IDISA_Builder::simd_ult(unsigned fw, Value * a, Value * b) {
[5729]151    if (fw < 8) report_fatal_error("Unsupported field width: ult " + std::to_string(fw));
[4898]152    return CreateSExt(CreateICmpULT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
[4651]153}
154
[6050]155Value * IDISA_Builder::simd_ule(unsigned fw, Value * a, Value * b) {
[6052]156    if (fw == 1) return simd_or(simd_not(a), b);
157    if (fw < 8) {
158        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_ule(2*fw, simd_and(simd_himask(2*fw), a), b));
159        Value * lo_rslt = simd_and(simd_lomask(2*fw), simd_ule(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b)));
160        return simd_or(hi_rslt, lo_rslt);
161    }
[6050]162    return CreateSExt(CreateICmpULE(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
163}
164
165Value * IDISA_Builder::simd_uge(unsigned fw, Value * a, Value * b) {
[6052]166    if (fw == 1) return simd_or(a, simd_not(b));
167    if (fw < 8) {
168        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_uge(2*fw, a, simd_and(simd_himask(2*fw), b)));
169        Value * lo_rslt = simd_and(simd_lomask(2*fw), simd_uge(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b)));
170        return simd_or(hi_rslt, lo_rslt);
171    }
[6050]172    if (fw < 8) report_fatal_error("Unsupported field width: ult " + std::to_string(fw));
173    return CreateSExt(CreateICmpUGE(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
174}
175
[4651]176Value * IDISA_Builder::simd_max(unsigned fw, Value * a, Value * b) {
[5729]177    if (fw < 8) report_fatal_error("Unsupported field width: max " + std::to_string(fw));
[4651]178    Value * aVec = fwCast(fw, a);
179    Value * bVec = fwCast(fw, b);
[4898]180    return CreateSelect(CreateICmpSGT(aVec, bVec), aVec, bVec);
[4651]181}
182
183Value * IDISA_Builder::simd_umax(unsigned fw, Value * a, Value * b) {
[6052]184    if (fw == 1) return simd_or(a, b);
185    if (fw < 8) {
186        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_umax(2*fw, a, b));
187        Value * lo_rslt = simd_umax(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b));
188        return simd_or(hi_rslt, lo_rslt);
189    }
[4651]190    Value * aVec = fwCast(fw, a);
191    Value * bVec = fwCast(fw, b);
[4898]192    return CreateSelect(CreateICmpUGT(aVec, bVec), aVec, bVec);
[4651]193}
194
195Value * IDISA_Builder::simd_min(unsigned fw, Value * a, Value * b) {
[5729]196    if (fw < 8) report_fatal_error("Unsupported field width: min " + std::to_string(fw));
[4651]197    Value * aVec = fwCast(fw, a);
198    Value * bVec = fwCast(fw, b);
[4898]199    return CreateSelect(CreateICmpSLT(aVec, bVec), aVec, bVec);
[4651]200}
201
202Value * IDISA_Builder::simd_umin(unsigned fw, Value * a, Value * b) {
[6052]203    if (fw == 1) return simd_and(a, b);
204    if (fw < 8) {
205        Value * hi_rslt = simd_and(simd_himask(2*fw), simd_umin(2*fw, a, b));
206        Value * lo_rslt = simd_umin(2*fw, simd_and(simd_lomask(2*fw), a), simd_and(simd_lomask(2*fw), b));
207        return simd_or(hi_rslt, lo_rslt);
208    }
[4651]209    Value * aVec = fwCast(fw, a);
210    Value * bVec = fwCast(fw, b);
[4898]211    return CreateSelect(CreateICmpULT(aVec, bVec), aVec, bVec);
[4651]212}
213
[5865]214Value * IDISA_Builder::mvmd_sll(unsigned fw, Value * value, Value * shift) {
215    VectorType * const vecTy = cast<VectorType>(value->getType());
216    IntegerType * const intTy = getIntNTy(vecTy->getBitWidth());
[5985]217    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
218        Type * const ty = shift->getType();
219        Value * const scaled = CreateMul(shift, ConstantInt::get(ty, fw));
220        Value * const inbounds = CreateICmpULE(scaled, ConstantInt::get(ty, vecTy->getBitWidth()));
221        CreateAssert(inbounds, "shift exceeds vector width");
222    }
[5865]223    value = CreateBitCast(value, intTy);
224    shift = CreateZExtOrTrunc(CreateMul(shift, ConstantInt::get(shift->getType(), fw)), intTy);
225    return CreateBitCast(CreateShl(value, shift), vecTy);
226}
227
[6045]228Value * IDISA_Builder::mvmd_dsll(unsigned fw, Value * a, Value * b, Value * shift) {
229    if (fw < 8) report_fatal_error("Unsupported field width: mvmd_dsll " + std::to_string(fw));
230    const auto field_count = mBitBlockWidth/fw;
231    Type * fwTy = getIntNTy(fw);
232   
233    Constant * Idxs[field_count];
234    for (unsigned i = 0; i < field_count; i++) {
235        Idxs[i] = ConstantInt::get(fwTy, i + field_count);
236    }
[6046]237    Value * shuffle = simd_sub(fw, ConstantVector::get({Idxs, field_count}), simd_fill(fw, shift));
238    Value * rslt = mvmd_shuffle2(fw, fwCast(fw, a), fwCast(fw, b), shuffle);
239    return rslt;
[6045]240}
241
[5865]242Value * IDISA_Builder::mvmd_srl(unsigned fw, Value * value, Value * shift) {
243    VectorType * const vecTy = cast<VectorType>(value->getType());
244    IntegerType * const intTy = getIntNTy(vecTy->getBitWidth());
[5985]245    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
246        Type * const ty = shift->getType();
247        Value * const scaled = CreateMul(shift, ConstantInt::get(ty, fw));
248        Value * const inbounds = CreateICmpULE(scaled, ConstantInt::get(ty, vecTy->getBitWidth()));
249        CreateAssert(inbounds, "shift exceeds vector width");
250    }
[5865]251    value = CreateBitCast(value, intTy);
252    shift = CreateZExtOrTrunc(CreateMul(shift, ConstantInt::get(shift->getType(), fw)), intTy);
253    return CreateBitCast(CreateLShr(value, shift), vecTy);
254}
255
[4651]256Value * IDISA_Builder::simd_slli(unsigned fw, Value * a, unsigned shift) {
[5729]257    if (fw < 16) {
258        Constant * value_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
259                                                          APInt::getSplat(mBitBlockWidth, APInt::getLowBitsSet(fw, fw-shift)));
260        return CreateShl(fwCast(32, simd_and(a, value_mask)), shift);
261    }
[4898]262    return CreateShl(fwCast(fw, a), shift);
[4651]263}
264
265Value * IDISA_Builder::simd_srli(unsigned fw, Value * a, unsigned shift) {
[5729]266    if (fw < 16) {
267        Constant * value_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
268                                                          APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw-shift)));
269        return CreateLShr(fwCast(32, simd_and(a, value_mask)), shift);
270    }
[4898]271    return CreateLShr(fwCast(fw, a), shift);
[4651]272}
273
274Value * IDISA_Builder::simd_srai(unsigned fw, Value * a, unsigned shift) {
[5729]275    if (fw < 8) report_fatal_error("Unsupported field width: srai " + std::to_string(fw));
[4898]276    return CreateAShr(fwCast(fw, a), shift);
[4651]277}
[5729]278   
279Value * IDISA_Builder::simd_sllv(unsigned fw, Value * v, Value * shifts) {
280    if (fw >= 8) return CreateShl(fwCast(fw, v), fwCast(fw, shifts));
281    Value * w = v;
282    for (unsigned shft_amt = 1; shft_amt < fw; shft_amt *= 2) {
283        APInt bit_in_field(fw, shft_amt);
284        // To simulate shift within a fw, we need to mask off the high shft_amt bits of each element.
285        Constant * value_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
286                                                          APInt::getSplat(mBitBlockWidth, APInt::getLowBitsSet(fw, fw-shft_amt)));
287        Constant * bit_select = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
288                                                          APInt::getSplat(mBitBlockWidth, bit_in_field));
289        Value * unshifted_field_mask = simd_eq(fw, simd_and(bit_select, shifts), allZeroes());
290        Value * fieldsToShift = simd_and(w, simd_and(value_mask, simd_not(unshifted_field_mask)));
291        w = simd_or(simd_and(w, unshifted_field_mask), simd_slli(32, fieldsToShift, shft_amt));
292    }
293    return w;
294}
[4651]295
[5729]296Value * IDISA_Builder::simd_srlv(unsigned fw, Value * v, Value * shifts) {
297    if (fw >= 8) return CreateLShr(fwCast(fw, v), fwCast(fw, shifts));
298    Value * w = v;
299    for (unsigned shft_amt = 1; shft_amt < fw; shft_amt *= 2) {
300        APInt bit_in_field(fw, shft_amt);
301        // To simulate shift within a fw, we need to mask off the low shft_amt bits of each element.
302        Constant * value_mask = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
303                                                          APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw-shft_amt)));
304        Constant * bit_select = Constant::getIntegerValue(getIntNTy(mBitBlockWidth),
305                                                          APInt::getSplat(mBitBlockWidth, bit_in_field));
306        Value * unshifted_field_mask = simd_eq(fw, simd_and(bit_select, shifts), allZeroes());
307        Value * fieldsToShift = simd_and(w, simd_and(value_mask, simd_not(unshifted_field_mask)));
308        w = simd_or(simd_and(w, unshifted_field_mask), simd_srli(32, fieldsToShift, shft_amt));
309    }
310    return w;
311}
312
313Value * IDISA_Builder::simd_pext(unsigned fieldwidth, Value * v, Value * extract_mask) {
314    Value * delcounts = CreateNot(extract_mask);  // initially deletion counts per 1-bit field
315    Value * w = simd_and(extract_mask, v);
316    for (unsigned fw = 2; fw < fieldwidth; fw = fw * 2) {
317        Value * shift_fwd_field_mask = simd_lomask(fw*2);
318        Value * shift_back_field_mask = simd_himask(fw*2);
319        Value * shift_back_count_mask = simd_and(shift_back_field_mask, simd_lomask(fw));
320        Value * shift_fwd_amts = simd_srli(fw, simd_and(shift_fwd_field_mask, delcounts), fw/2);
321        Value * shift_back_amts = simd_and(shift_back_count_mask, delcounts);
322        w = simd_or(simd_sllv(fw, simd_and(w, shift_fwd_field_mask), shift_fwd_amts),
323                    simd_srlv(fw, simd_and(w, shift_back_field_mask), shift_back_amts));
324        delcounts = simd_add(fw, simd_and(simd_lomask(fw), delcounts), simd_srli(fw, delcounts, fw/2));
325    }
326    // Now shift back all fw fields.
327    Value * shift_back_amts = simd_and(simd_lomask(fieldwidth), delcounts);
328    w = simd_srlv(fieldwidth, w, shift_back_amts);
329    return w;
330}
331
332Value * IDISA_Builder::simd_pdep(unsigned fieldwidth, Value * v, Value * deposit_mask) {
333    // simd_pdep is implemented by reversing the process of simd_pext.
334    // First determine the deletion counts necessary for each stage of the process.
335    std::vector<Value *> delcounts;
336    delcounts.push_back(simd_not(deposit_mask)); // initially deletion counts per 1-bit field
337    for (unsigned fw = 2; fw < fieldwidth; fw = fw * 2) {
338        delcounts.push_back(simd_add(fw, simd_and(simd_lomask(fw), delcounts.back()), simd_srli(fw, delcounts.back(), fw/2)));
339    }
340    //
341    // Now reverse the pext process.  First reverse the final shift_back.
342    Value * pext_shift_back_amts = simd_and(simd_lomask(fieldwidth), delcounts.back());
343    Value * w = simd_sllv(fieldwidth, v, pext_shift_back_amts);
344    //
345    // No work through the smaller field widths.
346    for (unsigned fw = fieldwidth/2; fw >= 2; fw = fw/2) {
347        delcounts.pop_back();
348        Value * pext_shift_fwd_field_mask = simd_lomask(fw*2);
349        Value * pext_shift_back_field_mask = simd_himask(fw*2);
350        Value * pext_shift_back_count_mask = simd_and(pext_shift_back_field_mask, simd_lomask(fw));
351        Value * pext_shift_fwd_amts = simd_srli(fw, simd_and(pext_shift_fwd_field_mask, delcounts.back()), fw/2);
352        Value * pext_shift_back_amts = simd_and(pext_shift_back_count_mask, delcounts.back());
353        w = simd_or(simd_srlv(fw, simd_and(w, pext_shift_fwd_field_mask), pext_shift_fwd_amts),
354                    simd_sllv(fw, simd_and(w, pext_shift_back_field_mask), pext_shift_back_amts));
355    }
[6052]356    return CreateAnd(w, deposit_mask);
[5729]357}
358
[5972]359Value * IDISA_Builder::simd_popcount(unsigned fw, Value * a) {
360    if (fw == 1) {
361        return a;
362    } else if (fw == 2) {
363        // For each 2-bit field ab we can use the subtraction ab - 0a to generate
364        // the popcount without carry/borrow from the neighbouring 2-bit field.
365        // case 00:  ab - 0a = 00 - 00 = 00
366        // case 01:  ab - 0a = 01 - 00 = 01
367        // case 10:  ab - 0a = 10 - 01 = 01 (no borrow)
368        // case 11:  ab - 0a = 11 - 01 = 10
369        return simd_sub(64, a, simd_srli(64, simd_and(simd_himask(2), a), 1));
[5977]370    } else if (fw <= 8) {
[5972]371        Value * c = simd_popcount(fw/2, a);
372        c = simd_add(64, simd_and(c, simd_lomask(fw)), simd_srli(fw, c, fw/2));
373        return c;
374    } else {
375        return CreatePopcount(fwCast(fw, a));
376    }
377}
378
[5488]379Value * IDISA_Builder::simd_bitreverse(unsigned fw, Value * a) {
380    /*  Pure sequential solution too slow!
381     Value * func = Intrinsic::getDeclaration(getModule(), Intrinsic::bitreverse, fwVectorType(fw));
382     return CreateCall(func, fwCast(fw, a));
383     */
384    if (fw > 8) {
385        // Reverse the bits of each byte and then use a byte shuffle to complete the job.
386        Value * bitrev8 = fwCast(8, simd_bitreverse(8, a));
387        const auto bytes_per_field = fw/8;
388        const auto byte_count = mBitBlockWidth / 8;
389        Constant * Idxs[byte_count];
390        for (unsigned i = 0; i < byte_count; i += bytes_per_field) {
391            for (unsigned j = 0; j < bytes_per_field; j++) {
392                Idxs[i + j] = getInt32(i + bytes_per_field - j - 1);
393            }
394        }
395        return CreateShuffleVector(bitrev8, UndefValue::get(fwVectorType(8)), ConstantVector::get({Idxs, byte_count}));
396    }
397    else {
398        if (fw > 2) {
399            a = simd_bitreverse(fw/2, a);
400        }
401        return simd_or(simd_srli(16, simd_and(a, simd_himask(fw)), fw/2), simd_slli(16, simd_and(a, simd_lomask(fw)), fw/2));
402    }
403}
404
[4891]405Value * IDISA_Builder::simd_if(unsigned fw, Value * cond, Value * a, Value * b) {
[4900]406    if (fw == 1) {
[4957]407        Value * a1 = bitCast(a);
408        Value * b1 = bitCast(b);
[4900]409        Value * c = bitCast(cond);
[4957]410        return CreateOr(CreateAnd(a1, c), CreateAnd(CreateXor(c, b1), b1));
[5309]411    } else {
[5729]412        if (fw < 8) report_fatal_error("Unsupported field width: simd_if " + std::to_string(fw));
[4900]413        Value * aVec = fwCast(fw, a);
414        Value * bVec = fwCast(fw, b);
415        return CreateSelect(CreateICmpSLT(cond, mZeroInitializer), aVec, bVec);
416    }
[4891]417}
418   
[5309]419Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {   
[6050]420    if (fw == 4) {
[6053]421        Value * abh = simd_or(simd_and(simd_himask(fw*2), b), simd_srli(32, simd_and(simd_himask(fw*2), a), fw));
422        Value * abl = simd_or(simd_slli(32, simd_and(simd_lomask(fw*2), b), fw), simd_and(simd_lomask(fw*2), a));
[6051]423        return esimd_mergeh(fw * 2, abl, abh);
[6050]424    }
425    if (fw < 4) report_fatal_error("Unsupported field width: mergeh " + std::to_string(fw));
[5309]426    const auto field_count = mBitBlockWidth / fw;
427    Constant * Idxs[field_count];
428    for (unsigned i = 0; i < field_count / 2; i++) {
429        Idxs[2 * i] = getInt32(i + field_count / 2); // selects elements from first reg.
430        Idxs[2 * i + 1] = getInt32(i + field_count / 2 + field_count); // selects elements from second reg.
[4652]431    }
[5309]432    return CreateShuffleVector(fwCast(fw, a), fwCast(fw, b), ConstantVector::get({Idxs, field_count}));
[4652]433}
434
[6050]435Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
436    if (fw == 4) {
[6053]437        Value * abh = simd_or(simd_and(simd_himask(fw*2), b), simd_srli(32, simd_and(simd_himask(fw*2), a), fw));
438        Value * abl = simd_or(simd_slli(32, simd_and(simd_lomask(fw*2), b), fw), simd_and(simd_lomask(fw*2), a));
[6051]439        return esimd_mergel(fw * 2, abl, abh);
[6050]440    }
441    if (fw < 4) report_fatal_error("Unsupported field width: mergel " + std::to_string(fw));
[5309]442    const auto field_count = mBitBlockWidth / fw;
443    Constant * Idxs[field_count];
444    for (unsigned i = 0; i < field_count / 2; i++) {
445        Idxs[2 * i] = getInt32(i); // selects elements from first reg.
446        Idxs[2 * i + 1] = getInt32(i + field_count); // selects elements from second reg.
[4652]447    }
[5309]448    return CreateShuffleVector(fwCast(fw, a), fwCast(fw, b), ConstantVector::get({Idxs, field_count}));
[4652]449}
450
[4892]451Value * IDISA_Builder::esimd_bitspread(unsigned fw, Value * bitmask) {
[5729]452    if (fw < 8) report_fatal_error("Unsupported field width: bitspread " + std::to_string(fw));
[5309]453    const auto field_count = mBitBlockWidth / fw;
[4898]454    Type * field_type = getIntNTy(fw);
[5309]455    Value * spread_field = CreateBitCast(CreateZExtOrTrunc(bitmask, field_type), VectorType::get(getIntNTy(fw), 1));
[4898]456    Value * undefVec = UndefValue::get(VectorType::get(getIntNTy(fw), 1));
457    Value * broadcast = CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(getInt32Ty(), field_count)));
[5309]458    Constant * bitSel[field_count];
459    Constant * bitShift[field_count];
[4879]460    for (unsigned i = 0; i < field_count; i++) {
[5309]461        bitSel[i] = ConstantInt::get(field_type, 1 << i);
462        bitShift[i] = ConstantInt::get(field_type, i);
[4879]463    }
[5309]464    Value * bitSelVec = ConstantVector::get({bitSel, field_count});
465    Value * bitShiftVec = ConstantVector::get({bitShift, field_count});
[4898]466    return CreateLShr(CreateAnd(bitSelVec, broadcast), bitShiftVec);
[4879]467}
468
[4653]469Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
[5837]470    if (fw <= 8) {
471        const unsigned fw_wkg = 32;
472        Value * aLo = simd_srli(fw_wkg, a, fw/2);
473        Value * bLo = simd_srli(fw_wkg, b, fw/2);
474        return hsimd_packl(fw, aLo, bLo);
475    }
[4653]476    Value * aVec = fwCast(fw/2, a);
477    Value * bVec = fwCast(fw/2, b);
[5309]478    const auto field_count = 2 * mBitBlockWidth / fw;
479    Constant * Idxs[field_count];
[4653]480    for (unsigned i = 0; i < field_count; i++) {
[5309]481        Idxs[i] = getInt32(2 * i + 1);
[4653]482    }
[5309]483    return CreateShuffleVector(aVec, bVec, ConstantVector::get({Idxs, field_count}));
[4653]484}
[4652]485
[4653]486Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
[5837]487    if (fw <= 8) {
[5843]488        const unsigned fw_wkg = 32;
[5837]489        Value * aLo = simd_srli(fw_wkg, a, fw/2);
490        Value * bLo = simd_srli(fw_wkg, b, fw/2);
491        return hsimd_packl(fw*2,
492                           bitCast(simd_or(simd_and(simd_himask(fw), aLo), simd_and(simd_lomask(fw), a))),
493                           bitCast(simd_or(simd_and(simd_himask(fw), bLo), simd_and(simd_lomask(fw), b))));
494    }
[4653]495    Value * aVec = fwCast(fw/2, a);
496    Value * bVec = fwCast(fw/2, b);
[5309]497    const auto field_count = 2 * mBitBlockWidth / fw;
498    Constant * Idxs[field_count];
[4653]499    for (unsigned i = 0; i < field_count; i++) {
[5309]500        Idxs[i] = getInt32(2 * i);
[4653]501    }
[5309]502    return CreateShuffleVector(aVec, bVec, ConstantVector::get({Idxs, field_count}));
[4653]503}
[4652]504
[4957]505Value * IDISA_Builder::hsimd_packh_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
[5729]506    if (fw < 16) report_fatal_error("Unsupported field width: packh_in_lanes " + std::to_string(fw));
[5309]507    const unsigned fw_out = fw / 2;
508    const unsigned fields_per_lane = mBitBlockWidth / (fw_out * lanes);
509    const unsigned field_offset_for_b = mBitBlockWidth / fw_out;
510    const unsigned field_count = mBitBlockWidth / fw_out;
511    Constant * Idxs[field_count];
512    for (unsigned lane = 0, j = 0; lane < lanes; lane++) {
513        const unsigned first_field_in_lane = lane * fields_per_lane; // every second field
514        for (unsigned i = 0; i < fields_per_lane / 2; i++) {
515            Idxs[j++] = getInt32(first_field_in_lane + (2 * i) + 1);
[4957]516        }
[5309]517        for (unsigned i = 0; i < fields_per_lane / 2; i++) {
518            Idxs[j++] = getInt32(field_offset_for_b + first_field_in_lane + (2 * i) + 1);
[4957]519        }
520    }
[5309]521    return CreateShuffleVector(fwCast(fw_out, a), fwCast(fw_out, b), ConstantVector::get({Idxs, field_count}));
[4957]522}
523
524Value * IDISA_Builder::hsimd_packl_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
[5729]525    if (fw < 16) report_fatal_error("Unsupported field width: packl_in_lanes " + std::to_string(fw));
[5309]526    const unsigned fw_out = fw / 2;
527    const unsigned fields_per_lane = mBitBlockWidth / (fw_out * lanes);
528    const unsigned field_offset_for_b = mBitBlockWidth / fw_out;
529    const unsigned field_count = mBitBlockWidth / fw_out;
530    Constant * Idxs[field_count];
531    for (unsigned lane = 0, j = 0; lane < lanes; lane++) {
532        const unsigned first_field_in_lane = lane * fields_per_lane; // every second field
533        for (unsigned i = 0; i < fields_per_lane / 2; i++) {
534            Idxs[j++] = getInt32(first_field_in_lane + (2 * i));
[4957]535        }
[5309]536        for (unsigned i = 0; i < fields_per_lane / 2; i++) {
537            Idxs[j++] = getInt32(field_offset_for_b + first_field_in_lane + (2 * i));
[4957]538        }
539    }
[5309]540    return CreateShuffleVector(fwCast(fw_out, a), fwCast(fw_out, b), ConstantVector::get({Idxs, field_count}));
[4957]541}
542
[4653]543Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
[5729]544    if (fw < 8) report_fatal_error("Unsupported field width: hsimd_signmask " + std::to_string(fw));
[4898]545    Value * mask = CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
[5956]546    mask = CreateBitCast(mask, getIntNTy(mBitBlockWidth/fw));
547    if (mBitBlockWidth/fw < 32) return CreateZExt(mask, getInt32Ty());
548    else return mask;
[4653]549}
550
[4697]551Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
[6052]552    if (fw < 8) {
553        unsigned byte_no = (fieldIndex * fw) / 8;
554        unsigned intrabyte_shift = (fieldIndex * fw) % 8;
555        Value * byte = CreateExtractElement(fwCast(8, a), getInt32(byte_no));
556        return CreateTrunc(CreateLShr(byte, getInt8(intrabyte_shift)), getIntNTy(fw));
557    }
[5202]558    return CreateExtractElement(fwCast(fw, a), getInt32(fieldIndex));
[4697]559}
560
[6052]561Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * a, Value * elt, unsigned fieldIndex) {
562    if (fw < 8) {
563        unsigned byte_no = (fieldIndex * fw) / 8;
564        unsigned intrabyte_shift = (fieldIndex * fw) % 8;
565        unsigned field_mask = ((1 << fw) - 1) << intrabyte_shift;
566        Value * byte = CreateAnd(CreateExtractElement(fwCast(8, a), getInt32(byte_no)), getInt8(0xFF &~ field_mask));
567        byte = CreateOr(byte, CreateShl(CreateZExtOrTrunc(elt, getInt8Ty()), getInt8(intrabyte_shift)));
568        return CreateInsertElement(fwCast(8, a), byte, getInt32(byte_no));
569    }
570    return CreateInsertElement(fwCast(fw, a), elt, getInt32(fieldIndex));
[4881]571}
572
[5007]573Value * IDISA_Builder::mvmd_slli(unsigned fw, Value * a, unsigned shift) {
[5729]574    if (fw < 8) report_fatal_error("Unsupported field width: mvmd_slli " + std::to_string(fw));
[5979]575    Value * shifted = mvmd_dslli(fw, a, Constant::getNullValue(fwVectorType(fw)), shift);
576    return shifted;
[5007]577}
578
579Value * IDISA_Builder::mvmd_srli(unsigned fw, Value * a, unsigned shift) {
[5729]580    if (fw < 8) report_fatal_error("Unsupported field width: mvmd_srli " + std::to_string(fw));
[5979]581    const auto field_count = mBitBlockWidth / fw;
582    return mvmd_dslli(fw, Constant::getNullValue(fwVectorType(fw)), a, field_count - shift);
[5007]583}
584
[4655]585Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
[5729]586    if (fw < 8) report_fatal_error("Unsupported field width: mvmd_dslli " + std::to_string(fw));
[5309]587    const auto field_count = mBitBlockWidth/fw;
588    Constant * Idxs[field_count];
[4845]589    for (unsigned i = 0; i < field_count; i++) {
[5979]590        Idxs[i] = getInt32(i + field_count - shift);
[4655]591    }
[5309]592    return CreateShuffleVector(fwCast(fw, b), fwCast(fw, a), ConstantVector::get({Idxs, field_count}));
[4655]593}
[4653]594
[6045]595Value * IDISA_Builder::mvmd_shuffle(unsigned fw, Value * a, Value * shuffle_table) {
596    report_fatal_error("Unsupported field width: mvmd_shuffle " + std::to_string(fw));
597}
598   
599Value * IDISA_Builder::mvmd_shuffle2(unsigned fw, Value * a, Value *b, Value * shuffle_table) {
600    //  Use two shuffles, with selection by the bit value within the shuffle_table.
601    const auto field_count = mBitBlockWidth/fw;
[6046]602    Constant * selectorSplat = ConstantVector::getSplat(field_count, ConstantInt::get(getIntNTy(fw), field_count));
[6045]603    Value * selectMask = simd_eq(fw, simd_and(shuffle_table, selectorSplat), selectorSplat);
[6046]604    Value * tbl = simd_and(shuffle_table, simd_not(selectorSplat));
605    Value * rslt= simd_or(simd_and(mvmd_shuffle(fw, a, tbl), simd_not(selectMask)), simd_and(mvmd_shuffle(fw, b, tbl), selectMask));
606    return rslt;
[6045]607}
608   
609
[6007]610llvm::Value * IDISA_Builder::mvmd_compress(unsigned fw, llvm::Value * a, llvm::Value * select_mask) {
611    report_fatal_error("Unsupported field width: mvmd_compress " + std::to_string(fw));
612}
613
[4662]614Value * IDISA_Builder::bitblock_any(Value * a) {
[4898]615    Type * iBitBlock = getIntNTy(mBitBlockWidth);
[5309]616    return CreateICmpNE(CreateBitCast(a, iBitBlock),  ConstantInt::getNullValue(iBitBlock));
[4662]617}
[4665]618
[5114]619// full add producing {carryout, sum}
[5115]620std::pair<Value *, Value *> IDISA_Builder::bitblock_add_with_carry(Value * a, Value * b, Value * carryin) {
[5114]621    Value * carrygen = simd_and(a, b);
622    Value * carryprop = simd_or(a, b);
623    Value * sum = simd_add(mBitBlockWidth, simd_add(mBitBlockWidth, a, b), carryin);
624    Value * carryout = CreateBitCast(simd_or(carrygen, simd_and(carryprop, CreateNot(sum))), getIntNTy(mBitBlockWidth));
625    return std::pair<Value *, Value *>(bitCast(simd_srli(mBitBlockWidth, carryout, mBitBlockWidth - 1)), bitCast(sum));
626}
627
628// full shift producing {shiftout, shifted}
629std::pair<Value *, Value *> IDISA_Builder::bitblock_advance(Value * a, Value * shiftin, unsigned shift) {
630    Value * shiftin_bitblock = CreateBitCast(shiftin, getIntNTy(mBitBlockWidth));
631    Value * a_bitblock = CreateBitCast(a, getIntNTy(mBitBlockWidth));
[5117]632    Value * shifted = bitCast(CreateOr(CreateShl(a_bitblock, shift), shiftin_bitblock));
633    Value * shiftout = bitCast(CreateLShr(a_bitblock, mBitBlockWidth - shift));
[5114]634    return std::pair<Value *, Value *>(shiftout, shifted);
635}
636
[5713]637// full shift producing {shiftout, shifted}
[5730]638std::pair<Value *, Value *> IDISA_Builder::bitblock_indexed_advance(Value * strm, Value * index_strm, Value * shiftIn, unsigned shiftAmount) {
[5832]639    const unsigned bitWidth = getSizeTy()->getBitWidth();
640    Type * const iBitBlock = getIntNTy(getBitBlockWidth());
641    Value * const shiftVal = getSize(shiftAmount);
[5730]642    Value * extracted_bits = simd_pext(bitWidth, strm, index_strm);
643    Value * ix_popcounts = simd_popcount(bitWidth, index_strm);
[5832]644    const auto n = getBitBlockWidth() / bitWidth;
645    VectorType * const vecTy = VectorType::get(getSizeTy(), n);
[5730]646    if (LLVM_LIKELY(shiftAmount < bitWidth)) {
647        Value * carry = mvmd_extract(bitWidth, shiftIn, 0);
[5832]648        Value * result = UndefValue::get(vecTy);
649        for (unsigned i = 0; i < n; i++) {
[5730]650            Value * ix_popcnt = mvmd_extract(bitWidth, ix_popcounts, i);
651            Value * bits = mvmd_extract(bitWidth, extracted_bits, i);
652            Value * adv = CreateOr(CreateShl(bits, shiftAmount), carry);
653            // We have two cases depending on whether the popcount of the index pack is < shiftAmount or not.
654            Value * popcount_small = CreateICmpULT(ix_popcnt, shiftVal);
[5832]655            Value * carry_if_popcount_small =
[5730]656                CreateOr(CreateShl(bits, CreateSub(shiftVal, ix_popcnt)),
657                            CreateLShr(carry, ix_popcnt));
658            Value * carry_if_popcount_large = CreateLShr(bits, CreateSub(ix_popcnt, shiftVal));
659            carry = CreateSelect(popcount_small, carry_if_popcount_small, carry_if_popcount_large);
660            result = mvmd_insert(bitWidth, result, adv, i);
661        }
662        Value * carryOut = mvmd_insert(bitWidth, allZeroes(), carry, 0);
663        return std::pair<Value *, Value *>{bitCast(carryOut), simd_pdep(bitWidth, result, index_strm)};
664    }
665    else if (shiftAmount <= mBitBlockWidth) {
666        // The shift amount is always greater than the popcount of the individual
667        // elements that we deal with.   This simplifies some of the logic.
668        Value * carry = CreateBitCast(shiftIn, iBitBlock);
[5832]669        Value * result = UndefValue::get(vecTy);
670        for (unsigned i = 0; i < n; i++) {
[5730]671            Value * ix_popcnt = mvmd_extract(bitWidth, ix_popcounts, i);
672            Value * bits = mvmd_extract(bitWidth, extracted_bits, i);  // All these bits are shifted out (appended to carry).
673            result = mvmd_insert(bitWidth, result, mvmd_extract(bitWidth, carry, 0), i);
674            carry = CreateLShr(carry, CreateZExt(ix_popcnt, iBitBlock)); // Remove the carry bits consumed, make room for new bits.
675            carry = CreateOr(carry, CreateShl(CreateZExt(bits, iBitBlock), CreateZExt(CreateSub(shiftVal, ix_popcnt), iBitBlock)));
676        }
677        return std::pair<Value *, Value *>{bitCast(carry), simd_pdep(bitWidth, result, index_strm)};
678    }
679    else {
680        // The shift amount is greater than the total popcount.   We will consume popcount
681        // bits from the shiftIn value only, and produce a carry out value of the selected bits.
682        Value * carry = CreateBitCast(shiftIn, iBitBlock);
[5832]683        Value * result = UndefValue::get(vecTy);
684        Value * carryOut = ConstantInt::getNullValue(iBitBlock);
[5730]685        Value * generated = getSize(0);
[5832]686        for (unsigned i = 0; i < n; i++) {
[5730]687            Value * ix_popcnt = mvmd_extract(bitWidth, ix_popcounts, i);
688            Value * bits = mvmd_extract(bitWidth, extracted_bits, i);  // All these bits are shifted out (appended to carry).
689            result = mvmd_insert(bitWidth, result, mvmd_extract(bitWidth, carry, 0), i);
690            carry = CreateLShr(carry, CreateZExt(ix_popcnt, iBitBlock)); // Remove the carry bits consumed.
691            carryOut = CreateOr(carryOut, CreateShl(CreateZExt(bits, iBitBlock), CreateZExt(generated, iBitBlock)));
692            generated = CreateAdd(generated, ix_popcnt);
693        }
694        return std::pair<Value *, Value *>{bitCast(carryOut), simd_pdep(bitWidth, result, index_strm)};
695    }
[5713]696}
697
[5730]698
[5121]699Value * IDISA_Builder::bitblock_mask_from(Value * pos) {
[5972]700    Value * p = CreateZExtOrTrunc(pos, getSizeTy());
701    const unsigned fw = getSizeTy()->getBitWidth();
702    const auto field_count = mBitBlockWidth / fw;
703    Constant * fwVal = ConstantInt::get(getSizeTy(), fw);
704    Constant * poaBase[field_count];
705    for (unsigned i = 0; i < field_count; i++) {
706        poaBase[i] = ConstantInt::get(getSizeTy(), fw * i);
707    }
708    Value * posBaseVec = ConstantVector::get({poaBase, field_count});
709    Value * mask1 = CreateSExt(CreateICmpUGT(posBaseVec, simd_fill(fw, pos)), fwVectorType(fw));
710    Value * bitField = CreateShl(ConstantInt::getAllOnesValue(getSizeTy()), CreateURem(p, fwVal));
711    Value * inBitBlock = CreateICmpULT(p, getSize(mBitBlockWidth));
712    Value * fieldNo = CreateUDiv(p, fwVal);
713    Value * const final_mask = CreateSelect(inBitBlock, CreateInsertElement(mask1, bitField, fieldNo), mask1);
714    return bitCast(final_mask);
[5121]715}
[5830]716
[5121]717Value * IDISA_Builder::bitblock_set_bit(Value * pos) {
[5972]718    Value * p = CreateZExtOrTrunc(pos, getSizeTy());
719    const unsigned fw = getSizeTy()->getBitWidth();
720    Constant * fwVal = ConstantInt::get(getSizeTy(), fw);
721    Value * bitField = CreateShl(ConstantInt::get(getSizeTy(), 1), CreateURem(p, fwVal));
722    Value * fieldNo = CreateUDiv(p, fwVal);
723    return bitCast(CreateInsertElement(Constant::getNullValue(fwVectorType(fw)), bitField, fieldNo));
[5121]724}
725
[5985]726Value * IDISA_Builder::bitblock_popcount(Value * const to_count) {
727    const auto fieldWidth = getSizeTy()->getBitWidth();
728    auto fields = (getBitBlockWidth() / fieldWidth);
729    Value * fieldCounts = simd_popcount(fieldWidth, to_count);
730    while (fields > 1) {
731        fields /= 2;
732        fieldCounts = CreateAdd(fieldCounts, mvmd_srli(fieldWidth, fieldCounts, fields));
733    }
734    return mvmd_extract(fieldWidth, fieldCounts, 0);
735}
736
[4837]737Value * IDISA_Builder::simd_and(Value * a, Value * b) {
[4898]738    return a->getType() == b->getType() ? CreateAnd(a, b) : CreateAnd(bitCast(a), bitCast(b));
[4665]739}
[4837]740
741Value * IDISA_Builder::simd_or(Value * a, Value * b) {
[4898]742    return a->getType() == b->getType() ? CreateOr(a, b) : CreateOr(bitCast(a), bitCast(b));
[4837]743}
744   
745Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
[4898]746    return a->getType() == b->getType() ? CreateXor(a, b) : CreateXor(bitCast(a), bitCast(b));
[4837]747}
748
749Value * IDISA_Builder::simd_not(Value * a) {
750    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
751}
752
[5865]753IDISA_Builder::IDISA_Builder(LLVMContext & C, unsigned vectorWidth, unsigned stride)
[5489]754: CBuilder(C)
755, mBitBlockWidth(vectorWidth)
[5240]756, mStride(stride)
[5489]757, mBitBlockType(VectorType::get(IntegerType::get(C, 64), vectorWidth / 64))
[5240]758, mZeroInitializer(Constant::getNullValue(mBitBlockType))
759, mOneInitializer(Constant::getAllOnesValue(mBitBlockType))
760, mPrintRegisterFunction(nullptr) {
761
[5230]762}
[5240]763
764IDISA_Builder::~IDISA_Builder() {
[5298]765
[5240]766}
767
768}
Note: See TracBrowser for help on using the repository browser.