Jlm
concat.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2010 2011 2012 2014 Helge Bahmann <hcb@chaoticmind.net>
3  * Copyright 2011 2012 2013 2014 Nico Reißmann <nico.reissmann@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
11 
12 namespace jlm::rvsdg
13 {
14 
16 bitconcat(const std::vector<jlm::rvsdg::Output *> & operands)
17 {
18  std::vector<std::shared_ptr<const jlm::rvsdg::BitType>> types;
19  for (const auto operand : operands)
20  types.push_back(std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type()));
21 
22  return CreateOpNode<BitConcatOperation>(operands, std::move(types)).output(0);
23 }
24 
25 std::shared_ptr<const BitType>
27  const std::vector<std::shared_ptr<const BitType>> & types) noexcept
28 {
29  size_t total = 0;
30  for (const auto & t : types)
31  {
32  total += t->nbits();
33  }
34  return BitType::Create(total);
35 }
36 
37 BitConcatOperation::~BitConcatOperation() noexcept = default;
38 
39 bool
40 BitConcatOperation::operator==(const Operation & other) const noexcept
41 {
42  auto op = dynamic_cast<const BitConcatOperation *>(&other);
43  if (!op || op->narguments() != narguments())
44  return false;
45 
46  for (size_t n = 0; n < narguments(); n++)
47  {
48  if (op->argument(n) != argument(n))
49  return false;
50  }
51 
52  return true;
53 }
54 
57  const jlm::rvsdg::Output * arg1,
58  const jlm::rvsdg::Output * arg2) const noexcept
59 {
60  auto node1 = TryGetOwnerNode<SimpleNode>(*arg1);
61  auto node2 = TryGetOwnerNode<SimpleNode>(*arg2);
62 
63  if (!node1 || !node2)
64  return binop_reduction_none;
65 
66  auto arg1_constant = is<BitConstantOperation>(node1->GetOperation());
67  auto arg2_constant = is<BitConstantOperation>(node2->GetOperation());
68 
69  if (arg1_constant && arg2_constant)
70  {
72  }
73 
74  auto arg1_slice = dynamic_cast<const BitSliceOperation *>(&node1->GetOperation());
75  auto arg2_slice = dynamic_cast<const BitSliceOperation *>(&node2->GetOperation());
76 
77  if (arg1_slice && arg2_slice)
78  {
79  auto origin1 = node1->input(0)->origin();
80  auto origin2 = node2->input(0)->origin();
81 
82  if (origin1 == origin2 && arg1_slice->high() == arg2_slice->low())
83  {
84  return binop_reduction_merge;
85  }
86 
87  /* FIXME: support sign bit */
88  }
89 
90  return binop_reduction_none;
91 }
92 
96  jlm::rvsdg::Output * arg1,
97  jlm::rvsdg::Output * arg2) const
98 {
99  auto & node1 = AssertGetOwnerNode<SimpleNode>(*arg1);
100  auto & node2 = AssertGetOwnerNode<SimpleNode>(*arg2);
101 
102  if (path == binop_reduction_constants)
103  {
104  auto & arg1_constant = static_cast<const BitConstantOperation &>(node1.GetOperation());
105  auto & arg2_constant = static_cast<const BitConstantOperation &>(node2.GetOperation());
106 
107  BitValueRepresentation bits(arg1_constant.value());
108  bits.Append(arg2_constant.value());
109  return &BitConstantOperation::create(*arg1->region(), std::move(bits));
110  }
111 
112  if (path == binop_reduction_merge)
113  {
114  auto arg1_slice = static_cast<const BitSliceOperation *>(&node1.GetOperation());
115  auto arg2_slice = static_cast<const BitSliceOperation *>(&node2.GetOperation());
116  return jlm::rvsdg::bitslice(node1.input(0)->origin(), arg1_slice->low(), arg2_slice->high());
117 
118  /* FIXME: support sign bit */
119  }
120 
121  return NULL;
122 }
123 
125 BitConcatOperation::flags() const noexcept
126 {
128 }
129 
130 std::string
132 {
133  return "BitConcat";
134 }
135 
136 std::unique_ptr<Operation>
138 {
139  return std::make_unique<BitConcatOperation>(*this);
140 }
141 
142 static std::vector<std::shared_ptr<const BitType>>
143 GetTypesFromOperands(const std::vector<rvsdg::Output *> & args)
144 {
145  std::vector<std::shared_ptr<const BitType>> types;
146  for (const auto arg : args)
147  {
148  types.push_back(std::dynamic_pointer_cast<const BitType>(arg->Type()));
149  }
150  return types;
151 }
152 
153 std::optional<std::vector<rvsdg::Output *>>
154 FlattenBitConcatOperation(const BitConcatOperation &, const std::vector<rvsdg::Output *> & operands)
155 {
156  JLM_ASSERT(!operands.empty());
157 
158  const auto newOperands = base::detail::associative_flatten(
159  operands,
160  [](jlm::rvsdg::Output * arg)
161  {
162  // FIXME: switch to comparing operator, not just typeid, after
163  // converting "concat" to not be a binary operator anymore
164  auto sn = TryGetOwnerNode<SimpleNode>(*arg);
165  return sn && is<BitConcatOperation>(sn->GetOperation());
166  });
167 
168  if (operands == newOperands)
169  {
170  JLM_ASSERT(newOperands.size() == 2);
171  return std::nullopt;
172  }
173 
174  JLM_ASSERT(newOperands.size() > 2);
175  return outputs(&CreateOpNode<BitConcatOperation>(newOperands, GetTypesFromOperands(newOperands)));
176 }
177 
178 }
std::string debug_string() const override
Definition: concat.cpp:131
static std::shared_ptr< const BitType > aggregate_arguments(const std::vector< std::shared_ptr< const BitType >> &types) noexcept
Definition: concat.cpp:26
enum BinaryOperation::flags flags() const noexcept override
Definition: concat.cpp:125
binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *arg1, const jlm::rvsdg::Output *arg2) const noexcept override
Definition: concat.cpp:56
std::unique_ptr< Operation > copy() const override
Definition: concat.cpp:137
jlm::rvsdg::Output * reduce_operand_pair(binop_reduction_path_t path, jlm::rvsdg::Output *arg1, jlm::rvsdg::Output *arg2) const override
Definition: concat.cpp:94
~BitConcatOperation() noexcept override
static Output & create(Region &region, BitValueRepresentation value)
Definition: constant.hpp:44
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
void Append(const BitValueRepresentation &other)
rvsdg::Region * region() const noexcept
Definition: node.cpp:151
#define JLM_ASSERT(x)
Definition: common.hpp:16
std::vector< jlm::rvsdg::Output * > associative_flatten(std::vector< jlm::rvsdg::Output * > args, const FlattenTester &flatten_tester)
static const binop_reduction_path_t binop_reduction_constants
Definition: binary.hpp:205
size_t binop_reduction_path_t
Definition: binary.hpp:19
std::optional< std::vector< rvsdg::Output * > > FlattenBitConcatOperation(const BitConcatOperation &, const std::vector< rvsdg::Output * > &operands)
Definition: concat.cpp:154
jlm::rvsdg::Output * bitconcat(const std::vector< jlm::rvsdg::Output * > &operands)
Definition: concat.cpp:16
static std::vector< std::shared_ptr< const BitType > > GetTypesFromOperands(const std::vector< rvsdg::Output * > &args)
Definition: concat.cpp:143
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058
static const binop_reduction_path_t binop_reduction_none
Definition: binary.hpp:203
jlm::rvsdg::Output * bitslice(jlm::rvsdg::Output *argument, size_t low, size_t high)
Create bitslice.
Definition: slice.cpp:106
static const binop_reduction_path_t binop_reduction_merge
Definition: binary.hpp:207