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

Last change on this file since 6110 was 6110, checked in by cameron, 10 months ago

Prefer simd_select_hi/select_lo in place of simd_himask/lomask for arbitrary vector width

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