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

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

hi_mask in s2p, lo_mask

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