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

Last change on this file since 5597 was 5597, checked in by nmedfort, 2 years ago

Modified stream set buffers to use heap memory.

File size: 11.5 KB
RevLine 
[5239]1/*
2 *  Copyright (c) 2016 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
[5425]8#include <IR_Gen/FunctionTypeBuilder.h>
[5239]9#include <llvm/IR/IRBuilder.h>
[5260]10#include <llvm/IR/Constants.h>
[5425]11#include <llvm/ADT/Triple.h>
[5440]12#ifndef NDEBUG
13#include <llvm/IR/Function.h>
14#endif
[5425]15
16namespace kernels { class KernelBuilder; }
[5260]17namespace llvm { class Function; }
18namespace llvm { class IntegerType; }
19namespace llvm { class Module; }
20namespace llvm { class PointerType; }
21namespace llvm { class Type; }
22namespace llvm { class Value; }
[5239]23
[5464]24class Driver;
[5425]25
[5260]26class CBuilder : public llvm::IRBuilder<> {
[5493]27    using Predicate = llvm::CmpInst::Predicate;
[5239]28public:
[5386]29
[5489]30    CBuilder(llvm::LLVMContext & C);
[5239]31   
32    virtual ~CBuilder() {}
33
[5260]34    llvm::Module * getModule() const {
[5440]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;
[5239]44    }
[5431]45
[5440]46    void setModule(llvm::Module * module) {
47        mModule = module;
48        ClearInsertionPoint();
[5239]49    }
[5541]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 = "");
[5340]54
[5541]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 = "");
[5543]58   
59    // Round up to a multiple of divisor.
60    llvm::Value * CreateRoundUp(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
61           
[5361]62    llvm::Value * CreateMalloc(llvm::Value * size);
63
64    llvm::Value * CreateAlignedMalloc(llvm::Value * size, const unsigned alignment);
[5280]65   
[5260]66    void CreateFree(llvm::Value * const ptr);
[5464]67
[5260]68    llvm::Value * CreateRealloc(llvm::Value * ptr, llvm::Value * size);
[5245]69
[5337]70    llvm::CallInst * CreateMemZero(llvm::Value * ptr, llvm::Value * size, const unsigned alignment = 1) {
[5353]71        return CreateMemSet(ptr, getInt8(0), size, alignment);
[5337]72    }
73
74    llvm::AllocaInst * CreateCacheAlignedAlloca(llvm::Type * Ty, llvm::Value * ArraySize = nullptr) {
[5245]75        llvm::AllocaInst * instr = CreateAlloca(Ty, ArraySize);
76        instr->setAlignment(getCacheAlignment());
77        return instr;
78    }
[5386]79
[5597]80    llvm::Value * CreateCacheAlignedMalloc(llvm::Value * size);
[5464]81
[5280]82    // stdio.h functions
83    //
[5308]84    //  Create a call to:  FILE * fopen(const char *filename, const char *mode);
[5280]85    llvm::Value * CreateFOpenCall(llvm::Value * filename, llvm::Value * mode);
[5281]86    //  Create a call to:  size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
87    llvm::Value * CreateFReadCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
[5280]88    //  Create a call to:  size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream));
89    llvm::Value * CreateFWriteCall(llvm::Value * ptr, llvm::Value * size, llvm::Value * nitems, llvm::Value * stream);
90    //  Create a call to:  int fclose ( FILE * stream );
91    llvm::Value * CreateFCloseCall(llvm::Value * stream);
[5415]92    //  Create a call to:  int remove(const char *path);
93    llvm::Value * CreateRemoveCall(llvm::Value * path);
[5280]94   
[5415]95    //  Create a call to:  int rename(const char *old, const char *new);
96    llvm::Value * CreateRenameCall(llvm::Value * oldName, llvm::Value * newName);
97   
[5267]98    llvm::Function * GetPrintf();
99
[5422]100    llvm::Function * GetDprintf();
101
[5280]102    //  Create calls to unistd.h functions.
103    //
[5308]104    //  Create a call to:  int open(const char *filename, int oflag, ...);
105    llvm::Value * CreateOpenCall(llvm::Value * filename, llvm::Value * oflag, llvm::Value * mode);
[5280]106    //  Create a call to:  ssize_t write(int fildes, const void *buf, size_t nbyte);
[5418]107    llvm::Value * CreateWriteCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
[5281]108    //  Create a call to:  ssize_t read(int fildes, void *buf, size_t nbyte);
[5418]109    llvm::Value * CreateReadCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
[5308]110    //  Create a call to:  int close(int filedes);
[5418]111    llvm::Value * CreateCloseCall(llvm::Value * fileDescriptor);
[5415]112    //  Create a call to:  int unlink(const char *path);
113    llvm::Value * CreateUnlinkCall(llvm::Value * path);
[5281]114
[5418]115    llvm::Value * CreateFileSize(llvm::Value * fileDescriptor);
116
[5415]117    //  Create calls to stdlib.h functions.
118    //
119    //  Create a call to:  int mkstemp (char *template);
120    llvm::Value * CreateMkstempCall(llvm::Value * ftemplate);
121   
122    //  Create a call to:  size_t strlen(const char *str);
123    llvm::Value * CreateStrlenCall(llvm::Value * str);
124   
[5386]125    llvm::Value * CreateAnonymousMMap(llvm::Value * size);
126
127    llvm::Value * CreateFileSourceMMap(llvm::Value * fd, llvm::Value * size);
128
[5419]129    enum Advice {
130        ADVICE_NORMAL
131        , ADVICE_RANDOM
132        , ADVICE_SEQUENTIAL
133        , ADVICE_WILLNEED
134        , ADVICE_DONTNEED
[5411]135    };
136
[5419]137    llvm::Value * CreateMAdvise(llvm::Value * addr, llvm::Value * length, Advice advice);
[5411]138
[5389]139    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);
140
[5411]141    llvm::Value * CreateMRemap(llvm::Value * addr, llvm::Value * oldSize, llvm::Value * newSize);
[5386]142
143    llvm::Value * CreateMUnmap(llvm::Value * addr, llvm::Value * size);
144
[5280]145    //  Posix thread (pthread.h) functions.
146    //
147    //  Create a call to:  int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
148    //                    void *(*start_routine)(void*), void *arg);
[5260]149    llvm::Value * CreatePThreadCreateCall(llvm::Value * thread, llvm::Value * attr, llvm::Function * start_routine, llvm::Value * arg);
[5486]150
151    //  Create a call to:  int pthread_yield(void);
152    llvm::Value * CreatePThreadYield();
[5280]153   
154    //  Create a call to:  void pthread_exit(void *value_ptr);
[5260]155    llvm::Value * CreatePThreadExitCall(llvm::Value * value_ptr);
[5280]156   
157    //  Create a call to:  int pthread_join(pthread_t thread, void **value_ptr);
[5260]158    llvm::Value * CreatePThreadJoinCall(llvm::Value * thread, llvm::Value * value_ptr);
[5242]159   
[5260]160    void CallPrintInt(const std::string & name, llvm::Value * const value);
[5239]161   
[5422]162    void CallPrintIntToStderr(const std::string & name, llvm::Value * const value);
163   
[5398]164    llvm::Value * GetString(llvm::StringRef Str);
[5422]165   
166    void CallPrintMsgToStderr(const std::string & message);
[5398]167
[5239]168    inline llvm::IntegerType * getSizeTy() const {
[5425]169        assert (mSizeType);
[5239]170        return mSizeType;
171    }
172   
[5267]173    inline llvm::ConstantInt * getSize(const size_t value) {
[5260]174        return llvm::ConstantInt::get(getSizeTy(), value);
[5239]175    }
176   
[5260]177    llvm::PointerType * getVoidPtrTy() const;
[5429]178
[5280]179    llvm::PointerType * getFILEptrTy();
[5239]180   
181    inline unsigned getCacheAlignment() const {
182        return mCacheLineAlignment;
183    }
184   
[5260]185    virtual llvm::LoadInst* CreateAtomicLoadAcquire(llvm::Value * ptr);
186
187    virtual llvm::StoreInst *  CreateAtomicStoreRelease(llvm::Value * val, llvm::Value * ptr);
[5398]188
[5493]189    void CreateAssert(llvm::Value * assertion, llvm::StringRef failureMessage) {
190        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
[5510]191            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
[5493]192        }
[5510]193        return __CreateAssert(CreateIsNotNull(assertion), failureMessage);
[5493]194    }
[5340]195
[5493]196    void CreateAssertZero(llvm::Value * assertion, llvm::StringRef failureMessage) {
197        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
[5510]198            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
[5493]199        }
[5510]200        return __CreateAssert(CreateIsNull(assertion), failureMessage);
[5493]201    }
202
[5347]203    void CreateExit(const int exitCode);
204
[5350]205    llvm::BranchInst * CreateLikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90);
206
207    llvm::BranchInst * CreateUnlikelyCondBr(llvm::Value * Cond, llvm::BasicBlock * True, llvm::BasicBlock * False, const int probability = 90) {
208        return CreateLikelyCondBr(Cond, True, False, 100 - probability);
209    }
210
[5440]211    llvm::BasicBlock * CreateBasicBlock(std::string && name);
212
[5435]213    virtual bool supportsIndirectBr() const {
[5472]214        return true;
[5350]215    }
216
[5398]217    llvm::Value * CreatePopcount(llvm::Value * bits);
218
219    llvm::Value * CreateCountForwardZeroes(llvm::Value * value);
220
221    llvm::Value * CreateCountReverseZeroes(llvm::Value * value);
[5427]222   
223    // Useful bit manipulation operations 
224    llvm::Value * CreateResetLowestBit(llvm::Value * bits);   
225   
226    llvm::Value * CreateIsolateLowestBit(llvm::Value * bits);
227   
228    llvm::Value * CreateMaskToLowestBitInclusive(llvm::Value * bits);
229   
230    llvm::Value * CreateMaskToLowestBitExclusive(llvm::Value * bits);
231   
232    llvm::Value * CreateExtractBitField(llvm::Value * bits, llvm::Value * start, llvm::Value * length);
233   
[5361]234    llvm::Value * CreateCeilLog2(llvm::Value * value);
[5424]235   
236    llvm::Value * CreateReadCycleCounter();
[5361]237
[5425]238    template <typename ExternalFunctionType>
239    llvm::Function * LinkFunction(llvm::StringRef name, ExternalFunctionType * functionPtr) const;
240
[5486]241    #ifdef HAS_ADDRESS_SANITIZER
[5493]242    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const char * Name);
[5486]243
[5493]244    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const llvm::Twine & Name = "");
[5486]245
[5493]246    virtual llvm::LoadInst * CreateLoad(llvm::Type * Ty, llvm::Value * Ptr, const llvm::Twine & Name = "");
[5486]247
[5493]248    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, bool isVolatile, const llvm::Twine & Name = "");
[5486]249
[5493]250    virtual llvm::StoreInst * CreateStore(llvm::Value * Val, llvm::Value * Ptr, bool isVolatile = false);
251    #endif
[5486]252
[5493]253    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const char * Name);
[5486]254
[5493]255    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const llvm::Twine & Name = "");
[5486]256
[5493]257    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, bool isVolatile, const llvm::Twine & Name = "");
[5486]258
[5493]259    llvm::StoreInst * CreateAlignedStore(llvm::Value * Val, llvm::Value * Ptr, unsigned Align, bool isVolatile = false);
[5486]260
[5464]261    void setDriver(Driver * const driver) {
262        mDriver = driver;
263    }
264
[5239]265protected:
[5425]266
[5493]267    bool hasAlignedAlloc() const;
268
269    bool hasPosixMemalign() const;
270
271    bool hasAddressSanitizer() const;
272
273    void __CreateAssert(llvm::Value * assertion, llvm::StringRef failureMessage);
274
[5425]275    llvm::Function * LinkFunction(llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const;
276
277protected:
[5440]278
279    llvm::Module *                  mModule;
[5368]280    unsigned                        mCacheLineAlignment;
[5489]281    llvm::IntegerType * const       mSizeType;
[5368]282    llvm::StructType *              mFILEtype;
[5493]283    Driver *                        mDriver;   
[5425]284    llvm::LLVMContext               mContext;
285    const std::string               mTriple;
[5239]286};
287
[5425]288template <typename ExternalFunctionType>
289llvm::Function *CBuilder::LinkFunction(llvm::StringRef name, ExternalFunctionType * functionPtr) const {
290    llvm::FunctionType * const type = FunctionTypeBuilder<ExternalFunctionType>::get(getContext());
291    assert ("FunctionTypeBuilder did not resolve a function type." && type);
292    return LinkFunction(name, type, reinterpret_cast<void *>(functionPtr));
293}
294
[5239]295#endif
Note: See TracBrowser for help on using the repository browser.