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

Last change on this file was 6263, checked in by cameron, 7 weeks ago

getPThreadTy()

File size: 17.5 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#ifndef CBUILDER_H
6#define CBUILDER_H
7
8#include <IR_Gen/FunctionTypeBuilder.h>
9#include <llvm/IR/IRBuilder.h>
10#include <llvm/IR/Constants.h>
11#include <llvm/ADT/Triple.h>
12#ifndef NDEBUG
13#include <llvm/IR/Function.h>
14#endif
15#include <unistd.h>
16
17namespace kernels { class KernelBuilder; }
18namespace llvm { class Function; }
19namespace llvm { class IntegerType; }
20namespace llvm { class Module; }
21namespace llvm { class PointerType; }
22namespace llvm { class Type; }
23namespace llvm { class Value; }
24
25class BaseDriver;
26
27class CBuilder : public llvm::IRBuilder<> {
28public:
29
30    CBuilder(llvm::LLVMContext & C);
31
32    virtual ~CBuilder() {}
33
34    llvm::Module * getModule() const {
35        #ifndef NDEBUG
36        llvm::BasicBlock * const bb = GetInsertBlock();
37        if (bb) {
38            llvm::Function * const f = bb->getParent();
39            assert ("CBuilder has an insert point that is not contained within a Function" && f);
40            assert ("CBuilder module differs from insertion point module" && (mModule == f->getParent()));
41        }
42        #endif
43        return mModule;
44    }
45
46    void setModule(llvm::Module * module) {
47        mModule = module;
48        ClearInsertionPoint();
49    }
50
51    // UDiv and URem with optimization for division by power-of-2 constants
52    llvm::Value * CreateUDiv(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
53    llvm::Value * CreateURem(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
54
55    // Division with rounding up to the ceiling
56    // Equivalent to CreateUDiv(CreateAdd(number, CreateSub(divisor, ConstantInt::get(divisor->getType(), 1))), divisor)
57    llvm::Value * CreateCeilUDiv(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
58
59    llvm::Value * CreateUDivCeil(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "") {
60        return CreateCeilUDiv(number, divisor, Name);
61    }
62
63    // Round up to a multiple of divisor.
64    llvm::Value * CreateRoundUp(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
65
66    // Get minimum of two unsigned numbers
67    llvm::Value * CreateUMin(llvm::Value * const a, llvm::Value * const b, const llvm::Twine &Name = "") {
68        if (LLVM_UNLIKELY(a == nullptr || a == b)) return b;
69        if (LLVM_UNLIKELY(b == nullptr)) return a;
70        assert (a->getType() == b->getType());
71        return CreateSelect(CreateICmpULT(a, b), a, b, Name);
72    }
73
74    // Get minimum of two signed numbers
75    llvm::Value * CreateSMin(llvm::Value * const a, llvm::Value * const b, const llvm::Twine &Name = "") {
76        if (LLVM_UNLIKELY(a == nullptr || a == b)) return b;
77        if (LLVM_UNLIKELY(b == nullptr)) return a;
78        assert (a->getType() == b->getType());
79        return CreateSelect(CreateICmpSLT(a, b), a, b, Name);
80    }
81
82    // Get maximum of two unsigned numbers
83    llvm::Value * CreateUMax(llvm::Value * const a, llvm::Value * const b, const llvm::Twine &Name = "") {
84        if (LLVM_UNLIKELY(a == nullptr || a == b)) return b;
85        if (LLVM_UNLIKELY(b == nullptr)) return a;
86        assert (a->getType() == b->getType());
87        return CreateSelect(CreateICmpUGT(a, b), a, b, Name);
88    }
89
90    // Get maximum of two signed numbers
91    llvm::Value * CreateSMax(llvm::Value * const a, llvm::Value * const b, const llvm::Twine &Name = "") {
92        if (LLVM_UNLIKELY(a == nullptr || a == b)) return b;
93        if (LLVM_UNLIKELY(b == nullptr)) return a;
94        assert (a->getType() == b->getType());
95        return CreateSelect(CreateICmpSGT(a, b), a, b, Name);
96    }
97
98    llvm::Value * CreateMalloc(llvm::Value * const size);
99
100    llvm::Value * CreateAlignedMalloc(llvm::Value * const size, const unsigned alignment);
101
102    llvm::Value * CreateCacheAlignedMalloc(llvm::Value * const size) {
103        return CreateAlignedMalloc(size, getCacheAlignment());
104    }
105
106    llvm::Value * CreateCacheAlignedMalloc(llvm::Type * const type, llvm::Value * const ArraySize = nullptr, const unsigned addressSpace = 0);
107
108    void CreateFree(llvm::Value * const ptr);
109
110    llvm::Value * CreateRealloc(llvm::Type * const type, llvm::Value * const base, llvm::Value * const ArraySize);
111
112    llvm::Value * CreateRealloc(llvm::Value * const base, llvm::Value * const size);
113
114    llvm::CallInst * CreateMemZero(llvm::Value * const ptr, llvm::Value * const size, const unsigned alignment = 1) {
115        return CreateMemSet(ptr, getInt8(0), size, alignment);
116    }
117
118    llvm::Value * CreateMemChr(llvm::Value * ptr, llvm::Value * byteVal, llvm::Value * num);
119
120    llvm::CallInst * CreateMemCmp(llvm::Value * ptr1, llvm::Value * ptr2, llvm::Value * num);
121
122    llvm::AllocaInst * CreateAlignedAlloca(llvm::Type * const Ty, const unsigned alignment, llvm::Value * const ArraySize = nullptr) {
123        llvm::AllocaInst * const alloc = CreateAlloca(Ty, ArraySize);
124        alloc->setAlignment(alignment);
125        return alloc;
126    }
127
128    llvm::AllocaInst * CreateCacheAlignedAlloca(llvm::Type * const Ty, llvm::Value * const ArraySize = nullptr) {
129        return CreateAlignedAlloca(Ty, getCacheAlignment(), ArraySize);
130    }
131
132    // stdio.h functions
133    //
134    //  Create a call to:  FILE * fopen(const char *filename, const char *mode);
135    llvm::Value * CreateFOpenCall(llvm::Value * filename, llvm::Value * mode);
136    //  Create a call to:  size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
137    llvm::Value * CreateFReadCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
138    //  Create a call to:  size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream));
139    llvm::Value * CreateFWriteCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
140    //  Create a call to:  int fclose ( FILE * stream );
141    llvm::Value * CreateFCloseCall(llvm::Value * stream);
142    //  Create a call to:  int remove(const char *path);
143    llvm::Value * CreateRemoveCall(llvm::Value * path);
144
145    //  Create a call to:  int rename(const char *old, const char *new);
146    llvm::Value * CreateRenameCall(llvm::Value * oldName, llvm::Value * newName);
147
148    llvm::Function * GetPrintf();
149
150    llvm::Function * GetDprintf();
151
152    //  Create calls to unistd.h functions.
153    //
154    //  Create a call to:  int open(const char *filename, int oflag, ...);
155    llvm::Value * CreateOpenCall(llvm::Value * filename, llvm::Value * oflag, llvm::Value * mode);
156    //  Create a call to:  ssize_t write(int fildes, const void *buf, size_t nbyte);
157    llvm::Value * CreateWriteCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
158    //  Create a call to:  ssize_t read(int fildes, void *buf, size_t nbyte);
159    llvm::Value * CreateReadCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
160    //  Create a call to:  int close(int filedes);
161    llvm::Value * CreateCloseCall(llvm::Value * fileDescriptor);
162    //  Create a call to:  int unlink(const char *path);
163    llvm::Value * CreateUnlinkCall(llvm::Value * path);
164
165    // llvm::Value * CreateFileSize(llvm::Value * fileDescriptor);
166
167    llvm::Value * CreateFSync(llvm::Value * fileDescriptor);
168
169    //  Create calls to stdlib.h functions.
170    //
171    //  Create a call to:  int mkstemp (char *template);
172    llvm::Value * CreateMkstempCall(llvm::Value * ftemplate);
173
174    //  Create a call to:  size_t strlen(const char *str);
175    llvm::Value * CreateStrlenCall(llvm::Value * str);
176
177    llvm::Value * CreateAnonymousMMap(llvm::Value * size);
178
179    llvm::Value * CreateFileSourceMMap(llvm::Value * fd, llvm::Value * size);
180
181    enum Advice {
182        ADVICE_NORMAL
183        , ADVICE_RANDOM
184        , ADVICE_SEQUENTIAL
185        , ADVICE_WILLNEED
186        , ADVICE_DONTNEED
187    };
188
189    llvm::Value * CreateMAdvise(llvm::Value * addr, llvm::Value * length, Advice advice);
190
191    llvm::Value * CreateMMap(llvm::Value * const addr, llvm::Value * size, llvm::Value * const prot, llvm::Value * const flags, llvm::Value * const fd, llvm::Value * const offset);
192
193    llvm::Value * CreateMRemap(llvm::Value * addr, llvm::Value * oldSize, llvm::Value * newSize);
194
195    llvm::Value * CreateMUnmap(llvm::Value * addr, llvm::Value * size);
196
197    enum Protect {
198        NONE = 0
199        , READ = 1
200        , WRITE = 2
201        , EXEC = 4
202    };
203
204    llvm::Value * CreateMProtect(llvm::Value * addr, const Protect protect) {
205        return CreateMProtect(addr, llvm::ConstantExpr::getSizeOf(addr->getType()->getPointerElementType()), protect);
206    }
207
208    llvm::Value * CreateMProtect(llvm::Value * addr, llvm::Value * size, const Protect protect);
209
210    //  Posix thread (pthread.h) functions.
211    //
212    llvm::Type * getPThreadTy();
213    //  Create a call to:  int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
214    //                    void *(*start_routine)(void*), void *arg);
215    llvm::Value * CreatePThreadCreateCall(llvm::Value * thread, llvm::Value * attr, llvm::Function * start_routine, llvm::Value * arg);
216
217    //  Create a call to:  int pthread_yield(void);
218    llvm::Value * CreatePThreadYield();
219
220    //  Create a call to:  void pthread_exit(void *value_ptr);
221    llvm::Value * CreatePThreadExitCall(llvm::Value * value_ptr);
222
223    //  Create a call to:  int pthread_join(pthread_t thread, void **value_ptr);
224    llvm::Value * CreatePThreadJoinCall(llvm::Value * thread, llvm::Value * value_ptr);
225
226    enum class STD_FD {
227        STD_IN = STDIN_FILENO
228        , STD_OUT = STDOUT_FILENO
229        , STD_ERR = STDERR_FILENO
230    };
231
232    void CallPrintIntCond(llvm::StringRef name, llvm::Value * const value, llvm::Value * const cond, const STD_FD fd = STD_FD::STD_ERR);
233
234    void CallPrintInt(llvm::StringRef name, llvm::Value * const value, const STD_FD fd = STD_FD::STD_ERR);
235
236    llvm::Value * GetString(llvm::StringRef Str);
237
238    inline llvm::IntegerType * getSizeTy() const {
239        assert (mSizeType);
240        return mSizeType;
241    }
242
243    inline llvm::ConstantInt * LLVM_READNONE getSize(const size_t value) {
244        return llvm::ConstantInt::get(getSizeTy(), value);
245    }
246
247    llvm::IntegerType * LLVM_READNONE getIntAddrTy() const;
248
249    llvm::PointerType * LLVM_READNONE getVoidPtrTy(const unsigned AddressSpace = 0) const;
250
251    llvm::PointerType * LLVM_READNONE getFILEptrTy();
252
253    inline unsigned getCacheAlignment() const {
254        return mCacheLineAlignment;
255    }
256
257    static LLVM_READNONE unsigned getPageSize();
258
259    virtual llvm::LoadInst* CreateAtomicLoadAcquire(llvm::Value * ptr);
260
261    virtual llvm::StoreInst *  CreateAtomicStoreRelease(llvm::Value * val, llvm::Value * ptr);
262
263    void CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage) {
264        return __CreateAssert(CreateIsNotNull(assertion), failureMessage);
265    }
266
267    void CreateAssertZero(llvm::Value * assertion, const llvm::Twine & failureMessage) {
268        return __CreateAssert(CreateIsNull(assertion), failureMessage);
269    }
270
271    void CreateExit(const int exitCode);
272
273    llvm::BranchInst * CreateLikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90);
274
275    llvm::BranchInst * CreateUnlikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90) {
276        return CreateLikelyCondBr(Cond, True, False, 100 - probability);
277    }
278
279    llvm::BasicBlock * CreateBasicBlock(const llvm::StringRef name = "", llvm::BasicBlock * insertBefore = nullptr);
280
281    virtual bool supportsIndirectBr() const;
282
283    llvm::Value * CreatePopcount(llvm::Value * bits);
284
285    // TODO: AVX512 offers these as vector instructions
286    llvm::Value * CreateCountForwardZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
287    llvm::Value * CreateCountReverseZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
288
289    // Useful bit manipulation operations
290    llvm::Value * CreateResetLowestBit(llvm::Value * bits);
291
292    llvm::Value * CreateIsolateLowestBit(llvm::Value * bits);
293
294    llvm::Value * CreateMaskToLowestBitInclusive(llvm::Value * bits);
295
296    llvm::Value * CreateMaskToLowestBitExclusive(llvm::Value * bits);
297
298    llvm::Value * CreateExtractBitField(llvm::Value * bits, llvm::Value * start, llvm::Value * length);
299
300    llvm::Value * CreateCeilLog2(llvm::Value * value);
301
302    llvm::Value * CreateReadCycleCounter();
303
304    template <typename ExternalFunctionType>
305    llvm::Function * LinkFunction(llvm::StringRef name, ExternalFunctionType & functionPtr) const;
306
307    llvm::Function * LinkFunction(llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const;
308
309    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const char * Name);
310
311    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const llvm::Twine & Name = "");
312
313    virtual llvm::LoadInst * CreateLoad(llvm::Type * Ty, llvm::Value * Ptr, const llvm::Twine & Name = "");
314
315    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, bool isVolatile, const llvm::Twine & Name = "");
316
317    virtual llvm::StoreInst * CreateStore(llvm::Value * Val, llvm::Value * Ptr, bool isVolatile = false);
318
319    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const char * Name);
320
321    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const llvm::Twine & Name = "");
322
323    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, bool isVolatile, const llvm::Twine & Name = "");
324
325    llvm::StoreInst * CreateAlignedStore(llvm::Value * Val, llvm::Value * Ptr, unsigned Align, bool isVolatile = false);
326
327    llvm::CallInst * CreateMemMove(llvm::Value *Dst, llvm::Value *Src, uint64_t Size, unsigned Align,
328                            bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
329                            llvm::MDNode *ScopeTag = nullptr,
330                            llvm::MDNode *NoAliasTag = nullptr) {
331        return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
332    }
333
334    llvm::CallInst * CreateMemMove(llvm::Value *Dst, llvm::Value *Src, llvm::Value *Size, unsigned Align,
335                            bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
336                            llvm::MDNode *ScopeTag = nullptr,
337                            llvm::MDNode *NoAliasTag = nullptr);
338
339    llvm::CallInst * CreateMemCpy(llvm::Value *Dst, llvm::Value *Src, uint64_t Size, unsigned Align,
340                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
341                           llvm::MDNode *TBAAStructTag = nullptr,
342                           llvm::MDNode *ScopeTag = nullptr,
343                           llvm::MDNode *NoAliasTag = nullptr) {
344        return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, TBAAStructTag, ScopeTag, NoAliasTag);
345    }
346
347    llvm::CallInst * CreateMemCpy(llvm::Value *Dst, llvm::Value *Src, llvm::Value *Size, unsigned Align,
348                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
349                           llvm::MDNode *TBAAStructTag = nullptr,
350                           llvm::MDNode *ScopeTag = nullptr,
351                           llvm::MDNode *NoAliasTag = nullptr);
352
353    llvm::CallInst * CreateMemSet(llvm::Value *Ptr, llvm::Value *Val, uint64_t Size, unsigned Align,
354                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
355                           llvm::MDNode *ScopeTag = nullptr,
356                           llvm::MDNode *NoAliasTag = nullptr) {
357        return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
358    }
359
360    llvm::CallInst * CreateMemSet(llvm::Value *Ptr, llvm::Value *Val, llvm::Value *Size, unsigned Align,
361                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
362                           llvm::MDNode *ScopeTag = nullptr,
363                           llvm::MDNode *NoAliasTag = nullptr);
364
365    llvm::Value * CreateExtractElement(llvm::Value *Vec, llvm::Value *Idx, const llvm::Twine &Name = "");
366
367    llvm::Value * CreateExtractElement(llvm::Value *Vec, uint64_t Idx, const llvm::Twine &Name = "") {
368        return CreateExtractElement(Vec, getInt64(Idx), Name);
369    }
370
371    llvm::Value * CreateInsertElement(llvm::Value *Vec, llvm::Value *NewElt, llvm::Value *Idx, const llvm::Twine &Name = "");
372
373    llvm::Value * CreateInsertElement(llvm::Value *Vec, llvm::Value *NewElt, uint64_t Idx, const llvm::Twine &Name = "") {
374        return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name);
375    }
376
377    llvm::CallInst * CreateSRandCall(llvm::Value * randomSeed);
378    llvm::CallInst * CreateRandCall();
379
380    void setDriver(BaseDriver * const driver) {
381        mDriver = driver;
382    }
383
384protected:
385
386    bool hasAlignedAlloc() const;
387
388    bool hasPosixMemalign() const;
389
390    bool hasAddressSanitizer() const;
391
392    virtual std::string getKernelName() const = 0;
393
394    void __CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage);
395
396protected:
397
398    llvm::Module *                  mModule;
399    unsigned                        mCacheLineAlignment;
400    llvm::IntegerType * const       mSizeType;
401    llvm::StructType *              mFILEtype;
402    BaseDriver *                    mDriver;
403    llvm::LLVMContext               mContext;
404    const std::string               mTriple;
405};
406
407template <typename ExternalFunctionType>
408llvm::Function * CBuilder::LinkFunction(llvm::StringRef name, ExternalFunctionType & functionPtr) const {
409    llvm::FunctionType * const type = FunctionTypeBuilder<ExternalFunctionType>::get(getContext());
410    assert ("FunctionTypeBuilder did not resolve a function type." && type);
411    return LinkFunction(name, type, reinterpret_cast<void *>(&functionPtr));
412}
413
414llvm::ModulePass * createRemoveRedundantAssertionsPass();
415
416#endif
Note: See TracBrowser for help on using the repository browser.