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

Last change on this file since 5374 was 5374, checked in by cameron, 2 years ago

Unique names for IDISA builders

File size: 7.2 KB
RevLine 
[4892]1/*
2 *  Copyright (c) 2015 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
9namespace IDISA {
[5374]10   
11std::string IDISA_AVX_Builder::getBuilderUniqueName() { return mBitBlockWidth != 256 ? "AVX_" + std::to_string(mBitBlockWidth) : "AVX";}
12std::string IDISA_AVX2_Builder::getBuilderUniqueName() { return mBitBlockWidth != 256 ? "AVX2_" + std::to_string(mBitBlockWidth) : "AVX2";}
[4892]13
[4903]14Value * IDISA_AVX_Builder::hsimd_signmask(unsigned fw, Value * a) {
[4996]15    // AVX2 special cases
[4956]16    if (mBitBlockWidth == 256) {
17        if (fw == 64) {
18            Value * signmask_f64func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_pd_256);
19            Type * bitBlock_f64type = VectorType::get(getDoubleTy(), mBitBlockWidth/64);
20            Value * a_as_pd = CreateBitCast(a, bitBlock_f64type);
[5309]21            return CreateCall(signmask_f64func, a_as_pd);
22        } else if (fw == 32) {
[4956]23            Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_ps_256);
24            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
25            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
[5309]26            return CreateCall(signmask_f32func, a_as_ps);
[4956]27        }
[5309]28    } else if (mBitBlockWidth == 512) {
[4956]29        if (fw == 64) {
[5309]30            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth / 32);
[4956]31            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
[5309]32            Constant * indicies[8];
[4956]33            for (unsigned i = 0; i < 8; i++) {
[5309]34                indicies[i] = getInt32(2 * i + 1);
[4956]35            }
[5309]36            Value * packh = CreateShuffleVector(a_as_ps, UndefValue::get(bitBlock_f32type), ConstantVector::get({indicies, 8}));
[4956]37            Type * halfBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/64);
38            Value * pack_as_ps = CreateBitCast(packh, halfBlock_f32type);
39            Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_ps_256);
[5309]40            return CreateCall(signmask_f32func, pack_as_ps);
[4956]41        }
[4892]42    }
[4996]43    // Otherwise use default SSE logic.
44    return IDISA_SSE_Builder::hsimd_signmask(fw, a);
[4892]45}
46   
[4955]47Value * IDISA_AVX2_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
[5309]48    if (fw <= 64) {       
49        Value * aVec = fwCast(fw / 2, a);
50        Value * bVec = fwCast(fw / 2, b);
51        const auto field_count = 2 * mBitBlockWidth / fw;
52        Constant * Idxs[field_count];
53        const auto H = (field_count / 2);
54        const auto Q = (field_count / 4);
55        for (unsigned i = 0; i < Q; i++) {
56            Idxs[i] = getInt32(2 * i);
57            Idxs[i + Q] = getInt32((2 * i) + 1);
58            Idxs[i + H] = getInt32((2 * i) + H);
59            Idxs[i + H + Q] = getInt32((2 * i) + 1 + H);
[4997]60        }
[5309]61        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get({Idxs, field_count}));
62        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get({Idxs, field_count}));
63        return hsimd_packh(mBitBlockWidth / 2, shufa, shufb);
[4955]64    }
[4996]65    // Otherwise use default SSE logic.
66    return IDISA_SSE_Builder::hsimd_packh(fw, a, b);
[4892]67}
[4955]68
69Value * IDISA_AVX2_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
70    if (fw <= 64) {
[5309]71        Value * aVec = fwCast(fw / 2, a);
72        Value * bVec = fwCast(fw / 2, b);
73        const auto field_count = 2 * mBitBlockWidth / fw;
74        Constant * Idxs[field_count];
75        const auto H = (field_count / 2);
76        const auto Q = (field_count / 4);
77        for (unsigned i = 0; i < Q; i++) {
78            Idxs[i] = getInt32(2 * i);
79            Idxs[i + Q] = getInt32((2 * i) + 1);
80            Idxs[i + H] = getInt32((2 * i) + H);
81            Idxs[i + H + Q] = getInt32((2 * i) + H + 1);
[4997]82        }
[5309]83        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get({Idxs, field_count}));
84        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get({Idxs, field_count}));
85        return hsimd_packl(mBitBlockWidth / 2, shufa, shufb);
[4955]86    }
[4996]87    // Otherwise use default SSE logic.
88    return IDISA_SSE_Builder::hsimd_packl(fw, a, b);
[4955]89}
[4957]90   
91Value * IDISA_AVX2_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
92    if ((fw == 128) && (mBitBlockWidth == 256)) {
93        Value * vperm2i128func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_vperm2i128);
[5014]94        return CreateCall(vperm2i128func, {fwCast(64, a), fwCast(64, b), getInt8(0x31)});
[4957]95    }
[4996]96    // Otherwise use default SSE logic.
97    return IDISA_SSE_Builder::esimd_mergeh(fw, a, b);
[4955]98}
[4957]99
100Value * IDISA_AVX2_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
101    if ((fw == 128) && (mBitBlockWidth == 256)) {
102        Value * vperm2i128func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_vperm2i128);
[5014]103        return CreateCall(vperm2i128func, {fwCast(64, a), fwCast(64, b), getInt8(0x20)});
[4957]104    }
[4996]105    // Otherwise use default SSE logic.
106    return IDISA_SSE_Builder::esimd_mergel(fw, a, b);
[4957]107}
108
109Value * IDISA_AVX2_Builder::hsimd_packl_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
110    if ((fw == 16)  && (lanes == 2)) {
111        Value * vpackuswbfunc = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_packuswb);
112        Value * a_low = fwCast(16, simd_and(a, simd_lomask(fw)));
113        Value * b_low = fwCast(16, simd_and(b, simd_lomask(fw)));
[5309]114        return CreateCall(vpackuswbfunc, {a_low, b_low});
[4957]115    }
[4996]116    // Otherwise use default SSE logic.
117    return IDISA_SSE_Builder::hsimd_packl_in_lanes(lanes, fw, a, b);
[4957]118}
119
120Value * IDISA_AVX2_Builder::hsimd_packh_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
121    if ((fw == 16)  && (lanes == 2)) {
122        Value * vpackuswbfunc = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_packuswb);
123        Value * a_low = simd_srli(fw, a, fw/2);
124        Value * b_low = simd_srli(fw, b, fw/2);
[5309]125        return CreateCall(vpackuswbfunc, {a_low, b_low});
[4957]126    }
[4996]127    // Otherwise use default SSE logic.
128    return IDISA_SSE_Builder::hsimd_packh_in_lanes(lanes, fw, a, b);
[4957]129}
130   
[5115]131std::pair<Value *, Value *> IDISA_AVX2_Builder::bitblock_add_with_carry(Value * e1, Value * e2, Value * carryin) {
132    // using LONG_ADD
133    Type * carryTy = carryin->getType();
134    if (carryTy == mBitBlockType) {
135        carryin = mvmd_extract(32, carryin, 0);
136    }
137    Value * carrygen = simd_and(e1, e2);
138    Value * carryprop = simd_or(e1, e2);
139    Value * digitsum = simd_add(64, e1, e2);
140    Value * digitcarry = simd_or(carrygen, simd_and(carryprop, CreateNot(digitsum)));
141    Value * carryMask = hsimd_signmask(64, digitcarry);
142    Value * carryMask2 = CreateOr(CreateAdd(carryMask, carryMask), carryin);
143    Value * bubble = simd_eq(64, digitsum, allOnes());
144    Value * bubbleMask = hsimd_signmask(64, bubble);
145    Value * incrementMask = CreateXor(CreateAdd(bubbleMask, carryMask2), bubbleMask);
146    Value * increments = esimd_bitspread(64,incrementMask);
147    Value * sum = simd_add(64, digitsum, increments);
148    Value * carry_out = CreateLShr(incrementMask, mBitBlockWidth / 64);
149    if (carryTy == mBitBlockType) {
150        carry_out = bitCast(CreateZExt(carry_out, getIntNTy(mBitBlockWidth)));
151    }
[5309]152    return std::pair<Value *, Value *>{carry_out, bitCast(sum)};
[4957]153}
[5115]154   
155}
Note: See TracBrowser for help on using the repository browser.