OpenASIP  2.0
ImmInfo.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2016 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * @file ImmInfo.cc
26  *
27  * Implementation/Declaration of ImmInfo class.
28  *
29  * Created on: 8.3.2016
30  * @author Henry Linjamäki 2016 (henry.linjamaki-no.spam-tut.fi)
31  * @note rating: red
32  */
33 
34 #include "ImmInfo.hh"
35 
36 #include <algorithm>
37 
38 #include "Machine.hh"
39 #include "RegisterFile.hh"
40 #include "Bus.hh"
41 #include "ImmediateUnit.hh"
42 #include "InstructionTemplate.hh"
43 
44 #include "Operation.hh"
45 #include "Operand.hh"
46 
48 
49 #include "Exception.hh"
50 #include "TCEString.hh"
51 #include "MathTools.hh"
52 
53 /**
54  * Returns key for ImmInfo data structure.
55  */
57 ImmInfo::key(const Operation& operation, int inputOperandId) {
58  return std::make_pair(operation.name().upper(), inputOperandId);
59 }
61 ImmInfo::key(const Operation& operation, const Operand& operand) {
62  return std::make_pair(operation.name().upper(), operand.index());
63 }
64 
65 
66 /**
67  * Returns the entry count for operation, operand pair (key).
68  */
69 size_t
70 ImmInfo::count(const Operation& operation, const Operand& operand) const {
71  return std::multimap<ImmInfoKey, ImmInfoValue>::count(
72  key(operation, operand));
73 }
74 
75 
76 /**
77  * Returns the entry count for operation, operand pair (key).
78  */
79 size_t
80 ImmInfo::count(const Operation& operation, int inputOperandId) const {
81  return count(operation, operation.operand(inputOperandId));
82 }
83 
84 
85 /**
86  * Returns the entry count by the key.
87  */
88 const ImmInfoValue&
90  if (std::multimap<ImmInfoKey, ImmInfoValue>::count(key)) {
91  const_iterator it;
92  const_iterator it_largest = this->lower_bound(key);
93  const_iterator it_begin = it_largest;
94  it_begin++;
95  const_iterator it_end = this->upper_bound(key);
96  for (it = it_begin; it != it_end; it++) {
97  if (*it > *it_largest) {
98  it_largest = it;
99  }
100  }
101  assert(it_largest != it_end);
102  return it_largest->second;
103  } else {
104  THROW_EXCEPTION(InstanceNotFound, "No immediate info for key found.");
105  }
106 }
107 
108 /**
109  * returns widest immediate bit width by the key.
110  *
111  * @param operation The operation as the part of the key.
112  * @param inputOperandId The input operand of the operation as the
113  * of the key.
114  */
115 const ImmInfoValue&
117  const Operation& operation, const Operand& operand) const {
118 
119  return widestImmediate(key(operation, operand));
120 }
121 
122 /**
123  * returns widest immediate bit width by the key.
124  *
125  * @param operation The operation as the part of the key.
126  * @param inputOperandId The input operand id of the operation as the
127  * of the key.
128  */
129 const ImmInfoValue&
131  const Operation& operation, int inputOperandId) const {
132 
133  return widestImmediate(operation, operation.operand(inputOperandId));
134 }
135 
136 /**
137  * returns narrowest (non-zero width) immediate bit width by the key.
138  */
139 const ImmInfoValue&
141  if (std::multimap<ImmInfoKey, ImmInfoValue>::count(key)) {
142  const_iterator it;
143  const_iterator it_largest = lower_bound(key);
144  const_iterator it_begin = it_largest;
145  it_begin++;
146  const_iterator it_end = upper_bound(key);
147  for (it = it_begin; it != it_end; it++) {
148  if (*it < *it_largest) {
149  it_largest = it;
150  }
151  }
152  assert(it_largest != it_end);
153  return it_largest->second;
154  } else {
156  "No immediate info found for the key.");
157  }
158 }
159 
160 
161 /**
162  * Default constructor. Set as zero width and as zero extending.
163  */
165  : pair(0, false) {
166 }
167 
168 
169 /**
170  * Constructor with the specified immediate width and sign-extension.
171  */
172 ImmInfoValue::ImmInfoValue(int immediateWidth, bool signExtending)
173  : pair(immediateWidth, signExtending) {
174 }
175 
176 
177 /**
178  * Return largest inclusive value that can be expressed as immediate.
179  */
180 int64_t
182  if (second) { // is sign extending?
183  return -(1ll << (first-1));
184  } else { // is then zero extending.
185  return 0;
186  }
187 }
188 
189 /**
190  * Return smallest inclusive value that can be expressed as immediate.
191  */
192 int64_t
194  if (second) { // is sign extending?
195  return (1ll << (first-1))-1;
196  } else { // is then zero extending.
197  return (1ll << (first));
198  }
199 }
200 
201 
202 /**
203  * Returns smallest and largest number that can be transported to operation
204  * operand.
205  *
206  * The bounds are merged from multiple immediate sources. For example, if
207  * immediates can be transported from two different sources, where the one is
208  * 4 bits zero extending and the another is 3 bits sign extending, the
209  * resulting bound is [-4, 15].
210  *
211  * if destination bit width is specified, then the bounds are ...TODO
212  *
213  * @param destWidth The destination width, where the immediates are
214  * transported to. By default it is unspecified/unlimited.
215  * @return std::pair, where the first is smallest value and second is largest.
216  * If no immediate can be transported, (0, 0) is returned.
217  */
218 std::pair<int64_t, int64_t>
220  const ImmInfoKey& key, int destWidth) const {
221 
222  std::pair<int64_t, int64_t> result{ 0, 0 };
223 
224  const_iterator it_begin = lower_bound(key);
225  const_iterator it_end = upper_bound(key);
226  const_iterator it;
227  for (it = it_begin; it != it_end; it++) {
228  if (destWidth > 0) {
229  if (it->second.width() >= destWidth) {
230  return { (-(1ll << (destWidth-1))), ((1ll << destWidth)-1) };
231  }
232  }
233 
234  int64_t currLowerBound = 0;
235  int64_t currUpperBound = 0;
236  if (it->second.signExtending()) {
237  currLowerBound = -(1ll << (it->second.width()-1));
238  currUpperBound = (1ll << (it->second.width()-1))-1;
239  } else {
240  currUpperBound = (1ll << (it->second.width()))-1;
241  }
242 
243  result.first = std::min(result.first, currLowerBound);
244  result.second = std::max(result.second, currUpperBound);
245  }
246 
247  return result;
248 }
249 
250 
251 bool
253  const Operation& operation,
254  int inputOperandId,
255  int64_t value,
256  int /*destWidth*/) {
257 
258  auto unsignedReqBits = MathTools::requiredBits(value);
259  auto signedReqBits = MathTools::requiredBitsSigned(value);
260  auto theKey = key(operation, inputOperandId);
261  const_iterator it_begin = lower_bound(theKey);
262  const_iterator it_end = upper_bound(theKey);
263  const_iterator it;
264  for (it = it_begin; it != it_end; it++) {
265  const ImmInfoValue& imm = it->second;
266  if ((imm.signExtending() && signedReqBits <= imm.width()) ||
267  (unsignedReqBits <= imm.width())) {
268  return true;
269  }
270  }
271  return false;
272 }
273 
274 bool
276  const Operation& operation,
277  int inputOperandId,
278  int bitWidth) {
279 
280  auto theKey = key(operation, inputOperandId);
281  const_iterator it_begin = lower_bound(theKey);
282  const_iterator it_end = upper_bound(theKey);
283  const_iterator it;
284  for (it = it_begin; it != it_end; it++) {
285  const ImmInfoValue& info = it->second;
286  if (bitWidth <= info.width()) return true;
287  }
288  return false;
289 }
290 
291 /**
292  * Same as immediateValueBounds(const ImmInfoKey& key).
293  *
294  */
295 std::pair<int64_t, int64_t>
297  const Operation& operation,
298  const Operand& operand,
299  int destWidth) const {
300  return immediateValueBounds(key(operation, operand), destWidth);
301 }
302 
303 
304 /**
305  * Same as immediateValueBounds(const ImmInfoKey& key).
306  *
307  */
308 std::pair<int64_t, int64_t>
310  const Operation& operation,
311  int inputOperandId,
312  int destWidth) const {
313 
314  return immediateValueBounds(
315  operation, operation.operand(inputOperandId), destWidth);
316 }
317 
318 /**
319  * Returns maximum immediate in bit width which can be transported to the RF.
320  *
321  * @param targetRF The target register file.
322  * @param allowSignExtension If representation of the transported immediate
323  * should not change set it to false (default).
324  */
325 int
327  const TTAMachine::RegisterFile& targetRF,
328  bool allowSignExtension) {
329 
330  using namespace TTAMachine;
331  using MCC = MachineConnectivityCheck;
332 
333  int result = 0;
334  assert(targetRF.machine());
335  const Machine& mach = *targetRF.machine();
336 
337  for (const Bus* bus : mach.busNavigator()) {
338  if (MCC::busConnectedToRF(*bus, targetRF)) {
339  int immWidth = bus->immediateWidth();
340  if (!allowSignExtension && bus->signExtends()) {
341  immWidth -= 1;
342  }
343  result = std::max(result, immWidth);
344  }
345  }
346 
347  for (auto* iu : mach.immediateUnitNavigator()) {
348  for (auto* it : mach.instructionTemplateNavigator()) {
349  int supportedWidth = it->supportedWidth(*iu);
350  if (!allowSignExtension && iu->signExtends()) {
351  supportedWidth -= 1;
352  }
353  result = std::max(result, supportedWidth);
354  }
355  }
356 
357  return result;
358 }
359 
360 
Operand
Definition: Operand.hh:52
ImmInfo::immediateValueBounds
std::pair< int64_t, int64_t > immediateValueBounds(const ImmInfoKey &key, int destWidth) const
Definition: ImmInfo.cc:219
ImmInfoValue::ImmInfoValue
ImmInfoValue()
Definition: ImmInfo.cc:164
MachineConnectivityCheck
Definition: MachineConnectivityCheck.hh:69
ImmInfo::canTakeImmediateByWidth
bool canTakeImmediateByWidth(const Operation &operation, int inputOperandId, int bitWidth)
Definition: ImmInfo.cc:275
MachineConnectivityCheck.hh
Exception.hh
ImmInfo::count
size_t count(const ImmInfoKey &key) const
Definition: ImmInfo.hh:87
ImmInfoValue
Definition: ImmInfo.hh:58
ImmInfoValue::lowerBound
int64_t lowerBound() const
Definition: ImmInfo.cc:181
TTAMachine::Bus
Definition: Bus.hh:53
ImmInfoKey
std::pair< std::string, int > ImmInfoKey
Definition: ImmInfo.hh:53
ImmediateUnit.hh
TCEString::upper
TCEString upper() const
Definition: TCEString.cc:86
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
ImmInfo::key
static ImmInfoKey key(const Operation &operation, int inputOperandId)
Definition: ImmInfo.cc:57
TCEString.hh
ImmInfo.hh
assert
#define assert(condition)
Definition: Application.hh:86
ImmInfoValue::upperBound
int64_t upperBound() const
Definition: ImmInfo.cc:193
TTAMachine::Machine::immediateUnitNavigator
virtual ImmediateUnitNavigator immediateUnitNavigator() const
Definition: Machine.cc:416
THROW_EXCEPTION
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition: Exception.hh:39
InstructionTemplate.hh
ImmInfo::canTakeImmediate
bool canTakeImmediate(const Operation &operation, int inputOperandId, int64_t value, int destWidth)
Definition: ImmInfo.cc:252
Operand::index
virtual int index() const
Definition: Operand.cc:135
Operation.hh
MathTools::requiredBits
static int requiredBits(unsigned long int number)
ImmInfo::widestImmediate
const ImmInfoValue & widestImmediate(const ImmInfoKey &key) const
Definition: ImmInfo.cc:89
Machine.hh
Bus.hh
Operation
Definition: Operation.hh:59
Operand.hh
Operation::operand
virtual Operand & operand(int id) const
Definition: Operation.cc:541
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
TTAMachine::Component::machine
virtual Machine * machine() const
RegisterFile.hh
ImmInfoValue::width
int width() const
Definition: ImmInfo.hh:71
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
MathTools.hh
TTAMachine
Definition: Assembler.hh:48
TTAMachine::Machine::instructionTemplateNavigator
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition: Machine.cc:428
MathTools::requiredBitsSigned
static int requiredBitsSigned(SLongWord number)
ImmInfoValue::signExtending
bool signExtending() const
Definition: ImmInfo.hh:75
InstanceNotFound
Definition: Exception.hh:304
TTAMachine::Machine
Definition: Machine.hh:73
ImmInfo::narrowestImmediate
const ImmInfoValue & narrowestImmediate(const ImmInfoKey &key) const
Definition: ImmInfo.cc:140
ImmInfo::registerImmediateLoadWidth
static int registerImmediateLoadWidth(const TTAMachine::RegisterFile &targetRF, bool allowSignExtension=false)
Definition: ImmInfo.cc:326