Lattice Land Core Library
abstract_deps.hpp
Go to the documentation of this file.
1 // Copyright 2021 Pierre Talbot
2 
3 #ifndef LALA_CORE_ABSTRACT_DEPS_HPP
4 #define LALA_CORE_ABSTRACT_DEPS_HPP
5 
6 #include "battery/utility.hpp"
7 #include "battery/vector.hpp"
8 #include "battery/string.hpp"
9 #include "battery/string.hpp"
10 #include "battery/tuple.hpp"
11 #include "battery/variant.hpp"
12 #include "logic/ast.hpp"
13 
14 namespace lala {
15 
16 template <class A>
17 using abstract_ptr = battery::shared_ptr<A, typename A::allocator_type>;
18 
19 /** Abstract domains are organized in a directed-acyclic graph (DAG).
20  * Therefore, it is not straighforward to copy the whole hierarchy, because the child of a node may be shared by another node, and might have already been copied.
21  * This class is useful to copy hierarchy of abstract domains.
22  * Moreover, the allocators between the original and the copied hierarchy can be different.
23  *
24  * The first allocator of the list is used for the internal allocations of this class.
25  */
26 template<class... Allocators>
28 {
29 public:
30  constexpr static size_t n = battery::tuple_size<battery::tuple<Allocators...>>{};
31  static_assert(n > 0, "AbstractDeps must have a non-empty list of allocators.");
32 
33  using allocators_type = battery::tuple<Allocators...>;
34  using allocator_type = typename battery::tuple_element<0, battery::tuple<Allocators...>>::type;
35 
36 private:
37  struct dep_erasure {
38  CUDA virtual ~dep_erasure() {}
39  };
40 
41  template <class A>
42  struct dep_holder : dep_erasure {
44  CUDA dep_holder(A* ptr): a(ptr, ptr->get_allocator()) {}
45  CUDA virtual ~dep_holder() {}
46  };
47 
48  allocators_type allocators;
49  battery::vector<battery::unique_ptr<dep_erasure, allocator_type>, allocator_type> deps;
50 
51  /** If the hierarchy to be copied is the root of the search tree, the children can share some elements with the root.
52  * For instance, this is the case of propagators in `PC`.
53  * This enables to share data among GPU blocks to avoid duplicating similar data, and to ease the contention on L2 cache. */
54  bool shared_copy;
55 
56 public:
57  CUDA AbstractDeps(bool shared_copy, const Allocators&... allocators)
58  : shared_copy(shared_copy)
59  , allocators(allocators...)
60  , deps(battery::get<0>(this->allocators))
61  {}
62 
63  CUDA AbstractDeps(const Allocators&... allocators)
64  : AbstractDeps(false, allocators...) {}
65 
66  CUDA size_t size() const {
67  return deps.size();
68  }
69 
70  CUDA bool is_shared_copy() const {
71  return shared_copy;
72  }
73 
74  template<class A>
76  assert(aty != UNTYPED);
77  assert(deps.size() > aty);
78  assert(deps[aty]);
79  return static_cast<dep_holder<A>*>(deps[aty].get())->a;
80  }
81 
82  template<class A2, class A>
84  {
85  auto to_alloc = battery::get<typename A2::allocator_type>(allocators);
86  if(!a) {
87  return abstract_ptr<A2>{to_alloc};
88  }
89  assert(a->aty() != UNTYPED); // Abstract domain must all have a unique identifier to be copied.
90  // If the dependency is not in the list, we copy it and add it.
91  if(deps.size() <= a->aty() || !static_cast<bool>(deps[a->aty()])) {
92  deps.resize(battery::max((int)deps.size(), a->aty()+1));
93  allocator_type internal_alloc = battery::get<0>(allocators);
94  A2* a2 = static_cast<A2*>(to_alloc.allocate(sizeof(A2)));
95  new(a2) A2(*a, *this);
96  dep_holder<A2>* dep_hold = static_cast<dep_holder<A2>*>(internal_alloc.allocate(sizeof(dep_holder<A2>)));
97  new(dep_hold) dep_holder<A2>(a2);
98  deps[a->aty()] = battery::unique_ptr<dep_erasure, allocator_type>(
99  dep_hold, internal_alloc);
100  // NOTE: Since we are copying a DAG, `A(*a, *this)` or one of its dependency cannot create `deps[a->aty()]`.
101  }
102  return extract<A2>(a->aty());
103  }
104 
105  template <class Alloc>
106  CUDA Alloc get_allocator() const {
107  return battery::get<Alloc>(allocators);
108  }
109 };
110 
111 }
112 
113 #endif
Definition: abstract_deps.hpp:28
CUDA abstract_ptr< A > extract(AType aty)
Definition: abstract_deps.hpp:75
CUDA Alloc get_allocator() const
Definition: abstract_deps.hpp:106
typename battery::tuple_element< 0, battery::tuple< Allocators... > >::type allocator_type
Definition: abstract_deps.hpp:34
CUDA AbstractDeps(bool shared_copy, const Allocators &... allocators)
Definition: abstract_deps.hpp:57
CUDA NI abstract_ptr< A2 > clone(const abstract_ptr< A > &a)
Definition: abstract_deps.hpp:83
constexpr static size_t n
Definition: abstract_deps.hpp:30
CUDA size_t size() const
Definition: abstract_deps.hpp:66
CUDA bool is_shared_copy() const
Definition: abstract_deps.hpp:70
CUDA AbstractDeps(const Allocators &... allocators)
Definition: abstract_deps.hpp:63
battery::tuple< Allocators... > allocators_type
Definition: abstract_deps.hpp:33
Definition: ast.hpp:223
Definition: abstract_deps.hpp:14
battery::shared_ptr< A, typename A::allocator_type > abstract_ptr
Definition: abstract_deps.hpp:17
int AType
Definition: sort.hpp:18
#define UNTYPED
Definition: sort.hpp:21