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

Last change on this file since 5761 was 5761, checked in by nmedfort, 14 months ago

Cache signature is now written into .kernel bitcode file. Minor bug fix and revision of GrepEngine::DoGrepThreadMethod?

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