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

Last change on this file since 6132 was 6120, checked in by cameron, 15 months ago

Random value streams

File size: 16.2 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
16namespace kernels { class KernelBuilder; }
17namespace llvm { class Function; }
18namespace llvm { class IntegerType; }
19namespace llvm { class Module; }
20namespace llvm { class PointerType; }
21namespace llvm { class Type; }
22namespace llvm { class Value; }
23
24class Driver;
25
26class CBuilder : public llvm::IRBuilder<> {
27    using Predicate = llvm::CmpInst::Predicate;
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) {
68        if (a == nullptr) return b;
69        if (b == nullptr) return a;
70        assert (a->getType() == b->getType());
71        return CreateSelect(CreateICmpULT(a, b), a, b);
72    }
73
74    // Get minimum of two signed numbers
75    llvm::Value * CreateSMin(llvm::Value * const a, llvm::Value * const b) {
76        if (a == nullptr) return b;
77        if (b == nullptr) return a;
78        assert (a->getType() == b->getType());
79        return CreateSelect(CreateICmpSLT(a, b), a, b);
80    }
81
82    // Get maximum of two unsigned numbers
83    llvm::Value * CreateUMax(llvm::Value * const a, llvm::Value * const b) {
84        if (a == nullptr) return b;
85        if (b == nullptr) return a;
86        assert (a->getType() == b->getType());
87        return CreateSelect(CreateICmpUGT(a, b), a, b);
88    }
89
90    // Get maximum of two signed numbers
91    llvm::Value * CreateSMax(llvm::Value * const a, llvm::Value * const b) {
92        if (a == nullptr) return b;
93        if (b == nullptr) return a;
94        assert (a->getType() == b->getType());
95        return CreateSelect(CreateICmpSGT(a, b), a, b);
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    void CreateFree(llvm::Value * const ptr);
107
108    llvm::Value * CreateRealloc(llvm::Value * const ptr, llvm::Value * const size);
109
110    llvm::CallInst * CreateMemZero(llvm::Value * const ptr, llvm::Value * const size, const unsigned alignment = 1) {
111        return CreateMemSet(ptr, getInt8(0), size, alignment);
112    }
113
114    llvm::Value * CreateMemChr(llvm::Value * ptr, llvm::Value * byteVal, llvm::Value * num);
115   
116    llvm::AllocaInst * CreateAlignedAlloca(llvm::Type * const Ty, const unsigned alignment, llvm::Value * const ArraySize = nullptr) {
117        llvm::AllocaInst * instr = CreateAlloca(Ty, ArraySize);
118        instr->setAlignment(alignment);
119        return instr;
120    }
121
122    llvm::AllocaInst * CreateCacheAlignedAlloca(llvm::Type * const Ty, llvm::Value * const ArraySize = nullptr) {
123        return CreateAlignedAlloca(Ty, getCacheAlignment(), ArraySize);
124    }
125
126    // stdio.h functions
127    //
128    //  Create a call to:  FILE * fopen(const char *filename, const char *mode);
129    llvm::Value * CreateFOpenCall(llvm::Value * filename, llvm::Value * mode);
130    //  Create a call to:  size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
131    llvm::Value * CreateFReadCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
132    //  Create a call to:  size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream));
133    llvm::Value * CreateFWriteCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
134    //  Create a call to:  int fclose ( FILE * stream );
135    llvm::Value * CreateFCloseCall(llvm::Value * stream);
136    //  Create a call to:  int remove(const char *path);
137    llvm::Value * CreateRemoveCall(llvm::Value * path);
138   
139    //  Create a call to:  int rename(const char *old, const char *new);
140    llvm::Value * CreateRenameCall(llvm::Value * oldName, llvm::Value * newName);
141   
142    llvm::Function * GetPrintf();
143
144    llvm::Function * GetDprintf();
145
146    //  Create calls to unistd.h functions.
147    //
148    //  Create a call to:  int open(const char *filename, int oflag, ...);
149    llvm::Value * CreateOpenCall(llvm::Value * filename, llvm::Value * oflag, llvm::Value * mode);
150    //  Create a call to:  ssize_t write(int fildes, const void *buf, size_t nbyte);
151    llvm::Value * CreateWriteCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
152    //  Create a call to:  ssize_t read(int fildes, void *buf, size_t nbyte);
153    llvm::Value * CreateReadCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
154    //  Create a call to:  int close(int filedes);
155    llvm::Value * CreateCloseCall(llvm::Value * fileDescriptor);
156    //  Create a call to:  int unlink(const char *path);
157    llvm::Value * CreateUnlinkCall(llvm::Value * path);
158
159    llvm::Value * CreateFileSize(llvm::Value * fileDescriptor);
160
161    //  Create calls to stdlib.h functions.
162    //
163    //  Create a call to:  int mkstemp (char *template);
164    llvm::Value * CreateMkstempCall(llvm::Value * ftemplate);
165   
166    //  Create a call to:  size_t strlen(const char *str);
167    llvm::Value * CreateStrlenCall(llvm::Value * str);
168   
169    llvm::Value * CreateAnonymousMMap(llvm::Value * size);
170
171    llvm::Value * CreateFileSourceMMap(llvm::Value * fd, llvm::Value * size);
172
173    enum Advice {
174        ADVICE_NORMAL
175        , ADVICE_RANDOM
176        , ADVICE_SEQUENTIAL
177        , ADVICE_WILLNEED
178        , ADVICE_DONTNEED
179    };
180
181    llvm::Value * CreateMAdvise(llvm::Value * addr, llvm::Value * length, Advice advice);
182
183    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);
184
185    llvm::Value * CreateMRemap(llvm::Value * addr, llvm::Value * oldSize, llvm::Value * newSize);
186
187    llvm::Value * CreateMUnmap(llvm::Value * addr, llvm::Value * size);
188
189    enum Protect {
190        NONE = 0
191        , READ = 1
192        , WRITE = 2
193        , EXEC = 4
194    };
195
196    llvm::Value * CreateMProtect(llvm::Value * addr, llvm::Value * size, int protect);
197
198    //  Posix thread (pthread.h) functions.
199    //
200    //  Create a call to:  int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
201    //                    void *(*start_routine)(void*), void *arg);
202    llvm::Value * CreatePThreadCreateCall(llvm::Value * thread, llvm::Value * attr, llvm::Function * start_routine, llvm::Value * arg);
203
204    //  Create a call to:  int pthread_yield(void);
205    llvm::Value * CreatePThreadYield();
206   
207    //  Create a call to:  void pthread_exit(void *value_ptr);
208    llvm::Value * CreatePThreadExitCall(llvm::Value * value_ptr);
209   
210    //  Create a call to:  int pthread_join(pthread_t thread, void **value_ptr);
211    llvm::Value * CreatePThreadJoinCall(llvm::Value * thread, llvm::Value * value_ptr);
212
213    void CallPrintIntCond(const std::string & name, llvm::Value * const value, llvm::Value * const cond);
214
215    void CallPrintInt(const std::string & name, llvm::Value * const value);
216   
217    void CallPrintIntToStderr(const std::string & name, llvm::Value * const value);
218   
219    llvm::Value * GetString(llvm::StringRef Str);
220
221    void CallPrintMsgToStderr(const std::string & message);
222
223    inline llvm::IntegerType * getSizeTy() const {
224        assert (mSizeType);
225        return mSizeType;
226    }
227   
228    inline llvm::ConstantInt * getSize(const size_t value) {
229        return llvm::ConstantInt::get(getSizeTy(), value);
230    }
231   
232    llvm::IntegerType * LLVM_READNONE getIntAddrTy() const;
233   
234    llvm::PointerType * LLVM_READNONE getVoidPtrTy(const unsigned AddressSpace = 0) const;
235   
236    llvm::PointerType * LLVM_READNONE getFILEptrTy();
237   
238    inline unsigned getCacheAlignment() const {
239        return mCacheLineAlignment;
240    }
241   
242    virtual llvm::LoadInst* CreateAtomicLoadAcquire(llvm::Value * ptr);
243
244    virtual llvm::StoreInst *  CreateAtomicStoreRelease(llvm::Value * val, llvm::Value * ptr);
245
246    void CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage) {
247        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
248            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
249        }
250        return __CreateAssert(CreateIsNotNull(assertion), failureMessage);
251    }
252
253    void CreateAssertZero(llvm::Value * assertion, const llvm::Twine & failureMessage) {
254        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
255            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
256        }
257        return __CreateAssert(CreateIsNull(assertion), failureMessage);
258    }
259
260    void CreateExit(const int exitCode);
261
262    llvm::BranchInst * CreateLikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90);
263
264    llvm::BranchInst * CreateUnlikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90) {
265        return CreateLikelyCondBr(Cond, True, False, 100 - probability);
266    }
267
268    llvm::BasicBlock * CreateBasicBlock(const llvm::StringRef name = "", llvm::BasicBlock * insertBefore = nullptr);
269
270    virtual bool supportsIndirectBr() const;
271
272    llvm::Value * CreatePopcount(llvm::Value * bits);
273
274    // TODO: AVX512 offers these as vector instructions
275    llvm::Value * CreateCountForwardZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
276    llvm::Value * CreateCountReverseZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
277   
278    // Useful bit manipulation operations 
279    llvm::Value * CreateResetLowestBit(llvm::Value * bits);   
280   
281    llvm::Value * CreateIsolateLowestBit(llvm::Value * bits);
282   
283    llvm::Value * CreateMaskToLowestBitInclusive(llvm::Value * bits);
284   
285    llvm::Value * CreateMaskToLowestBitExclusive(llvm::Value * bits);
286   
287    llvm::Value * CreateExtractBitField(llvm::Value * bits, llvm::Value * start, llvm::Value * length);
288   
289    llvm::Value * CreateCeilLog2(llvm::Value * value);
290   
291    llvm::Value * CreateReadCycleCounter();
292
293    template <typename ExternalFunctionType>
294    llvm::Function * LinkFunction(llvm::StringRef name, ExternalFunctionType * functionPtr) const;
295
296    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const char * Name);
297
298    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const llvm::Twine & Name = "");
299
300    virtual llvm::LoadInst * CreateLoad(llvm::Type * Ty, llvm::Value * Ptr, const llvm::Twine & Name = "");
301
302    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, bool isVolatile, const llvm::Twine & Name = "");
303
304    virtual llvm::StoreInst * CreateStore(llvm::Value * Val, llvm::Value * Ptr, bool isVolatile = false);
305
306    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const char * Name);
307
308    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const llvm::Twine & Name = "");
309
310    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, bool isVolatile, const llvm::Twine & Name = "");
311
312    llvm::StoreInst * CreateAlignedStore(llvm::Value * Val, llvm::Value * Ptr, unsigned Align, bool isVolatile = false);
313
314    llvm::CallInst * CreateMemMove(llvm::Value *Dst, llvm::Value *Src, uint64_t Size, unsigned Align,
315                            bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
316                            llvm::MDNode *ScopeTag = nullptr,
317                            llvm::MDNode *NoAliasTag = nullptr) {
318        return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
319    }
320
321    llvm::CallInst * CreateMemMove(llvm::Value *Dst, llvm::Value *Src, llvm::Value *Size, unsigned Align,
322                            bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
323                            llvm::MDNode *ScopeTag = nullptr,
324                            llvm::MDNode *NoAliasTag = nullptr);
325
326    llvm::CallInst * CreateMemCpy(llvm::Value *Dst, llvm::Value *Src, uint64_t Size, unsigned Align,
327                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
328                           llvm::MDNode *TBAAStructTag = nullptr,
329                           llvm::MDNode *ScopeTag = nullptr,
330                           llvm::MDNode *NoAliasTag = nullptr) {
331        return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, TBAAStructTag, ScopeTag, NoAliasTag);
332    }
333
334    llvm::CallInst * CreateMemCpy(llvm::Value *Dst, llvm::Value *Src, llvm::Value *Size, unsigned Align,
335                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
336                           llvm::MDNode *TBAAStructTag = nullptr,
337                           llvm::MDNode *ScopeTag = nullptr,
338                           llvm::MDNode *NoAliasTag = nullptr);
339
340    llvm::CallInst * CreateMemSet(llvm::Value *Ptr, llvm::Value *Val, uint64_t Size, unsigned Align,
341                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
342                           llvm::MDNode *ScopeTag = nullptr,
343                           llvm::MDNode *NoAliasTag = nullptr) {
344        return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag, ScopeTag, NoAliasTag);
345    }
346
347    llvm::CallInst * CreateMemSet(llvm::Value *Ptr, llvm::Value *Val, llvm::Value *Size, unsigned Align,
348                           bool isVolatile = false, llvm::MDNode *TBAATag = nullptr,
349                           llvm::MDNode *ScopeTag = nullptr,
350                           llvm::MDNode *NoAliasTag = nullptr);
351   
352    llvm::CallInst * CreateSRandCall(llvm::Value * randomSeed);
353    llvm::CallInst * CreateRandCall();
354
355    void setDriver(Driver * const driver) {
356        mDriver = driver;
357    }
358
359protected:
360
361    bool hasAlignedAlloc() const;
362
363    bool hasPosixMemalign() const;
364
365    bool hasAddressSanitizer() const;
366
367    void __CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage);
368
369    llvm::Function * LinkFunction(llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const;
370
371protected:
372
373    llvm::Module *                  mModule;
374    unsigned                        mCacheLineAlignment;
375    llvm::IntegerType * const       mSizeType;
376    llvm::StructType *              mFILEtype;
377    Driver *                        mDriver;   
378    llvm::LLVMContext               mContext;
379    const std::string               mTriple;
380};
381
382template <typename ExternalFunctionType>
383llvm::Function *CBuilder::LinkFunction(llvm::StringRef name, ExternalFunctionType * functionPtr) const {
384    llvm::FunctionType * const type = FunctionTypeBuilder<ExternalFunctionType>::get(getContext());
385    assert ("FunctionTypeBuilder did not resolve a function type." && type);
386    return LinkFunction(name, type, reinterpret_cast<void *>(functionPtr));
387}
388
389#endif
Note: See TracBrowser for help on using the repository browser.