source: icGREP/icgrep-devel/icgrep/IR_Gen/idisa_builder.h

Last change on this file was 6295, checked in by cameron, 4 months ago

Merge branch 'feat-simd-ternary' into 'master'

Implementing both simd_binary and simd_ternary operations

See merge request cameron/parabix-devel!1

File size: 10.8 KB
Line 
1#ifndef IDISA_BUILDER_H
2#define IDISA_BUILDER_H
3
4/*
5 *  Copyright (c) 2018 International Characters.
6 *  This software is licensed to the public under the Open Software License 3.0.
7 *  icgrep is a trademark of International Characters.
8 */
9#include "CBuilder.h"
10#include <llvm/IR/DerivedTypes.h>
11namespace llvm { class Constant; }
12namespace llvm { class LoadInst; }
13namespace llvm { class Module; }
14namespace llvm { class Value; }
15namespace llvm { class StringRef; }
16
17namespace IDISA {
18
19   
20inline bool isStreamTy(llvm::Type * t) {
21    return t->isVectorTy() && (t->getVectorNumElements() == 0);
22}
23
24inline bool isStreamSetTy(llvm::Type * t) {
25    return t->isArrayTy() && (isStreamTy(t->getArrayElementType()));
26}
27
28inline unsigned getNumOfStreams (llvm::Type * t) {
29    if (isStreamTy(t)) return 1;
30    assert(isStreamSetTy(t));
31    return t->getArrayNumElements();
32}
33
34inline unsigned getStreamFieldWidth (llvm::Type * t) {
35    if (isStreamTy(t)) return t->getScalarSizeInBits();
36    assert(isStreamSetTy(t));
37    return t->getArrayElementType()->getScalarSizeInBits();
38}
39
40unsigned getVectorBitWidth(llvm::Value * vec);
41   
42class IDISA_Builder : public CBuilder {
43
44public:
45
46    IDISA_Builder(llvm::LLVMContext & C, unsigned nativeVectorWidth, unsigned vectorWidth, unsigned laneWidth);
47
48    virtual ~IDISA_Builder();
49   
50    virtual std::string getBuilderUniqueName() = 0;  // A name uniquely identifying builder/bitBlockWidth/stride.
51   
52    llvm::Value * bitCast(llvm::Value * a) {
53        return fwCast(mLaneWidth, a);
54    }
55
56    unsigned getBitBlockWidth() const {
57        return mBitBlockWidth;
58    }
59
60    llvm::Constant * allZeroes() const {
61        return mZeroInitializer;
62    }
63
64    llvm::Constant * allOnes() const {
65        return mOneInitializer;
66    }
67   
68    llvm::Constant * getConstantVectorSequence(unsigned fw, unsigned first, unsigned last, unsigned by = 1);
69   
70    llvm::Value * CreateHalfVectorHigh(llvm::Value *);
71   
72    llvm::Value * CreateHalfVectorLow(llvm::Value *);
73
74    llvm::Value * CreateDoubleVector(llvm::Value * lo, llvm::Value * hi);
75   
76    llvm::LoadInst * CreateBlockAlignedLoad(llvm::Value * const ptr) {
77        return CreateAlignedLoad(ptr, mBitBlockWidth / 8);
78    }
79
80    llvm::LoadInst * CreateBlockAlignedLoad(llvm::Value * const ptr, llvm::Value * const index) {
81        return CreateBlockAlignedLoad(CreateGEP(ptr, index));
82    }
83
84    llvm::LoadInst * CreateBlockAlignedLoad(llvm::Value * const ptr, std::initializer_list<llvm::Value *> indices) {
85        return CreateBlockAlignedLoad(CreateGEP(ptr, indices));
86    }
87
88    llvm::StoreInst * CreateBlockAlignedStore(llvm::Value * const value, llvm::Value * const ptr) {
89        return CreateAlignedStore(value, ptr, mBitBlockWidth / 8);
90    }
91
92    llvm::StoreInst * CreateBlockAlignedStore(llvm::Value * const value, llvm::Value * const ptr, llvm::Value * const index) {
93        return CreateBlockAlignedStore(value, CreateGEP(ptr, index));
94    }
95
96    llvm::StoreInst * CreateBlockAlignedStore(llvm::Value * const value, llvm::Value * const ptr, std::initializer_list<llvm::Value *> indices) {
97        return CreateBlockAlignedStore(value, CreateGEP(ptr, indices));
98    }
99
100    llvm::Value * CreateBlockAlignedMalloc(llvm::Value * size) {
101        return CreateAlignedMalloc(size, mBitBlockWidth / 8);
102    }
103
104    llvm::VectorType * fwVectorType(const unsigned fw);
105
106    llvm::Constant * simd_himask(unsigned fw);
107    llvm::Constant * simd_lomask(unsigned fw);
108   
109    llvm::Value * simd_select_hi(unsigned fw, llvm::Value * a);
110    llvm::Value * simd_select_lo(unsigned fw, llvm::Value * a);
111
112    virtual llvm::Value * simd_fill(unsigned fw, llvm::Value * a);
113
114    virtual llvm::Value * simd_add(unsigned fw, llvm::Value * a, llvm::Value * b);
115    virtual llvm::Value * simd_sub(unsigned fw, llvm::Value * a, llvm::Value * b);
116    virtual llvm::Value * simd_mult(unsigned fw, llvm::Value * a, llvm::Value * b);
117    virtual llvm::Value * simd_eq(unsigned fw, llvm::Value * a, llvm::Value * b);
118    virtual llvm::Value * simd_gt(unsigned fw, llvm::Value * a, llvm::Value * b);
119    virtual llvm::Value * simd_ugt(unsigned fw, llvm::Value * a, llvm::Value * b);
120    virtual llvm::Value * simd_lt(unsigned fw, llvm::Value * a, llvm::Value * b);
121    virtual llvm::Value * simd_ult(unsigned fw, llvm::Value * a, llvm::Value * b);
122    virtual llvm::Value * simd_ule(unsigned fw, llvm::Value * a, llvm::Value * b);
123    virtual llvm::Value * simd_uge(unsigned fw, llvm::Value * a, llvm::Value * b);
124    virtual llvm::Value * simd_max(unsigned fw, llvm::Value * a, llvm::Value * b);
125    virtual llvm::Value * simd_umax(unsigned fw, llvm::Value * a, llvm::Value * b);
126    virtual llvm::Value * simd_min(unsigned fw, llvm::Value * a, llvm::Value * b);
127    virtual llvm::Value * simd_umin(unsigned fw, llvm::Value * a, llvm::Value * b);
128    virtual llvm::Value * simd_if(unsigned fw, llvm::Value * cond, llvm::Value * a, llvm::Value * b);
129    llvm::Value * simd_binary(unsigned char mask, llvm::Value * a, llvm::Value * b);
130    virtual llvm::Value * simd_ternary(unsigned char mask, llvm::Value * a, llvm::Value * b, llvm::Value * c);
131   
132    virtual llvm::Value * simd_slli(unsigned fw, llvm::Value * a, unsigned shift);
133    virtual llvm::Value * simd_srli(unsigned fw, llvm::Value * a, unsigned shift);
134    virtual llvm::Value * simd_srai(unsigned fw, llvm::Value * a, unsigned shift);
135    virtual llvm::Value * simd_sllv(unsigned fw, llvm::Value * a, llvm::Value * shifts);
136    virtual llvm::Value * simd_srlv(unsigned fw, llvm::Value * a, llvm::Value * shifts);
137   
138    virtual llvm::Value * simd_pext(unsigned fw, llvm::Value * v, llvm::Value * extract_mask);
139    virtual llvm::Value * simd_pdep(unsigned fw, llvm::Value * v, llvm::Value * deposit_mask);
140   
141    virtual llvm::Value * simd_popcount(unsigned fw, llvm::Value * a);
142    virtual llvm::Value * simd_cttz(unsigned fw, llvm::Value * a);
143
144    virtual llvm::Value * simd_bitreverse(unsigned fw, llvm::Value * a);
145   
146    virtual llvm::Value * esimd_mergeh(unsigned fw, llvm::Value * a, llvm::Value * b);
147    virtual llvm::Value * esimd_mergel(unsigned fw, llvm::Value * a, llvm::Value * b);
148    virtual llvm::Value * esimd_bitspread(unsigned fw, llvm::Value * bitmask);
149   
150    virtual llvm::Value * hsimd_packh(unsigned fw, llvm::Value * a, llvm::Value * b);
151    virtual llvm::Value * hsimd_packl(unsigned fw, llvm::Value * a, llvm::Value * b);
152    virtual llvm::Value * hsimd_packh_in_lanes(unsigned lanes, unsigned fw, llvm::Value * a, llvm::Value * b);
153    virtual llvm::Value * hsimd_packl_in_lanes(unsigned lanes, unsigned fw, llvm::Value * a, llvm::Value * b);
154
155    virtual llvm::Value * hsimd_signmask(unsigned fw, llvm::Value * a);
156   
157    virtual llvm::Value * mvmd_extract(unsigned fw, llvm::Value * a, unsigned fieldIndex);
158    virtual llvm::Value * mvmd_insert(unsigned fw, llvm::Value * blk, llvm::Value * elt, unsigned fieldIndex);
159
160    virtual llvm::Value * mvmd_sll(unsigned fw, llvm::Value * value, llvm::Value * shift, const bool safe = false);
161    virtual llvm::Value * mvmd_srl(unsigned fw, llvm::Value * value, llvm::Value * shift, const bool safe = false);
162    virtual llvm::Value * mvmd_slli(unsigned fw, llvm::Value * a, unsigned shift);
163    virtual llvm::Value * mvmd_srli(unsigned fw, llvm::Value * a, unsigned shift);
164    virtual llvm::Value * mvmd_dslli(unsigned fw, llvm::Value * a, llvm::Value * b, unsigned shift);
165    virtual llvm::Value * mvmd_dsll(unsigned fw, llvm::Value * a, llvm::Value * b, llvm::Value * shift);
166    virtual llvm::Value * mvmd_shuffle(unsigned fw, llvm::Value * data_table, llvm::Value * index_vector);
167    virtual llvm::Value * mvmd_shuffle2(unsigned fw, llvm::Value * table0, llvm::Value * table1, llvm::Value * index_vector);
168    virtual llvm::Value * mvmd_compress(unsigned fw, llvm::Value * a, llvm::Value * select_mask);
169
170   
171    virtual llvm::Value * bitblock_any(llvm::Value * a);
172    // full add producing {carryout, sum}
173    virtual std::pair<llvm::Value *, llvm::Value *> bitblock_add_with_carry(llvm::Value * a, llvm::Value * b, llvm::Value * carryin);
174    // full shift producing {shiftout, shifted}
175    virtual std::pair<llvm::Value *, llvm::Value *> bitblock_advance(llvm::Value * a, llvm::Value * shiftin, unsigned shift);
176    virtual std::pair<llvm::Value *, llvm::Value *> bitblock_indexed_advance(llvm::Value * a, llvm::Value * index_strm, llvm::Value * shiftin, unsigned shift);
177    virtual llvm::Value * bitblock_mask_from(llvm::Value * const position, const bool safe = false);
178    virtual llvm::Value * bitblock_mask_to(llvm::Value * const position, const bool safe = false);
179    virtual llvm::Value * bitblock_set_bit(llvm::Value * const position, const bool safe = false);
180
181    // returns a scalar with the popcount of this block
182    llvm::Value * bitblock_popcount(llvm::Value * const to_count);
183
184    virtual void CreateBaseFunctions() {}
185   
186    llvm::Value * simd_and(llvm::Value * a, llvm::Value * b, llvm::StringRef s = llvm::StringRef());
187    llvm::Value * simd_or(llvm::Value * a, llvm::Value * b, llvm::StringRef s = llvm::StringRef());
188    llvm::Value * simd_xor(llvm::Value * a, llvm::Value * b, llvm::StringRef s = llvm::StringRef());
189    llvm::Value * simd_not(llvm::Value * a, llvm::StringRef s = llvm::StringRef());
190    llvm::Value * fwCast(unsigned fw, llvm::Value * a);
191   
192    inline llvm::VectorType * getBitBlockType() const {
193        return mBitBlockType;
194    }
195
196    static llvm::VectorType * LLVM_READNONE getStreamTy(llvm::LLVMContext & C, const unsigned FieldWidth = 1) {
197        return llvm::VectorType::get(llvm::IntegerType::getIntNTy(C, FieldWidth), 0);
198    }
199
200    static llvm::ArrayType * LLVM_READNONE getStreamSetTy(llvm::LLVMContext & C, const unsigned NumElements = 1, const unsigned FieldWidth = 1) {
201        return llvm::ArrayType::get(getStreamTy(C, FieldWidth), NumElements);
202    }
203
204    llvm::VectorType * getStreamTy(const unsigned FieldWidth = 1) {
205        return getStreamTy(getContext(), FieldWidth);
206    }
207
208    llvm::ArrayType * getStreamSetTy(const unsigned NumElements = 1, const unsigned FieldWidth = 1) {
209        return getStreamSetTy(getContext(), NumElements, FieldWidth);
210    }
211
212    void CallPrintRegisterCond(llvm::StringRef regName, llvm::Value * const value, llvm::Value * const cond, const STD_FD fd = STD_FD::STD_ERR);
213    void CallPrintRegister(llvm::StringRef regName, llvm::Value * const value, const STD_FD fd = STD_FD::STD_ERR);
214
215protected:
216    LLVM_ATTRIBUTE_NORETURN void UnsupportedFieldWidthError(const unsigned FieldWidth, std::string op_name);
217   
218    llvm::Constant * bit_interleave_byteshuffle_table(unsigned fw);  // support function for merge using shuffles.
219
220    const unsigned              mNativeBitBlockWidth;
221    const unsigned              mBitBlockWidth;
222    const unsigned              mLaneWidth;
223    llvm::VectorType * const    mBitBlockType;
224    llvm::Constant * const      mZeroInitializer;
225    llvm::Constant * const      mOneInitializer;
226    llvm::Constant *            mPrintRegisterFunction;
227};
228
229}
230#endif // IDISA_BUILDER_H
Note: See TracBrowser for help on using the repository browser.