|
| 1 | +// RUN: %clangxx -fsycl %s -o %t.out |
| 2 | +// RUN: %t.out |
| 3 | +#include <CL/sycl.hpp> |
| 4 | + |
| 5 | +#include <memory> |
| 6 | +#include <vector> |
| 7 | + |
| 8 | +// This test checks the leaf limit imposed on the execution graph |
| 9 | + |
| 10 | +using namespace cl::sycl; |
| 11 | + |
| 12 | +class FakeCommand : public detail::Command { |
| 13 | +public: |
| 14 | + FakeCommand(detail::QueueImplPtr Queue, detail::Requirement Req) |
| 15 | + : Command{detail::Command::ALLOCA, Queue}, MRequirement{std::move(Req)} {} |
| 16 | + |
| 17 | + void printDot(std::ostream &Stream) const override {} |
| 18 | + |
| 19 | + const detail::Requirement *getRequirement() const final { |
| 20 | + return &MRequirement; |
| 21 | + }; |
| 22 | + |
| 23 | + cl_int enqueueImp() override { return MRetVal; } |
| 24 | + |
| 25 | + cl_int MRetVal = CL_SUCCESS; |
| 26 | + |
| 27 | +protected: |
| 28 | + detail::Requirement MRequirement; |
| 29 | +}; |
| 30 | + |
| 31 | +class TestScheduler : public detail::Scheduler { |
| 32 | +public: |
| 33 | + void AddNodeToLeaves(detail::MemObjRecord *Rec, detail::Command *Cmd, |
| 34 | + access::mode Mode) { |
| 35 | + return MGraphBuilder.AddNodeToLeaves(Rec, Cmd, Mode); |
| 36 | + } |
| 37 | + |
| 38 | + detail::MemObjRecord * |
| 39 | + getOrInsertMemObjRecord(const detail::QueueImplPtr &Queue, |
| 40 | + detail::Requirement *Req) { |
| 41 | + return MGraphBuilder.getOrInsertMemObjRecord(Queue, Req); |
| 42 | + } |
| 43 | +}; |
| 44 | + |
| 45 | +int main() { |
| 46 | + TestScheduler TS; |
| 47 | + queue Queue; |
| 48 | + buffer<int, 1> Buf(range<1>(1)); |
| 49 | + detail::Requirement FakeReq{{0, 0, 0}, |
| 50 | + {0, 0, 0}, |
| 51 | + {0, 0, 0}, |
| 52 | + access::mode::read_write, |
| 53 | + detail::getSyclObjImpl(Buf), |
| 54 | + 0, |
| 55 | + 0, |
| 56 | + 0}; |
| 57 | + FakeCommand *FakeDepCmd = |
| 58 | + new FakeCommand(detail::getSyclObjImpl(Queue), FakeReq); |
| 59 | + detail::MemObjRecord *Rec = |
| 60 | + TS.getOrInsertMemObjRecord(detail::getSyclObjImpl(Queue), &FakeReq); |
| 61 | + |
| 62 | + // Create commands that will be added as leaves exceeding the limit by 1 |
| 63 | + std::vector<FakeCommand *> LeavesToAdd; |
| 64 | + for (size_t i = 0; i < Rec->MWriteLeaves.capacity() + 1; ++i) { |
| 65 | + LeavesToAdd.push_back( |
| 66 | + new FakeCommand(detail::getSyclObjImpl(Queue), FakeReq)); |
| 67 | + } |
| 68 | + // Create edges: all soon-to-be leaves are direct users of FakeDep |
| 69 | + for (auto Leaf : LeavesToAdd) { |
| 70 | + FakeDepCmd->addUser(Leaf); |
| 71 | + Leaf->addDep(detail::DepDesc{FakeDepCmd, Leaf->getRequirement(), nullptr}); |
| 72 | + } |
| 73 | + // Add edges as leaves and exceed the leaf limit |
| 74 | + for (auto LeafPtr : LeavesToAdd) { |
| 75 | + TS.AddNodeToLeaves(Rec, LeafPtr, access::mode::read_write); |
| 76 | + } |
| 77 | + // Check that the oldest leaf has been removed from the leaf list |
| 78 | + // and added as a dependency of the newest one instead |
| 79 | + const detail::CircularBuffer<detail::Command *> &Leaves = Rec->MWriteLeaves; |
| 80 | + assert(std::find(Leaves.begin(), Leaves.end(), LeavesToAdd.front()) == |
| 81 | + Leaves.end()); |
| 82 | + for (size_t i = 1; i < LeavesToAdd.size(); ++i) { |
| 83 | + assert(std::find(Leaves.begin(), Leaves.end(), LeavesToAdd[i]) != |
| 84 | + Leaves.end()); |
| 85 | + } |
| 86 | + FakeCommand *OldestLeaf = LeavesToAdd.front(); |
| 87 | + FakeCommand *NewestLeaf = LeavesToAdd.back(); |
| 88 | + assert(OldestLeaf->MUsers.size() == 1); |
| 89 | + assert(OldestLeaf->MUsers[0] == NewestLeaf); |
| 90 | + assert(NewestLeaf->MDeps.size() == 2); |
| 91 | + assert(NewestLeaf->MDeps[1].MDepCommand == OldestLeaf); |
| 92 | +} |
0 commit comments