source: icGREP/icgrep-devel/icgrep/IDISA/idisa_builder.cpp @ 4879

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

Add esimd_bitspread

File size: 9.9 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_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
15VectorType * IDISA_Builder::fwVectorType(unsigned fw) {
16    int fieldCount = mBitBlockWidth/fw;
17    return VectorType::get(mLLVMBuilder->getIntNTy(fw), fieldCount);
18}
19
20Value * IDISA_Builder::fwCast(unsigned fw, Value * a) {
21    return a->getType() == fwVectorType(fw) ? a : mLLVMBuilder->CreateBitCast(a, fwVectorType(fw));
22}
23
24void IDISA_Builder::genPrintRegister(std::string regName, Value * bitblockValue) {
25    if (mPrintRegisterFunction == nullptr) {
26        mPrintRegisterFunction = mMod->getOrInsertFunction("wrapped_print_register", Type::getVoidTy(mMod->getContext()), Type::getInt8PtrTy(mMod->getContext()), mBitBlockType, NULL);
27    }
28    Constant * regNameData = ConstantDataArray::getString(mMod->getContext(), regName);
29    GlobalVariable *regStrVar = new GlobalVariable(*mMod,
30                                                   ArrayType::get(IntegerType::get(mMod->getContext(), 8), regName.length()+1),
31                                                   /*isConstant=*/ true,
32                                                   /*Linkage=*/ GlobalValue::PrivateLinkage,
33                                                   /*Initializer=*/ regNameData);
34    Value * regStrPtr = mLLVMBuilder->CreateGEP(regStrVar, std::vector<Value *>({mLLVMBuilder->getInt64(0), mLLVMBuilder->getInt32(0)}));
35    mLLVMBuilder->CreateCall(mPrintRegisterFunction, std::vector<Value *>({regStrPtr, bitCast(bitblockValue)}));
36}
37
38   
39Value * IDISA_Builder::simd_add(unsigned fw, Value * a, Value * b) {
40    return mLLVMBuilder->CreateAdd(fwCast(fw, a), fwCast(fw, b));
41}
42
43Value * IDISA_Builder::simd_sub(unsigned fw, Value * a, Value * b) {
44    return mLLVMBuilder->CreateSub(fwCast(fw, a), fwCast(fw, b));
45}
46
47Value * IDISA_Builder::simd_mult(unsigned fw, Value * a, Value * b) {
48    return mLLVMBuilder->CreateMul(fwCast(fw, a), fwCast(fw, b));
49}
50
51Value * IDISA_Builder::simd_eq(unsigned fw, Value * a, Value * b) {
52    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpEQ(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
53}
54
55Value * IDISA_Builder::simd_gt(unsigned fw, Value * a, Value * b) {
56    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpSGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
57}
58
59Value * IDISA_Builder::simd_ugt(unsigned fw, Value * a, Value * b) {
60    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpUGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
61}
62
63Value * IDISA_Builder::simd_lt(unsigned fw, Value * a, Value * b) {
64    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpSLT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
65}
66
67Value * IDISA_Builder::simd_ult(unsigned fw, Value * a, Value * b) {
68    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpULT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
69}
70
71Value * IDISA_Builder::simd_max(unsigned fw, Value * a, Value * b) {
72    Value * aVec = fwCast(fw, a);
73    Value * bVec = fwCast(fw, b);
74    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSGT(aVec, bVec), aVec, bVec);
75}
76
77Value * IDISA_Builder::simd_umax(unsigned fw, Value * a, Value * b) {
78    Value * aVec = fwCast(fw, a);
79    Value * bVec = fwCast(fw, b);
80    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpUGT(aVec, bVec), aVec, bVec);
81}
82
83Value * IDISA_Builder::simd_min(unsigned fw, Value * a, Value * b) {
84    Value * aVec = fwCast(fw, a);
85    Value * bVec = fwCast(fw, b);
86    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSLT(aVec, bVec), aVec, bVec);
87}
88
89Value * IDISA_Builder::simd_umin(unsigned fw, Value * a, Value * b) {
90    Value * aVec = fwCast(fw, a);
91    Value * bVec = fwCast(fw, b);
92    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpULT(aVec, bVec), aVec, bVec);
93}
94
95Value * IDISA_Builder::simd_slli(unsigned fw, Value * a, unsigned shift) {
96    return mLLVMBuilder->CreateShl(fwCast(fw, a), shift);
97}
98
99Value * IDISA_Builder::simd_srli(unsigned fw, Value * a, unsigned shift) {
100    return mLLVMBuilder->CreateLShr(fwCast(fw, a), shift);
101}
102
103Value * IDISA_Builder::simd_srai(unsigned fw, Value * a, unsigned shift) {
104    return mLLVMBuilder->CreateAShr(fwCast(fw, a), shift);
105}
106
107Value * IDISA_Builder::simd_cttz(unsigned fw, Value * a) {
108    Value * cttzFunc = Intrinsic::getDeclaration(mMod, Intrinsic::cttz, fwVectorType(fw));
109    Value * rslt = mLLVMBuilder->CreateCall(cttzFunc, std::vector<Value *>({fwCast(fw, a), ConstantInt::get(mLLVMBuilder->getInt1Ty(), 0)}));
110    return rslt;
111}
112
113Value * IDISA_Builder::simd_popcount(unsigned fw, Value * a) {
114    Value * ctpopFunc = Intrinsic::getDeclaration(mMod, Intrinsic::ctpop, fwVectorType(fw));
115    Value * rslt = mLLVMBuilder->CreateCall(ctpopFunc, std::vector<Value *>({fwCast(fw, a)}));
116    return rslt;
117}
118
119Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
120    unsigned field_count = mBitBlockWidth/fw;
121    Value * aVec = fwCast(fw, a);
122    Value * bVec = fwCast(fw, b);
123    std::vector<Constant*> Idxs;
124    for (unsigned i = field_count/2; i < field_count; i++) {
125        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
126        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
127    }
128    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
129}
130
131Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
132    unsigned field_count = mBitBlockWidth/fw;
133    Value * aVec = fwCast(fw, a);
134    Value * bVec = fwCast(fw, b);
135    std::vector<Constant*> Idxs;
136    for (unsigned i = 0; i < field_count/2; i++) {
137        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
138        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
139    }
140    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
141}
142
143Value * IDISA_Builder:: esimd_bitspread(unsigned fw, Value * bitmask) {
144    unsigned field_count = mBitBlockWidth/fw;
145    Type * field_type = mLLVMBuilder->getIntNTy(fw);
146    if (bitmask->getType()->getIntegerBitWidth() < fw) {
147        bitmask = mLLVMBuilder->CreateZExt(bitmask, field_type);
148    }
149    else if (bitmask->getType()->getIntegerBitWidth() > fw) {
150        bitmask = mLLVMBuilder->CreateTrunc(bitmask, field_type);
151    }
152    Value * spread_field = mLLVMBuilder->CreateBitCast(bitmask, VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
153    Value * undefVec = UndefValue::get(VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
154    Value * broadcast = mLLVMBuilder->CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(mLLVMBuilder->getInt32Ty(), field_count)));
155    std::vector<Constant*> bitSel;
156    std::vector<Constant*> bitShift;
157    for (unsigned i = 0; i < field_count; i++) {
158        bitSel.push_back(ConstantInt::get(field_type, 1 << i));
159        bitShift.push_back(ConstantInt::get(field_type, i));
160    }
161    Value * bitSelVec = ConstantVector::get(bitSel);
162    Value * bitShiftVec = ConstantVector::get(bitShift);
163    return mLLVMBuilder->CreateLShr(mLLVMBuilder->CreateAnd(bitSelVec, broadcast), bitShiftVec);
164}
165
166Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
167    unsigned field_count = 2 * mBitBlockWidth/fw;
168    Value * aVec = fwCast(fw/2, a);
169    Value * bVec = fwCast(fw/2, b);
170    std::vector<Constant*> Idxs;
171    for (unsigned i = 0; i < field_count; i++) {
172        Idxs.push_back(mLLVMBuilder->getInt32(2*i));
173    }
174    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
175}
176
177Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
178    unsigned field_count = 2 * mBitBlockWidth/fw;
179    Value * aVec = fwCast(fw/2, a);
180    Value * bVec = fwCast(fw/2, b);
181    std::vector<Constant*> Idxs;
182    for (unsigned i = 0; i < field_count; i++) {
183        Idxs.push_back(mLLVMBuilder->getInt32(2*i+1));
184    }
185    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
186}
187
188Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
189    Value * mask = mLLVMBuilder->CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
190    return mLLVMBuilder->CreateBitCast(mask, mLLVMBuilder->getIntNTy(mBitBlockWidth/fw));
191}
192
193Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
194    Value * aVec = fwCast(fw, a);
195    return mLLVMBuilder->CreateExtractElement(aVec, mLLVMBuilder->getInt32(fieldIndex));
196}
197
198Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
199    unsigned field_count = mBitBlockWidth/fw;
200    Value * aVec = fwCast(fw, a);
201    Value * bVec = fwCast(fw, b);
202    std::vector<Constant*> Idxs;
203    for (unsigned i = 0; i < field_count; i++) {
204        Idxs.push_back(mLLVMBuilder->getInt32(i + shift));
205    }
206    return mLLVMBuilder->CreateShuffleVector(bVec, aVec, ConstantVector::get(Idxs));
207}
208
209Value * IDISA_Builder::bitblock_any(Value * a) {
210    Type * iBitBlock = mLLVMBuilder->getIntNTy(mBitBlockWidth);
211    return mLLVMBuilder->CreateICmpNE(mLLVMBuilder->CreateBitCast(a, iBitBlock),  ConstantInt::get(iBitBlock, 0));
212}
213
214Value * IDISA_Builder::simd_and(Value * a, Value * b) {
215    return a->getType() == b->getType() ? mLLVMBuilder->CreateAnd(a, b) : mLLVMBuilder->CreateAnd(bitCast(a), bitCast(b));
216}
217
218Value * IDISA_Builder::simd_or(Value * a, Value * b) {
219    return a->getType() == b->getType() ? mLLVMBuilder->CreateOr(a, b) : mLLVMBuilder->CreateOr(bitCast(a), bitCast(b));
220}
221   
222Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
223    return a->getType() == b->getType() ? mLLVMBuilder->CreateXor(a, b) : mLLVMBuilder->CreateXor(bitCast(a), bitCast(b));
224}
225
226Value * IDISA_Builder::simd_not(Value * a) {
227    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
228}
229
230}
Note: See TracBrowser for help on using the repository browser.