source: icGREP/icgrep-devel/icgrep/IDISA/idisa_sse_builder.cpp @ 5014

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

Some updates for compatibility with LLVM 3.8

File size: 4.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_sse_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
15
16Value * IDISA_SSE2_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
17    if ((fw == 16) && (mBitBlockWidth == 128)) {
18        Value * packuswb_func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse2_packuswb_128);
19        return CreateCall(packuswb_func, {simd_srli(16, a, 8), simd_srli(16, b, 8)});
20    }
21    // Otherwise use default logic.
22    return IDISA_Builder::hsimd_packh(fw, a, b);
23}
24
25Value * IDISA_SSE2_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
26    if ((fw == 16) && (mBitBlockWidth == 128)) {
27        Value * packuswb_func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse2_packuswb_128);
28        Value * mask = simd_lomask(16);
29        return CreateCall(packuswb_func, {fwCast(16, simd_and(a, mask)), fwCast(16, simd_and(b, mask))});
30    }
31    // Otherwise use default logic.
32    return IDISA_Builder::hsimd_packl(fw, a, b);
33}
34
35Value * IDISA_SSE2_Builder::hsimd_signmask(unsigned fw, Value * a) {
36    // SSE2 special case using Intrinsic::x86_sse2_movmsk_pd (fw=32 only)
37    if (mBitBlockWidth == 128) {
38        if (fw == 64) {
39            Value * signmask_f64func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse2_movmsk_pd);
40            Type * bitBlock_f64type = VectorType::get(getDoubleTy(), mBitBlockWidth/64);
41            Value * a_as_pd = CreateBitCast(a, bitBlock_f64type);
42            Value * mask = CreateCall(signmask_f64func, a_as_pd);
43            return mask;
44        }
45        if (fw == 8) {
46            Value * pmovmskb_func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse2_pmovmskb_128);
47            Value * mask = CreateCall(pmovmskb_func, fwCast(8, a));
48            return mask;
49        }
50    }
51    int fieldCount = mBitBlockWidth/fw;
52    if ((fieldCount > 4) && (fieldCount <= 16)) {
53        Value * pmovmskb_func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse2_pmovmskb_128);
54        int fieldBytes = fw/8;
55        int hiByte = fieldBytes - 1;
56        std::vector<Constant*> Idxs;
57        for (unsigned i = 0; i < fieldCount; i++) {
58            Idxs.push_back(getInt32(fieldBytes*i+hiByte));
59        }
60        for (unsigned i = fieldCount; i < 16; i++) {
61            Idxs.push_back(getInt32(mBitBlockWidth/8));
62        }
63        Value * packh = CreateShuffleVector(fwCast(8, a), fwCast(8, allZeroes()), ConstantVector::get(Idxs));
64        Value * mask = CreateCall(pmovmskb_func, packh);
65        return mask;
66    }
67    // Otherwise use default SSE logic.
68    return IDISA_SSE_Builder::hsimd_signmask(fw, a);
69}
70
71Value * IDISA_SSE_Builder::hsimd_signmask(unsigned fw, Value * a) {
72    // SSE special cases using Intrinsic::x86_sse_movmsk_ps (fw=32 only)
73    if (fw == 32) {
74        Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse_movmsk_ps);
75        Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
76        Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
77        if (mBitBlockWidth == 128) {
78            return CreateCall(signmask_f32func, a_as_ps);
79        }
80    }
81    else if ((fw == 64) && (mBitBlockWidth == 256)) {
82        Type * bitBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/32);
83        Value * a_as_ps = CreateBitCast(a, bitBlock_f32type);
84        std::vector<Constant*> Idxs;
85        for (unsigned i = 0; i < mBitBlockWidth/fw; i++) {
86            Idxs.push_back(getInt32(2*i+1));
87        }
88        Value * packh = CreateShuffleVector(a_as_ps, UndefValue::get(bitBlock_f32type), ConstantVector::get(Idxs));
89        Type * halfBlock_f32type = VectorType::get(getFloatTy(), mBitBlockWidth/64);
90        Value * pack_as_ps = CreateBitCast(packh, halfBlock_f32type);
91        Value * signmask_f32func = Intrinsic::getDeclaration(mMod, Intrinsic::x86_sse_movmsk_ps);
92        Value * mask = CreateCall(signmask_f32func, pack_as_ps);
93        return mask;
94    }
95    // Otherwise use default logic.
96    return IDISA_Builder::hsimd_signmask(fw, a);
97}
98   
99}
Note: See TracBrowser for help on using the repository browser.