source: icGREP/icgrep-devel/icgrep/kernels/pipeline/pipeline_compiler.hpp @ 6237

Last change on this file since 6237 was 6237, checked in by nmedfort, 4 months ago

Re-enabled segment pipeline parallelism; moved logical segment number into pipeline kernel.

File size: 27.8 KB
Line 
1#ifndef PIPELINE_COMPILER_HPP
2#define PIPELINE_COMPILER_HPP
3
4#include <kernels/pipeline_kernel.h>
5#include <kernels/streamset.h>
6#include <kernels/kernel_builder.h>
7#include <toolchain/toolchain.h>
8#include <boost/container/flat_set.hpp>
9#include <boost/container/flat_map.hpp>
10#include <boost/graph/adjacency_list.hpp>
11#include <boost/graph/topological_sort.hpp>
12#include <boost/range/adaptor/reversed.hpp>
13//#include <boost/serialization/strong_typedef.hpp>
14#include <boost/math/common_factor_rt.hpp>
15#include <llvm/IR/Module.h>
16#include <llvm/Support/raw_ostream.h>
17#include <llvm/ADT/STLExtras.h>
18#include <queue>
19
20//#define PRINT_DEBUG_MESSAGES
21
22using namespace boost;
23using namespace boost::math;
24using namespace boost::adaptors;
25using boost::container::flat_set;
26using boost::container::flat_map;
27using namespace llvm;
28
29inline static unsigned floor_log2(const unsigned v) {
30    assert ("log2(0) is undefined!" && v != 0);
31    return 31 - __builtin_clz(v);
32}
33
34namespace kernel {
35
36#include <util/enum_flags.hpp>
37
38using Port = Kernel::Port;
39using StreamPort = Kernel::StreamSetPort;
40using AttrId = Attribute::KindId;
41using RateValue = ProcessingRate::RateValue;
42using RateId = ProcessingRate::KindId;
43using Scalars = PipelineKernel::Scalars;
44using Kernels = PipelineKernel::Kernels;
45using CallBinding = PipelineKernel::CallBinding;
46using BuilderRef = const std::unique_ptr<kernel::KernelBuilder> &;
47
48// TODO: replace ints used for port #s with the following
49// BOOST_STRONG_TYPEDEF(unsigned, PortNumber)
50
51#warning TODO: these graphs are similar; look into streamlining their generation.
52
53// TODO: split pipeline vertex into input and output vertices to keep all graphs DAGs
54// without having to delete edges.
55
56enum class BufferType : unsigned {
57    Internal = 0
58    , External = 1
59    , Managed = 2
60};
61
62struct BufferNode {
63    Value *             TotalItems;
64
65
66    kernel::Kernel *    Kernel;
67    StreamSetBuffer *   Buffer;
68
69    RateValue           Lower;
70    RateValue           Upper;
71
72    unsigned            Overflow;
73    unsigned            Fasimile;
74
75    BufferType          Type;
76
77    BufferNode() : TotalItems(nullptr), Kernel(nullptr), Buffer(nullptr), Lower(), Upper(), Overflow(0), Fasimile(0), Type(BufferType::Internal) {}
78};
79
80struct BufferRateData {
81
82    RateValue Minimum;
83    RateValue Maximum;
84    unsigned  Port;
85
86    BufferRateData() = default;
87
88    BufferRateData(const unsigned port, RateValue min, RateValue max)
89    : Minimum(std::move(min)), Maximum(std::move(max)), Port(port) { }
90};
91
92using BufferGraph = adjacency_list<vecS, vecS, bidirectionalS, BufferNode, BufferRateData>;
93
94template <typename vertex_descriptor>
95using RelationshipMap = flat_map<const Relationship *, vertex_descriptor>;
96
97using BufferMap = RelationshipMap<BufferGraph::vertex_descriptor>;
98
99struct ConsumerNode {
100    Value * Consumed = nullptr;
101    PHINode * PhiNode = nullptr;
102};
103
104enum : unsigned { FAKE_CONSUMER = (std::numeric_limits<unsigned>::max()) };
105
106using ConsumerGraph = adjacency_list<vecS, vecS, bidirectionalS, ConsumerNode, unsigned>;
107
108template <typename Value>
109using StreamSetBufferMap = flat_map<const StreamSetBuffer *, Value>;
110
111template <typename Value>
112using KernelMap = flat_map<const Kernel *, Value>;
113
114using TerminationGraph = adjacency_list<hash_setS, vecS, bidirectionalS, Value *>;
115
116using ScalarDependencyGraph = adjacency_list<vecS, vecS, bidirectionalS, Value *, unsigned>;
117
118struct OverflowRequirement {
119    unsigned copyBack;
120    unsigned facsimile;
121    OverflowRequirement() = default;
122    OverflowRequirement(const unsigned copyBack, const unsigned copyForward)
123    : copyBack(copyBack), facsimile(copyForward) { }
124};
125
126using OverflowRequirements = StreamSetBufferMap<OverflowRequirement>;
127
128struct PopCountData {
129    // compilation state
130    PHINode *    PhiNode;
131    Value *      Processed;
132    unsigned     Encountered;
133    Value *      InitialOffset;
134
135    // analysis state
136    RateValue    FieldWidth;
137    bool         HasArray;
138    bool         HasNegatedArray;
139    bool         UsesConsumedCount;
140    bool         AlwaysNegated;
141
142    PopCountData() = default;
143};
144
145enum CountingType : unsigned {
146    Unknown = 0
147    , Positive = 1
148    , Negative = 2
149    , Both = Positive | Negative
150};
151
152ENABLE_ENUM_FLAGS(CountingType)
153
154struct PopCountEdge {
155    CountingType Type;
156    unsigned     Port;
157    PopCountEdge() : Type(Unknown), Port(0) { }
158    PopCountEdge(const CountingType type, const unsigned port) : Type(type), Port(port) { }
159};
160
161using PopCountGraph = adjacency_list<vecS, vecS, bidirectionalS, no_property, PopCountEdge>;
162
163class PipelineCompiler {
164public:
165
166    PipelineCompiler(BuilderRef b, PipelineKernel * const pipelineKernel);
167
168    void addPipelineKernelProperties(BuilderRef b);
169    void generateInitializeMethod(BuilderRef b);
170    void generateSingleThreadKernelMethod(BuilderRef b);
171    void generateMultiThreadKernelMethod(BuilderRef b, const unsigned numOfThreads);
172    void generateFinalizeMethod(BuilderRef b);
173    std::vector<Value *> getFinalOutputScalars(BuilderRef b);
174
175protected:
176
177// main pipeline functions
178
179    void addInternalKernelProperties(BuilderRef b, const unsigned kernelIndex);
180
181    void start(BuilderRef b, Value * const initialSegNo);
182    void setActiveKernel(BuilderRef b, const unsigned index);
183    void synchronize(BuilderRef b);
184    void executeKernel(BuilderRef b);
185    void end(BuilderRef b, const unsigned step);
186
187    StructType * getLocalStateType(BuilderRef b);
188    Value * allocateThreadLocalSpace(BuilderRef b, StructType * localStateType);
189    void setThreadLocalSpace(BuilderRef b, Value * const localState);
190    void deallocateThreadLocalSpace(BuilderRef b, Value * const localState);
191
192// inter-kernel functions
193
194    void checkForSufficientInputDataAndOutputSpace(BuilderRef b);
195    void determineNumOfLinearStrides(BuilderRef b);
196    void calculateNonFinalItemCounts(BuilderRef b);
197    void calculateFinalItemCounts(BuilderRef b);
198    void writeKernelCall(BuilderRef b);
199    void computeFullyProcessedItemCounts(BuilderRef b);
200    void writeCopyBackLogic(BuilderRef b);
201    void writeCopyForwardLogic(BuilderRef b);
202
203    void zeroFillPartiallyWrittenOutputStreams(BuilderRef b);
204    void initializeKernelCallPhis(BuilderRef b);
205    void initializeKernelExitPhis(BuilderRef b);
206
207    void readInitialProducedItemCounts(BuilderRef b);
208    void computeMinimumConsumedItemCounts(BuilderRef b);
209    void writeFinalConsumedItemCounts(BuilderRef b);
210    void readFinalProducedItemCounts(BuilderRef b);
211    void releaseCurrentSegment(BuilderRef b);
212    void writeCopyToOverflowLogic(BuilderRef b);
213    void checkForSufficientInputData(BuilderRef b, const unsigned inputPort);
214    void checkForSufficientOutputSpaceOrExpand(BuilderRef b, const unsigned outputPort);
215    void incrementItemCountsOfCountableRateStreams(BuilderRef b);
216    enum class OverflowCopy { Forwards, Backwards };
217    Value * writeOverflowCopy(BuilderRef b, const StreamSetBuffer * const buffer, const OverflowCopy direction, Value * const itemsToCopy) const;
218
219
220// intra-kernel functions
221
222    void branchToTargetOrLoopExit(BuilderRef b, Value * const cond, BasicBlock * const target);
223    void expandOutputBuffers(BuilderRef b);
224    void expandOutputBuffer(BuilderRef b, const unsigned outputPort, Value * const hasEnough, BasicBlock * const target);
225
226    Value * getAlreadyProcessedItemCount(BuilderRef b, const unsigned inputPort);
227    Value * getAlreadyProducedItemCount(BuilderRef b, const unsigned outputPort);
228
229    Value * getInputStrideLength(BuilderRef b, const unsigned inputPort);
230    Value * getOutputStrideLength(BuilderRef b, const unsigned outputPort);
231    Value * getInitialStrideLength(BuilderRef b, const Port port, const unsigned portNum);
232    Value * getMaximumStrideLength(BuilderRef b, const Port port, const unsigned portNum);
233    Value * calculateNumOfLinearItems(BuilderRef b, const Port portType,  const unsigned portNum);
234    Value * getAccessibleInputItems(BuilderRef b, const unsigned inputPort);
235    Value * getNumOfAccessibleStrides(BuilderRef b, const unsigned inputPort);
236    Value * getNumOfWritableStrides(BuilderRef b, const unsigned outputPort);
237    Value * getWritableOutputItems(BuilderRef b, const unsigned outputPort);
238    Value * calculateBufferExpansionSize(BuilderRef b, const unsigned outputPort);
239    Value * willNotOverwriteOverflow(BuilderRef b, const unsigned outputPort);
240    Value * addLookahead(BuilderRef b, const unsigned inputPort, Value * itemCount) const;
241    Value * subtractLookahead(BuilderRef b, const unsigned inputPort, Value * itemCount) const;
242    Constant * getLookahead(BuilderRef b, const unsigned inputPort) const;
243    Value * truncateBlockSize(BuilderRef b, const Binding & binding, Value * itemCount, Value * all) const;
244    Value * getTotalItemCount(BuilderRef b, const unsigned inputPort) const;
245    Value * hasProducerTerminated(BuilderRef b, const unsigned inputPort) const;
246    Value * getInitialTerminationSignal(BuilderRef b) const;
247    void setTerminated(BuilderRef b, Value * const terminated);
248    void resetMemoizedFields();
249
250// pop-count functions
251
252    void addPopCountScalarsToPipelineKernel(BuilderRef b, const unsigned index);
253
254    void initializePopCounts();
255    void writePopCountComputationLogic(BuilderRef b);
256
257    void initializePopCountReferenceItemCount(BuilderRef b, const unsigned bufferVertex, not_null<Value *> produced);
258    void createPopCountReferenceCounts(BuilderRef b);
259    void computeMinimumPopCountReferenceCounts(BuilderRef b);
260    void updatePopCountReferenceCounts(BuilderRef b);
261    LLVM_READNONE Value * getPopCountReferenceConsumedCount(BuilderRef b, const unsigned bufferVertex);
262    LLVM_READNONE Value * getPopCountInitialOffset(BuilderRef b, const Binding & binding, const unsigned bufferVertex, PopCountData & pc);
263
264    Value * getMinimumNumOfLinearPopCountItems(BuilderRef b, const Binding & binding);
265    Value * getMaximumNumOfPopCountStrides(BuilderRef b, const Binding & binding, not_null<Value *> sourceItemCount, Constant * const lookAhead = nullptr);
266    Value * getNumOfLinearPopCountItems(BuilderRef b, const Binding & binding);
267
268    Value * getReferenceStreamOffset(BuilderRef b, const Binding & binding);
269
270    Value * getPopCountArray(BuilderRef b, const unsigned inputPort);
271    Value * getNegatedPopCountArray(BuilderRef b, const unsigned inputPort);
272    Value * getIndividualPopCountArray(BuilderRef b, const unsigned inputPort, const unsigned index);
273
274    LLVM_READNONE unsigned getPopCountReferencePort(const Kernel * kernel, const ProcessingRate & rate) const;
275    LLVM_READNONE unsigned getPopCountReferenceBuffer(const Kernel * kernel, const ProcessingRate & rate) const;
276
277    StructType * getPopCountThreadLocalStateType(BuilderRef b);
278    void allocatePopCountArrays(BuilderRef b, Value * base);
279    void deallocatePopCountArrays(BuilderRef b, Value * base);
280
281// pop-count analysis
282
283    PopCountGraph makePopCountGraph() const;
284
285    LLVM_READNONE PopCountData & getPopCountReference(const unsigned bufferVertex) ;
286    LLVM_READNONE PopCountData analyzePopCountReference(const unsigned bufferVertex) const;
287    LLVM_READNONE RateValue popCountReferenceFieldWidth(const unsigned bufferVertex) const;
288    LLVM_READNONE bool popCountReferenceCanUseConsumedItemCount(const unsigned bufferVertex) const;
289    LLVM_READNONE bool popCountReferenceRequiresBaseOffset(const unsigned bufferVertex) const;
290    LLVM_READNONE bool popCountBufferIsUsedBySingleKernel(const unsigned bufferVertex) const;
291    LLVM_READNONE std::pair<bool, bool> popCountReferenceRequiresPopCountArray(const unsigned bufferVertex) const;
292    LLVM_READNONE bool popCountReferenceIsAlwaysNegated(const unsigned bufferVertex) const;
293
294    template <typename LambdaFunction>
295    void forEachOutputBufferThatIsAPopCountReference(const unsigned kernelIndex, LambdaFunction func);
296
297    template <typename LambdaFunction>
298    void forEachPopCountReferenceInputPort(const unsigned kernelIndex, LambdaFunction func);
299
300// consumer recording
301
302    ConsumerGraph makeConsumerGraph() const;
303    void createConsumedPhiNodes(BuilderRef b);
304    void initializeConsumedItemCount(BuilderRef b, const unsigned bufferVertex, Value * const produced);
305    void setConsumedItemCount(BuilderRef b, const unsigned bufferVertex, Value * const consumed) const;
306    Value * getConsumedItemCount(BuilderRef b, const unsigned outputPort) const;
307
308// buffer analysis/management functions
309
310    BufferGraph makeBufferGraph(BuilderRef b);
311    void addBufferHandlesToPipelineKernel(BuilderRef b, const unsigned index);
312    void enumerateBufferProducerBindings(const unsigned producer, const Bindings & bindings, BufferGraph & G, BufferMap & M);
313    void enumerateBufferConsumerBindings(const unsigned consumer, const Bindings & bindings, BufferGraph & G, BufferMap & M);
314    BufferRateData getBufferRateData(const unsigned index, const unsigned port, bool input);
315
316    void constructBuffers(BuilderRef b);
317    void loadBufferHandles(BuilderRef b);
318    void releaseBuffers(BuilderRef b);
319    LLVM_READNONE bool requiresCopyBack(const unsigned bufferVertex) const;
320    LLVM_READNONE bool requiresFacsimile(const unsigned bufferVertex) const;
321    LLVM_READNONE unsigned getCopyBack(const unsigned bufferVertex) const;
322    LLVM_READNONE unsigned getFacsimile(const unsigned bufferVertex) const;
323    BufferType getOutputBufferType(const unsigned outputPort) const;
324
325    Value * getLogicalInputBaseAddress(BuilderRef b, const unsigned inputPort);
326    Value * getLogicalOutputBaseAddress(BuilderRef b, const unsigned outputPort);
327    Value * calculateLogicalBaseAddress(BuilderRef b, const Binding & binding, const StreamSetBuffer * const buffer, Value * const itemCount);
328
329// cycle counter functions
330
331    void startOptionalCycleCounter(BuilderRef b);
332    void updateOptionalCycleCounter(BuilderRef b);
333    void printOptionalCycleCounter(BuilderRef b);
334
335// analysis functions
336
337    std::vector<unsigned> lexicalOrderingOfStreamIO() const;
338    TerminationGraph makeTerminationGraph() const;
339    ScalarDependencyGraph makeScalarDependencyGraph() const;
340
341// misc. functions
342
343    Value * getFunctionFromKernelState(BuilderRef b, Type * const type, const std::string & suffix) const;
344    Value * getInitializationFunction(BuilderRef b) const;
345    Value * getDoSegmentFunction(BuilderRef b) const;
346    Value * getFinalizeFunction(BuilderRef b) const;
347
348    std::string makeKernelName(const unsigned kernelIndex) const;
349    std::string makeBufferName(const unsigned kernelIndex, const Binding & binding) const;
350    unsigned getInputBufferVertex(const unsigned inputPort) const;
351    unsigned getInputBufferVertex(const unsigned kernelVertex, const unsigned inputPort) const;
352    StreamSetBuffer * getInputBuffer(const unsigned inputPort) const;
353    unsigned getOutputBufferVertex(const unsigned outputPort) const;
354    unsigned getOutputBufferVertex(const unsigned kernelVertex, const unsigned outputPort) const;
355    StreamSetBuffer * getOutputBuffer(const unsigned outputPort) const;
356
357    static LLVM_READNONE const Binding & getBinding(const Kernel * kernel, const Port port, const unsigned i) {
358        if (port == Port::Input) {
359            return kernel->getInputStreamSetBinding(i);
360        } else if (port == Port::Output) {
361            return kernel->getOutputStreamSetBinding(i);
362        }
363        llvm_unreachable("unknown port binding type!");
364    }
365
366    void printBufferGraph(const BufferGraph & G, raw_ostream & out);
367
368    LLVM_READNONE const Binding & getInputBinding(const Kernel * const producer, const unsigned index) const;
369
370    LLVM_READNONE const Binding & getOutputBinding(const Kernel * const consumer, const unsigned index) const;
371
372    void writeOutputScalars(BuilderRef b, const unsigned u, std::vector<Value *> & args);
373
374    void itemCountSanityCheck(BuilderRef b, const Binding & binding, const std::string & pastLabel,
375                              Value * const itemCount, Value * const expected);
376
377protected:
378
379    PipelineKernel * const                      mPipelineKernel;
380    const Kernels &                             mPipeline;
381
382    OwnedStreamSetBuffers                       mOwnedBuffers;
383    unsigned                                    mKernelIndex = 0;
384    Kernel *                                    mKernel = nullptr;
385
386    // pipeline state
387    PHINode *                                   mTerminatedPhi = nullptr;
388    PHINode *                                   mTerminatedFlag = nullptr;
389    PHINode *                                   mSegNo = nullptr;
390    BasicBlock *                                mPipelineLoop = nullptr;
391    BasicBlock *                                mKernelEntry = nullptr;
392    BasicBlock *                                mKernelLoopEntry = nullptr;
393    BasicBlock *                                mKernelLoopCall = nullptr;
394    BasicBlock *                                mKernelLoopExit = nullptr;
395    BasicBlock *                                mKernelLoopExitPhiCatch = nullptr;
396    BasicBlock *                                mKernelExit = nullptr;
397    BasicBlock *                                mPipelineEnd = nullptr;
398    std::vector<Value *>                        mOutputScalars;
399
400    // kernel state
401    Value *                                     mNumOfLinearStrides = nullptr;
402    Value *                                     mTerminationExplicitly = nullptr;
403
404    std::vector<unsigned>                       mPortOrdering;
405
406    std::vector<Value *>                        mAlreadyProcessedItemCount; // entering the stride
407    std::vector<Value *>                        mInputStrideLength;
408    std::vector<Value *>                        mAccessibleInputItems;
409    std::vector<PHINode *>                      mLinearInputItemsPhi;
410    std::vector<Value *>                        mFullyProcessedItemCount;
411
412    std::vector<Value *>                        mInitiallyProducedItemCount; // entering the kernel
413    std::vector<Value *>                        mAlreadyProducedItemCount; // entering the stride
414    std::vector<Value *>                        mOutputStrideLength;
415    std::vector<Value *>                        mWritableOutputItems;
416    std::vector<PHINode *>                      mLinearOutputItemsPhi;
417
418    // debug + misc state
419    Value *                                     mCycleCountStart = nullptr;
420    PHINode *                                   mDeadLockCounter = nullptr;
421    Value *                                     mPipelineProgress = nullptr;
422    PHINode *                                   mHasProgressedPhi = nullptr;
423    PHINode *                                   mAlreadyProgressedPhi = nullptr;
424
425    // popcount state
426    Value *                                     mPopCountState;
427    flat_map<unsigned, PopCountData>            mPopCountData;
428
429
430    // analysis state
431    BufferGraph                                 mBufferGraph;
432    ConsumerGraph                               mConsumerGraph;
433    ScalarDependencyGraph                       mScalarDependencyGraph;
434    TerminationGraph                            mTerminationGraph;
435    PopCountGraph                               mPopCountGraph;
436
437};
438
439/** ------------------------------------------------------------------------------------------------------------- *
440 * @brief constructor
441 ** ------------------------------------------------------------------------------------------------------------- */
442inline PipelineCompiler::PipelineCompiler(BuilderRef b, PipelineKernel * const pipelineKernel)
443: mPipelineKernel(pipelineKernel)
444, mPipeline(pipelineKernel->mKernels)
445, mBufferGraph(makeBufferGraph(b))
446, mConsumerGraph(makeConsumerGraph())
447, mScalarDependencyGraph(makeScalarDependencyGraph())
448, mTerminationGraph(makeTerminationGraph())
449, mPopCountGraph(makePopCountGraph()) {
450
451
452}
453
454/** ------------------------------------------------------------------------------------------------------------- *
455 * @brief getInputBuffer
456 ** ------------------------------------------------------------------------------------------------------------- */
457inline unsigned PipelineCompiler::getInputBufferVertex(const unsigned inputPort) const {
458    return getInputBufferVertex(mKernelIndex, inputPort);
459}
460
461/** ------------------------------------------------------------------------------------------------------------- *
462 * @brief getInputBuffer
463 ** ------------------------------------------------------------------------------------------------------------- */
464inline unsigned PipelineCompiler::getInputBufferVertex(const unsigned kernelVertex, const unsigned inputPort) const {
465    for (const auto e : make_iterator_range(in_edges(kernelVertex, mBufferGraph))) {
466        if (mBufferGraph[e].Port == inputPort) {
467            return source(e, mBufferGraph);
468        }
469    }
470    llvm_unreachable("input buffer not found");
471}
472
473/** ------------------------------------------------------------------------------------------------------------- *
474 * @brief getInputBuffer
475 ** ------------------------------------------------------------------------------------------------------------- */
476inline StreamSetBuffer * PipelineCompiler::getInputBuffer(const unsigned inputPort) const {
477    return mBufferGraph[getInputBufferVertex(inputPort)].Buffer;
478}
479
480/** ------------------------------------------------------------------------------------------------------------- *
481 * @brief getOutputBufferVertex
482 ** ------------------------------------------------------------------------------------------------------------- */
483inline unsigned PipelineCompiler::getOutputBufferVertex(const unsigned outputPort) const {
484    return getOutputBufferVertex(mKernelIndex, outputPort);
485}
486
487/** ------------------------------------------------------------------------------------------------------------- *
488 * @brief getOutputBufferVertex
489 ** ------------------------------------------------------------------------------------------------------------- */
490inline unsigned PipelineCompiler::getOutputBufferVertex(const unsigned kernelVertex, const unsigned outputPort) const {
491    for (const auto e : make_iterator_range(out_edges(kernelVertex, mBufferGraph))) {
492        if (mBufferGraph[e].Port == outputPort) {
493            return target(e, mBufferGraph);
494        }
495    }
496    llvm_unreachable("output buffer not found");
497}
498
499
500/** ------------------------------------------------------------------------------------------------------------- *
501 * @brief getOutputBuffer
502 ** ------------------------------------------------------------------------------------------------------------- */
503inline StreamSetBuffer * PipelineCompiler::getOutputBuffer(const unsigned outputPort) const {
504    return mBufferGraph[getOutputBufferVertex(outputPort)].Buffer;
505}
506
507/** ------------------------------------------------------------------------------------------------------------- *
508 * @brief storedInKernel
509 ** ------------------------------------------------------------------------------------------------------------- */
510inline LLVM_READNONE bool storedInNestedKernel(const Binding & output) {
511    return output.getRate().isUnknown() || output.hasAttribute(AttrId::ManagedBuffer);
512}
513
514/** ------------------------------------------------------------------------------------------------------------- *
515 * @brief upperBound
516 ** ------------------------------------------------------------------------------------------------------------- */
517inline LLVM_READNONE RateValue upperBound(not_null<const Kernel *> kernel, const Binding & binding) {
518    assert (kernel->getStride() > 0);
519//    const auto ub = kernel->getUpperBound(binding);
520//    const auto stride = kernel->getStride();
521//    return (ub == 0) ? stride : ub * stride;
522    return kernel->getUpperBound(binding) * kernel->getStride();
523}
524
525/** ------------------------------------------------------------------------------------------------------------- *
526 * @brief lowerBound
527 ** ------------------------------------------------------------------------------------------------------------- */
528inline LLVM_READNONE RateValue lowerBound(not_null<const Kernel *> kernel, const Binding & binding) {
529    assert (kernel->getStride() > 0);
530    return kernel->getLowerBound(binding) * kernel->getStride();
531}
532
533/** ------------------------------------------------------------------------------------------------------------- *
534 * @brief makeKernelName
535 ** ------------------------------------------------------------------------------------------------------------- */
536inline LLVM_READNONE std::string PipelineCompiler::makeKernelName(const unsigned kernelIndex) const {
537    return PipelineKernel::makeKernelName(mPipeline[kernelIndex], kernelIndex);
538}
539
540/** ------------------------------------------------------------------------------------------------------------- *
541 * @brief makeBufferName
542 ** ------------------------------------------------------------------------------------------------------------- */
543inline LLVM_READNONE std::string PipelineCompiler::makeBufferName(const unsigned kernelIndex, const Binding & binding) const {
544    return PipelineKernel::makeBufferName(mPipeline[kernelIndex], kernelIndex, binding);
545}
546
547/** ------------------------------------------------------------------------------------------------------------- *
548 * @brief getRelationship
549 ** ------------------------------------------------------------------------------------------------------------- */
550inline const Relationship * getRelationship(not_null<const Relationship *> r) {
551    return r.get();
552}
553
554/** ------------------------------------------------------------------------------------------------------------- *
555 * @brief getRelationship
556 ** ------------------------------------------------------------------------------------------------------------- */
557inline const Relationship * getRelationship(const Binding & b) {
558    return getRelationship(b.getRelationship());
559}
560
561/** ------------------------------------------------------------------------------------------------------------- *
562 * @brief getLog2SizeWidth
563 ** ------------------------------------------------------------------------------------------------------------- */
564LLVM_READNONE inline Constant * getLog2SizeWidth(BuilderRef b) {
565    return b->getSize(std::log2(b->getSizeTy()->getBitWidth()));
566}
567
568/** ------------------------------------------------------------------------------------------------------------- *
569 * @brief getLog2BlockWidth
570 ** ------------------------------------------------------------------------------------------------------------- */
571LLVM_READNONE inline Constant * getLog2BlockWidth(BuilderRef b) {
572    return b->getSize(std::log2(b->getBitBlockWidth()));
573}
574
575/** ------------------------------------------------------------------------------------------------------------- *
576 * @brief getItemWidth
577 ** ------------------------------------------------------------------------------------------------------------- */
578LLVM_READNONE inline unsigned getItemWidth(const Type * ty ) {
579    if (LLVM_LIKELY(isa<ArrayType>(ty))) {
580        ty = ty->getArrayElementType();
581    }
582    return cast<IntegerType>(ty->getVectorElementType())->getBitWidth();
583}
584
585template <typename Graph>
586inline typename graph_traits<Graph>::edge_descriptor first_in_edge(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
587    return *in_edges(u, G).first;
588}
589
590template <typename Graph>
591inline typename graph_traits<Graph>::edge_descriptor in_edge(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
592    assert (in_degree(u, G) == 1);
593    return first_in_edge(u, G);
594}
595
596template <typename Graph>
597inline typename graph_traits<Graph>::vertex_descriptor parent(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
598    return source(in_edge(u, G), G);
599}
600
601template <typename Graph>
602inline typename graph_traits<Graph>::edge_descriptor first_out_edge(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
603    return *out_edges(u, G).first;
604}
605
606template <typename Graph>
607inline typename graph_traits<Graph>::edge_descriptor out_edge(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
608    assert (out_degree(u, G) == 1);
609    return first_out_edge(u, G);
610}
611
612template <typename Graph>
613inline typename graph_traits<Graph>::vertex_descriptor child(const typename graph_traits<Graph>::vertex_descriptor u, const Graph & G) {
614    return target(out_edge(u, G), G);
615}
616
617} // end of namespace
618
619#endif // PIPELINE_COMPILER_HPP
Note: See TracBrowser for help on using the repository browser.