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

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

Pablo support for byte comparisions; LineFeed? kernel processes byte streams directly. Some clean up of PabloBuilder? functionality.

File size: 15.7 KB
RevLine 
[5239]1/*
[5746]2 *  Copyright (c) 2017 International Characters.
[5239]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           
[5706]62    // Get minimum of two unsigned numbers
[5755]63    llvm::Value * CreateUMin(llvm::Value * const a, llvm::Value * const b) {
64        if (a == nullptr) return b;
65        if (b == nullptr) return a;
[5706]66        assert (a->getType() == b->getType());
67        return CreateSelect(CreateICmpULT(a, b), a, b);
68    }
69
70    // Get minimum of two signed numbers
[5755]71    llvm::Value * CreateSMin(llvm::Value * const a, llvm::Value * const b) {
72        if (a == nullptr) return b;
73        if (b == nullptr) return a;
[5706]74        assert (a->getType() == b->getType());
75        return CreateSelect(CreateICmpSLT(a, b), a, b);
76    }
77
78    // Get maximum of two unsigned numbers
[5755]79    llvm::Value * CreateUMax(llvm::Value * const a, llvm::Value * const b) {
80        if (a == nullptr) return b;
81        if (b == nullptr) return a;
[5706]82        assert (a->getType() == b->getType());
83        return CreateSelect(CreateICmpUGT(a, b), a, b);
84    }
85
86    // Get maximum of two signed numbers
[5755]87    llvm::Value * CreateSMax(llvm::Value * const a, llvm::Value * const b) {
88        if (a == nullptr) return b;
89        if (b == nullptr) return a;
[5706]90        assert (a->getType() == b->getType());
91        return CreateSelect(CreateICmpSGT(a, b), a, b);
92    }
93
[5755]94    llvm::Value * CreateMalloc(llvm::Value * const size);
[5361]95
[5755]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    }
[5280]101   
[5260]102    void CreateFree(llvm::Value * const ptr);
[5464]103
[5755]104    llvm::Value * CreateRealloc(llvm::Value * const ptr, llvm::Value * const size);
[5245]105
[5755]106    llvm::CallInst * CreateMemZero(llvm::Value * const ptr, llvm::Value * const size, const unsigned alignment = 1) {
[5353]107        return CreateMemSet(ptr, getInt8(0), size, alignment);
[5337]108    }
109
[5755]110    llvm::AllocaInst * CreateAlignedAlloca(llvm::Type * const Ty, const unsigned alignment, llvm::Value * const ArraySize = nullptr) {
[5245]111        llvm::AllocaInst * instr = CreateAlloca(Ty, ArraySize);
[5755]112        instr->setAlignment(alignment);
[5245]113        return instr;
114    }
[5386]115
[5755]116    llvm::AllocaInst * CreateCacheAlignedAlloca(llvm::Type * const Ty, llvm::Value * const ArraySize = nullptr) {
117        return CreateAlignedAlloca(Ty, getCacheAlignment(), ArraySize);
118    }
[5464]119
[5280]120    // stdio.h functions
121    //
[5308]122    //  Create a call to:  FILE * fopen(const char *filename, const char *mode);
[5280]123    llvm::Value * CreateFOpenCall(llvm::Value * filename, llvm::Value * mode);
[5281]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);
[5280]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);
[5415]130    //  Create a call to:  int remove(const char *path);
131    llvm::Value * CreateRemoveCall(llvm::Value * path);
[5280]132   
[5415]133    //  Create a call to:  int rename(const char *old, const char *new);
134    llvm::Value * CreateRenameCall(llvm::Value * oldName, llvm::Value * newName);
135   
[5267]136    llvm::Function * GetPrintf();
137
[5422]138    llvm::Function * GetDprintf();
139
[5280]140    //  Create calls to unistd.h functions.
141    //
[5308]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);
[5280]144    //  Create a call to:  ssize_t write(int fildes, const void *buf, size_t nbyte);
[5418]145    llvm::Value * CreateWriteCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
[5281]146    //  Create a call to:  ssize_t read(int fildes, void *buf, size_t nbyte);
[5418]147    llvm::Value * CreateReadCall(llvm::Value * fileDescriptor, llvm::Value * buf, llvm::Value * nbyte);
[5308]148    //  Create a call to:  int close(int filedes);
[5418]149    llvm::Value * CreateCloseCall(llvm::Value * fileDescriptor);
[5415]150    //  Create a call to:  int unlink(const char *path);
151    llvm::Value * CreateUnlinkCall(llvm::Value * path);
[5281]152
[5418]153    llvm::Value * CreateFileSize(llvm::Value * fileDescriptor);
154
[5415]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   
[5386]163    llvm::Value * CreateAnonymousMMap(llvm::Value * size);
164
165    llvm::Value * CreateFileSourceMMap(llvm::Value * fd, llvm::Value * size);
166
[5419]167    enum Advice {
168        ADVICE_NORMAL
169        , ADVICE_RANDOM
170        , ADVICE_SEQUENTIAL
171        , ADVICE_WILLNEED
172        , ADVICE_DONTNEED
[5411]173    };
174
[5419]175    llvm::Value * CreateMAdvise(llvm::Value * addr, llvm::Value * length, Advice advice);
[5411]176
[5389]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
[5411]179    llvm::Value * CreateMRemap(llvm::Value * addr, llvm::Value * oldSize, llvm::Value * newSize);
[5386]180
181    llvm::Value * CreateMUnmap(llvm::Value * addr, llvm::Value * size);
182
[5755]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
[5280]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);
[5260]196    llvm::Value * CreatePThreadCreateCall(llvm::Value * thread, llvm::Value * attr, llvm::Function * start_routine, llvm::Value * arg);
[5486]197
198    //  Create a call to:  int pthread_yield(void);
199    llvm::Value * CreatePThreadYield();
[5280]200   
201    //  Create a call to:  void pthread_exit(void *value_ptr);
[5260]202    llvm::Value * CreatePThreadExitCall(llvm::Value * value_ptr);
[5280]203   
204    //  Create a call to:  int pthread_join(pthread_t thread, void **value_ptr);
[5260]205    llvm::Value * CreatePThreadJoinCall(llvm::Value * thread, llvm::Value * value_ptr);
[5242]206   
[5260]207    void CallPrintInt(const std::string & name, llvm::Value * const value);
[5239]208   
[5422]209    void CallPrintIntToStderr(const std::string & name, llvm::Value * const value);
210   
[5398]211    llvm::Value * GetString(llvm::StringRef Str);
[5761]212
[5422]213    void CallPrintMsgToStderr(const std::string & message);
[5398]214
[5239]215    inline llvm::IntegerType * getSizeTy() const {
[5425]216        assert (mSizeType);
[5239]217        return mSizeType;
218    }
219   
[5267]220    inline llvm::ConstantInt * getSize(const size_t value) {
[5260]221        return llvm::ConstantInt::get(getSizeTy(), value);
[5239]222    }
223   
[5828]224    llvm::IntegerType * LLVM_READNONE getIntAddrTy() const;
[5675]225   
[5828]226    llvm::PointerType * LLVM_READNONE getVoidPtrTy(const unsigned AddressSpace = 0) const;
[5675]227   
[5828]228    llvm::PointerType * LLVM_READNONE getFILEptrTy();
[5239]229   
230    inline unsigned getCacheAlignment() const {
231        return mCacheLineAlignment;
232    }
233   
[5260]234    virtual llvm::LoadInst* CreateAtomicLoadAcquire(llvm::Value * ptr);
235
236    virtual llvm::StoreInst *  CreateAtomicStoreRelease(llvm::Value * val, llvm::Value * ptr);
[5398]237
[5771]238    void CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage) {
[5493]239        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
[5510]240            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
[5493]241        }
[5510]242        return __CreateAssert(CreateIsNotNull(assertion), failureMessage);
[5493]243    }
[5340]244
[5771]245    void CreateAssertZero(llvm::Value * assertion, const llvm::Twine & failureMessage) {
[5493]246        if (LLVM_UNLIKELY(assertion->getType()->isVectorTy())) {
[5510]247            assertion = CreateBitCast(assertion, getIntNTy(assertion->getType()->getPrimitiveSizeInBits()));
[5493]248        }
[5510]249        return __CreateAssert(CreateIsNull(assertion), failureMessage);
[5493]250    }
251
[5347]252    void CreateExit(const int exitCode);
253
[5350]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
[5828]260    llvm::BasicBlock * CreateBasicBlock(const llvm::StringRef name, llvm::BasicBlock * insertBefore = nullptr);
[5440]261
[5746]262    virtual bool supportsIndirectBr() const;
[5350]263
[5398]264    llvm::Value * CreatePopcount(llvm::Value * bits);
265
[5828]266    // TODO: AVX512 offers these as vector instructions
267    llvm::Value * CreateCountForwardZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
268    llvm::Value * CreateCountReverseZeroes(llvm::Value * value, const bool guaranteedNonZero = false);
[5427]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   
[5361]281    llvm::Value * CreateCeilLog2(llvm::Value * value);
[5424]282   
283    llvm::Value * CreateReadCycleCounter();
[5361]284
[5425]285    template <typename ExternalFunctionType>
286    llvm::Function * LinkFunction(llvm::StringRef name, ExternalFunctionType * functionPtr) const;
287
[5622]288
[5493]289    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const char * Name);
[5486]290
[5493]291    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, const llvm::Twine & Name = "");
[5486]292
[5493]293    virtual llvm::LoadInst * CreateLoad(llvm::Type * Ty, llvm::Value * Ptr, const llvm::Twine & Name = "");
[5486]294
[5493]295    virtual llvm::LoadInst * CreateLoad(llvm::Value * Ptr, bool isVolatile, const llvm::Twine & Name = "");
[5486]296
[5493]297    virtual llvm::StoreInst * CreateStore(llvm::Value * Val, llvm::Value * Ptr, bool isVolatile = false);
[5486]298
[5493]299    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const char * Name);
[5486]300
[5493]301    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, const llvm::Twine & Name = "");
[5486]302
[5493]303    llvm::LoadInst * CreateAlignedLoad(llvm::Value * Ptr, unsigned Align, bool isVolatile, const llvm::Twine & Name = "");
[5486]304
[5493]305    llvm::StoreInst * CreateAlignedStore(llvm::Value * Val, llvm::Value * Ptr, unsigned Align, bool isVolatile = false);
[5486]306
[5630]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
[5622]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
[5630]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
[5755]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    }
[5630]339
[5755]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
[5464]345    void setDriver(Driver * const driver) {
346        mDriver = driver;
347    }
348
[5239]349protected:
[5425]350
[5493]351    bool hasAlignedAlloc() const;
352
353    bool hasPosixMemalign() const;
354
355    bool hasAddressSanitizer() const;
356
[5771]357    void __CreateAssert(llvm::Value * assertion, const llvm::Twine & failureMessage);
[5493]358
[5425]359    llvm::Function * LinkFunction(llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const;
360
361protected:
[5440]362
363    llvm::Module *                  mModule;
[5368]364    unsigned                        mCacheLineAlignment;
[5489]365    llvm::IntegerType * const       mSizeType;
[5368]366    llvm::StructType *              mFILEtype;
[5493]367    Driver *                        mDriver;   
[5425]368    llvm::LLVMContext               mContext;
369    const std::string               mTriple;
[5239]370};
371
[5425]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
[5239]379#endif
Note: See TracBrowser for help on using the repository browser.