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

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

simd_himask

File size: 10.6 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
38Constant * IDISA_Builder::simd_himask(unsigned fw) {
39    return Constant::getIntegerValue(mLLVMBuilder->getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw/2)));
40}
41
42Value * IDISA_Builder::simd_add(unsigned fw, Value * a, Value * b) {
43    return mLLVMBuilder->CreateAdd(fwCast(fw, a), fwCast(fw, b));
44}
45
46Value * IDISA_Builder::simd_sub(unsigned fw, Value * a, Value * b) {
47    return mLLVMBuilder->CreateSub(fwCast(fw, a), fwCast(fw, b));
48}
49
50Value * IDISA_Builder::simd_mult(unsigned fw, Value * a, Value * b) {
51    return mLLVMBuilder->CreateMul(fwCast(fw, a), fwCast(fw, b));
52}
53
54Value * IDISA_Builder::simd_eq(unsigned fw, Value * a, Value * b) {
55    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpEQ(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
56}
57
58Value * IDISA_Builder::simd_gt(unsigned fw, Value * a, Value * b) {
59    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpSGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
60}
61
62Value * IDISA_Builder::simd_ugt(unsigned fw, Value * a, Value * b) {
63    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpUGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
64}
65
66Value * IDISA_Builder::simd_lt(unsigned fw, Value * a, Value * b) {
67    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpSLT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
68}
69
70Value * IDISA_Builder::simd_ult(unsigned fw, Value * a, Value * b) {
71    return mLLVMBuilder->CreateSExt(mLLVMBuilder->CreateICmpULT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
72}
73
74Value * IDISA_Builder::simd_max(unsigned fw, Value * a, Value * b) {
75    Value * aVec = fwCast(fw, a);
76    Value * bVec = fwCast(fw, b);
77    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSGT(aVec, bVec), aVec, bVec);
78}
79
80Value * IDISA_Builder::simd_umax(unsigned fw, Value * a, Value * b) {
81    Value * aVec = fwCast(fw, a);
82    Value * bVec = fwCast(fw, b);
83    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpUGT(aVec, bVec), aVec, bVec);
84}
85
86Value * IDISA_Builder::simd_min(unsigned fw, Value * a, Value * b) {
87    Value * aVec = fwCast(fw, a);
88    Value * bVec = fwCast(fw, b);
89    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSLT(aVec, bVec), aVec, bVec);
90}
91
92Value * IDISA_Builder::simd_umin(unsigned fw, Value * a, Value * b) {
93    Value * aVec = fwCast(fw, a);
94    Value * bVec = fwCast(fw, b);
95    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpULT(aVec, bVec), aVec, bVec);
96}
97
98Value * IDISA_Builder::simd_slli(unsigned fw, Value * a, unsigned shift) {
99    return mLLVMBuilder->CreateShl(fwCast(fw, a), shift);
100}
101
102Value * IDISA_Builder::simd_srli(unsigned fw, Value * a, unsigned shift) {
103    return mLLVMBuilder->CreateLShr(fwCast(fw, a), shift);
104}
105
106Value * IDISA_Builder::simd_srai(unsigned fw, Value * a, unsigned shift) {
107    return mLLVMBuilder->CreateAShr(fwCast(fw, a), shift);
108}
109
110Value * IDISA_Builder::simd_cttz(unsigned fw, Value * a) {
111    Value * cttzFunc = Intrinsic::getDeclaration(mMod, Intrinsic::cttz, fwVectorType(fw));
112    Value * rslt = mLLVMBuilder->CreateCall(cttzFunc, std::vector<Value *>({fwCast(fw, a), ConstantInt::get(mLLVMBuilder->getInt1Ty(), 0)}));
113    return rslt;
114}
115
116Value * IDISA_Builder::simd_popcount(unsigned fw, Value * a) {
117    Value * ctpopFunc = Intrinsic::getDeclaration(mMod, Intrinsic::ctpop, fwVectorType(fw));
118    Value * rslt = mLLVMBuilder->CreateCall(ctpopFunc, std::vector<Value *>({fwCast(fw, a)}));
119    return rslt;
120}
121
122Value * IDISA_Builder::simd_if(unsigned fw, Value * cond, Value * a, Value * b) {
123    Value * aVec = fwCast(fw, a);
124    Value * bVec = fwCast(fw, b);
125    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSLT(cond, mZeroInitializer), aVec, bVec);
126}
127
128   
129Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
130    unsigned field_count = mBitBlockWidth/fw;
131    Value * aVec = fwCast(fw, a);
132    Value * bVec = fwCast(fw, b);
133    std::vector<Constant*> Idxs;
134    for (unsigned i = field_count/2; i < field_count; i++) {
135        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
136        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
137    }
138    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
139}
140
141Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
142    unsigned field_count = mBitBlockWidth/fw;
143    Value * aVec = fwCast(fw, a);
144    Value * bVec = fwCast(fw, b);
145    std::vector<Constant*> Idxs;
146    for (unsigned i = 0; i < field_count/2; i++) {
147        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
148        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
149    }
150    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
151}
152
153Value * IDISA_Builder::esimd_bitspread(unsigned fw, Value * bitmask) {
154    unsigned field_count = mBitBlockWidth/fw;
155    Type * field_type = mLLVMBuilder->getIntNTy(fw);
156    if (bitmask->getType()->getIntegerBitWidth() < fw) {
157        bitmask = mLLVMBuilder->CreateZExt(bitmask, field_type);
158    }
159    else if (bitmask->getType()->getIntegerBitWidth() > fw) {
160        bitmask = mLLVMBuilder->CreateTrunc(bitmask, field_type);
161    }
162    Value * spread_field = mLLVMBuilder->CreateBitCast(bitmask, VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
163    Value * undefVec = UndefValue::get(VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
164    Value * broadcast = mLLVMBuilder->CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(mLLVMBuilder->getInt32Ty(), field_count)));
165    std::vector<Constant*> bitSel;
166    std::vector<Constant*> bitShift;
167    for (unsigned i = 0; i < field_count; i++) {
168        bitSel.push_back(ConstantInt::get(field_type, 1 << i));
169        bitShift.push_back(ConstantInt::get(field_type, i));
170    }
171    Value * bitSelVec = ConstantVector::get(bitSel);
172    Value * bitShiftVec = ConstantVector::get(bitShift);
173    return mLLVMBuilder->CreateLShr(mLLVMBuilder->CreateAnd(bitSelVec, broadcast), bitShiftVec);
174}
175
176Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
177    unsigned field_count = 2 * mBitBlockWidth/fw;
178    Value * aVec = fwCast(fw/2, a);
179    Value * bVec = fwCast(fw/2, b);
180    std::vector<Constant*> Idxs;
181    for (unsigned i = 0; i < field_count; i++) {
182        Idxs.push_back(mLLVMBuilder->getInt32(2*i));
183    }
184    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
185}
186
187Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
188    unsigned field_count = 2 * mBitBlockWidth/fw;
189    Value * aVec = fwCast(fw/2, a);
190    Value * bVec = fwCast(fw/2, b);
191    std::vector<Constant*> Idxs;
192    for (unsigned i = 0; i < field_count; i++) {
193        Idxs.push_back(mLLVMBuilder->getInt32(2*i+1));
194    }
195    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
196}
197
198Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
199    Value * mask = mLLVMBuilder->CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
200    return mLLVMBuilder->CreateZExt(mLLVMBuilder->CreateBitCast(mask, mLLVMBuilder->getIntNTy(mBitBlockWidth/fw)), mLLVMBuilder->getInt32Ty());
201}
202
203Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
204    Value * aVec = fwCast(fw, a);
205    return mLLVMBuilder->CreateExtractElement(aVec, mLLVMBuilder->getInt32(fieldIndex));
206}
207
208Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * blk, Value * elt, unsigned fieldIndex) {
209    Value * vec = fwCast(fw, blk);
210    return mLLVMBuilder->CreateInsertElement(vec, elt, mLLVMBuilder->getInt32(fieldIndex));
211}
212
213Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
214    unsigned field_count = mBitBlockWidth/fw;
215    Value * aVec = fwCast(fw, a);
216    Value * bVec = fwCast(fw, b);
217    std::vector<Constant*> Idxs;
218    for (unsigned i = 0; i < field_count; i++) {
219        Idxs.push_back(mLLVMBuilder->getInt32(i + shift));
220    }
221    return mLLVMBuilder->CreateShuffleVector(bVec, aVec, ConstantVector::get(Idxs));
222}
223
224Value * IDISA_Builder::bitblock_any(Value * a) {
225    Type * iBitBlock = mLLVMBuilder->getIntNTy(mBitBlockWidth);
226    return mLLVMBuilder->CreateICmpNE(mLLVMBuilder->CreateBitCast(a, iBitBlock),  ConstantInt::get(iBitBlock, 0));
227}
228
229Value * IDISA_Builder::simd_and(Value * a, Value * b) {
230    return a->getType() == b->getType() ? mLLVMBuilder->CreateAnd(a, b) : mLLVMBuilder->CreateAnd(bitCast(a), bitCast(b));
231}
232
233Value * IDISA_Builder::simd_or(Value * a, Value * b) {
234    return a->getType() == b->getType() ? mLLVMBuilder->CreateOr(a, b) : mLLVMBuilder->CreateOr(bitCast(a), bitCast(b));
235}
236   
237Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
238    return a->getType() == b->getType() ? mLLVMBuilder->CreateXor(a, b) : mLLVMBuilder->CreateXor(bitCast(a), bitCast(b));
239}
240
241Value * IDISA_Builder::simd_not(Value * a) {
242    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
243}
244
245}
Note: See TracBrowser for help on using the repository browser.