source: icGREP/icgrep-devel/icgrep/IR_Gen/idisa_avx_builder.cpp @ 6184

Last change on this file since 6184 was 6184, checked in by nmedfort, 6 months ago

Initial version of PipelineKernel? + revised StreamSet? model.

File size: 48.4 KB
Line 
1/*
2 *  Copyright (c) 2018 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_avx_builder.h"
8#include <toolchain/toolchain.h>
9#include <llvm/Support/raw_ostream.h>
10#include <llvm/IR/Intrinsics.h>
11
12using namespace llvm;
13
14namespace IDISA {
15
16std::string IDISA_AVX_Builder::getBuilderUniqueName() {
17    return mBitBlockWidth != 256 ? "AVX_" + std::to_string(mBitBlockWidth) : "AVX";
18}
19
20Value * IDISA_AVX_Builder::hsimd_signmask(unsigned fw, Value * a) {
21    // AVX2 special cases
22    if (mBitBlockWidth == 256) {
23        if (fw == 64) {
24            Value * signmask_f64func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx_movmsk_pd_256);
25            Type * bitBlock_f64type = VectorType::get(getDoubleTy(), mBitBlockWidth/64);
26            Value * a_as_pd = CreateBitCast(a, bitBlock_f64type);
27            return CreateCall(signmask_f64func, a_as_pd);
28        } else if (fw == 32) {
29            Value * signmask_f32func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx_movmsk_ps_256);
30            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
31            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
32            return CreateCall(signmask_f32func, a_as_ps);
33        }
34    } else if (mBitBlockWidth == 512) {
35        if (fw == 64) {
36            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth / 32);
37            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
38            Constant * indicies[8];
39            for (unsigned i = 0; i < 8; i++) {
40                indicies[i] = getInt32(2 * i + 1);
41            }
42            Value * packh = CreateShuffleVector(a_as_ps, UndefValue::get(bitBlock_f32type), ConstantVector::get({indicies, 8}));
43            Type * halfBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/64);
44            Value * pack_as_ps = CreateBitCast(packh, halfBlock_f32type);
45            Value * signmask_f32func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx_movmsk_ps_256);
46            return CreateCall(signmask_f32func, pack_as_ps);
47        }
48    }
49    // Otherwise use default SSE2 logic.
50    return IDISA_SSE2_Builder::hsimd_signmask(fw, a);
51}
52
53std::string IDISA_AVX2_Builder::getBuilderUniqueName() {
54    return mBitBlockWidth != 256 ? "AVX2_" + std::to_string(mBitBlockWidth) : "AVX2";
55}
56
57Value * IDISA_AVX2_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
58    if ((fw > 8) && (fw <= 64)) {
59        Value * aVec = fwCast(fw / 2, a);
60        Value * bVec = fwCast(fw / 2, b);
61        const auto field_count = 2 * mBitBlockWidth / fw;
62        Constant * Idxs[field_count];
63        const auto H = (field_count / 2);
64        const auto Q = (field_count / 4);
65        for (unsigned i = 0; i < Q; i++) {
66            Idxs[i] = getInt32(2 * i);
67            Idxs[i + Q] = getInt32((2 * i) + 1);
68            Idxs[i + H] = getInt32((2 * i) + H);
69            Idxs[i + H + Q] = getInt32((2 * i) + 1 + H);
70        }
71        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get({Idxs, field_count}));
72        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get({Idxs, field_count}));
73        return hsimd_packh(mBitBlockWidth / 2, shufa, shufb);
74    }
75    // Otherwise use default SSE logic.
76    return IDISA_SSE2_Builder::hsimd_packh(fw, a, b);
77}
78
79Value * IDISA_AVX2_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
80    if ((fw > 8) && (fw <= 64)) {
81        Value * aVec = fwCast(fw / 2, a);
82        Value * bVec = fwCast(fw / 2, b);
83        const auto field_count = 2 * mBitBlockWidth / fw;
84        Constant * Idxs[field_count];
85        const auto H = (field_count / 2);
86        const auto Q = (field_count / 4);
87        for (unsigned i = 0; i < Q; i++) {
88            Idxs[i] = getInt32(2 * i);
89            Idxs[i + Q] = getInt32((2 * i) + 1);
90            Idxs[i + H] = getInt32((2 * i) + H);
91            Idxs[i + H + Q] = getInt32((2 * i) + H + 1);
92        }
93        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get({Idxs, field_count}));
94        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get({Idxs, field_count}));
95        return hsimd_packl(mBitBlockWidth / 2, shufa, shufb);
96    }
97    // Otherwise use default SSE logic.
98    return IDISA_SSE2_Builder::hsimd_packl(fw, a, b);
99}
100
101Value * IDISA_AVX2_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
102    if (getVectorBitWidth(a) == mNativeBitBlockWidth) {
103        if ((fw == 1) || (fw == 2)) {
104            // Bit interleave using shuffle.
105            Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx2_pshuf_b);
106            // Make a shuffle table that translates the lower 4 bits of each byte in
107            // order to spread out the bits: xxxxdcba => .d.c.b.a
108            // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
109            Constant * interleave_table = bit_interleave_byteshuffle_table(fw);
110            // Merge the bytes.
111            Value * byte_merge = esimd_mergeh(8, a, b);
112            Value * low_bits = CreateCall(shufFn, {interleave_table,  fwCast(8, simd_select_lo(8, byte_merge))});
113            Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4))}), fw);
114            // For each 16-bit field, interleave the low bits of the two bytes.
115            low_bits = simd_or(simd_select_lo(16, low_bits), simd_srli(16, low_bits, 8-fw));
116            // For each 16-bit field, interleave the high bits of the two bytes.
117            high_bits = simd_or(simd_select_hi(16, high_bits), simd_slli(16, high_bits, 8-fw));
118            return simd_or(low_bits, high_bits);
119        }
120#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(6, 0, 0)
121        if (fw == 128) {
122            Value * vperm2i128func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_vperm2i128);
123            return CreateCall(vperm2i128func, {fwCast(64, a), fwCast(64, b), getInt8(0x31)});
124        }
125#endif
126    }
127    // Otherwise use default SSE logic.
128    return IDISA_SSE2_Builder::esimd_mergeh(fw, a, b);
129}
130
131Value * IDISA_AVX2_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
132    if (getVectorBitWidth(a) == mNativeBitBlockWidth) {
133        if ((fw == 1) || (fw == 2)) {
134            // Bit interleave using shuffle.
135            Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx2_pshuf_b);
136            // Make a shuffle table that translates the lower 4 bits of each byte in
137            // order to spread out the bits: xxxxdcba => .d.c.b.a
138            // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
139            Constant * interleave_table = bit_interleave_byteshuffle_table(fw);
140            // Merge the bytes.
141            Value * byte_merge = esimd_mergel(8, a, b);
142            Value * low_bits = CreateCall(shufFn, {interleave_table,  fwCast(8, simd_select_lo(8, byte_merge))});
143            Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4))}), fw);
144            // For each 16-bit field, interleave the low bits of the two bytes.
145            low_bits = simd_or(simd_select_lo(16, low_bits), simd_srli(16, low_bits, 8-fw));
146            // For each 16-bit field, interleave the high bits of the two bytes.
147            high_bits = simd_or(simd_select_hi(16, high_bits), simd_slli(16, high_bits, 8-fw));
148            return simd_or(low_bits, high_bits);
149        }
150    #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(6, 0, 0)
151        if ((fw == 128) && (mBitBlockWidth == 256)) {
152            Value * vperm2i128func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_vperm2i128);
153            return CreateCall(vperm2i128func, {fwCast(64, a), fwCast(64, b), getInt8(0x20)});
154        }
155    #endif
156    }
157    // Otherwise use default SSE logic.
158    return IDISA_SSE_Builder::esimd_mergel(fw, a, b);
159}
160
161Value * IDISA_AVX2_Builder::hsimd_packl_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
162    if ((fw == 16)  && (lanes == 2)) {
163        Value * vpackuswbfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_packuswb);
164        Value * a_low = fwCast(16, simd_and(a, simd_lomask(fw)));
165        Value * b_low = fwCast(16, simd_and(b, simd_lomask(fw)));
166        return CreateCall(vpackuswbfunc, {a_low, b_low});
167    }
168    // Otherwise use default SSE logic.
169    return IDISA_SSE_Builder::hsimd_packl_in_lanes(lanes, fw, a, b);
170}
171
172Value * IDISA_AVX2_Builder::hsimd_packh_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
173    if ((fw == 16)  && (lanes == 2)) {
174        Value * vpackuswbfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_packuswb);
175        Value * a_low = simd_srli(fw, a, fw/2);
176        Value * b_low = simd_srli(fw, b, fw/2);
177        return CreateCall(vpackuswbfunc, {a_low, b_low});
178    }
179    // Otherwise use default SSE logic.
180    return IDISA_SSE_Builder::hsimd_packh_in_lanes(lanes, fw, a, b);
181}
182
183std::pair<Value *, Value *> IDISA_AVX2_Builder::bitblock_add_with_carry(Value * e1, Value * e2, Value * carryin) {
184    // using LONG_ADD
185    Type * carryTy = carryin->getType();
186    if (carryTy == mBitBlockType) {
187        carryin = mvmd_extract(32, carryin, 0);
188    }
189    Value * carrygen = simd_and(e1, e2);
190    Value * carryprop = simd_or(e1, e2);
191    Value * digitsum = simd_add(64, e1, e2);
192    Value * digitcarry = simd_or(carrygen, simd_and(carryprop, CreateNot(digitsum)));
193    Value * carryMask = hsimd_signmask(64, digitcarry);
194    Value * carryMask2 = CreateOr(CreateAdd(carryMask, carryMask), carryin);
195    Value * bubble = simd_eq(64, digitsum, allOnes());
196    Value * bubbleMask = hsimd_signmask(64, bubble);
197    Value * incrementMask = CreateXor(CreateAdd(bubbleMask, carryMask2), bubbleMask);
198    Value * increments = esimd_bitspread(64,incrementMask);
199    Value * sum = simd_add(64, digitsum, increments);
200    Value * carry_out = CreateLShr(incrementMask, mBitBlockWidth / 64);
201    if (carryTy == mBitBlockType) {
202        carry_out = bitCast(CreateZExt(carry_out, getIntNTy(mBitBlockWidth)));
203    }
204    return std::pair<Value *, Value *>{carry_out, bitCast(sum)};
205}
206
207Value * IDISA_AVX2_Builder::simd_pext(unsigned fieldwidth, Value * v, Value * extract_mask) {
208    if ((fieldwidth == 64) || (fieldwidth == 32)) {
209        Value * PEXT_f = (fieldwidth == 64) ? Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pext_64)
210                                            : Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pext_32);
211        const auto n = getBitBlockWidth() / fieldwidth;
212        Value * result = UndefValue::get(fwVectorType(fieldwidth));
213        for (unsigned i = 0; i < n; i++) {
214            Value * v_i = mvmd_extract(fieldwidth, v, i);
215            Value * mask_i = mvmd_extract(fieldwidth, extract_mask, i);
216            Value * bits = CreateCall(PEXT_f, {v_i, mask_i});
217            result = mvmd_insert(fieldwidth, result, bits, i);
218        }
219        return bitCast(result);
220    }
221    return IDISA_Builder::simd_pext(fieldwidth, v, extract_mask);
222}
223
224Value * IDISA_AVX2_Builder::simd_pdep(unsigned fieldwidth, Value * v, Value * deposit_mask) {
225    if ((fieldwidth == 64) || (fieldwidth == 32)) {
226        Value * PDEP_f = (fieldwidth == 64) ? Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_64)
227                                            : Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_32);
228        const auto n = getBitBlockWidth() / fieldwidth;
229        Value * result = UndefValue::get(fwVectorType(fieldwidth));
230        for (unsigned i = 0; i < n; i++) {
231            Value * v_i = mvmd_extract(fieldwidth, v, i);
232            Value * mask_i = mvmd_extract(fieldwidth, deposit_mask, i);
233            Value * bits = CreateCall(PDEP_f, {v_i, mask_i});
234            result = mvmd_insert(fieldwidth, result, bits, i);
235        }
236        return bitCast(result);
237    }
238    return IDISA_Builder::simd_pdep(fieldwidth, v, deposit_mask);
239}
240
241std::pair<Value *, Value *> IDISA_AVX2_Builder::bitblock_indexed_advance(Value * strm, Value * index_strm, Value * shiftIn, unsigned shiftAmount) {
242    const unsigned bitWidth = getSizeTy()->getBitWidth();
243    if ((bitWidth == 64) || (bitWidth == 32)) {
244        Value * PEXT_f = (bitWidth == 64) ? Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pext_64)
245                                          : Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pext_32);
246        Value * PDEP_f = (bitWidth == 64) ? Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_64)
247                                          : Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_32);
248        Value * const popcount = Intrinsic::getDeclaration(getModule(), Intrinsic::ctpop, getSizeTy());
249        Type * iBitBlock = getIntNTy(getBitBlockWidth());
250        Value * shiftVal = getSize(shiftAmount);
251        const auto n = getBitBlockWidth() / bitWidth;
252        VectorType * const vecTy = VectorType::get(getSizeTy(), n);
253        if (LLVM_LIKELY(shiftAmount < bitWidth)) {
254            Value * carry = mvmd_extract(bitWidth, shiftIn, 0);
255            Value * result = UndefValue::get(vecTy);
256            for (unsigned i = 0; i < n; i++) {
257                Value * s = mvmd_extract(bitWidth, strm, i);
258                Value * ix = mvmd_extract(bitWidth, index_strm, i);
259                Value * ix_popcnt = CreateCall(popcount, {ix});
260                Value * bits = CreateCall(PEXT_f, {s, ix});
261                Value * adv = CreateOr(CreateShl(bits, shiftAmount), carry);
262                // We have two cases depending on whether the popcount of the index pack is < shiftAmount or not.
263                Value * popcount_small = CreateICmpULT(ix_popcnt, shiftVal);
264                Value * carry_if_popcount_small =
265                    CreateOr(CreateShl(bits, CreateSub(shiftVal, ix_popcnt)),
266                                CreateLShr(carry, ix_popcnt));
267                Value * carry_if_popcount_large = CreateLShr(bits, CreateSub(ix_popcnt, shiftVal));
268                carry = CreateSelect(popcount_small, carry_if_popcount_small, carry_if_popcount_large);
269                result = mvmd_insert(bitWidth, result, CreateCall(PDEP_f, {adv, ix}), i);
270            }
271            Value * carryOut = mvmd_insert(bitWidth, allZeroes(), carry, 0);
272            return std::pair<Value *, Value *>{bitCast(carryOut), bitCast(result)};
273        }
274        else if (shiftAmount <= mBitBlockWidth) {
275            // The shift amount is always greater than the popcount of the individual
276            // elements that we deal with.   This simplifies some of the logic.
277            Value * carry = CreateBitCast(shiftIn, iBitBlock);
278            Value * result = UndefValue::get(vecTy);
279            for (unsigned i = 0; i < n; i++) {
280                Value * s = mvmd_extract(bitWidth, strm, i);
281                Value * ix = mvmd_extract(bitWidth, index_strm, i);
282                Value * ix_popcnt = CreateCall(popcount, {ix});
283                Value * bits = CreateCall(PEXT_f, {s, ix});  // All these bits are shifted out (appended to carry).
284                result = mvmd_insert(bitWidth, result, CreateCall(PDEP_f, {mvmd_extract(bitWidth, carry, 0), ix}), i);
285                carry = CreateLShr(carry, CreateZExt(ix_popcnt, iBitBlock)); // Remove the carry bits consumed, make room for new bits.
286                carry = CreateOr(carry, CreateShl(CreateZExt(bits, iBitBlock), CreateZExt(CreateSub(shiftVal, ix_popcnt), iBitBlock)));
287            }
288            return std::pair<Value *, Value *>{bitCast(carry), bitCast(result)};
289        }
290        else {
291            // The shift amount is greater than the total popcount.   We will consume popcount
292            // bits from the shiftIn value only, and produce a carry out value of the selected bits.
293            // elements that we deal with.   This simplifies some of the logic.
294            Value * carry = CreateBitCast(shiftIn, iBitBlock);
295            Value * result = UndefValue::get(vecTy);
296            Value * carryOut = ConstantInt::getNullValue(iBitBlock);
297            Value * generated = getSize(0);
298            for (unsigned i = 0; i < n; i++) {
299                Value * s = mvmd_extract(bitWidth, strm, i);
300                Value * ix = mvmd_extract(bitWidth, index_strm, i);
301                Value * ix_popcnt = CreateCall(popcount, {ix});
302                Value * bits = CreateCall(PEXT_f, {s, ix});  // All these bits are shifted out (appended to carry).
303                result = mvmd_insert(bitWidth, result, CreateCall(PDEP_f, {mvmd_extract(bitWidth, carry, 0), ix}), i);
304                carry = CreateLShr(carry, CreateZExt(ix_popcnt, iBitBlock)); // Remove the carry bits consumed.
305                carryOut = CreateOr(carryOut, CreateShl(CreateZExt(bits, iBitBlock), CreateZExt(generated, iBitBlock)));
306                generated = CreateAdd(generated, ix_popcnt);
307            }
308            return std::pair<Value *, Value *>{bitCast(carryOut), bitCast(result)};
309        }
310    }
311    return IDISA_Builder::bitblock_indexed_advance(strm, index_strm, shiftIn, shiftAmount);
312}
313
314Value * IDISA_AVX2_Builder::hsimd_signmask(unsigned fw, Value * a) {
315    // AVX2 special cases
316    if (mBitBlockWidth == 256) {
317        if (fw == 8) {
318            Value * signmask_f8func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_pmovmskb);
319            Type * bitBlock_i8type = VectorType::get(getInt8Ty(), mBitBlockWidth/8);
320            Value * a_as_ps = CreateBitCast(a, bitBlock_i8type);
321            return CreateCall(signmask_f8func, a_as_ps);
322        }
323    }
324    // Otherwise use default SSE logic.
325    return IDISA_AVX_Builder::hsimd_signmask(fw, a);
326}
327
328llvm::Value * IDISA_AVX2_Builder::mvmd_srl(unsigned fw, llvm::Value * a, llvm::Value * shift, const bool safe) {
329    // Intrinsic::x86_avx2_permd) allows an efficient implementation for field width 32.
330    // Translate larger field widths to 32 bits.
331    if (fw > 32) {
332        return fwCast(fw, mvmd_srl(32, a, CreateMul(shift, ConstantInt::get(shift->getType(), fw/32)), safe));
333    }
334    if ((mBitBlockWidth == 256) && (fw == 32)) {
335        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_permd);
336        const unsigned fieldCount = mBitBlockWidth/fw;
337        Type * fieldTy = getIntNTy(fw);
338        Constant * indexes[fieldCount];
339        for (unsigned int i = 0; i < fieldCount; i++) {
340            indexes[i] = ConstantInt::get(fieldTy, i);
341        }
342        Constant * indexVec = ConstantVector::get({indexes, fieldCount});
343        Constant * fieldCountSplat = ConstantVector::getSplat(fieldCount, ConstantInt::get(fieldTy, fieldCount));
344        Value * shiftSplat = simd_fill(fw, CreateZExtOrTrunc(shift, fieldTy));
345        Value * permuteVec = CreateAdd(indexVec, shiftSplat);
346        // Zero out fields that are above the max.
347        permuteVec = simd_and(permuteVec, simd_ult(fw, permuteVec, fieldCountSplat));
348        // Insert a zero value at position 0 (OK for shifts > 0)
349        Value * a0 = mvmd_insert(fw, a, Constant::getNullValue(fieldTy), 0);
350        Value * shifted = CreateCall(permuteFunc, {a0, permuteVec});
351        return simd_if(1, simd_eq(fw, shiftSplat, allZeroes()), a, shifted);
352    }
353    return IDISA_Builder::mvmd_srl(fw, a, shift, safe);
354}
355
356llvm::Value * IDISA_AVX2_Builder::mvmd_sll(unsigned fw, llvm::Value * a, llvm::Value * shift, const bool safe) {
357    // Intrinsic::x86_avx2_permd) allows an efficient implementation for field width 32.
358    // Translate larger field widths to 32 bits.
359    if (fw > 32) {
360        return fwCast(fw, mvmd_sll(32, a, CreateMul(shift, ConstantInt::get(shift->getType(), fw/32)), safe));
361    }
362    if ((mBitBlockWidth == 256) && (fw == 32)) {
363        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_permd);
364        const unsigned fieldCount = mBitBlockWidth/fw;
365        Type * fieldTy = getIntNTy(fw);
366        Constant * indexes[fieldCount];
367        for (unsigned int i = 0; i < fieldCount; i++) {
368            indexes[i] = ConstantInt::get(fieldTy, i);
369        }
370        Constant * indexVec = ConstantVector::get({indexes, fieldCount});
371        Value * shiftSplat = simd_fill(fw, CreateZExtOrTrunc(shift, fieldTy));
372        Value * permuteVec = CreateSub(indexVec, shiftSplat);
373        // Negative indexes are for fields that must be zeroed.  Convert the
374        // permute constant to an all ones value, that will select item 7.
375        permuteVec = simd_or(permuteVec, simd_lt(fw, permuteVec, fwCast(fw, allZeroes())));
376        // Insert a zero value at position 7 (OK for shifts > 0)
377        Value * a0 = mvmd_insert(fw, a, Constant::getNullValue(fieldTy), 7);
378        Value * shifted = CreateCall(permuteFunc, {a0, permuteVec});
379        return simd_if(1, simd_eq(fw, shiftSplat, allZeroes()), a, shifted);
380    }
381    return IDISA_Builder::mvmd_sll(fw, a, shift, safe);
382}
383
384   
385llvm::Value * IDISA_AVX2_Builder::mvmd_shuffle(unsigned fw, llvm::Value * a, llvm::Value * index_vector) {
386    if (mBitBlockWidth == 256 && fw > 32) {
387        const unsigned fieldCount = mBitBlockWidth/fw;
388        // Create a table for shuffling with smaller field widths.
389        Constant * idxMask = ConstantVector::getSplat(fieldCount, ConstantInt::get(getIntNTy(fw), fieldCount-1));
390        Value * idx = simd_and(index_vector, idxMask);
391        unsigned half_fw = fw/2;
392        unsigned field_count = mBitBlockWidth/half_fw;
393        // Build a ConstantVector of alternating 0 and 1 values.
394        Constant * Idxs[field_count];
395        for (unsigned int i = 0; i < field_count; i++) {
396            Idxs[i] = ConstantInt::get(getIntNTy(fw/2), i & 1);
397        }
398        Constant * splat01 = ConstantVector::get({Idxs, field_count});
399        Value * half_fw_indexes = simd_or(idx, mvmd_slli(half_fw, idx, 1));
400        half_fw_indexes = simd_add(fw, simd_add(fw, half_fw_indexes, half_fw_indexes), splat01);
401        Value * rslt = mvmd_shuffle(half_fw, a, half_fw_indexes);
402        return rslt;
403    }
404    if (mBitBlockWidth == 256 && fw == 32) {
405        Value * shuf32Func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx2_permd);
406        return CreateCall(shuf32Func, {fwCast(32, a), fwCast(32, index_vector)});
407    }
408    return IDISA_Builder::mvmd_shuffle(fw, a, index_vector);
409}
410
411llvm::Value * IDISA_AVX2_Builder::mvmd_compress(unsigned fw, llvm::Value * a, llvm::Value * select_mask) {
412    if (mBitBlockWidth == 256 && fw == 64) {
413        Value * PDEP_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_32);
414        Value * mask = CreateZExt(select_mask, getInt32Ty());
415        Value * mask32 = CreateMul(CreateCall(PDEP_func, {mask, getInt32(0x55)}), getInt32(3));
416        Value * result = fwCast(fw, mvmd_compress(32, fwCast(32, a), CreateTrunc(mask32, getInt8Ty())));
417        return result;
418    }
419    if (mBitBlockWidth == 256 && fw == 32) {
420        Type * v1xi32Ty = VectorType::get(getInt32Ty(), 1);
421        Type * v8xi32Ty = VectorType::get(getInt32Ty(), 8);
422        Type * v8xi1Ty = VectorType::get(getInt1Ty(), 8);
423        Constant * mask0000000Fsplaat = ConstantVector::getSplat(8, ConstantInt::get(getInt32Ty(), 0xF));
424        Value * PEXT_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pext_32);
425        Value * PDEP_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_bmi_pdep_32);
426        Value * const popcount_func = Intrinsic::getDeclaration(getModule(), Intrinsic::ctpop, getInt32Ty());
427        // First duplicate each mask bit to select 4-bit fields
428        Value * mask = CreateZExt(select_mask, getInt32Ty());
429        Value * field_count = CreateCall(popcount_func, mask);
430        Value * spread = CreateCall(PDEP_func, {mask, getInt32(0x11111111)});
431        Value * ext_mask = CreateMul(spread, getInt32(0xF));
432        // Now extract the 4-bit index values for the required fields.
433        Value * indexes = CreateCall(PEXT_func, {getInt32(0x76543210), ext_mask});
434        // Broadcast to all fields
435        Value * bdcst = CreateShuffleVector(CreateBitCast(indexes, v1xi32Ty),
436                                            UndefValue::get(v1xi32Ty),
437                                            ConstantVector::getNullValue(v8xi32Ty));
438        Constant * Shifts[8];
439        for (unsigned int i = 0; i < 8; i++) {
440            Shifts[i] = getInt32(i*4);
441        }
442        Value * shuf = CreateAnd(CreateLShr(bdcst, ConstantVector::get({Shifts, 8})), mask0000000Fsplaat);
443        Value * compress = mvmd_shuffle(32, a, shuf);
444        Value * field_mask = CreateTrunc(CreateSub(CreateShl(getInt32(1), field_count), getInt32(1)), getInt8Ty());
445        Value * result = CreateAnd(compress, CreateSExt(CreateBitCast(field_mask, v8xi1Ty), v8xi32Ty));
446        return result;
447    }
448    return IDISA_Builder::mvmd_compress(fw, a, select_mask);
449}
450
451#if LLVM_VERSION_INTEGER >= LLVM_VERSION_CODE(3, 8, 0)
452
453std::string IDISA_AVX512F_Builder::getBuilderUniqueName() {
454    return mBitBlockWidth != 512 ? "AVX512F_" + std::to_string(mBitBlockWidth) : "AVX512BW";
455}
456
457llvm::Value * IDISA_AVX512F_Builder::hsimd_packh(unsigned fw, llvm::Value * a, llvm::Value * b) {
458    if ((mBitBlockWidth == 512) && (fw == 16)) {
459
460        const unsigned int field_count = 64;
461        Constant * Idxs[field_count];
462
463        for (unsigned int i = 0; i < field_count; i++) {
464            Idxs[i] = getInt32(i);
465        }
466
467        llvm::Value * pmovfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_pmov_wb_512);
468        llvm::Value * mask = getInt32(-1);
469        llvm::Constant * shuffleMask = ConstantVector::get({Idxs, 64});
470        llvm::Constant * src = UndefValue::get(VectorType::get(getInt8Ty(), 32));
471
472        a = fwCast(fw, a);
473        a = IDISA_Builder::simd_srli(fw, a, fw/2);
474        a = CreateCall(pmovfunc, {a, src, mask});
475        b = fwCast(fw, b);
476        b = IDISA_Builder::simd_srli(fw, b, fw/2);
477        b = CreateCall(pmovfunc, {b, src, mask});
478
479        llvm::Value * c = CreateShuffleVector(a, b, shuffleMask);
480        c = bitCast(c);
481        return c;
482    }
483    return IDISA_Builder::hsimd_packh(fw, a, b);
484}
485
486llvm::Value * IDISA_AVX512F_Builder::hsimd_packl(unsigned fw, llvm::Value * a, llvm::Value * b) {
487    if ((mBitBlockWidth == 512) && (fw == 16)) {
488
489        const unsigned int field_count = 64;
490        Constant * Idxs[field_count];
491        for (unsigned int i = 0; i < field_count; i++) {
492            Idxs[i] = getInt32(i);
493        }
494
495        llvm::Value * pmovfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_pmov_wb_512);
496        llvm::Value * mask = getInt32(-1);
497        llvm::Constant * shuffleMask = ConstantVector::get({Idxs, 64});
498        llvm::Constant * src = UndefValue::get(VectorType::get(getInt8Ty(), 32));
499        a = fwCast(fw, a);
500        a = CreateCall(pmovfunc, {a, src, mask});
501        b = fwCast(fw, b);
502        b = CreateCall(pmovfunc, {b, src, mask});
503
504        llvm::Value * c = CreateShuffleVector(a, b, shuffleMask);
505        c = bitCast(c);
506        return c;
507    }
508    return IDISA_Builder::hsimd_packl(fw, a, b);
509}
510
511llvm::Value * IDISA_AVX512F_Builder::esimd_bitspread(unsigned fw, llvm::Value * bitmask) {
512   
513    if (mBitBlockWidth == 512 && fw == 64) {
514        Value * broadcastFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_broadcasti64x4_512);
515        Value * broadcastMask = CreateZExtOrTrunc(bitmask, getInt8Ty());
516       
517        const unsigned int srcFieldCount = 8;
518        Constant * srcArr[srcFieldCount];
519        for (unsigned int i = 0; i < srcFieldCount; i++) {
520            srcArr[i] = getInt64(0);
521        }
522        Constant * src = ConstantVector::get({srcArr, srcFieldCount});
523       
524        const unsigned int aFieldCount = 4;
525        Constant * aArr[aFieldCount];
526        for (unsigned int i = 0; i < aFieldCount; i++) {
527            aArr[i] = getInt64(1);
528        }
529        Constant * a = ConstantVector::get({aArr, aFieldCount});
530       
531        return CreateCall(broadcastFunc, {a, src, broadcastMask});
532    }
533   
534    return IDISA_Builder::esimd_bitspread(fw, bitmask);
535}
536
537llvm::Value * IDISA_AVX512F_Builder::mvmd_srl(unsigned fw, llvm::Value * a, llvm::Value * shift, const bool safe) {
538    const unsigned fieldCount = mBitBlockWidth/fw;
539    Type * fieldTy = getIntNTy(fw);
540    Constant * indexes[fieldCount];
541    for (unsigned int i = 0; i < fieldCount; i++) {
542        indexes[i] = ConstantInt::get(fieldTy, i);
543    }
544    Constant * indexVec = ConstantVector::get({indexes, fieldCount});
545    Value * permuteVec = CreateAdd(indexVec, simd_fill(fw, CreateZExtOrTrunc(shift, fieldTy)));
546    Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
547    if (mBitBlockWidth == 512) {
548        Value * permuteFunc = nullptr;
549        if (fw == 64) permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_q_512);
550        else if (fw == 32) permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_d_512);
551        if (permuteFunc) {
552            Value * shifted = CreateCall(permuteFunc, {permuteVec, fwCast(fw, a), fwCast(fw, allZeroes()), mask});
553            return shifted;
554        }
555    }
556    return IDISA_Builder::mvmd_srl(fw, a, shift, safe);
557}
558 
559llvm::Value * IDISA_AVX512F_Builder::mvmd_sll(unsigned fw, llvm::Value * a, llvm::Value * shift, const bool safe) {
560    const unsigned fieldCount = mBitBlockWidth/fw;
561    Type * fieldTy = getIntNTy(fw);
562    Constant * indexes[fieldCount];
563    for (unsigned int i = 0; i < fieldCount; i++) {
564        indexes[i] = ConstantInt::get(fieldTy, fieldCount + i);
565    }
566    Constant * indexVec = ConstantVector::get({indexes, fieldCount});
567    Value * permuteVec = CreateSub(indexVec, simd_fill(fw, CreateZExtOrTrunc(shift, fieldTy)));
568    Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
569    if (mBitBlockWidth == 512) {
570        Value * permuteFunc = nullptr;
571        if (fw == 64) permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_q_512);
572        else if (fw == 32) permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_d_512);
573        if (permuteFunc) {
574            Value * shifted = CreateCall(permuteFunc, {permuteVec, fwCast(fw, allZeroes()), fwCast(fw, a), mask});
575            return shifted;
576        }
577    }
578    return IDISA_Builder::mvmd_sll(fw, a, shift);
579}
580
581llvm::Value * IDISA_AVX512F_Builder::mvmd_shuffle(unsigned fw, llvm::Value * data_table, llvm::Value * index_vector) {
582    const unsigned fieldCount = mBitBlockWidth/fw;
583    if (mBitBlockWidth == 512 && fw == 32) {
584        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_d_512);
585        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
586        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, data_table), fwCast(fw, data_table), mask});
587    }
588    if (mBitBlockWidth == 512 && fw == 64) {
589        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_q_512);
590        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
591        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, data_table), fwCast(fw, data_table), mask});
592    }
593    if (mBitBlockWidth == 512 && fw == 16 && hostCPUFeatures.hasAVX512BW) {
594        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
595        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
596        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, data_table), fwCast(fw, data_table), mask});
597    }
598    return IDISA_Builder::mvmd_shuffle(fw, data_table, index_vector);
599}
600
601llvm::Value * IDISA_AVX512F_Builder::mvmd_shuffle2(unsigned fw, Value * table0, llvm::Value * table1, llvm::Value * index_vector) {
602    const unsigned fieldCount = mBitBlockWidth/fw;
603    if (mBitBlockWidth == 512 && fw == 32) {
604        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_d_512);
605        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
606        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, table0), fwCast(fw, table1), mask});
607    }
608    if (mBitBlockWidth == 512 && fw == 64) {
609        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_vpermt2var_q_512);
610        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
611        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, table0), fwCast(fw, table1), mask});
612    }
613    if (mBitBlockWidth == 512 && fw == 16 && hostCPUFeatures.hasAVX512BW) {
614        Value * permuteFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
615        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
616        return CreateCall(permuteFunc, {fwCast(fw, index_vector), fwCast(fw, table0), fwCast(fw, table1), mask});
617    }
618    return IDISA_Builder::mvmd_shuffle2(fw, table0, table1, index_vector);
619}
620
621llvm::Value * IDISA_AVX512F_Builder::mvmd_compress(unsigned fw, llvm::Value * a, llvm::Value * select_mask) {
622    if (mBitBlockWidth == 512 && fw == 32) {
623        Value * compressFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_compress_d_512);
624        return CreateCall(compressFunc, {fwCast(32, a), fwCast(32, allZeroes()), CreateZExtOrTrunc(select_mask, getInt16Ty())});
625    }
626    if (mBitBlockWidth == 512 && fw == 64) {
627        Value * compressFunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_compress_q_512);
628        return CreateCall(compressFunc, {fwCast(64, a), fwCast(64, allZeroes()), CreateZExtOrTrunc(select_mask, getInt8Ty())});
629    }
630    return IDISA_Builder::mvmd_compress(fw, a, select_mask);
631}
632
633Value * IDISA_AVX512F_Builder:: mvmd_slli(unsigned fw, llvm::Value * a, unsigned shift) {
634    if (shift == 0) return a;
635    if (fw > 32) {
636        return mvmd_slli(32, a, shift * (fw/32));
637    } else if (((shift % 2) == 0) && (fw < 32)) {
638        return mvmd_slli(2 * fw, a, shift / 2);
639    }
640    const unsigned fieldCount = mBitBlockWidth/fw;
641    if ((fw == 32) || (hostCPUFeatures.hasAVX512BW && (fw == 16)))   {
642        // Mask with 1 bit per field indicating which fields are not zeroed out.
643        Type * fwTy = getIntNTy(fw);
644        Constant * fieldMask = ConstantInt::get(getIntNTy(fieldCount), (1 << fieldCount) - (1 << shift));
645        Value * permute_func = nullptr;
646        if (fw == 32) permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_d_512);
647        else permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
648        Constant * indices[fieldCount];
649        for (unsigned i = 0; i < fieldCount; i++) {
650            indices[i] = i < shift ? UndefValue::get(fwTy) : ConstantInt::get(fwTy, i - shift);
651        }
652        Value * args[4] = {ConstantVector::get({indices, fieldCount}), fwCast(fw, a), UndefValue::get(fwVectorType(fw)), fieldMask};
653        return bitCast(CreateCall(permute_func, args));
654    } else {
655        unsigned field32_shift = (shift * fw) / 32;
656        unsigned bit_shift = (shift * fw) % 32;
657        return simd_or(simd_slli(32, mvmd_slli(32, a, field32_shift), bit_shift),
658                       simd_srli(32, mvmd_slli(32, a, field32_shift + 1), 32-bit_shift));
659    }
660}
661
662Value * IDISA_AVX512F_Builder:: mvmd_dslli(unsigned fw, llvm::Value * a, llvm::Value * b, unsigned shift) {
663    if (shift == 0) return a;
664    if (fw > 32) {
665        return mvmd_dslli(32, a, b, shift * (fw/32));
666    } else if (((shift % 2) == 0) && (fw < 32)) {
667        return mvmd_dslli(2 * fw, a, b, shift / 2);
668    }
669    const unsigned fieldCount = mBitBlockWidth/fw;
670    if ((fw == 32) || (hostCPUFeatures.hasAVX512BW && (fw == 16)))   {
671        Type * fwTy = getIntNTy(fw);
672        Value * permute_func = nullptr;
673        if (fw == 32) permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_d_512);
674        else permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
675        Constant * indices[fieldCount];
676        for (unsigned i = 0; i < fieldCount; i++) {
677            indices[i] = ConstantInt::get(fwTy, i + fieldCount - shift);
678        }
679        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
680        Value * args[4] = {ConstantVector::get({indices, fieldCount}), fwCast(fw, b), fwCast(fw, a), mask};
681        return bitCast(CreateCall(permute_func, args));
682    } else {
683        unsigned field32_shift = (shift * fw) / 32;
684        unsigned bit_shift = (shift * fw) % 32;
685        return simd_or(simd_slli(32, mvmd_dslli(32, a, b, field32_shift), bit_shift),
686                       simd_srli(32, mvmd_dslli(32, a, b, field32_shift + 1), 32-bit_shift));
687    }
688}
689
690llvm::Value * IDISA_AVX512F_Builder::simd_popcount(unsigned fw, llvm::Value * a) {
691     if (fw == 512) {
692         Constant * zero16xi8 = Constant::getNullValue(VectorType::get(getInt8Ty(), 16));
693         Constant * zeroInt32 = Constant::getNullValue(getInt32Ty());
694         Value * c = simd_popcount(64, a);
695         //  Should probably use _mm512_reduce_add_epi64, but not found in LLVM 3.8
696         Value * pack64_8_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_mask_pmov_qb_512);
697         // popcounts of 64 bit fields will always fit in 8 bit fields.
698         // We don't need the masked version of this, but the unmasked intrinsic was not found.
699         c = CreateCall(pack64_8_func, {c, zero16xi8, Constant::getAllOnesValue(getInt8Ty())});
700         Value * horizSADfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_sse2_psad_bw);
701         c = CreateCall(horizSADfunc, {c, zero16xi8});
702         return CreateInsertElement(allZeroes(), CreateExtractElement(c, zeroInt32), zeroInt32);
703    }
704    if (hostCPUFeatures.hasAVX512VPOPCNTDQ && (fw == 32 || fw == 64)){
705        //llvm should use vpopcntd or vpopcntq instructions
706        return CreatePopcount(fwCast(fw, a));
707    }
708    if (hostCPUFeatures.hasAVX512BW && (fw == 64)) {
709        Value * horizSADfunc = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_psad_bw_512);
710        return bitCast(CreateCall(horizSADfunc, {fwCast(8, simd_popcount(8, a)), fwCast(8, allZeroes())}));
711    }
712    //https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
713    if((fw == 64) && (mBitBlockWidth == 512)){
714        Constant * m1Arr[8];
715        llvm::Constant * m1;
716        for (unsigned int i = 0; i < 8; i++) {
717            m1Arr[i] = getInt64(0x5555555555555555);
718        }
719        m1 = ConstantVector::get({m1Arr, 8});
720       
721        Constant * m2Arr[8];
722        llvm::Constant * m2;
723        for (unsigned int i = 0; i < 8; i++) {
724            m2Arr[i] = getInt64(0x3333333333333333);
725        }
726        m2 = ConstantVector::get({m2Arr, 8});
727       
728        Constant * m4Arr[8];
729        llvm::Constant * m4;
730        for (unsigned int i = 0; i < 8; i++) {
731            m4Arr[i] = getInt64(0x0f0f0f0f0f0f0f0f);
732        }
733        m4 = ConstantVector::get({m4Arr, 8});
734       
735        Constant * h01Arr[8];
736        llvm::Constant * h01;
737        for (unsigned int i = 0; i < 8; i++) {
738            h01Arr[i] = getInt64(0x0101010101010101);
739        }
740        h01 = ConstantVector::get({h01Arr, 8});
741       
742        a = simd_sub(fw, a, simd_and(simd_srli(fw, a, 1), m1));
743        a = simd_add(fw, simd_and(a, m2), simd_and(simd_srli(fw, a, 2), m2));
744        a = simd_and(simd_add(fw, a, simd_srli(fw, a, 4)), m4);
745        return simd_srli(fw, simd_mult(fw, a, h01), 56);
746       
747    }
748    return IDISA_Builder::simd_popcount(fw, a);
749}
750
751llvm::Value * IDISA_AVX512F_Builder::hsimd_signmask(unsigned fw, llvm::Value * a) {
752    //IDISA_Builder::hsimd_signmask outperforms IDISA_AVX2_Builder::hsimd_signmask
753    //when run with BlockSize=512
754    return IDISA_Builder::hsimd_signmask(fw, a);
755}
756
757Value * IDISA_AVX512F_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
758    if (hostCPUFeatures.hasAVX512BW && ((fw == 1) || (fw == 2))) {
759        // Bit interleave using shuffle.
760        // Make a shuffle table that translates the lower 4 bits of each byte in
761        // order to spread out the bits: xxxxdcba => .d.c.b.a
762        // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
763        Constant * interleave_table = bit_interleave_byteshuffle_table(fw);
764        // Merge the bytes.
765        Value * byte_merge = esimd_mergeh(8, a, b);
766#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(4, 0, 0)       
767        Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx512_mask_pshuf_b_512);
768        // Make a shuffle table that translates the lower 4 bits of each byte in
769        // order to spread out the bits: xxxxdcba => .d.c.b.a
770        // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
771        Value * zeroByteSplat = fwCast(8, allZeroes());
772        Constant * mask = ConstantInt::getAllOnesValue(getInt64Ty());
773        Value * low_bits = CreateCall(shufFn, {interleave_table, fwCast(8, simd_and(byte_merge, simd_lomask(8))), zeroByteSplat, mask});
774        Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4)), zeroByteSplat, mask}), fw);
775#else
776        Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx512_pshuf_b_512);
777        Value * low_bits = CreateCall(shufFn, {interleave_table, fwCast(8, simd_and(byte_merge, simd_lomask(8)))});
778        Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4))}), fw);
779#endif
780        Value * lo_move_back = simd_srli(16, low_bits, 8-fw);
781        Value * hi_move_fwd = simd_slli(16, high_bits, 8-fw);
782        return simd_or(simd_if(1, simd_himask(16), high_bits, low_bits), simd_or(lo_move_back, hi_move_fwd));
783    }
784    if ((fw == 32) || (hostCPUFeatures.hasAVX512BW && (fw == 16)))   {
785        const unsigned fieldCount = mBitBlockWidth/fw;
786        Value * permute_func = nullptr;
787        if (fw == 32) permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_d_512);
788        else permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
789        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
790        Constant * Idxs[fieldCount];
791        for (unsigned i = 0; i < fieldCount / 2; i++) {
792            Idxs[2 * i] = getInt32(i + fieldCount / 2); // selects elements from first reg.
793            Idxs[2 * i + 1] = getInt32(i + fieldCount / 2 + fieldCount); // selects elements from second reg.
794        }
795        Value * args[4] = {ConstantVector::get({Idxs, fieldCount}), fwCast(fw, b), fwCast(fw, a), mask};
796        return bitCast(CreateCall(permute_func, args));
797    }
798    if ((fw == 8) || (hostCPUFeatures.hasAVX512BW && (fw == 8)))   {
799        const unsigned fieldCount = mBitBlockWidth/fw;
800        Constant * Idxs[fieldCount/2];
801        for (unsigned i = 0; i < fieldCount / 2; i++) {
802            Idxs[i] = getInt32(i+fieldCount/2); // selects elements from first reg.
803        }
804        Constant * high_indexes = ConstantVector::get({Idxs, fieldCount/2});
805        Value * a_high = CreateShuffleVector(fwCast(8, a), UndefValue::get(fwVectorType(8)), high_indexes);
806        Value * b_high = CreateShuffleVector(fwCast(8, b), UndefValue::get(fwVectorType(8)), high_indexes);
807        Value * a_ext = CreateZExt(a_high, fwVectorType(16));
808        Value * b_ext = CreateZExt(b_high, fwVectorType(16));
809        Value * rslt = simd_or(a_ext, simd_slli(16, b_ext, 8));
810        return rslt;
811    }
812    // Otherwise use default AVX2 logic.
813    return IDISA_AVX2_Builder::esimd_mergeh(fw, a, b);
814}
815
816Value * IDISA_AVX512F_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
817    if (hostCPUFeatures.hasAVX512BW && ((fw == 1) || (fw == 2))) {
818        // Bit interleave using shuffle.
819        // Make a shuffle table that translates the lower 4 bits of each byte in
820        // order to spread out the bits: xxxxdcba => .d.c.b.a
821        // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
822        Constant * interleave_table = bit_interleave_byteshuffle_table(fw);
823        // Merge the bytes.
824        Value * byte_merge = esimd_mergel(8, a, b);
825       
826#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(4, 0, 0)       
827        Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx512_mask_pshuf_b_512);
828        // Make a shuffle table that translates the lower 4 bits of each byte in
829        // order to spread out the bits: xxxxdcba => .d.c.b.a
830        // We use two copies of the table for the AVX2 _mm256_shuffle_epi8
831        Value * zeroByteSplat = fwCast(8, allZeroes());
832        Constant * mask = ConstantInt::getAllOnesValue(getInt64Ty());
833        Value * low_bits = CreateCall(shufFn, {interleave_table, fwCast(8, simd_and(byte_merge, simd_lomask(8))), zeroByteSplat, mask});
834        Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4)), zeroByteSplat, mask}), fw);
835#else
836        Value * shufFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx512_pshuf_b_512);
837        Value * low_bits = CreateCall(shufFn, {interleave_table, fwCast(8, simd_and(byte_merge, simd_lomask(8)))});
838        Value * high_bits = simd_slli(16, CreateCall(shufFn, {interleave_table, fwCast(8, simd_srli(8, byte_merge, 4))}), fw);
839#endif
840        Value * lo_move_back = simd_srli(16, low_bits, 8-fw);
841        Value * hi_move_fwd = simd_slli(16, high_bits, 8-fw);
842        return simd_or(simd_if(1, simd_himask(16), high_bits, low_bits), simd_or(lo_move_back, hi_move_fwd));
843    }
844    if ((fw == 32) || (hostCPUFeatures.hasAVX512BW && (fw == 16)))   {
845        const unsigned fieldCount = mBitBlockWidth/fw;
846        Value * permute_func = nullptr;
847        if (fw == 32) permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_d_512);
848        else permute_func = Intrinsic::getDeclaration(getModule(), Intrinsic::x86_avx512_maskz_vpermt2var_hi_512);
849        Constant * mask = ConstantInt::getAllOnesValue(getIntNTy(fieldCount));
850        Constant * Idxs[fieldCount];
851        for (unsigned i = 0; i < fieldCount / 2; i++) {
852            Idxs[2 * i] = getInt32(i); // selects elements from first reg.
853            Idxs[2 * i + 1] = getInt32(i + fieldCount); // selects elements from second reg.
854        }
855        Value * args[4] = {ConstantVector::get({Idxs, fieldCount}), fwCast(fw, b), fwCast(fw, a), mask};
856        return bitCast(CreateCall(permute_func, args));
857    }
858    if ((fw == 8) || (hostCPUFeatures.hasAVX512BW && (fw == 8)))   {
859        const unsigned fieldCount = mBitBlockWidth/fw;
860        Constant * Idxs[fieldCount/2];
861        for (unsigned i = 0; i < fieldCount / 2; i++) {
862            Idxs[i] = getInt32(i); // selects elements from first reg.
863        }
864        Constant * low_indexes = ConstantVector::get({Idxs, fieldCount/2});
865        Value * a_low = CreateShuffleVector(fwCast(8, a), UndefValue::get(fwVectorType(8)), low_indexes);
866        Value * b_low = CreateShuffleVector(fwCast(8, b), UndefValue::get(fwVectorType(8)), low_indexes);
867        Value * a_ext = CreateZExt(a_low, fwVectorType(16));
868        Value * b_ext = CreateZExt(b_low, fwVectorType(16));
869        Value * rslt = simd_or(a_ext, simd_slli(16, b_ext, 8));
870        return rslt;
871    }
872    // Otherwise use default AVX2 logic.
873    return IDISA_AVX2_Builder::esimd_mergel(fw, a, b);
874}
875
876Value * IDISA_AVX512F_Builder::simd_if(unsigned fw, Value * cond, Value * a, Value * b) {
877    if (fw == 1) {
878        Value * ternLogicFn = Intrinsic::getDeclaration(getModule(),  Intrinsic::x86_avx512_mask_pternlog_d_512);
879        // Form the 8-bit table for simd-if based on the bitwise values from cond, a and b.
880        //   (cond, a, b) =  (111), (110), (101), (100), (011), (010), (001), (000)
881        // if(cond, a, b) =    1      1      0      0      1      0      1      0    = 0xCA
882        Constant * simd_if_mask = ConstantInt::get(getInt32Ty(), 0xCA);
883        Constant * writemask = ConstantInt::getAllOnesValue(getInt16Ty());
884        Value * args[5] = {fwCast(32, cond), fwCast(32, a), fwCast(32, b), simd_if_mask, writemask};
885        Value * rslt = CreateCall(ternLogicFn, args);
886        return rslt;
887    }
888    return IDISA_AVX2_Builder::simd_if(fw, cond, a, b);
889}
890
891void IDISA_AVX512F_Builder::getAVX512Features() {
892    llvm::StringMap<bool> features;
893    if (llvm::sys::getHostCPUFeatures(features)) {
894        hostCPUFeatures.hasAVX512CD = features.lookup("avx512cd");
895        hostCPUFeatures.hasAVX512BW = features.lookup("avx512bw");
896        hostCPUFeatures.hasAVX512DQ = features.lookup("avx512dq");
897        hostCPUFeatures.hasAVX512VL = features.lookup("avx512vl");
898       
899        //hostCPUFeatures.hasAVX512VBMI, hostCPUFeatures.hasAVX512VBMI2,
900        //hostCPUFeatures.hasAVX512VPOPCNTDQ have not been tested as we
901        //did not have hardware support. It should work in theory (tm)
902       
903        hostCPUFeatures.hasAVX512VBMI = features.lookup("avx512_vbmi");
904        hostCPUFeatures.hasAVX512VBMI2 = features.lookup("avx512_vbmi2");
905        hostCPUFeatures.hasAVX512VPOPCNTDQ = features.lookup("avx512_vpopcntdq");
906    }
907}
908#endif
909
910
911}
Note: See TracBrowser for help on using the repository browser.