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

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

Move AVX2 specific IDISA function implementations into subclassed builder

File size: 10.4 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::simd_if(unsigned fw, Value * cond, Value * a, Value * b) {
120    Value * aVec = fwCast(fw, a);
121    Value * bVec = fwCast(fw, b);
122    return mLLVMBuilder->CreateSelect(mLLVMBuilder->CreateICmpSLT(cond, mZeroInitializer), aVec, bVec);
123}
124
125   
126Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
127    unsigned field_count = mBitBlockWidth/fw;
128    Value * aVec = fwCast(fw, a);
129    Value * bVec = fwCast(fw, b);
130    std::vector<Constant*> Idxs;
131    for (unsigned i = field_count/2; i < field_count; i++) {
132        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
133        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
134    }
135    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
136}
137
138Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
139    unsigned field_count = mBitBlockWidth/fw;
140    Value * aVec = fwCast(fw, a);
141    Value * bVec = fwCast(fw, b);
142    std::vector<Constant*> Idxs;
143    for (unsigned i = 0; i < field_count/2; i++) {
144        Idxs.push_back(mLLVMBuilder->getInt32(i));    // selects elements from first reg.
145        Idxs.push_back(mLLVMBuilder->getInt32(i + field_count)); // selects elements from second reg.
146    }
147    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
148}
149
150Value * IDISA_Builder::esimd_bitspread(unsigned fw, Value * bitmask) {
151    unsigned field_count = mBitBlockWidth/fw;
152    Type * field_type = mLLVMBuilder->getIntNTy(fw);
153    if (bitmask->getType()->getIntegerBitWidth() < fw) {
154        bitmask = mLLVMBuilder->CreateZExt(bitmask, field_type);
155    }
156    else if (bitmask->getType()->getIntegerBitWidth() > fw) {
157        bitmask = mLLVMBuilder->CreateTrunc(bitmask, field_type);
158    }
159    Value * spread_field = mLLVMBuilder->CreateBitCast(bitmask, VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
160    Value * undefVec = UndefValue::get(VectorType::get(mLLVMBuilder->getIntNTy(fw), 1));
161    Value * broadcast = mLLVMBuilder->CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(mLLVMBuilder->getInt32Ty(), field_count)));
162    std::vector<Constant*> bitSel;
163    std::vector<Constant*> bitShift;
164    for (unsigned i = 0; i < field_count; i++) {
165        bitSel.push_back(ConstantInt::get(field_type, 1 << i));
166        bitShift.push_back(ConstantInt::get(field_type, i));
167    }
168    Value * bitSelVec = ConstantVector::get(bitSel);
169    Value * bitShiftVec = ConstantVector::get(bitShift);
170    return mLLVMBuilder->CreateLShr(mLLVMBuilder->CreateAnd(bitSelVec, broadcast), bitShiftVec);
171}
172
173Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
174    unsigned field_count = 2 * mBitBlockWidth/fw;
175    Value * aVec = fwCast(fw/2, a);
176    Value * bVec = fwCast(fw/2, b);
177    std::vector<Constant*> Idxs;
178    for (unsigned i = 0; i < field_count; i++) {
179        Idxs.push_back(mLLVMBuilder->getInt32(2*i));
180    }
181    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
182}
183
184Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
185    unsigned field_count = 2 * mBitBlockWidth/fw;
186    Value * aVec = fwCast(fw/2, a);
187    Value * bVec = fwCast(fw/2, b);
188    std::vector<Constant*> Idxs;
189    for (unsigned i = 0; i < field_count; i++) {
190        Idxs.push_back(mLLVMBuilder->getInt32(2*i+1));
191    }
192    return mLLVMBuilder->CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
193}
194
195Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
196    Value * mask = mLLVMBuilder->CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
197    return mLLVMBuilder->CreateZExt(mLLVMBuilder->CreateBitCast(mask, mLLVMBuilder->getIntNTy(mBitBlockWidth/fw)), mLLVMBuilder->getInt32Ty());
198}
199
200Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
201    Value * aVec = fwCast(fw, a);
202    return mLLVMBuilder->CreateExtractElement(aVec, mLLVMBuilder->getInt32(fieldIndex));
203}
204
205Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * blk, Value * elt, unsigned fieldIndex) {
206    Value * vec = fwCast(fw, blk);
207    return mLLVMBuilder->CreateInsertElement(vec, elt, mLLVMBuilder->getInt32(fieldIndex));
208}
209
210Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
211    unsigned field_count = mBitBlockWidth/fw;
212    Value * aVec = fwCast(fw, a);
213    Value * bVec = fwCast(fw, b);
214    std::vector<Constant*> Idxs;
215    for (unsigned i = 0; i < field_count; i++) {
216        Idxs.push_back(mLLVMBuilder->getInt32(i + shift));
217    }
218    return mLLVMBuilder->CreateShuffleVector(bVec, aVec, ConstantVector::get(Idxs));
219}
220
221Value * IDISA_Builder::bitblock_any(Value * a) {
222    Type * iBitBlock = mLLVMBuilder->getIntNTy(mBitBlockWidth);
223    return mLLVMBuilder->CreateICmpNE(mLLVMBuilder->CreateBitCast(a, iBitBlock),  ConstantInt::get(iBitBlock, 0));
224}
225
226Value * IDISA_Builder::simd_and(Value * a, Value * b) {
227    return a->getType() == b->getType() ? mLLVMBuilder->CreateAnd(a, b) : mLLVMBuilder->CreateAnd(bitCast(a), bitCast(b));
228}
229
230Value * IDISA_Builder::simd_or(Value * a, Value * b) {
231    return a->getType() == b->getType() ? mLLVMBuilder->CreateOr(a, b) : mLLVMBuilder->CreateOr(bitCast(a), bitCast(b));
232}
233   
234Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
235    return a->getType() == b->getType() ? mLLVMBuilder->CreateXor(a, b) : mLLVMBuilder->CreateXor(bitCast(a), bitCast(b));
236}
237
238Value * IDISA_Builder::simd_not(Value * a) {
239    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
240}
241
242}
Note: See TracBrowser for help on using the repository browser.