Jlm
reduction-helpers.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Helge Bahmann <hcb@chaoticmind.net>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_RVSDG_REDUCTION_HELPERS_HPP
7 #define JLM_RVSDG_REDUCTION_HELPERS_HPP
8 
9 #include <jlm/rvsdg/node.hpp>
10 
11 #include <algorithm>
12 
13 namespace jlm::rvsdg
14 {
15 namespace base
16 {
17 namespace detail
18 {
19 
20 /* Test whether any pair of adjacent elements of "args" can be reduced according
21  * to "reduction_tester". */
22 template<typename Container, typename ReductionTester>
23 bool
24 pairwise_test_reduce(const Container & args, const ReductionTester & reduction_tester) noexcept
25 {
26  if (args.empty())
27  {
28  return false;
29  }
30 
31  auto left = args.begin();
32  auto right = std::next(left);
33 
34  while (right != args.end())
35  {
36  if (reduction_tester(*left, *right))
37  {
38  return true;
39  }
40  left = right;
41  ++right;
42  }
43 
44  return false;
45 }
46 
47 /* Apply "reductor" to each pair of adjacent elements of "args", replace the two
48  * with the result if not nullptr. */
49 template<typename Container, typename Reductor>
50 Container
51 pairwise_reduce(Container args, const Reductor & reductor)
52 {
53  if (args.empty())
54  {
55  return args;
56  }
57 
58  auto left = args.begin();
59  auto right = std::next(left);
60 
61  while (right != args.end())
62  {
63  auto res = reductor(*left, *right);
64  if (res)
65  {
66  *left = res;
67  ++right;
68  }
69  else
70  {
71  ++left;
72  *left = *right;
73  ++right;
74  }
75  }
76  args.erase(std::next(left), args.end());
77 
78  return args;
79 }
80 
81 /* Test whether any pair of elements of "args" can be reduced according
82  * to "reduction_tester". */
83 template<typename Container, typename ReductionTester>
84 bool
86  const Container & args,
87  const ReductionTester & reduction_tester) noexcept
88 {
89  auto left = args.begin();
90  while (left != args.end())
91  {
92  auto right = std::next(left);
93  while (right != args.end())
94  {
95  if (reduction_tester(*left, *right))
96  {
97  return true;
98  }
99  else
100  {
101  ++right;
102  }
103  }
104  ++left;
105  }
106 
107  return false;
108 }
109 
110 /* Apply "reductor" to each pair of elements of "args", replace the two
111  * with the result if not nullptr. */
112 template<typename Container, typename Reductor>
113 Container
114 commutative_pairwise_reduce(Container args, const Reductor & reductor)
115 {
116  auto left = args.begin();
117  while (left != args.end())
118  {
119  auto right = std::next(left);
120  while (right != args.end())
121  {
122  auto result = reductor(*left, *right);
123  if (result)
124  {
125  *left = result;
126  *right = args.back();
127  args.pop_back();
128  /* Start over and compare with everything */
129  left = args.begin();
130  right = std::next(left);
131  }
132  else
133  {
134  ++right;
135  }
136  }
137  ++left;
138  }
139 
140  return args;
141 }
142 
143 /* Test whether "flatten_tester" applies to any element of "args". */
144 template<typename Container, typename FlattenTester>
145 bool
146 associative_test_flatten(const Container & args, const FlattenTester & flatten_tester)
147 {
148  return std::any_of(args.begin(), args.end(), flatten_tester);
149 }
150 
151 /* Replace each argument of "args" with the arguments of its defining node
152  * for each where "flatten_tester" returns true. */
153 template<typename FlattenTester>
154 std::vector<jlm::rvsdg::Output *>
155 associative_flatten(std::vector<jlm::rvsdg::Output *> args, const FlattenTester & flatten_tester)
156 {
157  size_t n = 0;
158  while (n < args.size())
159  {
160  if (flatten_tester(args[n]))
161  {
162  auto arg = args[n];
163  JLM_ASSERT(is<NodeOutput>(arg));
164  auto sub_args = jlm::rvsdg::operands(TryGetOwnerNode<Node>(*arg));
165  args[n] = sub_args[0];
166  args.insert(args.begin() + n + 1, sub_args.begin() + 1, sub_args.end());
167  }
168  else
169  {
170  ++n;
171  }
172  }
173  return args;
174 }
175 
176 }
177 }
178 }
179 
180 #endif
#define JLM_ASSERT(x)
Definition: common.hpp:16
Container pairwise_reduce(Container args, const Reductor &reductor)
std::vector< jlm::rvsdg::Output * > associative_flatten(std::vector< jlm::rvsdg::Output * > args, const FlattenTester &flatten_tester)
bool associative_test_flatten(const Container &args, const FlattenTester &flatten_tester)
bool commutative_pairwise_test_reduce(const Container &args, const ReductionTester &reduction_tester) noexcept
Container commutative_pairwise_reduce(Container args, const Reductor &reductor)
bool pairwise_test_reduce(const Container &args, const ReductionTester &reduction_tester) noexcept
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049