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

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

Dynamic generation of s2p code

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(getIntNTy(fw), fieldCount);
18}
19
20Value * IDISA_Builder::fwCast(unsigned fw, Value * a) {
21    return a->getType() == fwVectorType(fw) ? a : 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 = CreateGEP(regStrVar, std::vector<Value *>({getInt64(0), getInt32(0)}));
35    CreateCall(mPrintRegisterFunction, std::vector<Value *>({regStrPtr, bitCast(bitblockValue)}));
36}
37
38    Constant * IDISA_Builder::simd_himask(unsigned fw) {
39        return Constant::getIntegerValue(getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw/2)));
40    }
41   
42    Constant * IDISA_Builder::simd_lomask(unsigned fw) {
43        return Constant::getIntegerValue(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 CreateAdd(fwCast(fw, a), fwCast(fw, b));
48}
49
50Value * IDISA_Builder::simd_sub(unsigned fw, Value * a, Value * b) {
51    return CreateSub(fwCast(fw, a), fwCast(fw, b));
52}
53
54Value * IDISA_Builder::simd_mult(unsigned fw, Value * a, Value * b) {
55    return CreateMul(fwCast(fw, a), fwCast(fw, b));
56}
57
58Value * IDISA_Builder::simd_eq(unsigned fw, Value * a, Value * b) {
59    return CreateSExt(CreateICmpEQ(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
60}
61
62Value * IDISA_Builder::simd_gt(unsigned fw, Value * a, Value * b) {
63    return CreateSExt(CreateICmpSGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
64}
65
66Value * IDISA_Builder::simd_ugt(unsigned fw, Value * a, Value * b) {
67    return CreateSExt(CreateICmpUGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
68}
69
70Value * IDISA_Builder::simd_lt(unsigned fw, Value * a, Value * b) {
71    return CreateSExt(CreateICmpSLT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
72}
73
74Value * IDISA_Builder::simd_ult(unsigned fw, Value * a, Value * b) {
75    return CreateSExt(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 CreateSelect(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 CreateSelect(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 CreateSelect(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 CreateSelect(CreateICmpULT(aVec, bVec), aVec, bVec);
100}
101
102Value * IDISA_Builder::simd_slli(unsigned fw, Value * a, unsigned shift) {
103    return CreateShl(fwCast(fw, a), shift);
104}
105
106Value * IDISA_Builder::simd_srli(unsigned fw, Value * a, unsigned shift) {
107    return CreateLShr(fwCast(fw, a), shift);
108}
109
110Value * IDISA_Builder::simd_srai(unsigned fw, Value * a, unsigned shift) {
111    return 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 = CreateCall(cttzFunc, std::vector<Value *>({fwCast(fw, a), ConstantInt::get(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 = 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    if (fw == 1) {
128        Value * c = bitCast(cond);
129        return CreateOr(CreateAnd(c, bitCast(a)), CreateAnd(CreateNot(c), bitCast(b)));
130    }
131    else {
132        Value * aVec = fwCast(fw, a);
133        Value * bVec = fwCast(fw, b);
134        return CreateSelect(CreateICmpSLT(cond, mZeroInitializer), aVec, bVec);
135    }
136}
137
138   
139Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
140    unsigned field_count = mBitBlockWidth/fw;
141    Value * aVec = fwCast(fw, a);
142    Value * bVec = fwCast(fw, b);
143    std::vector<Constant*> Idxs;
144    for (unsigned i = field_count/2; i < field_count; i++) {
145        Idxs.push_back(getInt32(i));    // selects elements from first reg.
146        Idxs.push_back(getInt32(i + field_count)); // selects elements from second reg.
147    }
148    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
149}
150
151Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
152    unsigned field_count = mBitBlockWidth/fw;
153    Value * aVec = fwCast(fw, a);
154    Value * bVec = fwCast(fw, b);
155    std::vector<Constant*> Idxs;
156    for (unsigned i = 0; i < field_count/2; i++) {
157        Idxs.push_back(getInt32(i));    // selects elements from first reg.
158        Idxs.push_back(getInt32(i + field_count)); // selects elements from second reg.
159    }
160    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
161}
162
163Value * IDISA_Builder::esimd_bitspread(unsigned fw, Value * bitmask) {
164    unsigned field_count = mBitBlockWidth/fw;
165    Type * field_type = getIntNTy(fw);
166    if (bitmask->getType()->getIntegerBitWidth() < fw) {
167        bitmask = CreateZExt(bitmask, field_type);
168    }
169    else if (bitmask->getType()->getIntegerBitWidth() > fw) {
170        bitmask = CreateTrunc(bitmask, field_type);
171    }
172    Value * spread_field = CreateBitCast(bitmask, VectorType::get(getIntNTy(fw), 1));
173    Value * undefVec = UndefValue::get(VectorType::get(getIntNTy(fw), 1));
174    Value * broadcast = CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(getInt32Ty(), field_count)));
175    std::vector<Constant*> bitSel;
176    std::vector<Constant*> bitShift;
177    for (unsigned i = 0; i < field_count; i++) {
178        bitSel.push_back(ConstantInt::get(field_type, 1 << i));
179        bitShift.push_back(ConstantInt::get(field_type, i));
180    }
181    Value * bitSelVec = ConstantVector::get(bitSel);
182    Value * bitShiftVec = ConstantVector::get(bitShift);
183    return CreateLShr(CreateAnd(bitSelVec, broadcast), bitShiftVec);
184}
185
186Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
187    unsigned field_count = 2 * mBitBlockWidth/fw;
188    Value * aVec = fwCast(fw/2, a);
189    Value * bVec = fwCast(fw/2, b);
190    std::vector<Constant*> Idxs;
191    for (unsigned i = 0; i < field_count; i++) {
192        Idxs.push_back(getInt32(2*i+1));
193    }
194    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
195}
196
197Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
198    unsigned field_count = 2 * mBitBlockWidth/fw;
199    Value * aVec = fwCast(fw/2, a);
200    Value * bVec = fwCast(fw/2, b);
201    std::vector<Constant*> Idxs;
202    for (unsigned i = 0; i < field_count; i++) {
203        Idxs.push_back(getInt32(2*i));
204    }
205    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
206}
207
208Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
209    Value * mask = CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
210    return CreateZExt(CreateBitCast(mask, getIntNTy(mBitBlockWidth/fw)), getInt32Ty());
211}
212
213Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
214    Value * aVec = fwCast(fw, a);
215    return CreateExtractElement(aVec, getInt32(fieldIndex));
216}
217
218Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * blk, Value * elt, unsigned fieldIndex) {
219    Value * vec = fwCast(fw, blk);
220    return CreateInsertElement(vec, elt, getInt32(fieldIndex));
221}
222
223Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
224    unsigned field_count = mBitBlockWidth/fw;
225    Value * aVec = fwCast(fw, a);
226    Value * bVec = fwCast(fw, b);
227    std::vector<Constant*> Idxs;
228    for (unsigned i = 0; i < field_count; i++) {
229        Idxs.push_back(getInt32(i + shift));
230    }
231    return CreateShuffleVector(bVec, aVec, ConstantVector::get(Idxs));
232}
233
234Value * IDISA_Builder::bitblock_any(Value * a) {
235    Type * iBitBlock = getIntNTy(mBitBlockWidth);
236    return CreateICmpNE(CreateBitCast(a, iBitBlock),  ConstantInt::get(iBitBlock, 0));
237}
238
239Value * IDISA_Builder::simd_and(Value * a, Value * b) {
240    return a->getType() == b->getType() ? CreateAnd(a, b) : CreateAnd(bitCast(a), bitCast(b));
241}
242
243Value * IDISA_Builder::simd_or(Value * a, Value * b) {
244    return a->getType() == b->getType() ? CreateOr(a, b) : CreateOr(bitCast(a), bitCast(b));
245}
246   
247Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
248    return a->getType() == b->getType() ? CreateXor(a, b) : CreateXor(bitCast(a), bitCast(b));
249}
250
251Value * IDISA_Builder::simd_not(Value * a) {
252    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
253}
254
255}
Note: See TracBrowser for help on using the repository browser.