source: icGREP/icgrep-devel/icgrep/IDISA/idisa_avx_builder.cpp @ 4997

Last change on this file since 4997 was 4997, checked in by cameron, 3 years ago

Fix AVX2 packh/l

File size: 6.2 KB
Line 
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#include <llvm/IR/IRBuilder.h>
9#include <llvm/IR/Constants.h>
10#include <llvm/IR/Intrinsics.h>
11#include <llvm/IR/Function.h>
12
13namespace IDISA {
14
15Value * IDISA_AVX_Builder::hsimd_signmask(unsigned fw, Value * a) {
16    // AVX2 special cases
17    if (mBitBlockWidth == 256) {
18        if (fw == 64) {
19            Value * signmask_f64func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_pd_256);
20            Type * bitBlock_f64type = VectorType::get(getDoubleTy(), mBitBlockWidth/64);
21            Value * a_as_pd = CreateBitCast(a, bitBlock_f64type);
22            Value * mask = CreateCall(signmask_f64func, std::vector<Value *>({a_as_pd}));
23            return mask;
24        }
25        else if (fw == 32) {
26            Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_ps_256);
27            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
28            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
29            Value * mask = CreateCall(signmask_f32func, std::vector<Value *>({a_as_ps}));
30            return mask;
31        }
32    }
33    else if (mBitBlockWidth == 512) {
34        if (fw == 64) {
35            Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
36            Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
37            std::vector<Constant*> Idxs;
38            for (unsigned i = 0; i < 8; i++) {
39                Idxs.push_back(getInt32(2*i+1));
40            }
41            Value * packh = CreateShuffleVector(a_as_ps, UndefValue::get(bitBlock_f32type), ConstantVector::get(Idxs));
42            Type * halfBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/64);
43            Value * pack_as_ps = CreateBitCast(packh, halfBlock_f32type);
44            Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx_movmsk_ps_256);
45            Value * mask = CreateCall(signmask_f32func, std::vector<Value *>({pack_as_ps}));
46            return mask;
47        }
48    }
49    // Otherwise use default SSE logic.
50    return IDISA_SSE_Builder::hsimd_signmask(fw, a);
51}
52   
53Value * IDISA_AVX2_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
54    unsigned field_count = 2 * mBitBlockWidth/fw;
55    Value * aVec = fwCast(fw/2, a);
56    Value * bVec = fwCast(fw/2, b);
57    if (fw <= 64) {
58        std::vector<Constant*> Idxs;
59        for (unsigned i = 0; i < field_count/4; i++) {
60            Idxs.push_back(getInt32(2*i));
61        }
62        for (unsigned i = 0; i < field_count/4; i++) {
63            Idxs.push_back(getInt32(2*i + 1));
64        }
65        for (unsigned i = 0; i < field_count/4; i++) {
66            Idxs.push_back(getInt32(field_count/2 + 2*i));
67        }
68        for (unsigned i = 0; i < field_count/4; i++) {
69            Idxs.push_back(getInt32(field_count/2 + 2*i + 1));
70        }
71        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get(Idxs));
72        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get(Idxs));
73        return hsimd_packh(mBitBlockWidth/2, shufa, shufb);
74    }
75    // Otherwise use default SSE logic.
76    return IDISA_SSE_Builder::hsimd_packh(fw, a, b);
77}
78
79Value * IDISA_AVX2_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
80    unsigned field_count = 2 * mBitBlockWidth/fw;
81    Value * aVec = fwCast(fw/2, a);
82    Value * bVec = fwCast(fw/2, b);
83    if (fw <= 64) {
84        std::vector<Constant*> Idxs;
85        for (unsigned i = 0; i < field_count/4; i++) {
86            Idxs.push_back(getInt32(2*i));
87        }
88        for (unsigned i = 0; i < field_count/4; i++) {
89            Idxs.push_back(getInt32(2*i + 1));
90        }
91        for (unsigned i = 0; i < field_count/4; i++) {
92            Idxs.push_back(getInt32(field_count/2 + 2*i));
93        }
94        for (unsigned i = 0; i < field_count/4; i++) {
95            Idxs.push_back(getInt32(field_count/2 + 2*i + 1));
96        }
97        Value * shufa = CreateShuffleVector(aVec, aVec, ConstantVector::get(Idxs));
98        Value * shufb = CreateShuffleVector(bVec, bVec, ConstantVector::get(Idxs));
99        return hsimd_packl(mBitBlockWidth/2, shufa, shufb);
100    }
101    // Otherwise use default SSE logic.
102    return IDISA_SSE_Builder::hsimd_packl(fw, a, b);
103}
104   
105Value * IDISA_AVX2_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
106    if ((fw == 128) && (mBitBlockWidth == 256)) {
107        Value * vperm2i128func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_vperm2i128);
108        return CreateCall3(vperm2i128func, fwCast(64, a), fwCast(64, b), getInt8(0x31));
109    }
110    // Otherwise use default SSE logic.
111    return IDISA_SSE_Builder::esimd_mergeh(fw, a, b);
112}
113
114Value * IDISA_AVX2_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
115    if ((fw == 128) && (mBitBlockWidth == 256)) {
116        Value * vperm2i128func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_vperm2i128);
117        return CreateCall3(vperm2i128func, fwCast(64, a), fwCast(64, b), getInt8(0x20));
118    }
119    // Otherwise use default SSE logic.
120    return IDISA_SSE_Builder::esimd_mergel(fw, a, b);
121}
122
123Value * IDISA_AVX2_Builder::hsimd_packl_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
124    if ((fw == 16)  && (lanes == 2)) {
125        Value * vpackuswbfunc = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_packuswb);
126        Value * a_low = fwCast(16, simd_and(a, simd_lomask(fw)));
127        Value * b_low = fwCast(16, simd_and(b, simd_lomask(fw)));
128        Value * pack = CreateCall2(vpackuswbfunc, a_low, b_low);
129        return pack;
130    }
131    // Otherwise use default SSE logic.
132    return IDISA_SSE_Builder::hsimd_packl_in_lanes(lanes, fw, a, b);
133}
134
135Value * IDISA_AVX2_Builder::hsimd_packh_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
136    if ((fw == 16)  && (lanes == 2)) {
137        Value * vpackuswbfunc = Intrinsic::getDeclaration(mMod, Intrinsic::x86_avx2_packuswb);
138        Value * a_low = simd_srli(fw, a, fw/2);
139        Value * b_low = simd_srli(fw, b, fw/2);
140        Value * pack = CreateCall2(vpackuswbfunc, a_low, b_low);
141        return pack;
142    }
143    // Otherwise use default SSE logic.
144    return IDISA_SSE_Builder::hsimd_packh_in_lanes(lanes, fw, a, b);
145}
146   
147}
Note: See TracBrowser for help on using the repository browser.