OpenASIP  2.0
TDGen.cc
Go to the documentation of this file.
1  /*
2  Copyright (c) 2002-2020 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  * Architecture plugin generator for LLVM TCE backend.
26  *
27  * @author Veli-Pekka Jääskeläinen 2007 (vjaaskel-no.spam-cs.tut.fi)
28  * @author Mikael Lepistö 2009 (mikael.lepisto-no.spam-tut.fi)
29  * @author Pekka Jääskeläinen 2010-2011
30  * @author Heikki Kultala 2012
31  *
32  * @note rating: red
33  */
34 
35 #include <fstream>
36 #include <algorithm>
37 
38 #include "TDGen.hh"
39 #include "Machine.hh"
40 #include "ADFSerializer.hh"
41 #include "ControlUnit.hh"
42 #include "Operation.hh"
43 #include "HWOperation.hh"
44 #include "FUPort.hh"
45 #include "Conversion.hh"
47 #include "ImmediateAnalyzer.hh"
48 #include "ImmInfo.hh"
49 #include "Bus.hh"
50 #include "Guard.hh"
51 #include "StringTools.hh"
52 #include "OperationPool.hh"
53 #include "OperationNode.hh"
54 #include "TerminalNode.hh"
55 #include "ConstantNode.hh"
56 #include "OperationDAG.hh"
57 #include "OperationDAGEdge.hh"
58 #include "OperationDAGSelector.hh"
59 #include "TCEString.hh"
60 #include "Operand.hh"
61 #include "Application.hh"
62 #include "LLVMBackend.hh" // llvmRequiredOps..
63 #include "MathTools.hh"
64 #include "tce_config.h"
65 #include "LLVMTCECmdLineOptions.hh"
66 #include "MachineInfo.hh"
67 
68 // -----------
69 /// @todo These two lines can be removed after C++11 features can be used in
70 /// the source code, since it has native support for initializing std::map.
71 #include "boost/assign.hpp"
72 using namespace boost::assign;
73 // -----------
74 
75 using std::endl;
76 
77 using namespace TDGenerator;
78 
79 // Vector value types that can be used in TTA machines.
80 const std::set<TCEString> ValueType::SUPPORTED_LLVM_VALUE_TYPES =
81  list_of
82  ("v2i1") ("v4i1") ("v8i1") ("v16i1") // i1 subword
83  ("v2i8") ("v4i8") ("v8i8") ("v16i8") ("v32i8") // i8 subword
84  ("v2i16") ("v4i16") ("v8i16") ("v16i16") // i16 subword
85  ("v1i32") ("v2i32") ("v4i32") ("v8i32") ("v16i32") // i32 subword
86  ("v2f16") ("v4f16") ("v8f16") // f16 subword
87  ("v2f32") ("v4f32") ("v8f32") ("v16f32") // f32 subword
88  ("v32i1") ("v64i1") // i1 subword
89  ("v64i8") // i8 subword
90  ("v32i16") // i16 subword
91 
92  ("v512i1") ("v1024i1") ("v128i8") ("v256i8")
93  ("v64i16") ("v128i16") ("v32i32") ("v64i32")
94 
95  ("v128i1")
96  ("v2048i1")
97  ("v256i8") // i8 subword
98 
99 // New values that the custom vector extension patch unlocks.
100 #if defined(LLVM_HAS_CUSTOM_VECTOR_EXTENSION)
101  ("v16f16") ("v32f16") ("v64f16") // f16 subword
102  ("v32f32") // f32 subword
103 
104  ("v256i1")
105  ("v2048i1")
106  ("v128i1") // i1 subword
107 
108 // new wider extension, for up to 4096 bits
109 #if LLVM_HAS_CUSTOM_VECTOR_EXTENSION == 2
110  ("v4096i1") ("v512i8") ("v256i16") ("v256f16") ("v128i32") ("v128f32")
111  ("v64f32") ("v128f16")
112 
113 #endif
114 #endif
115 ;
116 
117 const int TDGen::FP_SUBW_WIDTH =
119 const int TDGen::HFP_SUBW_WIDTH =
121 const int TDGen::BOOL_SUBW_WIDTH =
123 
124 const int TDGen::MAX_SCALAR_WIDTH = 64;
125 
126 // Same as in generate_simd.py.in
128 
129 const bool TDGen::EXPLOIT_BIGGER_REGISTERS = true;
130 
131 // Operand type characters.
132 const char TDGen::OT_REG_BOOL = 'b';
133 const char TDGen::OT_REG_INT = 'r';
134 const char TDGen::OT_REG_FP = 'f';
135 const char TDGen::OT_REG_HFP = 'h';
136 const char TDGen::OT_REG_LONG = 's';
137 const char TDGen::OT_REG_DOUBLE = 'd';
138 const char TDGen::OT_IMM_BOOL = 'j';
139 const char TDGen::OT_IMM_INT = 'i';
140 const char TDGen::OT_IMM_FP = 'k';
141 const char TDGen::OT_IMM_HFP = 'l';
142 const char TDGen::OT_IMM_LONG = 'a';
143 const char TDGen::OT_VREG_BOOL = 'a';
144 const char TDGen::OT_VREG_INT8 = 'q';
145 const char TDGen::OT_VREG_INT16 = 't';
146 const char TDGen::OT_VREG_INT32 = 'u';
147 const char TDGen::OT_VREG_FP = 'e';
148 const char TDGen::OT_VREG_HFP = 'g';
149 
150 // Operation base names (key) that have a pattern (value). Add new
151 // OSAL vector operations here, which have an LLVM pattern.
152 const std::map<TCEString, TCEString> TDGen::OPERATION_PATTERNS_ =
153  map_list_of
154  ("load","load %1%")
155  ("store","store %2%, %1%")
156 
157  ("ld","load %1%")
158  ("ld8","load %1%")
159  ("ld16","load %1%")
160  ("ld32","load %1%")
161 
162  ("st","store %2%, %1%")
163  ("st8","store %2%, %1%")
164  ("st16","store %2%, %1%")
165  ("st32","store %2%, %1%")
166 
167  ("ldq","load %1%")
168  ("ldh","load %1%")
169  ("ldw","load %1%")
170  ("stq","store %2%, %1%")
171  ("sth","store %2%, %1%")
172  ("stw","store %2%, %1%")
173 
174  ("not","not %1%")
175  ("and","and %1%, %2%")
176  ("ior","or %1%, %2%")
177  ("xor","xor %1%, %2%")
178  ("sxqh","sext %1%")
179  ("sxqw","sext %1%")
180  ("sxhw","sext %1%")
181  ("sxbw","sext %1%")
182  ("sxbh","sext %1%")
183  ("sxbq","sext %1%")
184  ("zxqh","zext %1%")
185  ("zxqw","zext %1%")
186  ("zxhw","zext %1%")
187  ("truncwh","trunc %1%")
188  ("truncwb","trunc %1%")
189  ("trunchb","trunc %1%")
190 
191  ("shl","shl %1%, %2%")
192  ("shr","sra %1%, %2%")
193  ("shru","srl %1%, %2%")
194  ("add","add %1%, %2%")
195  ("sub","sub %1%, %2%")
196  ("mul","mul %1%, %2%")
197  ("div","sdiv %1%, %2%")
198  ("divu","udiv %1%, %2%")
199  ("eq","seteq %1%, %2%")
200  ("ne","setne %1%, %2%")
201  ("gt","setgt %1%, %2%")
202  ("gtu","setugt %1%, %2%")
203  ("ge","setge %1%, %2%")
204  ("geu","setuge %1%, %2%")
205  ("lt","setlt %1%, %2%")
206  ("ltu","setult %1%, %2%")
207  ("le","setle %1%, %2%")
208  ("leu","setule %1%, %2%")
209  ("mac","add %1%, (mul %2%, %3%)")
210 
211  ("addf","fadd %1%, %2%")
212  ("subf","fsub %1%, %2%")
213  ("mulf","fmul %1%, %2%")
214  ("divf","fdiv %1%, %2%")
215  ("absf","fabs %1%")
216  ("negf","fneg %1%")
217  ("eqf","setoeq %1%, %2%")
218  ("equf","setueq %1%, %2%")
219  ("nef","setone %1%, %2%")
220  ("neuf","setune %1%, %2%")
221  ("gtf","setogt %1%, %2%")
222  ("gtuf","setugt %1%, %2%")
223  ("gef","setoge %1%, %2%")
224  ("geuf","setuge %1%, %2%")
225  ("ltf","setolt %1%, %2%")
226  ("ltuf","setult %1%, %2%")
227  ("lef","setole %1%, %2%")
228  ("leuf","setule %1%, %2%")
229  ("macf","fadd %1%, (fmul %2%, %3%)")
230  ("msuf","fsub %1%, (fmul %2%, %3%)")
231  ("cif","sint_to_fp %1%")
232  ("cfi","fp_to_sint %1%")
233  ("cifu","uint_to_fp %1%")
234  ("cfiu","fp_to_uint %1%")
235  ("sqrtf","fsqrt %1%")
236  ("chf","fpextend %1%")
237  ("cfh","fpround %1%")
238  ("csh","sint_to_fp %1%")
239  ("cshu","uint_to_fp %1%")
240  ("chs","fp_to_sint %1%")
241  ("chsu","fp_to_uint %1%")
242 
243  ("addh","fadd %1%, %2%")
244  ("subh","fsub %1%, %2%")
245  ("mulh","fmul %1%, %2%")
246  ("divh","fdiv %1%, %2%")
247  ("absh","fabs %1%")
248  ("negh","fneg %1%")
249  ("eqh","setoeq %1%, %2%")
250  ("neh","setone %1%, %2%")
251  ("neuh","setune %1%, %2%")
252  ("gth","setogt %1%, %2%")
253  ("geh","setoge %1%, %2%")
254  ("lth","setolt %1%, %2%")
255  ("leh","setole %1%, %2%")
256  ("mach","fadd %1%, (fmul %2%, %3%)")
257  ("msuh","fsub %1%, (fmul %2%, %3%)")
258 
259  ("vselect","vselect %3%, %1%, %2%")
260  ("insertelem","vector_insert %1%, %2%, %3%")
261  ("extractelem", "vector_extract %1%, %2%")
262  //("gather", "") /// @todo Once supported by LLVM
263  //("scatter", "") /// @todo Once supported by LLVM
264  // "pack" /// @note Has varying pattern, and thus, is generated separately.
265 
266  // Utilization of the following vector operations is defined in the
267  // custom instruction selector since they don't have an LLVM pattern.
268  // "andsame"
269  // "iorsame"
270  // "xorsame"
271  // "shlsame"
272  // "shrsame"
273  // "shrusame"
274  // "vbcast"
275  // "vshuffle1"
276  // "vshuffle2"
277 
278  // The following can be currently used only by invoking _TCE intrinsic.
279  // "unpack"
280  ;
281 
282 /**
283  * Custom comparator that orders operation names correctly number-wise.
284  *
285  * For instance, in an std::set operation names are ordered followingly:
286  * ADD32X16, ADD32X4, ADD32X8, XOR1024, XOR512, XOR64
287  *
288  * This function corrects the operation name order to be the following:
289  * ADD32X4, ADD32X8, ADD32X16, XOR64, XOR512, XOR1024
290  */
291 bool
292 numbersToAscending(const TCEString& lhs, const TCEString& rhs) {
293  size_t lhsI = lhs.length() - 1;
294  size_t rhsI = rhs.length() - 1;
295 
296  // Reverse operation name to the position where the last number begins.
297  while (lhsI > 0 && std::isdigit(lhs[lhsI])) --lhsI;
298  while (rhsI > 0 && std::isdigit(rhs[rhsI])) --rhsI;
299 
300  // Make sure both strings contain a number.
301  if (lhsI > 0 && lhsI != lhs.length() - 1 && rhsI > 0 &&
302  rhsI != rhs.length() - 1) {
303  // The string part before the number must match between both names.
304  if (lhs.substr(0, lhsI + 1) == rhs.substr(0, rhsI + 1)) {
305  // Make the smaller number precede the larger one.
306  try {
307  int lhsNumber = Conversion::toInt(lhs.substr(lhsI + 1));
308  int rhsNumber = Conversion::toInt(rhs.substr(rhsI + 1));
309  return lhsNumber < rhsNumber;
310  } catch (const NumberFormatException& e) {
312  }
313  }
314  }
315 
316  // Basic comparison for std::string.
317  return lhs < rhs;
318 }
319 
320 // SP, RES, KLUDGE, 2 GPRs?
321 //unsigned const TDGen::REQUIRED_I32_REGS = 5;
322 
323 /* Leave this part (percent) of regs unallocated in each RF so
324  the scheduler's reg renamer always has some registers.
325  Rounds downwards.
326 
327  This probably should be a progressive percentage. More regs you
328  have, less likely is that you need them to avoid spills and more
329  likely it is that the reg renamer can use them to remove restricting
330  antideps.
331 */
332 static const unsigned REG_RENAMER_PART = 0;
333 const std::string TDGen::guardRegTemplateName = "Guard";
334 
335 
336 /**
337  * Constructor.
338  *
339  * @param mach Machine to generate plugin for.
340  */
342  mach_(mach), dregNum_(0),
343  highestLaneInt_(-1), highestLaneBool_(-1),
344  hasExBoolRegs_(false), hasExIntRegs_(false), hasSelect_(false),
345  littleEndian_(mach.isLittleEndian()),
346  argRegCount_(1),
347  requiredI32Regs_(0), requiredI64Regs_(0), prebypassStackIndeces_(false),
348  use64bitForFP_(false) {
350 
351  prebypassStackIndeces_ = false;
352 
353  if (mach.is64bit()) {
354  std::set<int> scalarWidths { 1, 32 };
357 
358  // TODO: this does not make sense! requires more!
359  requiredI64Regs_ = 0;
361 
362  } else {
363  std::set<int> scalarWidths { 1, 32 };
366 
367  // TODO: this does not make sense! requires more!
368  requiredI32Regs_ = 0;
370  }
371 
373  maxScalarWidth_ = mach.is64bit() ? 64 : 32;
374 }
375 
376 /**
377  * Destructor.
378  */
380  delete immInfo_;
381 }
382 
383 /**
384  * Generates all files required to build a tce backend plugin
385  * (excluding static plugin code included from include/llvm/TCE/).
386  */
387 void
388 TDGen::generateBackend(std::string& path) {
389  std::ofstream regTD;
390  regTD.open((path + "/GenRegisterInfo.td").c_str());
391  writeRegisterInfo(regTD);
392  regTD.close();
393 
394  std::ofstream instrTD0;
395  instrTD0.open((path + "/GenInstrInfo0.td").c_str());
396  writeAddressingModeDefs(instrTD0);
397  instrTD0.close();
398 
399  std::ofstream operandTD;
400  operandTD.open((path + "/GenOperandInfo.td").c_str());
401  writeOperandDefs(operandTD);
402  operandTD.close();
403 
404  std::ofstream instrTD;
405  instrTD.open((path + "/GenInstrInfo.td").c_str());
406  writeInstrInfo(instrTD);
407 #ifdef DEBUG_TDGEN
408  writeInstrInfo(std::cerr);
409 #endif
410  instrTD.close();
411 
412  std::ofstream formatTD;
413  formatTD.open((path + "/GenTCEInstrFormats.td").c_str());
414  writeInstrFormats(formatTD);
415  formatTD.close();
416 
417  std::ofstream ccTD;
418  ccTD.open((path + "/GenCallingConv.td").c_str());
419  writeCallingConv(ccTD);
420  ccTD.close();
421 
422  std::ofstream argArr;
423  argArr.open((path + "/ArgRegs.hh").c_str());
424  writeArgRegsArray(argArr);
425  argArr.close();
426 
427  std::ofstream pluginInc;
428  pluginInc.open((path + "/Backend.inc").c_str());
429  writeBackendCode(pluginInc);
430  pluginInc.close();
431 
432  std::ofstream topLevelTD;
433  topLevelTD.open((path + "/TCE.td").c_str());
434  writeTopLevelTD(topLevelTD);
435  topLevelTD.close();
436 }
437 
438 /**
439  * Writes .td definition of a single register to the output stream.
440  *
441  * @param o Output stream to write the definition to.
442  * @param reg Information about the physical register.
443  * @param regName Name for the register in the llvm framework.
444  * @param regTemplate Base class for the register.
445  * @param aliases Comma-separated list of aliases for this register.
446  */
447 void
449  std::ostream& o,
450  const RegInfo& reg,
451  const std::string regName,
452  const std::string regTemplate,
453  const std::string aliases,
454  RegType type) {
455 
456  std::string templ = regTemplate;
457 
458  o << "def " << regName << " : " << templ
459  << "<\"" << reg.rf << "." << reg.idx
460  << "\", [" << aliases << "]>, DwarfRegNum<"
461  << "[" << dregNum_ << "]>;"
462  << std::endl;
463 
464 
465  if (type == GPR) {
466  gprRegNames_.push_back(regName);
467  } else if (type == ARGUMENT) {
468  argRegNames_.push_back(regName);
469  } else if (type == RESULT) {
470  argRegNames_.push_back(regName);
471  resRegNames_.push_back(regName);
472  } else {
473  assert(type == RESERVED);
474  }
475 
476  regs_[regName] = reg;
477 
478  regsInClasses_[regTemplate].push_back(regName);
479 
480  if (guardedRegs_.find(reg) != guardedRegs_.end()) {
481  llvmGuardRegs_.push_back(regName);
482  regsInClasses_[guardRegTemplateName].push_back(regName);
483  }
484 
485  dregNum_++;
486 }
487 
488 
489 /**
490  * Writes .td definitions of all registers in the machine to an output stream.
491  *
492  * @param o Output stream for the .td definitions.
493  * @return True, if the definitions were succesfully generated.
494  */
495 bool
496 TDGen::writeRegisterInfo(std::ostream& o) {
498 
499  if (!checkRequiredRegisters()) {
500  return false;
501  }
502 
504 
505  // Write scalar register information without old vector backend registers.
510 // write16bitRegisterInfo(o); // currently not supported properly
513 
514  // Gather and separate all operations to vector and scalar containers.
516 
517  // Create register classes for vector operands.
519  // Group registers by width.
521  // Associate register groups properly with register classes.
523 
524  // Write register related information to the .td file.
529 
530  return true;
531 }
532 
533 /**
534  * Writes static register info to the beginning of register info .td file.
535  *
536  * @param o Output stream to the file.
537  */
538 void
540  o << "//" << endl;
541  o << "// This file is generated automatically!" << endl;
542  o << "// Do not edit." << endl;
543  o << "//" << endl;
544  o << endl;
545 
546  o << "class TCEReg<string n, list<Register> aliases> : "
547  << "Register<n> {"
548  << endl;
549 
550  o << " let Namespace = \"TCE\";" << endl;
551  o << " let Aliases = aliases;" << endl;
552  o << "}" << endl;
553  o << "class TCEVectorReg<string n, list<Register> subregs> : "
554  << "RegisterWithSubRegs<n, subregs> {"
555  << endl
556  << " let Namespace = \"TCE\";" << endl
557  << "}\n" << endl;
558 }
559 
560 /**
561  * Writes all short immediate definitions to the stream.
562  *
563  * @param o The output stream.
564  */
565 void
566 TDGen::writeOperandDefs(std::ostream& o) {
567  assert(immInfo_ != nullptr
568  && "Short immediate analysis results are not available!");
569 
570  o << "// Immediate definitions for TCE instructions." << std::endl;
571 
573 
574  o << std::endl;
575  o << "// Immediate definitions for immediate to register moves."
576  << std::endl;
578 
579  o << std::endl;
580 }
581 
582 /**
583  * Writes unique immediate operands (ImmLeafs) for all operations that can have
584  * short immediates to transported to theirs operands.
585  *
586  * The names of the immediate operands are stored in i32immOperandDefs_ map.
587  * Note: operations, that can not have short immediates to be trasported at
588  * all, do not entry in the map.
589  *
590  * @param o The output stream.
591  * @param iivs The immediate info.
592  */
593 void
595  std::ostream& o,
596  const ImmInfo& iivs) {
597 
598  TCEString immDefBaseName = mach_.is64bit() ? "i64imm" : "i32imm";
599  TCEString immDefType = mach_.is64bit() ? "i64" : "i32";
600  int bits = mach_.is64bit() ? 64 : 32;
601  using ImmBounds = std::pair<int64_t, int64_t>;
602 
603  OperationPool opPool;
604  std::set<const Operation*> opset;
605  for (auto& iiv : iivs) {
606  const Operation& op = opPool.operation(iiv.first.first.c_str());
607  if (&op == &NullOperation::instance())
608  continue;
609  opset.insert(&op);
610  }
611 
612  std::map<ImmBounds, std::string> immediateClasses;
613  int immId = 0;
614  for (auto op : opset) {
615  // Divide input operands into groups that can be swapped together.
616  // Commutative instructions with immediate operands in the patterns
617  // are defined having the immediate operands as last operands
618  // (e.g. ADDrri). For these a combined ImmLeaf is created (union of
619  // each of ImmLeaf of the inputs).
620  std::vector<std::set<int>> inputGroups;
621  for (int opdIdx = 1; opdIdx < op->numberOfInputs() + 1; opdIdx++) {
622  const Operand& opd = op->operand(opdIdx);
623 
624  bool alreadyGrouped = false;
625  for (auto& group : inputGroups) {
626  if (group.count(opdIdx)) {
627  alreadyGrouped = true;
628  break;
629  }
630  }
631  if (alreadyGrouped) continue;
632 
633  inputGroups.push_back(std::set<int>());
634  inputGroups.back().insert(opdIdx);
635  for (int otherOpdIdx : opd.swap()) {
636  inputGroups.back().insert(otherOpdIdx);
637  }
638  }
639 
640  // For each input operand group assign an ImmLeaf operand definition.
641  // The names of ImmLeaf definitions are stored in immOperandDefs_,
642  // which is accessed using operation and operand as the key.
643  for (auto group : inputGroups) {
644  ImmBounds widestImmBound;
645  for (auto idx : group) {
646  // Determine max transportable immediate value range.
647  if (iivs.count(*op, idx)) {
648  // perform union
649  ImmBounds immBound = iivs.immediateValueBounds(
650  *op, idx, bits);
651  widestImmBound.first = std::min(
652  widestImmBound.first, immBound.first);
653  widestImmBound.second = std::max(
654  widestImmBound.second, immBound.second);
655  }
656  // Can not transport immediates at all.
657  if (widestImmBound == ImmBounds()) continue;
658 
659  // immediateClasses stores unique encountered immediate value
660  // ranges.
661  if (immediateClasses.count(widestImmBound) == 0) {
662  std::string immDefName = std::string("i32imm")
663  + Conversion::toString(immId);
664  if (!mach_.is64bit()) {
665  immediateClasses[widestImmBound] = immDefName;
666  }
668  o, immDefName, "i32", immediatePredicate(
669  widestImmBound.first, widestImmBound.second));
670 
671  immDefName = std::string("i64imm")
672  + Conversion::toString(immId);
673 
674  if (mach_.is64bit()) {
675  immediateClasses[widestImmBound] = immDefName;
676  }
677 
679  o, immDefName, "i64", immediatePredicate(
680  widestImmBound.first, widestImmBound.second));
681 
682  immId++;
683 
684  }
685  immOperandDefs_[ImmInfo::key(*op, idx)] =
686  immediateClasses.at(widestImmBound);
687  }
688  }
689  }
690 }
691 
692 /**
693  * Writes immediate operand definitions that are used for MOV instructions.
694  *
695  * Creates immediate operand definitions for immediate to register instructions
696  * (MOVI), that only accept supported immediate values.
697  *
698  * @note Implemented currently only for i32 registers.
699  */
700 void
702  using MCC = MachineConnectivityCheck;
703 
704  TCEString immDefBaseName = mach_.is64bit() ? "i64imm" : "i32imm";
705  TCEString immDefType = mach_.is64bit() ? "i64" : "i32";
706  int bits = mach_.is64bit() ? 64 : 32;
707 
708  std::pair<int64_t, uint64_t> moveImm{ 0, 0 };
709  for (auto& rf : mach_.registerFileNavigator()) {
710  if (rf->width() != bits) continue;
711 
712  for (auto& bus : mach_.busNavigator()) {
713  if (!MCC::busConnectedToRF(*bus, *rf)
714  || bus->immediateWidth() == 0) {
715  continue;
716  }
717 
718  if (bus->immediateWidth() >= bits) {
719  moveImm.first = -(1ll << (bits-1));
720  moveImm.second = (1ll << bits)-1;
721  break;
722  } else {
723  std::pair<int64_t, uint64_t> imm =
724  MathTools::bitsToIntegerRange<int64_t, uint64_t>(
725  bus->immediateWidth(),
726  bus->signExtends());
727 
728  moveImm.first = std::min(moveImm.first, imm.first);
729  moveImm.second = std::max(moveImm.second, imm.second);
730  }
731  }
732  }
733 
734  for (auto& iu : mach_.immediateUnitNavigator()) {
735  for (auto& it : mach_.instructionTemplateNavigator()) {
736  int supportedWidth = it->supportedWidth(*iu);
737  if (supportedWidth >= bits) {
738  moveImm.first = -(1ll << (bits-1));
739  moveImm.second = (1ll << bits)-1;
740  break;
741  } else {
742  std::pair<int64_t, uint64_t> imm =
743  MathTools::bitsToIntegerRange<int64_t, uint64_t>(
744  supportedWidth, iu->signExtends());
745 
746  moveImm.first = std::min(moveImm.first, imm.first);
747  moveImm.second = std::max(moveImm.second, imm.second);
748  }
749  }
750  }
751 
752  writeImmediateDef(o, "i32MoveImm", "i32", immediatePredicate(
753  moveImm.first, moveImm.second));
754 
755  writeImmediateDef(o, "i64MoveImm", "i64", immediatePredicate(
756  moveImm.first, moveImm.second));
757 
758 }
759 
760 void
761 TDGen::writeRegisterClasses(std::ostream& o) {
762 
763  o << "class R1<string n, list<Register> aliases> : TCEReg<n, aliases> {"
764  << "}" << std::endl;
765 
766  o << "class R32<string n, list<Register> aliases> : TCEReg<n, aliases> {"
767  << "}" << std::endl;
768 
769  o << "class R64<string n, list<Register> aliases> : TCEReg<n, aliases> {"
770  << "}" << std::endl;
771 
772 
773  o << "class R16<string n, list<Register> aliases> : TCEReg<n, aliases> {"
774  << "}" << std::endl;
775 }
776 
777 
778 /**
779  * Iterates through all registers in the machine and adds register information
780  * to the register sets.
781  */
782 void
784 
785  const TTAMachine::Machine::BusNavigator busNav =
787 
788  // Check which registers have guards and put their info in
789  // guardedRegs_ set.
790  for (int i = 0; i < busNav.count(); i++) {
791  const TTAMachine::Bus& bus = *busNav.item(i);
792  for (int g = 0; g < bus.guardCount(); g++) {
793  const TTAMachine::RegisterGuard* rg =
794  dynamic_cast<const TTAMachine::RegisterGuard*>(bus.guard(g));
795 
796  if (rg != NULL) {
797  RegInfo reg = {
798  rg->registerFile()->name(),
799  (unsigned)rg->registerIndex() };
800 
801  guardedRegs_.insert(reg);
802  }
803  }
804  }
805 
808 
809  bool regsFound = true;
810  int currentIdx = 0;
811  while (regsFound) {
812  regsFound = false;
813  for (int i = 0; i < nav.count(); i++) {
814  const TTAMachine::RegisterFile* rf = nav.item(i);
815 
816  // Skip definition for registers that are marked as 'reserved'
817  if (rf->isReserved()) continue;
818 
819  // Skip the 0th index of a register file with zero register flag
820  if (currentIdx == 0 && rf->zeroRegister()) {
821  continue;
822  }
823 
824  // Check that the registerfile has both input and output ports.
825  bool hasInput = false;
826  bool hasOutput = false;
827  for (int p = 0; p < rf->portCount(); p++) {
828  if (rf->port(p)->isInput()) hasInput = true;
829  if (rf->port(p)->isOutput()) hasOutput = true;
830  }
831 
832  if (!hasInput) {
835 
837  << "Warning: Skipping register file '"
838  << rf->name()
839  << "': no input ports."
840  << std::endl;
841  }
842  continue;
843  }
844 
845  if (!hasOutput) {
848 
850  << "Warning Skipping register file '"
851  << rf->name()
852  << "': no output ports."
853  << std::endl;
854  }
855  continue;
856  }
857 
858  unsigned width = rf->width();
859  std::vector<RegInfo>* ri = NULL;
860  if (width == 64) ri = &regs64bit_;
861  else if (width == 32) ri = &regs32bit_;
862  //else if (width == 16) ri = &regs16bit_;
863  else if (width == 8) ri = &regs8bit_;
864  else if (width == 1) ri = &regs1bit_;
865  else {
866  continue;
867  }
868 
869  int lastIdx = rf->size();
870  // todo: find a good solution to use just one big rf for this.
871 
872  bool isTempRegRf = AssocTools::containsKey(tempRegFiles_, rf);
873  if (isTempRegRf) {
874  // If the machine is not enough connected,
875  // preserve last register
876  // of all register files for routing values.
877  lastIdx--;
878  }
879 
880  // leave some 32bit regs unallocated for the post pass scheduler's
881  // register renamer
882  if (width == 32) {
883  int renamerRegs = rf->size() * REG_RENAMER_PART / 100;
884  lastIdx -= renamerRegs;
885  }
886 
887  if (currentIdx < lastIdx) {
888  RegInfo reg = {rf->name(), (unsigned)currentIdx};
889  if (!(width == 32 &&
890  guardedRegs_.find(reg) != guardedRegs_.end())) {
891  ri->push_back(reg);
892  }
893  regsFound = true;
894  }
895  }
896  currentIdx++;
897  }
898 }
899 
900 
901 /**
902  * Writes 1-bit register definitions to the output stream.
903  */
904 void
906  if (regs1bit_.size() < 1) {
907  RegInfo reg = {"dummy1", 0};
908  std::string name = "I1DUMMY";
909  writeRegisterDef(o, reg, name, "R1", "", RESERVED);
910  } else {
911  for (unsigned i = 0; i < regs1bit_.size(); i++) {
912  std::string regName = "B" + Conversion::toString(i);
913  writeRegisterDef(o, regs1bit_[i], regName, "R1", "", GPR);
914  }
915  }
916 
917  int stackSize = mach_.is64bit() ? 64 : 32;
918  for (RegClassMap::iterator ri = regsInClasses_.begin();
919  ri != regsInClasses_.end(); ri++) {
920  // go through all 1-bit RF classes
921  if (ri->first.find("R1") == 0) {
922  o << std::endl
923  << "def " << ri->first << "Regs : RegisterClass<\"TCE\", [i1]"
924  << ", " << stackSize << ", (add ";
925  o << ri->second[0];
926  for (unsigned i = 1; i < ri->second.size(); i++) {
927  o << " , " << ri->second[i];
928  }
929  o << ")> {" << std::endl
930  << " let Size=" << stackSize << ";" << std::endl
931  << "}" << std::endl;
932  }
933  }
934 }
935 
936 /**
937  * Gathers all machine op names and sorts them to vector and scalar
938  * operations.
939  */
940 void
942  // Get all operation names to one container.
944 
945  OperationPool opPool;
946  OperationDAGSelector::OperationSet::const_iterator it;
947  for (it = allOpNames_.begin(); it != allOpNames_.end(); ++it) {
948  TCEString opName = *it;
949  Operation* op = &opPool.operation(opName.c_str());
950 
951  if (op != &NullOperation::instance()) {
952  if (op->isVectorOperation()) {
953  vectorOps_.insert(std::make_pair(opName, op));
954  } else {
955  scalarOps_.insert(std::make_pair(opName, op));
956  }
957  }
958  }
959 }
960 
961 /*
962  * Writes 32-bit register definitions to the output stream.
963  */
964 void
966 
967  std::string i32regs;
968  size_t i = 0;
969 
970  if (!mach_.is64bit()) {
971  // --- Hardcoded reserved registers. ---
972  writeRegisterDef(o, regs32bit_[0], "SP", "R32", "", RESERVED);
973  writeRegisterDef(o, regs32bit_[1], "IRES0", "R32", "", RESULT);
974  writeRegisterDef(o, regs32bit_[2], "FP", "R32", "", RESERVED);
975 
978  o, regs32bit_[3], "KLUDGE_REGISTER", "R32", "", GPR);
979  } else {
981  o, regs32bit_[3], "KLUDGE_REGISTER", "R32", "", RESERVED);
982  }
983 
984  i32regs = "SP, IRES0, FP, KLUDGE_REGISTER";
985 
986  //after the loop, i will have the index of first non-special reg.
987  for (i = 4;
988  i < std::min((size_t)argRegCount_ + 3, regs32bit_.size());
989  i++) {
990  std::string regName = "A" + Conversion::toString(i);
991  writeRegisterDef(o, regs32bit_[i], regName, "R32", "", ARGUMENT);
992  i32regs += ", ";
993  i32regs += regName;
994  }
995  }
996 
997  if (regs32bit_.size() < 1) {
998  RegInfo reg = { "dummy32", 0 };
999  writeRegisterDef(o, reg, "dummy32", "R64", "", RESERVED);
1000  o << "def R32Regs : RegisterClass<\"TCE\", [i32,f32,f16,i1], 32, (add dummy32)>;"
1001  << std::endl;
1002  o << "def R32IRegs : RegisterClass<\"TCE\", [i32], 32, (add dummy32)>;"
1003  << std::endl;
1004  o << "def R32FPRegs : RegisterClass<\"TCE\", [f32], 32, (add dummy32)>;"
1005  << std::endl;
1006  o << "def R32HFPRegs : RegisterClass<\"TCE\", [f16], 32, (add dummy32)>;"
1007  << std::endl;
1008  }
1009 
1010  // Generate data structure that contain registers grouped by their
1011  // physical RFs
1012  for (; i < regs32bit_.size(); i++) {
1013  std::string regName = "I" + Conversion::toString(i);
1014  writeRegisterDef(o, regs32bit_[i], regName, "R32", "", GPR);
1015 
1016  if (!regsInRFClasses_.count(regs32bit_[i].rf)) {
1017  regsInRFClasses_[regs32bit_[i].rf] = std::vector<std::string>();
1018  }
1019  i32regs += ", ";
1020  i32regs += regName;
1021  regsInRFClasses_[regs32bit_[i].rf].push_back(regName);
1022  }
1023 
1024  o << std::endl;
1025 
1026  if (!mach_.is64bit()) {
1027  // Bypass registers
1028  for (size_t j = 0; j < 256; ++j) {
1029  std::string regName = "BP" + Conversion::toString(j);
1030 
1031  o << "def " << regName << " : "
1032  << "R32<\"ByPass_Regs"
1033  << "\", []>, DwarfRegNum<"
1034  << "[" << dregNum_++ << "]>;"
1035  << std::endl;
1036  }
1037 
1038  // Bypass register class
1039  o << "def R32_ByPass_Regs : RegisterClass<\"TCE\", [i32,f32,f16], 32, (add ";
1040  for (size_t j = 0; j < 256; ++j) {
1041  std::string regName = "BP" + Conversion::toString(j);
1042 
1043  if (j != 0) {
1044  o << ", ";
1045  }
1046 
1047  o << regName;
1048  }
1049 
1050  o << ")>;" << std::endl;
1051  }
1052 
1053 
1054  for (RegClassMap::iterator
1055  it = regsInRFClasses_.begin(); it != regsInRFClasses_.end(); ++it) {
1056  o << "def R32_"
1057  << it->first
1058  << "_Regs : RegisterClass<\"TCE\", [i32,f32,f16], 32, (add ";
1059 
1060  for (std::vector<std::string>::iterator r = it->second.begin();
1061  r != it->second.end(); ++r) {
1062  if (r != it->second.begin()) {
1063  o << ", ";
1064  }
1065 
1066  o << *r;
1067  }
1068 
1069  o << ")>;" << std::endl;
1070  }
1071 
1072  o << std::endl;
1073 
1074  // Register classes for all 32-bit registers.
1075  // TODO: why are these needed? same as integer classes below?
1076  for (RegClassMap::iterator ri = regsInClasses_.begin();
1077  ri != regsInClasses_.end(); ri++) {
1078  // go through all 1-bit RF classes
1079  if (ri->first.find("R32") == 0) {
1080 
1081  o << "def " << ri->first << "Regs : RegisterClass<\"TCE\", [i32,f32,f16,i1], 32, (add ";
1082  o << ri->second[0];
1083  for (unsigned i = 1; i < ri->second.size(); i++) {
1084  o << " , " << ri->second[i];
1085  }
1086  o << ")>;" << std::endl;
1087  }
1088  }
1089  o << std::endl;
1090 
1091  // Integer register classes for 32-bit registers
1092  for (RegClassMap::iterator ri = regsInClasses_.begin();
1093  ri != regsInClasses_.end(); ri++) {
1094  // go through all 32-bit RF classes
1095  if (ri->first.find("R32") == 0) {
1096  o << "def " << ri->first << "IRegs : RegisterClass<\"TCE\", [i32], 32, (add ";
1097  o << ri->second[0];
1098  for (unsigned i = 1; i < ri->second.size(); i++) {
1099  o << " , " << ri->second[i];
1100  }
1101  o << ")>;" << std::endl;
1102  }
1103  }
1104  o << std::endl;
1105 
1106  // Floating point register classes for 32-bit registers
1107  for (RegClassMap::iterator ri = regsInClasses_.begin();
1108  ri != regsInClasses_.end(); ri++) {
1109  // go through all 32-bit RF classes
1110  if (ri->first.find("R32") == 0) {
1111 
1112  o << "def " << ri->first << "FPRegs : RegisterClass<\"TCE\", [f32], 32, (add ";
1113  o << ri->second[0];
1114  for (unsigned i = 1; i < ri->second.size(); i++) {
1115  o << " , " << ri->second[i];
1116  }
1117  o << ")>;" << std::endl;
1118  }
1119  }
1120 
1121  // Half-float register classes for 32-bit registers (TODO: 16-bit registers also?)
1122  for (RegClassMap::iterator ri = regsInClasses_.begin();
1123  ri != regsInClasses_.end(); ri++) {
1124  // go through all 32-bit RF classes
1125  if (ri->first.find("R32") == 0) {
1126  o << "def " << ri->first << "HFPRegs : RegisterClass<\"TCE\", [f16], 32, (add ";
1127  o << ri->second[0];
1128  for (unsigned i = 1; i < ri->second.size(); i++) {
1129  o << " , " << ri->second[i];
1130  }
1131  o << ")>;" << std::endl;
1132  }
1133  }
1134 
1135 // if (regs32bit_.size() <3) {
1136  if (mach_.is64bit()) { // for now. later try to use 32-b it regs for float.
1137  use64bitForFP_ = true;
1138  }
1139 
1140  if (!use64bitForFP_) {
1141 
1142  o << "def FPRegs : RegisterClass<\"TCE\", [f32], 32, (add "
1143  << i32regs << ")>;" << std::endl;
1144 
1145  o << "def HFPRegs : RegisterClass<\"TCE\", [f16], 32, (add "
1146  << i32regs << ")>;" << std::endl;
1147  }
1148  o << std::endl;
1149 }
1150 
1151 /**
1152  * Writes 16-bit register definitions to the output stream.
1153  */
1154 void
1156  // --- Hardcoded reserved registers. ---
1157  writeRegisterDef(o, regs16bit_[0], "HIRES0", "R16", "", RESULT);
1158 
1159  // -------------------------------------
1160 
1161  for (unsigned i = 1; i < regs16bit_.size(); i++) {
1162  std::string regName = "H" + Conversion::toString(i);
1163  writeRegisterDef(o, regs16bit_[i], regName, "R16", "", GPR);
1164  }
1165 
1166  o << std::endl;
1167 
1168  // All 16-bit regs.
1169  for (RegClassMap::iterator ri = regsInClasses_.begin();
1170  ri != regsInClasses_.end(); ri++) {
1171  // go through all 1-bit RF classes
1172  if (ri->first.find("R16") == 0) {
1173  o << "def " << ri->first
1174  << "Regs : RegisterClass<\"TCE\", [i16], 32, (add ";
1175  o << ri->second[0];
1176  for (unsigned i = 1; i < ri->second.size(); i++) {
1177  o << " , " << ri->second[i];
1178  }
1179  o << ")>;" << std::endl;
1180  }
1181  }
1182  o << std::endl;
1183 
1184  for (RegClassMap::iterator ri = regsInClasses_.begin();
1185  ri != regsInClasses_.end(); ri++) {
1186  // go through all 1-bit RF classes
1187  if (ri->first.find("R16") == 0) {
1188  o << "def " << ri->first
1189  << "IRegs : RegisterClass<\"TCE\", [i16], 32, (add ";
1190  o << ri->second[0];
1191  for (unsigned i = 1; i < ri->second.size(); i++) {
1192  o << " , " << ri->second[i];
1193  }
1194  o << ")>;" << std::endl;
1195  }
1196  }
1197  o << std::endl;
1198 
1199  // floating-point-versions of these
1200 
1201  for (RegClassMap::iterator ri = regsInClasses_.begin();
1202  ri != regsInClasses_.end(); ri++) {
1203  // go through all 1-bit RF classes
1204  if (ri->first.find("R16") == 0) {
1205  o << "def " << ri->first
1206  << "FPRegs : RegisterClass<\"TCE\", [f16], 32, (add ";
1207  o << ri->second[0];
1208  for (unsigned i = 1; i < ri->second.size(); i++) {
1209  o << " , " << ri->second[i];
1210  }
1211  o << ")>;" << std::endl;
1212  }
1213  }
1214 
1215  o << std::endl;
1216 }
1217 
1218 /**
1219  * Creates vector register classes required by the machine.
1220  *
1221  * The function goes through all operations and lists all different vector
1222  * operand value types, after which a register class is created for each
1223  * vector value type to support the vector value type.
1224  */
1225 void
1227  OperationPool opPool;
1228 
1229  // Has all vector value types (e.g. "v4i32", "v16i8", "v2f16", "v8f32")
1230  // that can be found among all the operands present in the machine.
1231  // Register classes will be defined based on these vector value types.
1232  std::set<TCEString> reqRegClassTypes;
1233 
1234  // List all existing vector value types in the machine.
1235  OperationDAGSelector::OperationSet::iterator opnIt;
1236  for (opnIt = allOpNames_.begin(); opnIt != allOpNames_.end(); ++opnIt) {
1237  Operation& op = opPool.operation((*opnIt).c_str());
1238 
1239  if (&op == &NullOperation::instance()) {
1240  continue;
1241  }
1242 
1243  // Go through every operand of the operation.
1244  for (int i = 1; i <= op.operandCount(); ++i) {
1245  Operand& operand = op.operand(i);
1246 
1247  // We are only interested in vector operands, skip otherwise.
1248  if (!operand.isVector()) {
1249  continue;
1250  }
1251 
1252  TCEString vtStr = ValueType::valueTypeStr(operand);
1253  if (vRegClasses_.find(vtStr) == vRegClasses_.end()) {
1254  reqRegClassTypes.insert(vtStr);
1255  }
1256 
1257  // If operand type is "raw" and vector subword width matches
1258  // float or half float width, list it also.
1259  if (operand.type() == Operand::RAW_DATA &&
1260  (operand.elementWidth() == FP_SUBW_WIDTH ||
1261  operand.elementWidth() == HFP_SUBW_WIDTH)) {
1262 
1263  ValueType vt(operand);
1264  vt.isFloat_ = true;
1265  const TCEString floatVtStr = vt.valueTypeStr();
1266 
1267  if (vRegClasses_.find(floatVtStr) == vRegClasses_.end()) {
1268  reqRegClassTypes.insert(floatVtStr);
1269  }
1270  }
1271  }
1272  }
1273 
1274  // Now we have listed all differend vector value types from the machine.
1275  // Create a register class for every LLVM supported vector value type.
1276 
1277  std::set<TCEString>::iterator it;
1278  for (it = reqRegClassTypes.begin(); it != reqRegClassTypes.end(); ++it) {
1279  const TCEString& vtStr = *it;
1280  const ValueType vt(vtStr);
1281 
1282  if (vt.isSupportedByLLVM()) {
1283  TCEString name = "V" + Conversion::toString(vt.subwCount_);
1284 
1285  if ((vt.isFloat_ && vt.subwWidth_ == FP_SUBW_WIDTH) ||
1286  (vt.isFloat_ && vt.subwWidth_ == HFP_SUBW_WIDTH)) {
1287  name += "F";
1288  } else {
1289  name += "I";
1290  }
1291 
1292  name += Conversion::toString(vt.subwWidth_) + "Regs";
1293 
1294  RegisterClass newRegClass(vt, name);
1295  vRegClasses_.insert(std::make_pair(vtStr, newRegClass));
1296  } else {
1297  verbose("Warning: RegisterClass not created for type: " + vtStr);
1298  }
1299  }
1300 }
1301 
1302 
1303 /**
1304  * Writes 64-bit register definitions to the output stream.
1305  */
1306 void
1308 
1309  // --- Hardcoded reserved registers. ---
1310  std::string i64regs;
1311  std::string f64regs;
1312  size_t i = 0;
1313 
1314  if (mach_.is64bit()) {
1315  // --- Hardcoded reserved registers. ---
1316  writeRegisterDef(o, regs64bit_[0], "SP", "R64", "", RESERVED);
1317  writeRegisterDef(o, regs64bit_[1], "IRES0", "R64", "", RESULT);
1318  writeRegisterDef(o, regs64bit_[2], "FP", "R64", "", RESERVED);
1320  o, regs64bit_[3], "KLUDGE_REGISTER", "R64", "", RESERVED);
1321  i64regs = "SP, IRES0, FP, KLUDGE_REGISTER";
1322 
1323  //after the loop, i will have the index of first non-special reg.
1324  for (i = 4;
1325  i < std::min(argRegCount_ + 3, (unsigned int)regs64bit_.size());
1326  i++) {
1327  std::string regName = "A" + Conversion::toString(i);
1328  writeRegisterDef(o, regs64bit_[i], regName, "R64", "", ARGUMENT);
1329  i64regs += ", ";
1330  i64regs += regName;
1331  }
1332  } else {
1333 
1334  if (regs64bit_.size() < 1) {
1335  RegInfo reg = { "DUMMY64", 0 };
1336  writeRegisterDef(o, reg, "DUMMY64", "R64", "", RESERVED);
1337  i64regs = "DUMMY64";
1338  }
1339 
1340  }
1341 
1342  // i already contains the correct starting index.
1343  for (; i < regs64bit_.size(); i++) {
1344  std::string intRegName = "L" + Conversion::toString(i);
1345  if (i != 0)
1346  i64regs += ", ";
1347  i64regs += intRegName;
1348  writeRegisterDef(o, regs64bit_[i], intRegName, "R64", "", GPR);
1349  }
1350 
1351  if (mach_.is64bit()) {
1352  // Bypass registers
1353  for (size_t j = 0; j < 256; ++j) {
1354  std::string regName = "BP" + Conversion::toString(j);
1355 
1356  o << "def " << regName << " : "
1357  << "R64<\"ByPass_Regs"
1358  << "\", []>, DwarfRegNum<"
1359  << "[" << dregNum_++ << "]>;"
1360  << std::endl;
1361  }
1362 
1363  // Bypass register class
1364  o << "def R64_ByPass_Regs : RegisterClass<\"TCE\", [i64,i32,f64,f32,f16], 64, (add ";
1365  for (size_t j = 0; j < 256; ++j) {
1366  std::string regName = "BP" + Conversion::toString(j);
1367 
1368  if (j != 0) {
1369  o << ", ";
1370  }
1371 
1372  o << regName;
1373  }
1374 
1375  o << ")>;" << std::endl;
1376  }
1377 
1378  TCEString dataTypes64 = use64bitForFP_ ?
1379  "[i64,f64,f32,f16]" :
1380  "[i64,f64]";
1381 
1382  o << std::endl
1383  << "def R64Regs : RegisterClass<\"TCE\", " << dataTypes64
1384  << ", 64, (add " << i64regs << ")> ;"
1385  << std::endl;
1386 
1387  o << std::endl
1388  << "def R64IRegs : RegisterClass<\"TCE\", [i64], 64, (add "
1389  << i64regs << ")> ;"
1390  << std::endl;
1391 
1392  o << std::endl
1393  << "def R64FPRegs : RegisterClass<\"TCE\", [f32], 64, (add "
1394  << i64regs << ")>;" << std::endl;
1395 
1396  o << std::endl
1397  << "def R64HFPRegs : RegisterClass<\"TCE\", [f16], 64, (add "
1398  << i64regs << ")>;" << std::endl;
1399 
1400  o << std::endl
1401  << "def R64DFPRegs : RegisterClass<\"TCE\", [f64], 64, (add "
1402  << i64regs << ")>;" << std::endl << std::endl;
1403 
1404  if (use64bitForFP_) {
1405  o << "def FPRegs : RegisterClass<\"TCE\", [f32], 64, (add "
1406  << i64regs << ")>;" << std::endl << std::endl;
1407 
1408  o << "def HFPRegs : RegisterClass<\"TCE\", [f16], 64, (add "
1409  << i64regs << ")>;" << std::endl << std::endl;
1410  }
1411 }
1412 
1413 
1414 /**
1415  * Groups all registers in the machine by register width.
1416  *
1417  * Goes through register files and sorts all real machine registers into
1418  * <Width, vector<Register>> groups. A base class for each Width is also
1419  * created.
1420  */
1421 void
1425  std::map<int, std::vector<RegisterInfo>>::iterator it;
1426 
1427  // Go through every register file in the machine.
1428  for (int i = 0; i < nav.count(); i++) {
1429  const TTAMachine::RegisterFile* rf = nav.item(i);
1430  assert(rf != NULL);
1431 
1432  // Check that the registerfile has both input and output ports.
1433  bool hasInput = false;
1434  bool hasOutput = false;
1435  for (int p = 0; p < rf->portCount(); p++) {
1436  if (rf->port(p)->isInput()) hasInput = true;
1437  if (rf->port(p)->isOutput()) hasOutput = true;
1438  }
1439 
1440  if (!hasInput) {
1443 
1445  << "Warning: Skipping register file '"
1446  << rf->name()
1447  << "': no input ports."
1448  << std::endl;
1449  }
1450  continue;
1451  }
1452 
1453  if (!hasOutput) {
1457  << "Warning Skipping register file '"
1458  << rf->name()
1459  << "': no output ports."
1460  << std::endl;
1461  }
1462  continue;
1463  }
1464 
1465  int rfWidth = rf->width();
1466 
1467  // If there is no entry for the width of the registers, create one.
1468  if (registers_.find(rfWidth) == registers_.end()) {
1469  registers_.insert(
1470  std::make_pair(rfWidth, std::vector<RegisterInfo>()));
1471  }
1472 
1473  it = registers_.find(rfWidth);
1474  std::vector<RegisterInfo>& registers = it->second;
1475 
1476  // Skip scalar size registers, they have been listed in TDGen.
1477  if (rfWidth > MAX_SCALAR_WIDTH) {
1478  // Kludge fix: Machines with >32 bit regs but without any vector
1479  // operations generates register info td file with 64 bit register
1480  // definition which are not associated to any register class.
1481  // This triggers assertion in LLVM side.
1482  if (vRegClasses_.empty()) continue;
1483 
1484  int lastIdx = rf->size();
1485 
1486  bool isTempRegRf = AssocTools::containsKey(tempRegFiles_, rf);
1487  if (isTempRegRf) {
1488  // If the machine is not enough connected,
1489  // preserve last register
1490  // of all register files for routing values.
1491  lastIdx--;
1492  }
1493 
1494  // Associate register file's registers with the width.
1495  for (int index = 0; index < lastIdx; ++index) {
1496  TCEString regName(
1497  rf->name() + "_" + Conversion::toString(index));
1498  RegisterInfo reg(regName, rf->name(), index, rfWidth);
1499  registers.push_back(reg);
1500  }
1501  }
1502  }
1503 
1505 
1506  // TDGen has hardcoded register name definitions, some
1507  // inspection needs to be done to create correct register names.
1508 
1509  std::vector<RegisterInfo> regs1bit;
1510  for (size_t i = 0; i < regs1bit_.size(); ++i) {
1511  RegisterInfo reg(
1512  "B" + Conversion::toString(i),
1513  regs1bit_[i].rf,
1514  regs1bit_[i].idx,
1515  1);
1516  regs1bit.push_back(reg);
1517  }
1518  registers_[1] = regs1bit;
1519 
1520  /// @todo Apparently TDGen does not write information of 8 bit
1521  /// registers -> can't add them.
1522 
1523  std::vector<RegisterInfo> regs16bit;
1524  for (size_t i = 0; i < regs16bit_.size(); ++i) {
1525  RegisterInfo reg(
1526  "H" + Conversion::toString(i),
1527  regs16bit_[i].rf,
1528  regs16bit_[i].idx,
1529  16);
1530 
1531  if (i == 0) {
1532  reg.regName_ = "HIRES0";
1533  }
1534 
1535  regs16bit.push_back(reg);
1536  }
1537  registers_[16] = regs16bit;
1538 
1539  std::vector<RegisterInfo> regs32bit;
1540  for (size_t i = 0; i < regs32bit_.size(); ++i) {
1541  RegisterInfo reg(
1542  "I" + Conversion::toString(i),
1543  regs32bit_[i].rf,
1544  regs32bit_[i].idx,
1545  32);
1546 
1547 
1548  if (!mach_.is64bit()) {
1549  if (i == 0) {
1550  reg.regName_ = "SP";
1551  } else if (i == 1) {
1552  reg.regName_ = "IRES0";
1553  } else if (i == 2) {
1554  reg.regName_ = "FP";
1555  } else if (i == 3) {
1556  reg.regName_ = "KLUDGE_REGISTER";
1557  } else if (i < argRegCount_ + 3) {
1558  reg.regName_ = "A" + Conversion::toString(i);
1559  }
1560  }
1561  regs32bit.push_back(reg);
1562  }
1563  registers_[32] = regs32bit;
1564 
1565  std::vector<RegisterInfo> regs64bit;
1566  for (size_t i = 0; i < regs64bit_.size(); ++i) {
1567  RegisterInfo reg(
1568  "L" + Conversion::toString(i),
1569  regs64bit_[i].rf,
1570  regs64bit_[i].idx,
1571  64);
1572 
1573  if (mach_.is64bit()) {
1574  if (i == 0) {
1575  reg.regName_ = "SP";
1576  } else if (i == 1) {
1577  reg.regName_ = "IRES0";
1578  } else if (i == 2) {
1579  reg.regName_ = "FP";
1580  } else if (i == 3) {
1581  reg.regName_ = "KLUDGE_REGISTER";
1582  } else if (i < argRegCount_ + 3) {
1583  reg.regName_ = "A" + Conversion::toString(i);
1584  }
1585  }
1586  regs64bit.push_back(reg);
1587  }
1588  registers_[64] = regs64bit;
1589 
1590  // Create base classes for different register widths.
1591  for (it = registers_.begin(); it != registers_.end(); ++it) {
1592  int width = it->first;
1593  if (width > MAX_SCALAR_WIDTH) {
1594  baseClasses_.insert(
1595  std::make_pair(width, "VR" + Conversion::toString(width)));
1596  } else {
1597  baseClasses_.insert(
1598  std::make_pair(width, "R" + Conversion::toString(width)));
1599  }
1600  }
1601 }
1602 
1603 /**
1604  * Sets registers to use round robin order in register allocation.
1605  *
1606  * Starting from register index number 0, all same width registers having
1607  * the same index number are pushed to a vector. Then, index is increased
1608  * by one and same action is performed, index increased etc., until all
1609  * registers of same width are pushed to the vector. Then, the vector is
1610  * used to replace old register order.
1611  *
1612  * For example, two register files R64_1 (register indices 0, 1, 2 and 3)
1613  * and R64_2 (register indices 0, 1) are ordered as:
1614  * R64_1(0), R64_2(0), R64_1(1), R64_2(1), R64_1(2), R64_1(3), and LLVM
1615  * register allocator will use this order to allocate the registers.
1616  */
1617 void
1619  std::vector<RegisterInfo> roundRobinOrder;
1620 
1621  // Loop through every different group of register widths.
1622  std::map<int, std::vector<RegisterInfo>>::iterator it;
1623  for (it = registers_.begin(); it != registers_.end(); ++it) {
1624  roundRobinOrder.clear();
1625  std::vector<RegisterInfo>& registers = it->second;
1626 
1627  unsigned i = 0;
1628  unsigned idx = 0;
1629 
1630  // Loop until all registers of same width are reordered.
1631  while (roundRobinOrder.size() != registers.size()) {
1632  RegisterInfo& info = registers[i];
1633  if (info.regIndex_ == idx) {
1634  roundRobinOrder.push_back(info);
1635  }
1636 
1637  if (i == registers.size() - 1) {
1638  i = 0;
1639  ++idx;
1640  } else {
1641  ++i;
1642  }
1643  }
1644 
1645  registers = roundRobinOrder;
1646  }
1647 }
1648 
1649 /**
1650  * Attaches proper register groups to register files.
1651  */
1652 void
1654  std::map<TCEString, RegisterClass>::iterator rcIt;
1655  for (rcIt = vRegClasses_.begin(); rcIt != vRegClasses_.end(); ++rcIt) {
1656  RegisterClass& regClass = rcIt->second;
1657 
1658  // Go through all register groups (they are in ascending order by
1659  // width -> starts from the smallest width always towards wider ones).
1660  std::map<int, std::vector<RegisterInfo>>::iterator regsIt =
1661  registers_.begin();
1662 
1663  bool found = false;
1664  while (!found && regsIt != registers_.end()) {
1665  int regsWidth = regsIt->first;
1666  size_t amountOfRegs = (regsIt->second).size();
1667 
1668  // If can find a group of registers which satisfies the
1669  // register class width requirement, choose those registers.
1670  if (regsWidth >= regClass.valueType().width() &&
1671  amountOfRegs > 0) {
1672  const std::vector<RegisterInfo>& regs = regsIt->second;
1673  regClass.addRegisters(regs);
1674  found = true;
1675  }
1676 
1677  ++regsIt;
1678  }
1679 
1680  // If bigger register exploitation is desired, append all the rest
1681  // of the registers, because there are only wider registers left.
1683  while (regsIt != registers_.end()) {
1684  const std::vector<RegisterInfo>& biggerRegs = regsIt->second;
1685  regClass.addRegisters(biggerRegs);
1686  ++regsIt;
1687  }
1688  }
1689  }
1690 }
1691 
1692 /**
1693  * Checks if operation has operands of raw type.
1694  *
1695  * @param op Operation to be checked.
1696  * @return True, if operation has at least one operand of raw type.
1697  */
1698 bool
1700  for (int i = 1; i <= op.operandCount(); ++i) {
1701  const Operand& operand = op.operand(i);
1702  if (operand.type() == Operand::RAW_DATA && operand.isVector()) {
1703  return true;
1704  }
1705  }
1706  return false;
1707 }
1708 
1709 /**
1710  * Returns subword width of vector operands of "raw" type.
1711  *
1712  * @note This function chooses the subword width based on subword width
1713  * of the WIDEST "raw" data operand that can be found from the operation,
1714  * since that approach works for current SIMD operation definitions.
1715  * If this approach doesn't work for your operation, modify the function
1716  * properly to fulfil your needs.
1717  *
1718  * @param op Operation that has raw operands.
1719  * @return Subword width of the raw vector operands.
1720  */
1721 int
1723  int widestWidth = -1;
1724  int widestRawOperandIndex = -1;
1725  for (int i = 1; i <= op.operandCount(); ++i) {
1726  const Operand& operand = op.operand(i);
1727  if (operand.type() == Operand::RAW_DATA && operand.isVector()) {
1728  if (operand.width() > widestWidth) {
1729  widestWidth = operand.width();
1730  widestRawOperandIndex = i;
1731  }
1732  }
1733  }
1734 
1735  if (widestRawOperandIndex >= 0) {
1736  return op.operand(widestRawOperandIndex).elementWidth();
1737  }
1738 
1739  assert(false && "Invalid input operation.");
1740 }
1741 
1742 /**
1743  * Checks if all operands of the operation have a supporting register class.
1744  *
1745  * @param op Operation whose operands will be checked.
1746  * @return True, if all operands are supported by register classes.
1747  */
1748 bool
1750  for (int i = 1; i <= op.operandCount(); ++i) {
1751  const Operand& operand = op.operand(i);
1752 
1753  if (operand.isVector()) {
1754  TCEString vtStr = ValueType::valueTypeStr(operand);
1755  if (vRegClasses_.find(vtStr) == vRegClasses_.end()) {
1756  return false;
1757  }
1758  }
1759  }
1760 
1761  return true;
1762 }
1763 
1764 /**
1765  * Checks if the ValueType has a supporting register class.
1766  *
1767  * @param vt ValueType to be checked.
1768  * @return True, if the value type is supported by a register class.
1769  */
1770 bool
1772  if (vRegClasses_.find(vt.valueTypeStr()) == vRegClasses_.end()) {
1773  return false;
1774  }
1775 
1776  return true;
1777 }
1778 
1779 /**
1780  * Returns the name of the vector class that supports given operand.
1781  *
1782  * @param operand Checked if any register class supports value type of this.
1783  * @return Name of the register class that supports operand's value type.
1784  */
1785 TCEString
1787  std::map<TCEString, RegisterClass>::const_iterator it =
1788  vRegClasses_.find(ValueType::valueTypeStr(operand));
1789 
1790  if (it == vRegClasses_.end()) {
1791  // Shouldn't get here because any operation whose operands are not
1792  // supported will not get created.
1793  assert(false);
1794  }
1795 
1796  const RegisterClass& regClass = it->second;
1797  return regClass.name();
1798 }
1799 
1800 /**
1801  * Prints debugging information if verbose switch is used.
1802  *
1803  * @param msg Debug message.
1804  */
1805 void
1806 TDGen::verbose(const TCEString& msg) const {
1808  Application::logStream() << msg << endl;
1809  }
1810 }
1811 
1812 /**
1813  * Writes a pattern fragment definition.
1814  *
1815  * @param origPat Pattern that instruction selector should replace.
1816  * @param replacerPat Pattern that will replace the original pattern.
1817  */
1818 void
1820  std::ostream& o,
1821  const TCEString& origPat,
1822  const TCEString& replacerPat) const {
1823  o << "def : Pat<(" << origPat << "), (" << replacerPat << ")>;" << endl;
1824 }
1825 
1826 /**
1827  * Writes operation definition using given operand types.
1828  *
1829  * Changes the operands to match the provided ones, after which a definition
1830  * is written. Finally, original operands are restored.
1831  *
1832  * @param o Output stream.
1833  * @param op Operation used to create new operation definitions.
1834  * @param skipPattern If true, operation pattern writing is skipped.
1835  * @param inputs Input operand types for the new operation.
1836  * @param outputs Output operand types for the new operation.
1837  * @param instrSuffix Optional suffix that will be added to instruction name.
1838  */
1839 void
1841  std::ostream& o,
1842  Operation& op,
1843  bool skipPattern,
1844  std::vector<ValueType> inputs,
1845  std::vector<ValueType> outputs,
1846  TCEString instrSuffix) {
1847  assert(
1848  inputs.size() == static_cast<size_t>(op.numberOfInputs()) &&
1849  "Given input operand count doesn't match operation's count.");
1850  assert(
1851  outputs.size() == static_cast<size_t>(op.numberOfOutputs()) &&
1852  "Given output operand count doesn't match operation's count.");
1853 
1854  std::vector<ValueType> oldInputs;
1855  std::vector<ValueType> oldOutputs;
1856 
1857  // Change operands to match the provided ones.
1858  for (int i = 0; i < op.numberOfInputs(); ++i) {
1859  Operand& input = op.input(i);
1860  oldInputs.push_back(ValueType(input));
1861 
1862  ValueType vt = inputs[i];
1863  input.setType(vt.operandType());
1864  input.setElementWidth(vt.subwWidth_);
1865  input.setElementCount(vt.subwCount_);
1866  }
1867 
1868  for (int i = 0; i < op.numberOfOutputs(); ++i) {
1869  Operand& output = op.output(i);
1870  oldOutputs.push_back(ValueType(output));
1871 
1872  ValueType vt = outputs[i];
1873  output.setType(vt.operandType());
1874  output.setElementWidth(vt.subwWidth_);
1875  output.setElementCount(vt.subwCount_);
1876  }
1877 
1878  // Write new operation definition.
1879  TCEString types = createDefaultOperandTypeString(op) + instrSuffix;
1880  writeVectorOperationDef(o, op, types, "", skipPattern);
1881 
1882  // Restore old operands.
1883  for (int i = 0; i < op.numberOfInputs(); ++i) {
1884  Operand& input = op.input(i);
1885 
1886  ValueType vt = oldInputs[i];
1887  input.setType(vt.operandType());
1888  input.setElementWidth(vt.subwWidth_);
1889  input.setElementCount(vt.subwCount_);
1890  }
1891 
1892  for (int i = 0; i < op.numberOfOutputs(); ++i) {
1893  Operand& output = op.output(i);
1894 
1895  ValueType vt = oldOutputs[i];
1896  output.setType(vt.operandType());
1897  output.setElementWidth(vt.subwWidth_);
1898  output.setElementCount(vt.subwCount_);
1899  }
1900 }
1901 
1902 /**
1903  * Checks if the given operation is a vector load memory operation.
1904  *
1905  * @param op Operation which is checked.
1906  * @return True, if operation is a vector load memory operation.
1907  */
1908 bool
1910  abortWithError("WiP");
1911  return false;
1912 }
1913 
1914 /**
1915  * Checks if the given operation is a vector store memory operation.
1916  *
1917  * @param op Operation which is checked.
1918  * @return True, if operation is a vector store memory operation.
1919  */
1920 bool
1922  abortWithError("WiP");
1923  return false;
1924 }
1925 
1926 bool
1928  abortWithError("WiP");
1929  return false;
1930 }
1931 
1932 /**
1933  * Checks if the given operation is a bitwise operation.
1934  *
1935  * @param op Operation which is checked.
1936  * @return True, if operation is a bitwise operation.
1937  */
1938 bool
1940  abortWithError("WiP");
1941  return false;
1942 }
1943 
1944 
1945 /**
1946  * Writes register class for registers usable as guard.
1947  *
1948  * Call this after all regular register definitions are written (after all
1949  * calls to writeRegisterDef());
1950  */
1951 void
1953 
1954  int bits = mach_.is64bit() ? 64 : 32;
1955  o << std::endl
1956  << "// #################################" << std::endl
1957  << "// Register class definitions for guards" << std::endl;
1958 
1959  if (llvmGuardRegs_.empty()) {
1960  o << "// No guard registers in this machine" << std::endl;
1961  RegInfo reg = {"noGuardReg", 0};
1962  std::string name = "NOGUARD";
1963  writeRegisterDef(o, reg, name, "R1", "", RESERVED);
1964  o << "def " << guardRegTemplateName
1965  << "Regs : RegisterClass<\"TCE\", [i1], " << bits << ", (add "
1966  << name << ")>;" << std::endl;
1967  return;
1968  }
1969 
1970  o << "def " << guardRegTemplateName
1971  << "Regs : RegisterClass<\"TCE\", [i1], " << bits << ", (add ";
1972  bool firstItem = true;
1973  for (auto& regDef : llvmGuardRegs_) {
1974  if (firstItem) {
1975  o << regDef;
1976  firstItem = false;
1977  continue;
1978  }
1979  o << ", " << regDef;
1980  }
1981  o << ")> {" << std::endl;
1982  o << " let Size=" << bits << ";" << std::endl;
1983  o << "}" << std::endl;
1984  o << "// #################################" << std::endl << std::endl;
1985 }
1986 
1987 /**
1988  * Writes base class definitions to the .td file.
1989  */
1990 void
1992  o << endl
1993  << "// #################################" << endl
1994  << "// Vector register base class definitions" << endl;
1995 
1996  std::map<int, TCEString>::const_iterator bcIt;
1997  for (bcIt = baseClasses_.begin(); bcIt != baseClasses_.end(); ++bcIt) {
1998  int width = bcIt->first;
1999 
2000  if (width > MAX_SCALAR_WIDTH) {
2001  TCEString baseClassName = bcIt->second;
2002  o << "class " << baseClassName
2003  << "<string n, list<Register> aliases> : "
2004  << "TCEVectorReg<n, aliases> {}" << endl;
2005  }
2006  }
2007  o << "// #################################" << endl;
2008 }
2009 
2010 /**
2011  * Writes register definitions to the .td file.
2012  */
2013 void
2015  o << endl
2016  << "// #################################" << endl
2017  << "// Register name definitions for vector registers" << endl;
2018 
2019  std::set<TCEString> declaredRegNames;
2020 
2021  std::map<int, std::vector<RegisterInfo>>::const_iterator it;
2022  for (it = registers_.begin(); it != registers_.end(); ++it) {
2023  int regsWidth = it->first;
2024 
2025  const std::vector<RegisterInfo>& regs = it->second;
2026  TCEString baseClass = baseClasses_.find(regsWidth)->second;
2027 
2028  for (size_t i = 0; i < regs.size(); ++i) {
2029  // Don't declare <=32b registers again, it has been done in TDGen.
2030  if (regsWidth > MAX_SCALAR_WIDTH) {
2031  RegisterInfo reg = regs[i];
2032  RegInfo oldRegInfo = {reg.regFileName_, reg.regIndex_};
2034  o, oldRegInfo, reg.regName_, baseClass, "", RESERVED);
2035  declaredRegNames.insert(reg.regName_);
2036  }
2037  }
2038  }
2039  o << "// #################################" << endl;
2040 }
2041 
2042 /**
2043  * Writes register class definitions to the .td file.
2044  */
2045 void
2046 TDGen::writeVectorRegisterClasses(std::ostream& o) const {
2047  o << endl
2048  << "// #################################" << endl
2049  << "// Register class definitions for vector registers" << endl;
2050 
2051  std::map<TCEString, RegisterClass>::const_iterator it;
2052  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2053  const TCEString& vtStr = it->first;
2054  const RegisterClass& regClass = it->second;
2055 
2056  if (regClass.numberOfRegisters() == 0) {
2057  std::string msg =
2058  std::string("The machine is missing registers for ") +
2059  regClass.valueType().valueTypeStr() + " operands" +
2060  " required by some operation(s).";
2061 
2062  std::cerr << "Error: Illegal machine: " << msg << std::endl;
2064  }
2065 
2066  o << "def " << regClass.name() << " : "
2067  << "RegisterClass<\"TCE\", "
2068  << "[" << vtStr << "], " << regClass.alignment() << ", (add ";
2069 
2070  // Add registers to the register class.
2071  for (size_t i = 0; i < regClass.numberOfRegisters(); ++i) {
2072  const RegisterInfo& reg = regClass.registerInfo(i);
2073  o << reg.regName_;
2074 
2075  if (i != regClass.numberOfRegisters() - 1) {
2076  o << ", ";
2077  }
2078  }
2079  o << ")> ";
2080 
2081  // Register classes below 8 bit of total width need to be set as
2082  // "8 bit of size" so that when they are spilled to stack, the
2083  // byte size of the register class is at least 1.
2084  if (regClass.valueType().width() < 8) {
2085  o << "{" << endl << " let Size=8;" << endl << "}" << endl;
2086  } else {
2087  o << ";" << endl;
2088  }
2089  }
2090 
2091  o << "// #################################" << endl;
2092 }
2093 
2094 /**
2095  * Writes needed defitinion(s) of the vector operation to the .td file.
2096  *
2097  * Creates 4 differend instructions of the operation at most:
2098  * - Integer version (register)
2099  * - Integer version (immediate)
2100  * - Float/half float version (register)
2101  * - Float/half float version (immediate)
2102  *
2103  * @param o Output stream to the .td file.
2104  * @param op Vector operation of which the definitions will be created.
2105  * @param skipPattern True, if skip pattern creation.
2106  */
2107 void
2109  abortWithError("WiP");
2110 }
2111 
2112 /**
2113  * Writes instruction of the vector operation to the .td file.
2114  *
2115  * Creates register version and possibly an immediate version of the
2116  * vector operation in case there are any scalar operands.
2117  *
2118  * @param o Output stream to the file.
2119  * @param op Operation to be written as an instruction to the .td file.
2120  * @param valueTypes Operand value type identifier characters.
2121  * @param attributes Operation attributes.
2122  * @param skipPattern True, if skip pattern creation.
2123  */
2124 void
2126  std::ostream& o, Operation& op, TCEString valueTypes,
2127  const TCEString& attributes, bool skipPattern) {
2128  // Make sure operation's operands are fully supported by
2129  // vector register classes.
2130  if (!hasRegisterClassSupport(op)) {
2131  verbose(
2132  "Warning: " + op.name() + valueTypes +
2133  " was not created due to unsupported operands.");
2134  return;
2135  }
2136 
2137  // Write register version of the operation.
2138  TDGen::writeOperationDef(o, op, valueTypes, attributes, skipPattern);
2139 
2140  // Information of some operations is needed later, save it if needed.
2141  saveAdditionalVectorOperationInfo(op, valueTypes, true);
2142 
2143  // Create the same instruction with immediate inputs if there are
2144  // any input operands that are scalars.
2145  bool scalarsFound = false;
2146  for (int i = op.numberOfOutputs(); i < op.operandCount(); ++i) {
2147  char& c = valueTypes[i];
2148  switch (c) {
2149  case OT_REG_BOOL:
2150  c = OT_IMM_BOOL;
2151  scalarsFound = true;
2152  break;
2153  case OT_REG_INT:
2154  c = OT_IMM_INT;
2155  scalarsFound = true;
2156  break;
2157  case OT_REG_FP:
2158  c = OT_IMM_FP;
2159  scalarsFound = true;
2160  break;
2161  case OT_REG_HFP:
2162  c = OT_IMM_HFP;
2163  scalarsFound = true;
2164  break;
2165  default:
2166  continue;
2167  }
2168  }
2169 
2170  if (scalarsFound) {
2171  // Write immediate version of the operation.
2172  TDGen::writeOperationDef(o, op, valueTypes, attributes, skipPattern);
2173 
2174  // Information of some immediate versions are needed also.
2175  saveAdditionalVectorOperationInfo(op, valueTypes, false);
2176  }
2177 }
2178 
2179 /**
2180  * Saves information of some operations.
2181  *
2182  * Additional information of some operations is needed later, and thus,
2183  * they need to be saved for later reference.
2184  *
2185  * @param op Vector operation.
2186  * @param valueTypes Operand value type identifier characters.
2187  * @param isRegisterOp If false, operation has immediate operands.
2188  */
2189 void
2191  const Operation&, const TCEString&, bool) {
2192  abortWithError("WiP");
2193 }
2194 
2195 /**
2196  * Writes instruction definitions for memory vector operations.
2197  *
2198  * Subword aligned LDQ/LDH/LDW/STQ/STH/STQ vector operations can be passed
2199  * directly to writing vector operation definitions, but vector aligned
2200  * LOAD and STORE operations can be used for several different vector types
2201  * of the same width, thus, all the different vector types need to be
2202  * covered and separate memory instruction have to be made for them.
2203  */
2204 void
2206  std::ostream&, Operation&, bool) {
2207  abortWithError("WiP");
2208 }
2209 
2210 /**
2211  * Writes MOV instructions between vector register classes.
2212  */
2213 void
2215  o << endl
2216  << "// Vector register->register move definitions." << endl
2217  << "let isAsCheapAsAMove = 1 in {" << endl;
2218 
2219  std::map<TCEString, RegisterClass>::const_iterator it;
2220  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2221  const RegisterClass& regClass = it->second;
2222 
2223  const TCEString opcode = "MOV" + regClass.name();
2224  const TCEString vtStr = regClass.valueType().valueTypeStr();
2225 
2226  const TCEString outs = "(outs " + regClass.name() + ":$dst), ";
2227  const TCEString ins = "(ins " + regClass.name() + ":$src), ";
2228  const TCEString insPred =
2229  "(ins GuardRegs:$pred, " + regClass.name() + ":$src), ";
2230  const TCEString asmOp = "\"$src -> $dst;\", []";
2231 
2232  o << "def " << opcode << " : "
2233  << "InstTCE<" << outs << ins << asmOp << ">;" << endl;
2234 
2235  opNames_[opcode] = opcode;
2236  movOperations_.insert(opcode);
2237 
2238  if (hasConditionalMoves_) {
2239  o << "def PRED_TRUE_" << opcode << " : "
2240  << "InstTCE<" << outs << insPred << asmOp << ">;" << endl;
2241 
2242  o << "def PRED_FALSE_" << opcode << " : "
2243  << "InstTCE<" << outs << insPred << asmOp << ">;" << endl;
2244 
2245  opNames_["PRED_TRUE_" + opcode] = "?" + opcode;
2246  opNames_["PRED_FALSE_" + opcode] = "!" + opcode;
2247  truePredOps_[opcode] = "PRED_TRUE_" + opcode;
2248  falsePredOps_[opcode] = "PRED_TRUE_" + opcode;
2249 
2250  movOperations_.insert("PRED_TRUE_" + opcode);
2251  movOperations_.insert("PRED_FALSE_" + opcode);
2252  }
2253  }
2254 
2255  o << "}" << endl;
2256 }
2257 
2258 /**
2259  * Writes truncstore patterns for vector value types.
2260  */
2261 void
2262 TDGen::writeVectorTruncStoreDefs(std::ostream& o) const {
2263  o << endl << "// Vector truncstore definitions, needed below." << endl;
2264 
2265  // Create truncstore definitions for vector value types, there has to
2266  // exist store operations for the same value type that the TRUNC
2267  // operation has. For example, in order to create truncstore using
2268  // TRUNCWH16X4, there has to be store operations in the machine that
2269  // supports storing v4i16 value type.
2270 
2271  std::map<TCEString, RegisterClass>::const_iterator rcIt;
2272  for (rcIt = vRegClasses_.begin(); rcIt != vRegClasses_.end(); ++rcIt) {
2273  o << "def truncstore" << rcIt->first << " : "
2274  << "PatFrag<(ops node:$val, node:$ptr),"
2275  << "(truncstore node:$val, node:$ptr), "
2276  << "[{return cast<StoreSDNode>(N)->getMemoryVT() == "
2277  << "MVT::" << rcIt->first << ";}]>;" << endl;
2278  }
2279  // Create patterns which will replace "truncstore" pattern with separate
2280  // TRUNC and then STORE operations.
2281 
2282  o << endl << "// Pattern definitions for truncstores." << endl;
2283  std::vector<std::pair<const Operation*, TCEString>>::const_iterator it;
2284  for (it = truncOperations_.begin(); it != truncOperations_.end(); ++it) {
2285  const TCEString& truncInstr = it->second;
2286  const TCEString& vtFromStr =
2287  ValueType::valueTypeStr(it->first->input(0));
2288  const TCEString targetVtStr =
2289  ValueType::valueTypeStr(it->first->output(0));
2290 
2291  std::map<TCEString, InstructionInfo>::const_iterator regStoreIt =
2292  registerStores_.find(targetVtStr);
2293 
2294  // Use register version of store operations.
2295  if (regStoreIt != registerStores_.end()) {
2296  const TCEString& regStoreInstr = (regStoreIt->second).instrName_;
2297  const TCEString originalPattern = "truncstore" + targetVtStr +
2298  " " + vtFromStr +
2299  ":$op2, ADDRrr:$op1";
2300  const RegisterClass& regClass =
2301  vRegClasses_.find(vtFromStr)->second;
2302  const TCEString replacerPattern =
2303  regStoreInstr + " ADDRrr:$op1, (" + truncInstr + " " +
2304  regClass.name() + ":$op2)";
2305 
2306  writePatternReplacement(o, originalPattern, replacerPattern);
2307  }
2308 
2309  std::map<TCEString, InstructionInfo>::const_iterator immStoreIt =
2310  immediateStores_.find(targetVtStr);
2311 
2312  // Use immediate version of store operations.
2313  if (immStoreIt != immediateStores_.end()) {
2314  const TCEString& immStoreInstr = (immStoreIt->second).instrName_;
2315  const TCEString originalPattern = "truncstore" + targetVtStr +
2316  " " + vtFromStr +
2317  ":$op2, ADDRri:$op1";
2318  const RegisterClass& regClass =
2319  vRegClasses_.find(vtFromStr)->second;
2320  const TCEString replacerPattern =
2321  immStoreInstr + " ADDRri:$op1, (" + truncInstr + " " +
2322  regClass.name() + ":$op2)";
2323  writePatternReplacement(o, originalPattern, replacerPattern);
2324  }
2325  }
2326 }
2327 
2328 /**
2329  * Writes scalar_to_vector patterns for vector value types.
2330  */
2331 void
2332 TDGen::writeScalarToVectorDefs(std::ostream& o) const {
2333  o << endl << "// Scalar to vector definitions." << endl;
2334  std::map<TCEString, TCEString>::const_iterator it;
2335  for (it = vbcastOperations_.begin(); it != vbcastOperations_.end();
2336  ++it) {
2337  const TCEString& vtStr = it->first;
2338  const TCEString& vbcastInstr = it->second;
2339 
2340  ValueType scalarVt(vtStr);
2341  scalarVt.subwCount_ = 1; // Change vector type to scalar.
2342  TCEString scalarVtStr = scalarVt.valueTypeStr();
2343 
2344  /// @todo Add i8 and i16 subword support once those types have
2345  /// RegisterClass support. For now, just skip generation for them.
2346  if (scalarVtStr == "f16" || scalarVtStr == "f32" ||
2347  scalarVtStr == "i32") {
2348  TCEString originalPattern =
2349  vtStr + " (scalar_to_vector " + scalarVtStr + ":$in)";
2350  TCEString replacerPattern =
2351  vbcastInstr + " " + scalarVtStr + ":$in";
2352 
2353  writePatternReplacement(o, originalPattern, replacerPattern);
2354  }
2355  }
2356 }
2357 
2358 /**
2359  * Writes bit conversion patterns.
2360  */
2361 void
2362 TDGen::writeVectorBitConversions(std::ostream& o) const {
2363  o << endl << "// Bit conversions between vector types." << endl;
2364 
2365  std::map<TCEString, RegisterClass>::const_iterator it1;
2366  for (it1 = vRegClasses_.begin(); it1 != vRegClasses_.end(); ++it1) {
2367  const TCEString& vtStr1 = it1->first;
2368  const RegisterClass& regClass1 = it1->second;
2369 
2370  std::map<TCEString, RegisterClass>::const_iterator it2;
2371  for (it2 = vRegClasses_.begin(); it2 != vRegClasses_.end(); ++it2) {
2372  const TCEString& vtStr2 = it2->first;
2373  const RegisterClass& regClass2 = it2->second;
2374  if (regClass1.valueType().width() !=
2375  regClass2.valueType().width() ||
2376  vtStr1 == vtStr2) {
2377  continue;
2378  }
2379  const TCEString originalPattern = vtStr2 + " (bitconvert (" +
2380  vtStr1 + " " +
2381  regClass1.name() + ":$src))";
2382  const TCEString replacerPattern =
2383  vtStr2 + " " + regClass2.name() + ":$src";
2384  writePatternReplacement(o, originalPattern, replacerPattern);
2385  }
2386  }
2387 
2388  o << endl << "// Bit conversions to/from i32." << endl;
2389 
2390  // Write i32 -> same size vector type bit conversions.
2391  std::map<TCEString, RegisterClass>::const_iterator it;
2392  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2393  const TCEString& vtStr = it->first;
2394  const RegisterClass& regClass = it->second;
2395 
2396  if (regClass.valueType().width() == 32 && vtStr != "i32") {
2397  TCEString originalPattern = "i32 (bitconvert (" + vtStr + " " +
2398  regClass.name() + ":$src))";
2399  TCEString replacerPattern = "i32 R32IRegs:$src";
2400  writePatternReplacement(o, originalPattern, replacerPattern);
2401 
2402  originalPattern = vtStr + " (bitconvert (i32 R32IRegs:$src))";
2403  replacerPattern = vtStr + " " + regClass.name() + ":$src";
2404  writePatternReplacement(o, originalPattern, replacerPattern);
2405  }
2406  }
2407 }
2408 
2409 /**
2410  * This function writes scalar operation exploitations.
2411  *
2412  * Some scalar operations can be exploited to execute vector operations.
2413  * For instance, bitwise logical operations are same for any operand width.
2414  * A 32-bit scalar XOR operation can execute bitwise exclusive OR operation
2415  * for v32i1, v4i8 and v2i16 vector operands similarly as it does for i32
2416  * type.
2417  */
2418 void
2420  o << endl
2421  << endl
2422  << "// Scalar operations exploited to execute small vector operations."
2423  << endl;
2424 
2425  // Use minimal architecture NOT/AND/IOR/XOR 32-bit operations to execute
2426  // bitwise vector operations with operands of 32 bits or lower width.
2427  OperationPool opPool;
2428 
2429  std::vector<Operation*> scalarBitwiseOps;
2430  scalarBitwiseOps.push_back(&opPool.operation("NOT"));
2431  scalarBitwiseOps.push_back(&opPool.operation("AND"));
2432  scalarBitwiseOps.push_back(&opPool.operation("IOR"));
2433  scalarBitwiseOps.push_back(&opPool.operation("XOR"));
2434  scalarBitwiseOps.push_back(&opPool.operation("NOT64"));
2435  scalarBitwiseOps.push_back(&opPool.operation("AND64"));
2436  scalarBitwiseOps.push_back(&opPool.operation("IOR64"));
2437  scalarBitwiseOps.push_back(&opPool.operation("XOR64"));
2438 
2439 
2440  for (size_t opI = 0; opI < scalarBitwiseOps.size(); ++opI) {
2441  Operation& op = *scalarBitwiseOps[opI];
2442  if (&op == &NullOperation::instance() ||
2443  !mach_.hasOperation(op.name())) {
2444  continue;
2445  }
2446 
2447  int width = 2;
2448 
2449  while (width <= op.output(0).width()) {
2450  // Get vector value types for the current width, e.g v4i8, v2i16
2451  // and v32i1 value types for width 32.
2452  std::vector<ValueType> intVecVts =
2453  ValueType::vectorTypesOfWidth(width, true);
2454 
2455  for (size_t i = 0; i < intVecVts.size(); ++i) {
2456  ValueType& vecVt = intVecVts[i];
2457  const TCEString vecVtStr = vecVt.valueTypeStr();
2458 
2459  if (hasRegisterClassSupport(vecVt)) {
2460  std::vector<ValueType> inputs;
2461  std::vector<ValueType> outputs;
2462 
2463  for (int i = 0; i < op.numberOfInputs(); ++i) {
2464  inputs.push_back(vecVt);
2465  }
2466  for (int i = 0; i < op.numberOfOutputs(); ++i) {
2467  outputs.push_back(vecVt);
2468  }
2469 
2471  o, op, false, inputs, outputs, vecVtStr);
2472  }
2473  }
2474 
2475  width *= 2;
2476  }
2477  }
2478 
2479  // Use LDQ/LDH/LDW and STQ/STH/STW operations to create memory access
2480  // operations for vector operands of 32-bit or lower width.
2481  int memDataOpndWidth = 2;
2482 
2483  const char* defaultType = mach_.is64bit() ? "i64" : "i32";
2484 
2485  while (memDataOpndWidth <= MAX_SCALAR_WIDTH) {
2486  std::vector<ValueType> vecVts =
2487  ValueType::vectorTypesOfWidth(memDataOpndWidth);
2488 
2489  for (size_t i = 0; i < vecVts.size(); ++i) {
2490  const ValueType& dataOpndVt = vecVts[i];
2491  const TCEString dataOpndVtStr = dataOpndVt.valueTypeStr();
2492 
2493  if (hasRegisterClassSupport(dataOpndVt)) {
2494  Operation* op = NULL;
2495  if (memDataOpndWidth <= 8) {
2496  if (littleEndian_) {
2497  op = &opPool.operation("LD8");
2498  } else {
2499  op = &opPool.operation("LDQ");
2500  }
2501  } else if (memDataOpndWidth <= 16) {
2502  if (littleEndian_) {
2503  op = &opPool.operation("LD16");
2504  } else {
2505  op = &opPool.operation("LDH");
2506  }
2507  } else if (memDataOpndWidth <= 32){
2508  if (littleEndian_) {
2509  op = &opPool.operation("LD32");
2510  } else {
2511  op = &opPool.operation("LDW");
2512  }
2513  } else {
2514  if (littleEndian_) {
2515  op = &opPool.operation("LD64");
2516  } else {
2517  op = &opPool.operation("LDD");
2518  std::cerr << "Warning: SIMD support with "
2519  << "big-endian adf is deprecated" << std::endl;
2520  }
2521  }
2522 
2523  std::vector<ValueType> inputs;
2524  std::vector<ValueType> outputs;
2525 
2526  // Address operand 32 or 64 bits
2527  inputs.push_back(ValueType(defaultType));
2528  // Data operand.
2529  outputs.push_back(dataOpndVt);
2530 
2532  o, *op, false, inputs, outputs, dataOpndVtStr);
2533  }
2534  }
2535 
2536  for (size_t i = 0; i< vecVts.size(); ++i) {
2537  const ValueType& dataOpndVt = vecVts[i];
2538  const TCEString dataOpndVtStr = dataOpndVt.valueTypeStr();
2539 
2540  if (hasRegisterClassSupport(dataOpndVt)) {
2541  Operation* op = NULL;
2542  if (memDataOpndWidth <= 8) {
2543  if (littleEndian_) {
2544  op = &opPool.operation("ST8");
2545  } else {
2546  op = &opPool.operation("STQ");
2547  }
2548  } else if (memDataOpndWidth <= 16) {
2549  if (littleEndian_) {
2550  op = &opPool.operation("ST16");
2551  } else {
2552  op = &opPool.operation("STH");
2553  }
2554  } else if (memDataOpndWidth <= 32) {
2555  if (littleEndian_) {
2556  op = &opPool.operation("ST32");
2557  } else {
2558  op = &opPool.operation("STW");
2559  }
2560  } else {
2561  if (littleEndian_) {
2562  op = &opPool.operation("ST64");
2563  } else {
2564  op = &opPool.operation("STD");
2565  std::cerr << "Warning: SIMD support with "
2566  << "big-endian adf is deprecated" << std::endl;
2567  }
2568  }
2569 
2570  std::vector<ValueType> inputs;
2571  std::vector<ValueType> outputs;
2572 
2573  // Address operand 32 or 64 bits.
2574  inputs.push_back(ValueType(defaultType));
2575  inputs.push_back(dataOpndVt);
2576  // There is no output operands for store.
2577 
2579  o, *op, false, inputs, outputs, dataOpndVtStr);
2580 
2581  }
2582  }
2583 
2584  memDataOpndWidth *= 2;
2585  }
2586 }
2587 
2588 /**
2589  * Writes bitwise NOT/AND/IOR/XOR operation definitions for vector operations.
2590  *
2591  * For 32-bit or less vector widths, 32-bit base operation is used. For
2592  * bitwise bool vector operations wider than 32 bits, corresponding bitwise
2593  * operation is searched from the machine, and used to create operation
2594  * definitions if it exists.
2595  *
2596  * @param o Output stream.
2597  * @param op Operation used to create bitwise operations.
2598  * @param skipPattern If true, operation pattern writing is skipped.
2599  */
2600 void
2602  std::ostream& o, Operation& op, bool skipPattern) {
2603  o << endl;
2604 
2605  if (op.numberOfOutputs() == 0) {
2606  assert(false && "Bitwise operation has 0 outputs.");
2607  }
2608 
2609  int opWidth = op.output(0).width();
2610  std::vector<ValueType> vts = ValueType::vectorTypesOfWidth(opWidth);
2611 
2612  for (size_t i = 0; i < vts.size(); ++i) {
2613  const ValueType& vecVt = vts[i];
2614  const TCEString vecVtStr = vecVt.valueTypeStr();
2615 
2616  // Only integer value types are used in bitwise operations.
2617  if (!vecVt.isFloat_ && hasRegisterClassSupport(vecVt)) {
2618  std::vector<ValueType> inputs;
2619  std::vector<ValueType> outputs;
2620 
2621  for (int i = 0; i < op.numberOfInputs(); ++i) {
2622  inputs.push_back(vecVt);
2623  }
2624  for (int i = 0; i < op.numberOfOutputs(); ++i) {
2625  outputs.push_back(vecVt);
2626  }
2627 
2629  o, op, skipPattern, inputs, outputs, vecVtStr);
2630  }
2631  }
2632 
2633  o << endl;
2634 }
2635 
2636 /**
2637  * Attaches load and store operations to vector types that don't have them.
2638  *
2639  * Checks first which vector value types don't have load and store operations
2640  * for memory accessing. After collecting the value types without load/store,
2641  * the function tries to search existing load/store instructions whose
2642  * data operand width matches the vector value type that doesn't have a
2643  * load/store operation. If the function can find matching memory
2644  * instructions, it creates new memory instructions for the vector value types
2645  * by exploiting existing matching memory instructions.
2646  */
2647 void
2649  std::ostream& o) {
2650 
2651  const char* defaultTypeStr = mach_.is64bit() ? "i64" : "i32";
2652 
2653  // Value type string of the register class.
2654  std::set<TCEString> withoutLoadOperation;
2655  std::set<TCEString> withoutStoreOperation;
2656 
2657  // Collect all vector value types that are without load or store
2658  // operation support for memory accessing.
2659  std::map<TCEString, RegisterClass>::iterator it;
2660  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2661  const TCEString vtStr = it->first;
2662  const ValueType vt(vtStr);
2663 
2664  // 32-bit and smaller vectors are covered by LDQ/LDH/LDW/STQ/STH/STW.
2665  // TODO: shoudl this have 64 also for 32-bit ADFs?
2666  if (vt.width() > maxScalarWidth_) {
2667  if (registerLoads_.find(vtStr) == registerLoads_.end()) {
2668  withoutLoadOperation.insert(vtStr);
2669  }
2670 
2671  if (registerStores_.find(vtStr) == registerStores_.end()) {
2672  withoutStoreOperation.insert(vtStr);
2673  }
2674  }
2675  }
2676 
2677  o << endl << "// Define memory operations for vector operands without"
2678  << endl << "// load or store operation definition by exploiting"
2679  << endl << "// existing memory operations of proper width." << endl;
2680 
2681  OperationPool opPool;
2682 
2683  std::set<TCEString>::const_iterator wLoadIt;
2684  for (wLoadIt = withoutLoadOperation.begin();
2685  wLoadIt != withoutLoadOperation.end(); ++wLoadIt) {
2686  const TCEString& dataOpndVtStr = *wLoadIt;
2687  const ValueType vt(dataOpndVtStr);
2688 
2689  bool foundExploitable = false;
2690  std::map<TCEString, InstructionInfo>::const_iterator loadIt =
2691  registerLoads_.begin();
2692 
2693  // Try to find any machine load instruction that is able to load
2694  // equal amount of bytes from memory as the ValueType is wide.
2695  while (!foundExploitable && loadIt != registerLoads_.end()) {
2696  const ValueType loadInstrVt(loadIt->first);
2697 
2698  // If found a match, remove the last two characters of the
2699  // load instruction name to get the OSAL operation name.
2700  if (vt.width() == loadInstrVt.width()) {
2701  foundExploitable = true;
2702  const TCEString opName = (loadIt->second).osalOpName_;
2703  Operation& op = opPool.operation(opName.c_str());
2704 
2705  std::vector<ValueType> inputs;
2706  std::vector<ValueType> outputs;
2707 
2708  // Address operand always 32 or 64 bits.
2709  inputs.push_back(ValueType(defaultTypeStr));
2710  // Data operand.
2711  outputs.push_back(dataOpndVtStr);
2712 
2714  o, op, false, inputs, outputs, dataOpndVtStr);
2715  }
2716 
2717  ++loadIt;
2718  }
2719  }
2720 
2721  std::set<TCEString>::const_iterator wStoreIt;
2722  for (wStoreIt = withoutStoreOperation.begin();
2723  wStoreIt != withoutStoreOperation.end(); ++wStoreIt) {
2724  const TCEString& dataOpndVtStr = *wStoreIt;
2725  const ValueType vt(dataOpndVtStr);
2726 
2727  bool foundExploitable = false;
2728  std::map<TCEString, InstructionInfo>::const_iterator storeIt =
2729  registerStores_.begin();
2730 
2731  // Try to find any machine store instruction that is able to store
2732  // equal amount of bytes to memory as the ValueType is wide.
2733  while (!foundExploitable && storeIt != registerStores_.end()) {
2734  const ValueType storeInstrVt(storeIt->first);
2735 
2736  // If found a match, remove the last two characters of the
2737  // store instruction name to get the OSAL operation name.
2738  if (vt.width() == storeInstrVt.width()) {
2739  foundExploitable = true;
2740  const TCEString opName = (storeIt->second).osalOpName_;
2741  Operation& op = opPool.operation(opName.c_str());
2742 
2743  std::vector<ValueType> inputs;
2744  std::vector<ValueType> outputs;
2745 
2746  // Address operand always i32 or 64 bits.
2747  inputs.push_back(ValueType(defaultTypeStr));
2748  inputs.push_back(dataOpndVtStr);
2749  // There is no output operands for store.
2750 
2752  o, op, false, inputs, outputs, dataOpndVtStr);
2753  }
2754 
2755  ++storeIt;
2756  }
2757  }
2758 
2759  o << endl;
2760 }
2761 
2762 /**
2763  * Writes vector operation definitions that exploit bigger vector operations.
2764  *
2765  * Exploited vector operands are written in ascending order by their subword
2766  * count, meaning that e.g. ADD32X16, ADD32X32, and ADD32X4 operation
2767  * exploitations are listed so that ADD32X4 are written first, then
2768  * ADD32X16, and then ADD32X32. This way the instruction selection will
2769  * first use ADD32X4 to execute vector addition for v2i32 vector operand
2770  * types, and thus, is more optimal solution than executing the same
2771  * v2i32 addition with ADD32X16 (though ADD32X4 would be also available
2772  * in the machine).
2773  */
2774 void
2776  abortWithError("WiP");
2777 }
2778 
2779 /**
2780  * Generates implementation of getStore() function.
2781  */
2782 void
2784  TCEString prefix = "&"; // Address of -operator.
2785  TCEString rcpf = "RegsRegClass";
2786  TCEString rapf = "TCE::RARegRegClass";
2787  TCEString storeB = littleEndian_ ? "ST8Brb;" : "STQBrb;";
2788  TCEString storeW = littleEndian_ ? "ST32" : "STW";
2789  TCEString storeH = littleEndian_ ? "ST16" : "STH";
2790  TCEString storeL = "ST64";
2791 
2792  o << "#include <stdio.h>" << endl
2793  << "int GeneratedTCEPlugin::getStore(const TargetRegisterClass *rc)"
2794  << " const {" << endl;
2795 
2796  o << "\tif (rc == " << prefix << rapf
2797  << ") return TCE::STWRArr;"
2798  << endl;
2799 
2800  for (RegClassMap::const_iterator ri = regsInClasses_.begin();
2801  ri != regsInClasses_.end(); ri++) {
2802 
2803  if ((ri->first.find("R1") == 0 ||
2804  ri->first.find(TDGen::guardRegTemplateName) == 0) &&
2805  ri->first.find("R16") != 0) {
2806  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2807  << rcpf << ") return TCE::" << storeB << endl;
2808  }
2809  if (ri->first.find("R32") == 0) {
2810  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2811  << rcpf << ") return TCE::" << storeW << "rr;" << endl;
2812 
2813  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2814  << "I" << rcpf << ") return TCE::" << storeW << "rr;" << endl;
2815 
2816  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2817  << "FP" << rcpf << ") return TCE::" << storeW << "fr;" << endl;
2818 
2819  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2820  << "HFP" << rcpf << ") return TCE::" << storeH << "hr;" << endl;
2821  }
2822  if (mach_.is64bit()) {
2823  if (ri->first.find("R64") == 0) {
2824  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2825  << rcpf << ") return TCE::" << storeL << "ss;" << endl;
2826 
2827  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2828  << "I" << rcpf << ") return TCE::" << storeL << "ss;"
2829  << endl;
2830 
2831  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2832  << "DFP" << rcpf << ") return TCE::" << storeL << "ds;"
2833  << endl;
2834  }
2835  // TODO: double support here?
2836  }
2837  }
2838 
2839  if (use64bitForFP_) {
2840  o << "\tif (rc == &TCE::FPRegsRegClass) return TCE::ST64fs;"
2841  << std::endl;
2842 
2843  o << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::ST64hs;"
2844  << std::endl;
2845  } else {
2846  o << "\tif (rc == &TCE::FPRegsRegClass) return TCE::"
2847  << storeW << "fr;" << std::endl;
2848 
2849  o << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::"
2850  << storeW << "hr;" << std::endl;
2851  }
2852 
2853  std::map<TCEString, RegisterClass>::const_iterator it;
2854  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2855  const TCEString& vtStr = it->first;
2856  const RegisterClass& regClass = it->second;
2857 
2858  std::map<TCEString, InstructionInfo>::const_iterator storeIt =
2859  registerStores_.find(vtStr);
2860 
2861  if (storeIt != registerStores_.end()) {
2862  o << "\tif (rc == &TCE::" << regClass.name() << "RegClass) "
2863  << "return TCE::" << (storeIt->second).instrName_ << ";" << endl;
2864  } else {
2865  verbose("Warning: no store generated for RegisterClass " +
2866  regClass.name() + " to GeneratedTCEPlugin::getStore");
2867  }
2868  }
2869 
2870  o << "\tstd::cerr << \"regclass id:\" <<rc->getID() << \"of size \" "
2871  << "<<rc->MC->RegsSize<< std::endl;" << std::endl;
2872  o << "\tassert(0&&\"Storing given regclass to stack not supported. "
2873  << "Bug in backend?\");"
2874  << endl
2875  << "} " << endl
2876  << endl;
2877 }
2878 
2879 /**
2880  * Generates implementation of getLoad() function.
2881  */
2882 void
2884  TCEString prefix = "&"; // Address of -operator.
2885  TCEString rcpf = "RegsRegClass";
2886  TCEString rapf = "TCE::RARegRegClass";
2887 
2888  TCEString loadB = littleEndian_ ? "LD8" : "LDQ";
2889  if (!mach_.hasOperation(loadB)) {
2890  loadB = littleEndian_ ? "LDU8" : "LDQU";
2891  if (!mach_.hasOperation(loadB)) {
2892  loadB="";
2893  }
2894  }
2895 
2896  TCEString loadW = littleEndian_ ? "LD32" : "LDW";
2897  TCEString loadH = littleEndian_ ? "LD16" : "LDH";
2898  TCEString loadL = "LD64";
2899  if (!mach_.hasOperation(loadH)) {
2900  loadH = littleEndian_ ? "LDU16;" : "LDHU";
2901  if (!mach_.hasOperation(loadH)) {
2902  loadH="";
2903  }
2904  }
2905 
2906  o << "int GeneratedTCEPlugin::getLoad(const TargetRegisterClass *rc)"
2907  << " const {" << endl;
2908 
2909  o << "\tif (rc == " << prefix << rapf << ") return TCE::"
2910  << loadW << "RAr;" << endl;
2911 
2912  if (!mach_.hasOperation(loadW) && mach_.hasOperation("LDU32")) {
2913  loadW = "LDU32";
2914  }
2915 
2916  for (RegClassMap::const_iterator ri = regsInClasses_.begin();
2917  ri != regsInClasses_.end(); ri++) {
2918  if ((ri->first.find("R1") == 0 ||
2919  ri->first.find(TDGen::guardRegTemplateName) == 0) &&
2920  ri->first.find("R16") != 0 && loadB != "") {
2921  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2922  << rcpf <<") return TCE::" << loadB << "Br;" << endl;
2923  }
2924  if (ri->first.find("R32") == 0) {
2925  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2926  << rcpf << ") return TCE::" << loadW << "rr;" << endl;
2927 
2928  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2929  << "I" << rcpf << ") return TCE::" << loadW << "rr;" << endl;
2930 
2931  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2932  << "FP" << rcpf << ") return TCE::" << loadW << "fr;" << endl;
2933  if (loadH != "") {
2934  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2935  << "HFP" << rcpf << ") return TCE::" << loadH << "hr;" << endl;
2936  }
2937  }
2938  if (mach_.is64bit()) {
2939  if (ri->first.find("R64") == 0) {
2940  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2941  << rcpf << ") return TCE::" << loadL << "ss;" << endl;
2942 
2943  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2944  << "I" << rcpf << ") return TCE::" << loadL << "ss;" << endl;
2945 
2946  o << "\tif (rc == " << prefix << "TCE::" << ri->first
2947  << "DFP" << rcpf << ") return TCE::" << loadL << "ds;" << endl;
2948 
2949  }
2950  }
2951  }
2952 
2953  if (use64bitForFP_) {
2954  o << "\tif (rc == &TCE::FPRegsRegClass) return TCE::LD64fs;"
2955  << std::endl;
2956 
2957  o << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::LD64hs;"
2958  << std::endl;
2959  } else {
2960  o << "\tif (rc == &TCE::FPRegsRegClass) return TCE::"
2961  << loadW << "fr;" << std::endl;
2962 
2963  o << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::"
2964  << loadW << "hr;" << std::endl;
2965  }
2966 
2967  std::map<TCEString, RegisterClass>::const_iterator it;
2968  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
2969  const TCEString& vtStr = it->first;
2970  const RegisterClass& regClass = it->second;
2971 
2972  std::map<TCEString, InstructionInfo>::const_iterator loadIt =
2973  registerLoads_.find(vtStr);
2974 
2975  if (loadIt != registerLoads_.end()) {
2976  o << "\tif (rc == &TCE::" << regClass.name() << "RegClass) "
2977  << "return TCE::" << (loadIt->second).instrName_ << ";" << endl;
2978  } else {
2979  verbose("Warning: no load generated for RegisterClass " +
2980  regClass.name() + " to GeneratedTCEPlugin::getLoad");
2981  }
2982  }
2983 
2984  o << "\tprintf(\"regclass of size %d \\n\", rc->MC->RegsSize);" << std::endl
2985  << "\tassert(0&&\"loading from stack to given regclass not supported."
2986  << " Bug in backend?\");"
2987  << endl
2988  << "} " << endl
2989  << endl;
2990 }
2991 
2992 
2993 /**
2994  * Generates a function that adds existing register classes in lowering phase.
2995  */
2996 void
2998  std::ostream& o) const {
2999  o << endl << "// Adds all vector classes to backend" << endl
3000  << "void TCETargetLowering::addVectorRegisterClasses() {" << endl;
3001  std::map<TCEString, RegisterClass>::const_iterator it;
3002  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3003  const RegisterClass& regClass = it->second;
3004 
3005  o << "\taddRegisterClass("
3006  << "MVT::" << regClass.valueType().valueTypeStr() << ", "
3007  << "&TCE::" << regClass.name() << "RegClass);"
3008  << endl;
3009  }
3010 
3011  o << "}" << endl;
3012 
3013  o << endl << "// Sets build and extract lowering" << endl
3014  << "void TCETargetLowering::addVectorLowerings() {" << endl;
3015 
3016  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3017  const RegisterClass& regClass = it->second;
3018 
3019  o << "\tsetOperationAction(ISD::BUILD_VECTOR,"
3020  << "MVT::" << regClass.valueType().valueTypeStr() << ", "
3021  << "Custom);" << endl;
3022 
3023  o << "\tsetOperationAction(ISD::EXTRACT_SUBVECTOR,"
3024  << "MVT::" << regClass.valueType().valueTypeStr() << ", "
3025  << "Expand);" << endl;
3026 
3027  for (auto vt : ValueType::SUPPORTED_LLVM_VALUE_TYPES) {
3028  if (vRegClasses_.find(vt) == vRegClasses_.end()) {
3029  o << "\tsetTruncStoreAction(MVT::"
3030  << regClass.valueType().valueTypeStr()
3031  << ", MVT::" << vt << ", Expand);" << endl;
3032  }
3033  }
3034  }
3035  o << "}" << endl;
3036 }
3037 
3038 /**
3039  * Generates a function that returns correct reg class for a value type.
3040  */
3041 void
3043  std::ostream& o) const {
3044  o << endl << "// Returns vector register class for given value type"
3045  << endl
3046  << "std::pair<unsigned, const TargetRegisterClass*> "
3047  << "TCETargetLowering::associatedVectorRegClass(const EVT& vt) "
3048  << "const {"
3049  << endl;
3050 
3051  std::map<TCEString, RegisterClass>::const_iterator it;
3052  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3053  const TCEString& vtStr = it->first;
3054  const RegisterClass& regClass = it->second;
3055 
3056  o << "\tif (vt == MVT::" << vtStr << ") "
3057  << "return std::make_pair(0U, &TCE::"
3058  << regClass.name() << "RegClass);" << endl;
3059  }
3060 
3061  o << "\treturn std::make_pair(0U, (TargetRegisterClass*)0);" << endl
3062  << "}" << endl;
3063 }
3064 
3065 /**
3066  * Generates a function that returns correct return value type for comparisons.
3067  *
3068  * In LLVM vector comparison operations result into boolean vectors,
3069  * which have the same subword count as input vectors.
3070  */
3071 void
3073  o << endl
3074  << "llvm::EVT TCETargetLowering::getSetCCResultVT(const EVT& vt) "
3075  << "const {"
3076  << endl;
3077 
3078  int subwCount = 2;
3079  while (subwCount <= MAX_SUBW_COUNT) {
3080  TCEString boolVecVtStr = "v" + Conversion::toString(subwCount) + "i1";
3081  ValueType boolVecVt(boolVecVtStr);
3082 
3083  if (!boolVecVt.isSupportedByLLVM()) {
3084  break;
3085  }
3086 
3087  o << "\tif (vt.getVectorElementCount().getKnownMinValue() == "
3088  << Conversion::toString(subwCount) << ") return llvm::MVT::"
3089  << boolVecVtStr << ";" << endl;
3090  subwCount *= 2;
3091  }
3092 
3093  o << "\treturn llvm::MVT::INVALID_SIMPLE_VALUE_TYPE;" << endl
3094  << "}" << endl;
3095 }
3096 
3097 /**
3098  * Writes return address register definition to the output stream.
3099  */
3100 void
3101 TDGen::writeRARegisterInfo(std::ostream& o) {
3102  o << "class Rra<string n> : TCEReg<n, []>;" << std::endl;
3103  o << "def RA : Rra<\"return-address\">, ";
3104  o << "DwarfRegNum<[" << dregNum_++ << "]>;";
3105  o << std::endl;
3106  if (mach_.is64bit()) {
3107  o << "def RAReg : RegisterClass<\"TCE\", [i64], 64, (add RA)>;" <<
3108  std::endl;
3109  } else {
3110  o << "def RAReg : RegisterClass<\"TCE\", [i32], 32, (add RA)>;" <<
3111  std::endl;
3112  }
3113 }
3114 
3115 
3116 
3117 #if 0 // TODO: where does this belong???
3118 
3119  o << "\treturn llvm::MVT::INVALID_SIMPLE_VALUE_TYPE;" << endl
3120  << "}" << endl;
3121 }
3122 #endif
3123 
3124 /**
3125  * Generates implementation of copyPhysVectorReg().
3126  *
3127  * Only the previously created vector register classes are added
3128  * to the implementation to make LLVM compilation flow work.
3129  */
3130 void
3132  o << endl
3133  << "#include <llvm/CodeGen/MachineInstrBuilder.h>" << endl
3134  << "// Copies a vector register to another" << endl
3135 
3136  << "bool TCEInstrInfo::copyPhysVectorReg(" << endl
3137  << "\tMachineBasicBlock& mbb," << endl
3138  << "\tMachineBasicBlock::iterator mbbi," << endl
3139  << "const DebugLoc& dl," << endl
3140  << "\tMCRegister destReg, MCRegister srcReg," << endl
3141  << "\tbool killSrc) const {" << endl
3142  << endl;
3143 
3144  std::map<TCEString, RegisterClass>::const_iterator it;
3145  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3146  const RegisterClass& regClass = it->second;
3147 
3148  o << "\tif (TCE::" << regClass.name()
3149  << "RegClass.contains(destReg, srcReg)) {" << endl
3150  << "\t\tBuildMI(mbb, mbbi, dl, get(TCE::"
3151  << "MOV" << regClass.name() << "), destReg)" << endl
3152  << "\t\t.addReg(srcReg, getKillRegState(killSrc));" << endl
3153  << "\t\treturn true;" << endl
3154  << "\t}" << endl;
3155  }
3156  o << "\treturn false;" << endl << "}" << endl;
3157 }
3158 
3159 void
3160 TDGen::writeVectorImmediateWriteDefs(std::ostream& instrInfoTD) {
3161  for (auto it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3162  const RegisterClass& regClass = it->second;
3163  TCEString regClassName = regClass.name();
3164  ValueType valType = regClass.valueType();
3165  TCEString valTypeName = valType.valueTypeStr();
3166  if (valType.width() <= 32) {
3167  TCEString opName = "MOVI" + valTypeName;
3168  instrInfoTD << "def " << opName << " : InstTCE<(outs "
3169  << regClassName
3170  << ":$dst), (ins i32imm:$val), \"\",[]>;"
3171  << std::endl;
3172 
3173  opNames_[opName] = "MOVE";
3174  }
3175  }
3176 }
3177 
3178 void
3180  std::ostream& backendCode) const {
3181  backendCode << "int GeneratedTCEPlugin::getVectorImmediateOpcode(const "
3182  "EVT& vt) const {"
3183  << std::endl;
3184  for (auto it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
3185  const RegisterClass& regClass = it->second;
3186  TCEString regClassName = regClass.name();
3187  ValueType valType = regClass.valueType();
3188  TCEString valTypeName = valType.valueTypeStr();
3189  if (valType.width() <= 32) {
3190  TCEString opName = "MOVI" + valTypeName;
3191  backendCode << "\tif (vt == MVT::" << valTypeName
3192  << ") return TCE::" << opName << ";" << std::endl;
3193  }
3194  }
3195  backendCode << "\treturn -1;\n}" << endl;
3196 }
3197 
3198 void
3200  o << endl
3201  << "// Returns correct vector GATHER opcode" << endl
3202  << "int GeneratedTCEPlugin::getGatherOpcode("
3203  << "const EVT& vt) const {" << endl;
3204 
3205  for (auto it = gatherOperations_.begin(); it != gatherOperations_.end();
3206  ++it) {
3207  o << "\tif (vt == MVT::" << it->first
3208  << ") return TCE::" << it->second << ";" << endl;
3209  }
3210 
3211  o << "\treturn -1;" << endl << "}" << endl;
3212 }
3213 
3214 void
3216  o << endl
3217  << "// Returns correct load opcode" << endl
3218  << "int GeneratedTCEPlugin::getLoadOpcode("
3219  << "const EVT& vt) const {" << endl;
3220 
3221  for (auto it = registerLoads_.begin(); it != registerLoads_.end(); ++it) {
3222  o << "\tif (vt == MVT::" << it->first
3223  << ") return TCE::" << it->second.instrName_ << ";" << endl;
3224  }
3225  o << "\treturn -1;" << endl << "}" << endl;
3226 }
3227 
3228 void
3230  o << endl
3231  << "// Returns correct vector ADD opcode" << endl
3232  << "int GeneratedTCEPlugin::getAddOpcode("
3233  << "const EVT& vt) const {" << endl;
3234 
3235  for (auto it = addOperations_.begin(); it != addOperations_.end(); ++it) {
3236  o << "\tif (vt == MVT::" << it->first
3237  << ") return TCE::" << it->second << ";" << endl;
3238  }
3239 
3240  o << "\treturn -1;" << endl << "}" << endl;
3241 }
3242 
3243 void
3245  o << endl
3246  << "// Returns correct vector SHL opcode" << endl
3247  << "int GeneratedTCEPlugin::getShlOpcode("
3248  << "const EVT& vt) const {" << endl;
3249 
3250  for (auto it = shlOperations_.begin(); it != shlOperations_.end(); ++it) {
3251  o << "\tif (vt == MVT::" << it->first
3252  << ") return TCE::" << it->second << ";" << endl;
3253  }
3254 
3255  o << "\treturn -1;" << endl << "}" << endl;
3256 }
3257 
3258 void
3260  o << endl
3261  << "// Returns correct vector SHL opcode" << endl
3262  << "int GeneratedTCEPlugin::getIorOpcode("
3263  << "const EVT& vt) const {" << endl;
3264 
3265  for (auto it = iorOperations_.begin(); it != iorOperations_.end(); ++it) {
3266  o << "\tif (vt == MVT::" << it->first
3267  << ") return TCE::" << it->second << ";" << endl;
3268  }
3269 
3270  o << "\treturn -1;" << endl << "}" << endl;
3271 }
3272 
3273 /**
3274  * Checks that the target machine has required registers to build a usable
3275  * plugin.
3276  *
3277  * @return True if required registers were found, false if not.
3278  */
3279 bool
3281  if (!mach_.is64bit() && regs32bit_.size() < requiredI32Regs_) {
3282  std::string msg =
3283  (boost::format(
3284  "Architecture doesn't meet the minimal requirements.\n"
3285  "Only %d 32-bit general purpose registers found. At least %d\n"
3286  "needed.")
3287  % regs32bit_.size() % requiredI32Regs_)
3288  .str();
3289 
3290  if (tempRegFiles_.size() > 0) {
3291  msg += "Your machine is not fully connected, thus one register\n"
3292  "from each register file are reserved for temp moves and\n"
3293  "not used as general purpose registers.";
3294  }
3295 
3296  throw InvalidData(__FILE__, __LINE__, __func__, msg);
3297  return false;
3298  }
3299 
3300  if (regs64bit_.size() < requiredI64Regs_) {
3301  std::string msg =
3302  (boost::format(
3303  "Architecture doesn't meet the minimal requirements.\n"
3304  "Only %d 64-bit general purpose registers found. At least %d\n"
3305  "needed. ")
3306  % regs64bit_.size() % requiredI64Regs_)
3307  .str();
3308 
3309  if (tempRegFiles_.size() > 0) {
3310  msg += "Your machine is not fully connected, thus one register\n"
3311  "from each register file is reserved for temp moves and\n"
3312  "not used as general purpose registers.";
3313  }
3314 
3315  throw InvalidData(__FILE__, __LINE__, __func__, msg);
3316  return false;
3317  }
3318 
3319  return true;
3320 }
3321 
3322 /**
3323  * Writes all machine instructions to instruction info .td file.
3324  *
3325  * @param os Output stream to the file.
3326  */
3327 void
3328 TDGen::writeInstrInfo(std::ostream& os) {
3329 
3330  writeCallSeqStart(os);
3331 
3335 
3338 
3339  OperationPool opPool;
3340 
3341  for (int i = 0; i < fuNav.count(); i++) {
3342  const TTAMachine::FunctionUnit* fu = fuNav.item(i);
3343  for (int o = 0; o < fu->operationCount(); o++) {
3344  const std::string opName = fu->operation(o)->name();
3345  opNames.insert(StringTools::stringToUpper(opName));
3346  }
3347  }
3348 
3349  if (littleEndian_) {
3350  if (mach_.is64bit()) {
3351  opNames_["ST64fa"] = "ST64";
3352  opNames_["ST64fs"] = "ST64";
3353  opNames_["ST64ha"] = "ST64";
3354  opNames_["ST64hs"] = "ST64";
3355  opNames_["ST64da"] = "ST64";
3356  opNames_["ST64ds"] = "ST64";
3357 
3358  opNames_["LD64fa"] = "LD64";
3359  opNames_["LD64fs"] = "LD64";
3360  opNames_["LD64ha"] = "LD64";
3361  opNames_["LD64hs"] = "LD64";
3362  opNames_["LD64da"] = "LD64";
3363  opNames_["LD64ds"] = "LD64";
3364  }
3365 
3366  if (mach_.hasOperation("LD32")) {
3367  opNames_["LD32fr"] = "LD32";
3368  opNames_["LD32fi"] = "LD32";
3369 
3370  opNames_["LD32hr"] = "LD32";
3371  opNames_["LD32hi"] = "LD32";
3372 
3373  } else if (mach_.hasOperation("LDU32")) {
3374  opNames_["LD32fr"] = "LDU32";
3375  opNames_["LD32fi"] = "LDU32";
3376 
3377  opNames_["LD32hr"] = "LDU32";
3378  opNames_["LD32hi"] = "LDU32";
3379  }
3380  opNames_["ST32fr"] = "ST32";
3381  opNames_["ST32fi"] = "ST32";
3382 
3383  opNames_["ST32hr"] = "ST32";
3384  opNames_["ST32hi"] = "ST32";
3385 
3386  opNames_["ST16hr"] = "ST16";
3387  opNames_["ST16hi"] = "ST16";
3388  } else {
3389  opNames_["LDWfr"] = "LDW";
3390  opNames_["LDWfi"] = "LDW";
3391  opNames_["LDWhr"] = "LDW";
3392  opNames_["LDWhi"] = "LDW";
3393 
3394  opNames_["STWfr"] = "STW";
3395  opNames_["STWfi"] = "STW";
3396 
3397  opNames_["STWhr"] = "STW";
3398  opNames_["STWhi"] = "STW";
3399  opNames_["STHhr"] = "STH";
3400  opNames_["STHhi"] = "STH";
3401  }
3402 
3403  // Some global/address immediate if conversion fails
3404  // so commented out.
3405  // TODO: ^ up-to-date comment? ^
3406  if (hasConditionalMoves_) {
3407 
3408  if (mach_.is64bit()) {
3409  truePredOps_["MOV64ss"] = "PRED_TRUE_MOV64ss";
3410  falsePredOps_["MOV64ss"] = "PRED_FALSE_MOV64ss";
3411  }
3412 
3413  truePredOps_["MOVI32rr"] = "PRED_TRUE_MOVI32rr";
3414  falsePredOps_["MOVI32rr"] = "PRED_FALSE_MOVI32rr";
3415  truePredOps_["MOVI1rr"] = "PRED_TRUE_MOVI1rr";
3416  falsePredOps_["MOVI1rr"] = "PRED_FALSE_MOVI1rr";
3417  }
3418 
3419  OperationDAGSelector::OperationSet::const_iterator iter = opNames.begin();
3420  for (; iter != opNames.end(); iter++) {
3421  OperationDAGSelector::OperationSet::iterator r =
3422  requiredOps.find(*iter);
3423  if (r != requiredOps.end()) {
3424  requiredOps.erase(r);
3425  }
3426  Operation& op = opPool.operation((*iter).c_str());
3427  bool skipPattern = false;
3428 
3429  if (&op == &NullOperation::instance()) {
3430  continue;
3431  }
3432 
3433  // TODO: Allow multioutput (remove last or)
3434  if (!operationCanBeMatched(op)) {
3435  // TODO: write opeation def without graphs
3436  if (&op != &NullOperation::instance()) {
3437  skipPattern = true;
3438  if (Application::verboseLevel() > 0) {
3440  << "Skipped writing operation pattern for "
3441  << op.name() << endl;
3442  }
3443  } else {
3444  // NULL op - ignore
3445  continue;
3446  }
3447  }
3448 
3449  // TODO: remove this. For now MIMO operation patterns are not
3450  // supported by tablegen.
3451  if (op.numberOfOutputs() > 1) {
3452  skipPattern = true;
3453  continue;
3454  }
3455 
3456  if (op.isVectorOperation()) {
3458  writeVectorMemoryOperationDefs(os, op, skipPattern);
3459  } else if (isVectorBitwiseOperation(op)) {
3460  writeVectorBitwiseOperationDefs(os, op, skipPattern);
3461  } else {
3462  writeVectorOperationDefs(os, op, skipPattern);
3463  }
3464  } else {
3465  writeOperationDefs(os, op, skipPattern);
3466  }
3467  }
3468 
3476 
3477  // Call operations.
3479 
3480  // Hardware loop instructions
3481  writeHWLoopDef(os);
3482 
3483  // Emulated operations.
3484  for (iter = requiredOps.begin(); iter != requiredOps.end(); iter++) {
3485  const Operation& op = opPool.operation((*iter).c_str());
3486 
3487  if (&op == &NullOperation::instance()) {
3488  std::string msg = "Required OP '" + *iter + "' not found.";
3489  throw InvalidData(__FILE__, __LINE__, __func__, msg);
3490  }
3491 
3492  const OperationDAGSelector::OperationDAGList emulationDAGs =
3494 
3495  if (emulationDAGs.empty()) {
3498  Application::logStream() << "Warning: Operation '" << *iter
3499  << "' not supported." << endl;
3500  }
3501  } else {
3502  /// @note This todo marking is from TDGenSIMD
3503  // TODO: write all dags of operation (first as normal, the rest
3504  // as pattern)
3505  writeEmulationPattern(os, op, emulationDAGs.smallestNodeCount());
3506  }
3507  }
3508 
3511  if (mach_.is64bit()) {
3513  }
3514 
3516 
3517  writeMiscPatterns(os);
3522 }
3523 
3524 void TDGen::writeCallDefRegs(std::ostream& o) {
3525  for (unsigned i = 0; i < resRegNames_.size(); i++) {
3526  if (i > 0) o << ", ";
3527  o << resRegNames_[i];
3528  }
3529  for (unsigned i = 0; i < gprRegNames_.size(); i++) {
3530  o << ", " << gprRegNames_[i];
3531  }
3532 
3533  // call dest may call others which may mess up these
3534  for (unsigned i = 0; i < argRegNames_.size(); i++) {
3535  o << ", " << argRegNames_[i];
3536  }
3537 
3538  std::map<int, std::vector<RegisterInfo>>::const_iterator it;
3539  for (it = registers_.begin(); it != registers_.end(); ++it) {
3540  int regsWidth = it->first;
3541 
3542  const std::vector<RegisterInfo>& regs = it->second;
3543  TCEString baseClass = baseClasses_.find(regsWidth)->second;
3544 
3545  for (size_t i = 0; i < regs.size(); ++i) {
3546  // Don't declare <=32b registers again, it has been done in TDGen.
3547  if (regsWidth > maxScalarWidth_) {
3548  RegisterInfo reg = regs[i];
3549  o << ", " << reg.regName_;
3550  }
3551  }
3552  }
3553 }
3554 
3555 
3556 /**
3557  * Writes control flow instructions definitions and patterns
3558  */
3559 void
3561 
3562  writeCondBranchDefs(os);
3563 
3564  writeCallDef(os);
3565 }
3566 
3567 /**
3568  * Writes hwloop instructions and patterns.
3569  */
3570 void
3571 TDGen::writeHWLoopDef(std::ostream& os) {
3572  os << std::endl << "// Hardware loop instructions" << std::endl;
3573  if (mach_.controlUnit()->hasOperation("hwloop")) {
3574  os << "let isTerminator=1 in {" << std::endl
3575  << " def HWLOOPii : InstTCE<(outs), (ins i32imm0:$rIter, "
3576  "i32imm0:$rInstr), \"\", []>;"
3577  << std::endl
3578  << " def HWLOOPri : InstTCE<(outs), (ins i32imm0:$rIter, "
3579  "i32imm0:$rInstr), \"\", []>;"
3580  << std::endl
3581  << "}" << std::endl
3582  << "def : Pat<(int_set_loop_iterations i32imm0:$rIter), "
3583  "(HWLOOPii i32imm0:$rIter, 0)>;"
3584  << std::endl
3585  << "def : Pat<(int_set_loop_iterations R32IRegs:$rIter), "
3586  "(HWLOOPri R32IRegs:$rIter, 0)>;"
3587  << std::endl;
3588  opNames_["HWLOOPii"] = "hwloop";
3589  opNames_["HWLOOPri"] = "hwloop";
3590  }
3591 
3592  // Write loop jump pseudo
3593  os << "let isTerminator = 1 in {" << std::endl
3594  << " def LJUMP : InstTCE<(outs), (ins brtarget:$dst), \"\", []>;"
3595  << std::endl
3596  << "}" << std::endl
3597  << std::endl;
3598  opNames_["LJUMP"] = "PSEUDO";
3599 }
3600 
3601 /**
3602  * Writes instructions definitions and patterns for conditional branches.
3603  */
3604 void
3605 TDGen::writeCondBranchDefs(std::ostream& os) {
3606 
3607  auto cuOpset = MachineInfo::getOpset(*mach_.controlUnit());
3608 
3610 
3611  os << std::endl << "let isTerminator = 1, isBranch = 1 in {" << std::endl;
3612 
3613  if (cuOpset.count("JUMP") && opNames_.count("TCEBRCOND") == 0) {
3614  writeInstrDef(os, "TCEBRCOND", "",
3615  "GuardRegs:$gr, brtarget:$dst",
3616  "? $gr $dst -> jump.1;",
3617  "(brcond GuardRegs:$gr, bb:$dst)");
3618  os << std::endl;
3619  opNames_["TCEBRCOND"] = "?jump";
3620  }
3621 
3622  if (cuOpset.count("JUMP") && opNames_.count("TCEBRICOND") == 0) {
3623  writeInstrDef(os, "TCEBRICOND", "",
3624  "GuardRegs:$gr, brtarget:$dst",
3625  "! $gr $dst -> jump.1;",
3626  "(brcond (not GuardRegs:$gr), bb:$dst)");
3627  opNames_["TCEBRICOND"] = "!jump";
3628  }
3629  os << "}" << std::endl;
3630 
3631  // generate brcc pseudo jumps. these are split in llvmtcebuilder into
3632  // separate comparison and jump.
3634 
3635  if (!writePortGuardedJumpDefPair(os, "EQ", "NE")) {
3636  abortWithError("Required eq/ne op not found. please add to adf.");
3637  }
3638  if (!writePortGuardedJumpDefPair(os, "GT", "LE")) {
3639  abortWithError("Required gt/le op not found. please add to adf.");
3640  }
3641  if (!writePortGuardedJumpDefPair(os, "GTU", "LEU")) {
3642  abortWithError("Required gtu/leu op not found. please add to adf.");
3643  }
3644 
3645  // floating point ops are optional.
3646  writePortGuardedJumpDefPair(os, "EQF", "NEF", true);
3647  writePortGuardedJumpDefPair(os, "LEF", "GTF", true);
3648  writePortGuardedJumpDefPair(os, "LTF", "GEF", true);
3649 
3650  if (MachineInfo::supportsPortGuardedJump(mach_, false, "AND")) {
3651  writeInstrDef(os, "AND_JUMP", "",
3652  "R32IRegs:$cmp1, R32IRegs:$cmp2, brtarget:$dst", "",
3653  "(brcond (and R32IRegs:$cmp1, R32IRegs:$cmp2), bb:$dst)");
3654  } else {
3655  std::cerr << "Missing AND operation as true-guard source to jump." << std::endl;
3656  assert(false);
3657  }
3658 
3659  if (MachineInfo::supportsPortGuardedJump(mach_, false, "IOR")) {
3660  writeInstrDef(os, "IOR_JUMP", "",
3661  "R32IRegs:$cmp1, R32IRegs:$cmp2, brtarget:$dst", "",
3662  "(brcond (or R32IRegs:$cmp1, R32IRegs:$cmp2), bb:$dst)");
3663  } else {
3664  std::cerr << "Missing IOR operation as true-guard source to jump." << std::endl;
3665  assert(false);
3666  }
3667 
3668  os << std::endl << "let isTerminator = 1, isBranch = 1 in {" << std::endl;
3669 
3670  // dummy br(i)cond ops
3671  writeInstrDef(os, "TCEBRCOND", "",
3672  "GuardRegs:$gr, brtarget:$dst",
3673  "? $gr $dst -> jump.1;",
3674  "");
3675  os << std::endl;
3676 
3677  writeInstrDef(os, "TCEBRICOND", "",
3678  "GuardRegs:$gr, brtarget:$dst",
3679  "? $gr $dst -> jump.1;",
3680  "");
3681  os << std::endl;
3682 
3683 
3684  os << "}" << std::endl;
3685 
3686  os << "def: Pat<(brcc SETLT, R32IRegs:$cmp1, R32IRegs:$cmp2, bb:$dst),"
3687  << " (GT_JUMP R32IRegs:$cmp2, R32IRegs:$cmp1, brtarget:$dst)>;" << std::endl;
3688 
3689 
3690  os << "def: Pat<(brcc SETGE, R32IRegs:$cmp1, R32IRegs:$cmp2, bb:$dst),"
3691  << " (LE_JUMP R32IRegs:$cmp2, R32IRegs:$cmp1, brtarget:$dst)>;" << std::endl;
3692 
3693  os << "def: Pat<(brcc SETULT, R32IRegs:$cmp1, R32IRegs:$cmp2, bb:$dst),"
3694  << " (GTU_JUMP R32IRegs:$cmp2, R32IRegs:$cmp1, brtarget:$dst)>;" << std::endl;
3695 
3696 
3697  os << "def: Pat<(brcc SETUGE, R32IRegs:$cmp1, R32IRegs:$cmp2, bb:$dst),"
3698  << " (LEU_JUMP R32IRegs:$cmp2, R32IRegs:$cmp1, brtarget:$dst)>;" << std::endl;
3699 
3700 
3701  opNames_["AND_JUMP"] = "and+?jump";
3702  opNames_["IOR_JUMP"] = "ior+?jump";
3703 
3704  // conditional jumps without guard.
3705  } else {
3706 
3707  os << std::endl << "let isTerminator = 1, isBranch = 1 in {" << std::endl;
3708 
3709  if (cuOpset.count("BNZ1")) {
3710  // TODO: Check if has R1 regs or not!
3711 
3712  writeInstrDef(os, "TCEBRCOND", "", "R32IRegs:$gr, brtarget:$dst",
3713  "", "(brcond R32IRegs:$gr, bb:$dst)");
3714  os << std::endl;
3715  opNames_["TCEBRCOND"] = "BNZ1";
3716  } else {
3717  if (cuOpset.count("BNZ")) {
3718  writeInstrDef(os, "TCEBRCOND", "", "R32IRegs:$gr, brtarget:$dst",
3719  "", "(brcond R32IRegs:$gr, bb:$dst)");
3720  os << std::endl;
3721  opNames_["TCEBRCOND"] = "BNZ";
3722  } else {
3723  std::cerr << "Does not have guarded jumps or neither bnz or bnz1" << std::endl;
3724  }
3725  }
3726 
3727  if (cuOpset.count("BZ1")) {
3728  // TODO: Check if has R1 regs or not!
3729 
3730  writeInstrDef(os, "TCEBRICOND", "", "R32IRegs:$gr, brtarget:$dst",
3731  "", "(brcond (not R32IRegs:$gr), bb:$dst)");
3732  os << std::endl;
3733  opNames_["TCEBRICOND"] = "BZ1";
3734  } else {
3735  if (cuOpset.count("BZ")) {
3736  writeInstrDef(os, "TCEBRICOND", "", "R32IRegs:$gr, brtarget:$dst",
3737  "", "(brcond (not R32IRegs:$gr), bb:$dst)");
3738  os << std::endl;
3739  opNames_["TCEBRICOND"] = "BZ";
3740  } else {
3741  std::cerr << "Does not have guarded jumps or neither bz or bz1" << std::endl;
3742  }
3743  }
3744 
3745  if (cuOpset.count("BEQ")) {
3746  writeInstrDef(os, "TCEBREQrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3747  "", "(brcond (i32 (seteq R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3748  opNames_["TCEBREQrr"] = "BEQ";
3749  writeInstrDef(os, "TCEBREQri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3750  "", "(brcond (i32 (seteq R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3751  opNames_["TCEBREQri"] = "BEQ";
3752  }
3753 
3754  if (cuOpset.count("BNE")) {
3755  writeInstrDef(os, "TCEBRNErr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3756  "", "(brcond (i32 (setne R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3757  opNames_["TCEBRNErr"] = "BNE";
3758  writeInstrDef(os, "TCEBRNEri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3759  "", "(brcond (i32 (setne R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3760  opNames_["TCEBRNEri"] = "BNE";
3761  }
3762 
3763  if (cuOpset.count("BGT")) {
3764  writeInstrDef(os, "TCEBRGTrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3765  "", "(brcond (i32 (setgt R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3766  opNames_["TCEBRGTrr"] = "BGT";
3767  writeInstrDef(os, "TCEBRGTri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3768  "", "(brcond (i32 (setgt R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3769  opNames_["TCEBRGTri"] = "BGT";
3770  }
3771 
3772  if (cuOpset.count("BGTU")) {
3773  writeInstrDef(os, "TCEBRGTUrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3774  "", "(brcond (i32 (setugt R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3775  opNames_["TCEBRGTUrr"] = "BGTU";
3776  writeInstrDef(os, "TCEBRGTUri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3777  "", "(brcond (i32 (setugt R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3778  opNames_["TCEBRGTUri"] = "BGTU";
3779  }
3780 
3781  if (cuOpset.count("BLT")) {
3782  writeInstrDef(os, "TCEBRLTrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3783  "", "(brcond (i32 (setlt R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3784  opNames_["TCEBRLTrr"] = "BLT";
3785  writeInstrDef(os, "TCEBRLTri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3786  "", "(brcond (i32 (setlt R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3787  opNames_["TCEBRLTri"] = "BLT";
3788  }
3789 
3790  if (cuOpset.count("BLTU")) {
3791  writeInstrDef(os, "TCEBRLTUrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3792  "", "(brcond (i32 (setult R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3793  opNames_["TCEBRLTUrr"] = "BLTU";
3794  writeInstrDef(os, "TCEBRLTUri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3795  "", "(brcond (i32 (setult R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3796  opNames_["TCEBRLTUri"] = "BLTU";
3797  }
3798 
3799  if (cuOpset.count("BLE")) {
3800  writeInstrDef(os, "TCEBRLErr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3801  "", "(brcond (i32 (setle R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3802  opNames_["TCEBRLErr"] = "BLE";
3803  writeInstrDef(os, "TCEBRLEri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3804  "", "(brcond (i32 (setle R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3805  opNames_["TCEBRLEri"] = "BLE";
3806  }
3807 
3808  if (cuOpset.count("BLEU")) {
3809  writeInstrDef(os, "TCEBRLEUrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3810  "", "(brcond (i32 (setule R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3811  opNames_["TCEBRLEUrr"] = "BLEU";
3812  writeInstrDef(os, "TCEBRLEUri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3813  "", "(brcond (i32 (setule R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3814  opNames_["TCEBRLEUri"] = "BLEU";
3815  }
3816 
3817  if (cuOpset.count("BGE")) {
3818  writeInstrDef(os, "TCEBRGErr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3819  "", "(brcond (i32 (setge R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3820  opNames_["TCEBRGErr"] = "BGE";
3821  writeInstrDef(os, "TCEBRGEri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3822  "", "(brcond (i32 (setge R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3823  opNames_["TCEBRGEri"] = "BGE";
3824  }
3825 
3826  if (cuOpset.count("BGEU")) {
3827  writeInstrDef(os, "TCEBRGEUrr", "", "R32IRegs:$c1, R32IRegs:$c2, brtarget:$dst",
3828  "", "(brcond (i32 (setuge R32IRegs:$c1, R32IRegs:$c2)), bb:$dst)");
3829  opNames_["TCEBRGEUrr"] = "BGEU";
3830  writeInstrDef(os, "TCEBRGEUri", "", "R32IRegs:$c1, i32imm:$c2, brtarget:$dst",
3831  "", "(brcond (i32 (setuge R32IRegs:$c1, i32MoveImm:$c2)), bb:$dst)");
3832  opNames_["TCEBRGEUri"] = "BGEU";
3833  }
3834 
3835  os << "}" << std::endl;
3836  }
3837 }
3838 
3839 
3840 
3842  std::ostream& os, const TCEString& tceop1, const TCEString& tceop2, bool fp) {
3843 
3844  TCEString llvmop1 = TDGen::llvmOperationName(tceop1).upper();
3845  TCEString llvmop2 = TDGen::llvmOperationName(tceop2).upper();
3846 
3847  TCEString regclass = fp ? "R32FPRegs" : "R32IRegs";
3848  if (MachineInfo::supportsPortGuardedJump(mach_, false, tceop1) ||
3850 
3851  os << std::endl << "let isTerminator = 1, isBranch = 1 in {" << std::endl;
3852 
3853  writeInstrDef(os, tceop1+"_JUMP", "",
3854  regclass + ":$cmp1, "+ regclass + ":$cmp2, brtarget:$dst", "",
3855  "(brcc "+ llvmop1 +", "+ regclass + ":$cmp1, " + regclass + ":$cmp2, bb:$dst)");
3856 
3857  os << "}" << std::endl;
3858  if (MachineInfo::supportsPortGuardedJump(mach_, false, tceop1)) {
3859  opNames_[tceop1 + "_JUMP"] = tceop1 + "+?jump";
3860  } else {
3861  opNames_[tceop1 + "_JUMP"] = tceop2 + "+!jump";
3862  }
3863  } else {
3864  std::cerr << "Missing "<< tceop1 << " operation as true-guard source"
3865  << " or " << tceop2 << " operation as invarted guard source to jump." << std::endl;
3866  return false;
3867  }
3868 
3869  if (MachineInfo::supportsPortGuardedJump(mach_, true, tceop1) ||
3870  MachineInfo::supportsPortGuardedJump(mach_, false, tceop2)) {
3871 
3872  os << std::endl << "let isTerminator = 1, isBranch = 1 in {" << std::endl;
3873 
3874 
3875  writeInstrDef(os, tceop2+"_JUMP", "",
3876  regclass + ":$cmp1, "+ regclass + ":$cmp2, brtarget:$dst", "",
3877  "(brcc "+ llvmop2 +", "+ regclass + ":$cmp1, " + regclass + ":$cmp2, bb:$dst)");
3878 
3879  os << "}" << std::endl;
3880 
3881  if (MachineInfo::supportsPortGuardedJump(mach_, false, tceop2)) {
3882  opNames_[tceop2 + "_JUMP"] = tceop2 + "+?jump";
3883  } else {
3884  opNames_[tceop2 + "_JUMP"] = tceop1 + "+!jump";
3885  }
3886  } else {
3887  std::cerr << "Missing " << tceop2 << " operation as true-guard source"
3888  << " or " << tceop1 << " operation as inverted guard source to jump."
3889  << std::endl;
3890  return false;
3891  }
3892  return true;
3893 }
3894 
3895 /**
3896  * Writes .td pattern for the call instruction(s) to the output stream.
3897  */
3898 void
3899 TDGen::writeCallDef(std::ostream& o) {
3900  o << "let ";
3901 
3902  if (!argRegNames_.empty()) {
3903  o << "Uses = [";
3904  for (unsigned i = 0; i < argRegNames_.size(); i++) {
3905  if (i > 0) o << ", ";
3906  o << argRegNames_[i];
3907  }
3908  o << "],";
3909  }
3910 
3911  o << "hasDelaySlot = 1, isCall = 1,";
3912  o << "Defs = [";
3913 
3914  writeCallDefRegs(o);
3915 
3916  o << "] in {" << std::endl;
3917  o << "def CALL : InstTCE<(outs), (ins calltarget:$dst),";
3918  o << "\"$dst -> call.1;\", []>;" << std::endl;
3919 
3920  o << "def CALL_MEMrr : InstTCE<(outs), (ins MEMrr:$ptr),";
3921  o << "\"$ptr -> call.1;\", [(call ADDRrr:$ptr)]>;" << std::endl;
3922 
3923  o << "def CALL_MEMri : InstTCE<(outs), (ins MEMri:$ptr),";
3924  o << "\"$ptr -> call.1;\", [(call ADDRri:$ptr)]>;" << std::endl;
3925  o << "}" << std::endl;
3926 
3927  o << "def : Pat<(call tglobaladdr:$dst), (CALL tglobaladdr:$dst)>;"
3928  << std::endl;
3929 
3930  o << "def : Pat<(call texternalsym:$dst), (CALL texternalsym:$dst)>;"
3931  << std::endl;
3932 
3933 }
3934 
3935 /**
3936  * Generates required function definitions for the backend plugin.
3937  *
3938  * @param o Output stream to write the c++ code to.
3939  */
3940 void
3941 TDGen::writeBackendCode(std::ostream& o) {
3942  // Register & operation info table initialization
3943 
3944  o << "void" << std::endl
3945  << "GeneratedTCEPlugin::initialize() {" << std::endl;
3946 
3947  // operation names
3948  std::map<std::string, std::string>::const_iterator iter =
3949  opNames_.begin();
3950 
3951  for (; iter != opNames_.end(); iter++) {
3952  o << " opNames_[TCE::" << (*iter).first
3953  << "] = \"" << (*iter).second
3954  << "\";" << std::endl;
3955  }
3956 
3957  for (iter = truePredOps_.begin(); iter != truePredOps_.end(); iter++) {
3958  o << " truePredOps_[TCE::" << (*iter).first
3959  << "] = TCE::" << (*iter).second
3960  << ";" << std::endl;
3961  }
3962 
3963  for (iter = falsePredOps_.begin(); iter != falsePredOps_.end(); iter++) {
3964  o << " falsePredOps_[TCE::" << (*iter).first
3965  << "] = TCE::" << (*iter).second
3966  << ";" << std::endl;
3967  }
3968 
3969  // Register names & indices
3970  std::map<std::string, RegInfo>::const_iterator rIter = regs_.begin();
3971  rIter = regs_.begin();
3972  for (; rIter != regs_.end(); rIter++) {
3973  const RegInfo& regInfo = rIter->second;
3974  o << " regNames_[TCE::" << (*rIter).first
3975  << "] = \"" << regInfo.rf
3976  << "\";" << std::endl;
3977 
3978  o << " regIndices_[TCE::" << (*rIter).first
3979  << "] = " << regInfo.idx
3980  << ";" << std::endl;
3981 
3982  TCEString ttaRegName = regInfo.rf + "." + std::to_string(regInfo.idx);
3983  o << " ttallvmRegMap_[\"" << ttaRegName << "\"] = "
3984  << "TCE::" << (*rIter).first << ";" << std::endl;
3985  }
3986 
3987  // Supported stack access opcodes
3988  o << std::endl;
3989  for (std::string opName : supportedStackAccessOperations(mach_)) {
3990  o << " validStackAccessOperations_.insert(\"" << opName << "\");"
3991  << std::endl;
3992  }
3993 
3994  // Target machine .adf XML string.
3995  o << std::endl;
3996  std::string adfXML;
3997  ADFSerializer serializer;
3998  serializer.setDestinationString(adfXML);
3999  serializer.writeMachine(mach_);
4000  o << " adfXML_ = \"";
4001  for (unsigned int i = 0; i < adfXML.length(); i++) {
4002  if (adfXML[i] == '"') o << "\\\"";
4003  else if (adfXML[i] == '\n') o << "\"\n\"";
4004  else o << adfXML[i];
4005  }
4006  o << "\";" << std::endl;
4007 
4008 
4009  // data address space
4012  std::string asName = "";
4013  for (int i = 0; i < nav.count(); i++) {
4014  if (nav.item(i) != mach_.controlUnit() &&
4015  nav.item(i)->addressSpace() != NULL) {
4016  asName = nav.item(i)->addressSpace()->name();
4017  }
4018  }
4019 
4020  if (asName == "") {
4021  std::string msg = "Couldn't determine data address space.";
4022  throw InvalidData(__FILE__, __LINE__, __func__, msg);
4023  }
4024  o << " dataASName_ = \"" << asName << "\";" << std::endl;
4025 
4026  o << "}" << std::endl;
4027 
4028 
4029  bool hasSDIV = false;
4030  bool hasUDIV = false;
4031  bool hasSREM = false;
4032  bool hasUREM = false;
4033  bool hasMUL = false;
4034  bool hasROTL = false;
4035  bool hasROTR = false;
4036  bool hasSXHW = false;
4037  bool hasSXQW = false;
4038  bool hasSQRTF = false;
4039  bool hasSHR = false;
4040  bool hasSHRU = false;
4041  bool hasSHL = false;
4042  bool has8bitLoads = false;
4043  bool has16bitLoads = false;
4044 // bool has32bitLoads = false; // used only for 64-bit system
4045 
4048 
4049  for (int i = 0; i < fuNav.count(); i++) {
4050  const TTAMachine::FunctionUnit* fu = fuNav.item(i);
4051  for (int o = 0; o < fu->operationCount(); o++) {
4052  const std::string opName =
4054 
4055  if (mach_.is64bit()) {
4056  if (opName == "div64") hasSDIV = true;
4057  if (opName == "divu64") hasUDIV = true;
4058  if (opName == "mod64") hasSREM = true;
4059  if (opName == "modu64") hasUREM = true;
4060  if (opName == "mul64") hasMUL = true;
4061  if (opName == "rotl64") hasROTL = true;
4062  if (opName == "rotr64") hasROTR = true;
4063  if (opName == "sxh64") hasSXHW = true;
4064  if (opName == "sxq64") hasSXQW = true;
4065  if (opName == "shr64") hasSHR = true;
4066  if (opName == "shru64") hasSHRU = true;
4067  if (opName == "shl64") hasSHL = true;
4068  } else {
4069  if (opName == "div") hasSDIV = true;
4070  if (opName == "divu") hasUDIV = true;
4071  if (opName == "mod") hasSREM = true;
4072  if (opName == "modu") hasUREM = true;
4073  if (opName == "mul") hasMUL = true;
4074  if (opName == "rotl") hasROTL = true;
4075  if (opName == "rotr") hasROTR = true;
4076  if (opName == "sxhw") hasSXHW = true;
4077  if (opName == "sxqw") hasSXQW = true;
4078  if (opName == "shr") hasSHR = true;
4079  if (opName == "shru") hasSHRU = true;
4080  if (opName == "shl") hasSHL = true;
4081  }
4082  if (opName == "sqrtf") hasSQRTF = true;
4083 
4084  if (littleEndian_) {
4085  if (opName == "ld16" || opName == "ldu16") {
4086  has16bitLoads = true;
4087  } else if(opName == "ld8" || opName == "ldu8") {
4088  has8bitLoads = true;
4089 // } else if (opName == "ld32" || opName == "ldu32") {
4090 // has32bitLoads = true;
4091  }
4092  } else {
4093  if (opName == "ldh" || opName == "ldhu") {
4094  has16bitLoads = true;
4095  } else if (opName == "ldq" || opName == "ldqu") {
4096  has8bitLoads = true;
4097 // } else if (opName == "ldw") {
4098 // has32bitLoads = true;
4099  }
4100  }
4101  }
4102  }
4103 
4104  o << "bool GeneratedTCEPlugin::hasSDIV() const { return "
4105  << hasSDIV << "; }" << std::endl
4106  << "bool GeneratedTCEPlugin::hasUDIV() const { return "
4107  << hasUDIV << "; }" << std::endl
4108  << "bool GeneratedTCEPlugin::hasSREM() const { return "
4109  << hasSREM << "; }" << std::endl
4110  << "bool GeneratedTCEPlugin::hasUREM() const { return "
4111  << hasUREM << "; }" << std::endl
4112  << "bool GeneratedTCEPlugin::hasMUL() const { return "
4113  << hasMUL << "; }" << std::endl
4114  << "bool GeneratedTCEPlugin::hasROTL() const { return "
4115  << hasROTL << "; }" << std::endl
4116  << "bool GeneratedTCEPlugin::hasROTR() const { return "
4117  << hasROTR << "; }" << std::endl
4118  << "bool GeneratedTCEPlugin::hasSXHW() const { return "
4119  << hasSXHW << "; }" << std::endl
4120  << "bool GeneratedTCEPlugin::hasSXQW() const { return "
4121  << hasSXQW << "; }" << std::endl
4122  << "bool GeneratedTCEPlugin::hasSQRTF() const { return "
4123  << hasSQRTF << "; }" << std::endl
4124  << "bool GeneratedTCEPlugin::hasSHR() const { return "
4125  << hasSHR << "; }" << std::endl
4126  << "bool GeneratedTCEPlugin::hasSHL() const { return "
4127  << hasSHL << "; }" << std::endl
4128  << "bool GeneratedTCEPlugin::hasSHRU() const { return "
4129  << hasSHRU << ";}" << std::endl
4130  << "bool GeneratedTCEPlugin::has8bitLoads() const { return "
4131  << has8bitLoads << ";}" << std::endl
4132  << "bool GeneratedTCEPlugin::has16bitLoads() const { return "
4133  << has16bitLoads << ";}" << std::endl;
4134 // << "bool GeneratedTCEPlugin::has32bitLoads() const { return "
4135 // << has32bitLoads << ";}" << std::endl
4136 
4137  o << "int GeneratedTCEPlugin::maxVectorSize() const { return "
4138  << maxVectorSize_ << "; }" << std::endl;
4139 
4140  // create dummy version here
4142 
4151 
4160 }
4161 
4163  std::ostream& os) const {
4164  os << "void TCERegisterInfo::setReservedVectorRegs("
4165  << "llvm::BitVector& reserved) const {" << std::endl;
4166 
4167  std::set<TCEString> processedRegs;
4168  for (auto rcIt : vRegClasses_) {
4169  const RegisterClass& regClass = rcIt.second;
4170 
4171  int width = regClass.valueType().width();
4172  if (regClass.numberOfRegisters() > 0) {
4173  const TCEString& name = regClass.registerInfo(0).regName_;
4174  if (processedRegs.find(name) == processedRegs.end() &&
4175  width > maxScalarWidth_) {
4176  processedRegs.insert(name);
4177  os << "reserved.set(TCE::" << name << ");" << std::endl;
4178  }
4179  }
4180  }
4181  os << "}" << std::endl;
4182 }
4183 
4184 /**
4185  * Writes a top level TCE.td file which includes generated .td definitions.
4186  *
4187  * @param o Output stream to the file.
4188  */
4189 void
4190 TDGen::writeTopLevelTD(std::ostream& o) {
4191  o << "include \"Target.td\"" << std::endl;
4192  o << "include \"TCEItinerary.td\"" << std::endl;
4193  o << "include \"GenRegisterInfo.td\"" << std::endl;
4194  o << "include \"GenTCEInstrFormats.td\"" << std::endl;
4195  o << "include \"TCEInstrInfo.td\"" << std::endl;
4196  o << "include \"GenCallingConv.td\"" << std::endl;
4197  o << "def TCEInstrInfo : InstrInfo { }" << std::endl;
4198  o << "class Proc<string Name, SchedMachineModel Model,";
4199  o << " list<SubtargetFeature> Features>";
4200  o << " : ProcessorModel<Name, Model, Features>;";
4201  o << std::endl;
4202  o << "def : Proc<\"generic\", TCEModelV0,[]>;";
4203  o << std::endl;
4204  o << "def TCE : Target { let InstructionSet = TCEInstrInfo; }"
4205  << std::endl;
4206 }
4207 
4208 /**
4209  * Writes details about instruction formatting
4210  *
4211  * @param o Output stream to the file.
4212  */
4213 void
4214 TDGen::writeInstrFormats(std::ostream& o) {
4215  o << "//" << endl;
4216  o << "// TCE Instruction formats." << endl;
4217  o << "//" << endl;
4218  o << "// Only one simple format is currently available" << endl;
4219  o << "//" << endl;
4220  o << "// Automatically generated file, do not edit!" << endl;
4221  o << "//" << endl;
4222  o << "" << endl;
4223  o << "class InstTCE<dag outOps, dag inOps, string asmstr," << endl;
4224  o << " list<dag> pattern = []," << endl;
4225  o << " InstrItinClass itin = IT_FU>" << endl;
4226  o << " : Instruction {" << endl;
4227  o << " let Namespace = \"TCE\";" << endl;
4228  o << " dag InOperandList = inOps;" << endl;
4229  o << " dag OutOperandList = outOps;" << endl;
4230  o << " let AsmString = asmstr;" << endl;
4231  o << " let Pattern = pattern;" << endl;
4232  o << " let Itinerary = itin;" << endl;
4233  o << "}" << endl;
4234  o << "" << endl;
4235  o << "class Pseudo<dag outOps, dag inOps," << endl;
4236  o << " string asmstr, list<dag> pattern>" << endl;
4237  o << " : InstTCE<outOps, inOps, asmstr, pattern>;" << endl;
4238 }
4239 
4240 /*
4241  * Operand type characters defined by this TD generator:
4242  * a = Boolean vector
4243  * b = Boolean/predicate register
4244  * c
4245  * d
4246  * e = Float vector register
4247  * f = Float32 register
4248  * g = Half float vector register
4249  * h = Float16 register
4250  * i = Immediate integer
4251  * j = immediate boolean
4252  * k = immediate float?
4253  * l = immediate float16?
4254  * p
4255  * q
4256  * r = integer Register
4257  * s
4258  * t
4259  * u
4260  * y
4261  * z
4262  */
4263 /**
4264  * Writes scalar operation definition(s).
4265  *
4266  * @param o Output stream to write the definition to.
4267  * @param op Operation to write definition for.
4268  * @param skipPattern True, if skip pattern generation.
4269  */
4270 void
4272  std::ostream& o,
4273  Operation& op,
4274  bool skipPattern) {
4275 
4276  std::string attrs;
4277 
4278  // These white listed operations have mayLoad/mayStore flag
4279  // inferred from the llvm pattern and declaring it
4280  // explicitly will display warning in tablegen.
4281  if (op.name() != "LDQ" && op.name() != "LDQU" &&
4282  op.name() != "LDH" && op.name() != "LDHU" &&
4283  op.name() != "LDW" && op.name() != "LDD" &&
4284  op.name() != "STQ" && op.name() != "STH" &&
4285  op.name() != "STW" && op.name() != "STD" &&
4286  op.name() != "ALDQ" && op.name() != "ALDQU" &&
4287  op.name() != "ALDH" && op.name() != "ALDHU" &&
4288  op.name() != "ALDW" && op.name() != "ALDD" &&
4289  op.name() != "ASTQ" && op.name() != "ASTH" &&
4290  op.name() != "ASTW" && op.name() != "ASTD" &&
4291 
4292  op.name() != "LD8" && op.name() != "LDU8" &&
4293  op.name() != "LD16" && op.name() != "LDU16" &&
4294  op.name() != "LD32" && op.name() != "LDU32" &&
4295  op.name() != "LD64" &&
4296  op.name() != "ST8" && op.name() != "ST16" &&
4297  op.name() != "ST32" && op.name() != "ST64" &&
4298  op.name() != "ALD8" && op.name() != "ALDU8" &&
4299  op.name() != "ALD16" && op.name() != "ALDU16" &&
4300  op.name() != "ALD32" && op.name() != "ALDU32" &&
4301  op.name() != "ALD64" &&
4302  op.name() != "AST8" && op.name() != "AST16" &&
4303  op.name() != "AST32" && op.name() != "AST64" &&
4304  op.name() != "CAS") {
4305 
4306  if (op.readsMemory()) attrs += " mayLoad = 1";
4307  if (op.readsMemory() && op.writesMemory()) attrs += ", ";
4308  if (op.writesMemory()) attrs += " mayStore = 1";
4309  }
4310 
4311  // no bool outs for some operatios
4312  if (op.name() == "CFI" || op.name() == "CFIU") {
4313  writeOperationDef(o, op, "rf", attrs, skipPattern);
4314  return;
4315  }
4316 
4317  if (op.name() == "CDL" || op.name() == "CDLU") {
4318  writeOperationDef(o, op, "sd", attrs, skipPattern);
4319  return;
4320  }
4321 
4322  if (op.name() == "CLD" || op.name() == "CLDU") {
4323  writeOperationDef(o, op, "ds", attrs, skipPattern);
4324  return;
4325  }
4326 
4327  // no bool outs for some operatios
4328  if (op.name() == "CFD") {
4329  writeOperationDef(o, op, "df", attrs, skipPattern);
4330  return;
4331  }
4332 
4333  // no bool outs for some operatios
4334  if (op.name() == "CDF") {
4335  writeOperationDef(o, op, "fd", attrs, skipPattern);
4336  return;
4337  }
4338 
4339  // rotations are allways n x n -> n bits.
4340  if (op.name() == "ROTL" || op.name() == "ROTR" ||
4341  op.name() == "SHL" || op.name() == "SHR" || op.name() == "SHRU") {
4342  writeOperationDefs(o, op, "rrr", attrs, skipPattern);
4343  return;
4344  }
4345 
4346  if (op.name() == "SXHW" || op.name() == "SXQW") {
4347  writeOperationDef(o, op, "rr", attrs, skipPattern);
4348  return;
4349  }
4350 
4351  if (op.name() == "SXW64" || op.name() == "ZXW64") {
4352  writeOperationDef(o, op, "ss", attrs, skipPattern);
4353  return;
4354  }
4355 
4356  // these can have 1-bit inputs
4357  // TODO: this is lacking some 64-bit ops??
4358  if (op.name() == "XOR" || op.name() == "IOR" || op.name() == "AND" ||
4359  op.name() == "ANDN" || op.name() == "ADD" || op.name() == "SUB" ||
4360  op.name() == "XOR64" || op.name() == "IOR64" || op.name() == "AND64") {
4361  writeOperationDefs(o, op, "bbb", attrs, skipPattern);
4362  }
4363 
4364  if (op.name() == "SELECT") {
4365  if (!hasConditionalMoves_) {
4366  writeOperationDef(o, op, "rrrb", attrs, skipPattern);
4367  writeOperationDef(o, op, "riib", attrs, skipPattern);
4368  writeOperationDef(o, op, "rrib", attrs, skipPattern);
4369  writeOperationDef(o, op, "rirb", attrs, skipPattern);
4370  writeOperationDef(o, op, "bbbb", attrs, skipPattern);
4371  writeOperationDef(o, op, "bjjb", attrs, skipPattern);
4372  writeOperationDef(o, op, "bjbb", attrs, skipPattern);
4373  writeOperationDef(o, op, "bbjb", attrs, skipPattern);
4374  // TODO: what about floating-point values?
4375  writeOperationDef(o, op, "fffb", attrs, skipPattern);
4376  writeOperationDef(o, op, "hhhb", attrs, skipPattern);
4377 
4378  // ADFs with boolan values in GPRs
4379  writeOperationDef(o, op, "rrrr", attrs, skipPattern);
4380  writeOperationDef(o, op, "riir", attrs, skipPattern);
4381  writeOperationDef(o, op, "rrir", attrs, skipPattern);
4382  writeOperationDef(o, op, "rirr", attrs, skipPattern);
4383  writeOperationDef(o, op, "bbbr", attrs, skipPattern);
4384  writeOperationDef(o, op, "bjjr", attrs, skipPattern);
4385  writeOperationDef(o, op, "bjbr", attrs, skipPattern);
4386  writeOperationDef(o, op, "bbjr", attrs, skipPattern);
4387  // TODO: what about floating-point values?
4388  writeOperationDef(o, op, "fffr", attrs, skipPattern);
4389  writeOperationDef(o, op, "hhhr", attrs, skipPattern);
4390 
4391  hasSelect_ = true;
4392  return;
4393  } else {
4394  std::cerr << "The target architecture has both"
4395  << "conditional moves and select instruction."
4396  << "Ignoring select and using conditional moves instead"
4397  << std::endl;
4398  return;
4399  }
4400  }
4401 
4402  // store likes this. store immediate to immediate address
4403  if (op.numberOfInputs() == 2 && op.numberOfOutputs() == 0) {
4404  Operand& operand1 = op.operand(1);
4405  Operand& operand2 = op.operand(2);
4406  /// @note This todo marking is from TDGen.
4407  // TODO: add an else branch here for float immediates
4408  if ((operand1.type() == Operand::UINT_WORD ||
4409  operand1.type() == Operand::SINT_WORD ||
4410  operand1.type() == Operand::RAW_DATA) &&
4411  (operand2.type() == Operand::UINT_WORD ||
4412  operand2.type() == Operand::SINT_WORD ||
4413  operand2.type() == Operand::RAW_DATA)) {
4414 
4415  if (mach_.is64bit()) {
4416  writeOperationDef(o, op, "aa", attrs, skipPattern);
4417  } else {
4418  writeOperationDef(o, op, "ii", attrs, skipPattern);
4419  }
4420  }
4421  }
4422 
4423  std::string operandTypes = createDefaultOperandTypeString(op);
4424  // this the ordinary def
4425 
4426  // then try with immediates.
4427  /// @note This todo marking is from TDGen.
4428  // TODO: this should be 2^n loop instead of n loop, to get
4429  // all permutations.
4430 
4431  writeOperationDefs(o, op, operandTypes, attrs, skipPattern);
4432 
4433  // then with boolean outs, and vector versions.
4434  if (op.numberOfOutputs() == 1 && !op.readsMemory()) {
4435  Operand& outOperand = op.operand(op.numberOfInputs()+1);
4436  if (outOperand.type() == Operand::UINT_WORD ||
4437  outOperand.type() == Operand::SINT_WORD ||
4438  outOperand.type() == Operand::ULONG_WORD ||
4439  outOperand.type() == Operand::SLONG_WORD) {
4440 
4441  // 32/64 to 1-bit operations
4442  operandTypes[0] = OT_REG_BOOL;
4443  writeOperationDefs(o, op, operandTypes, attrs, skipPattern);
4444  }
4445 
4446  // create vector versions.
4447  }
4448 }
4449 
4451  switch(c) {
4452  case TDGen::OT_REG_LONG:
4453  return TDGen::OT_IMM_LONG;
4454  case TDGen::OT_REG_INT:
4455  return TDGen::OT_IMM_INT;
4456  case TDGen::OT_REG_BOOL:
4457  return TDGen::OT_IMM_BOOL;
4458  case TDGen::OT_REG_FP:
4459  return TDGen::OT_IMM_FP;
4460  case TDGen::OT_REG_HFP:
4461  return TDGen::OT_IMM_HFP;
4462  default:
4463  return 0;
4464  }
4465 }
4466 
4467 /**
4468  * Writes operation defs for single operation, with different immediate params.
4469  *
4470  * @param o Output stream to write the definition to.
4471  * @param op Operation to write definition for.
4472  * @param operandTypes value types of operands.
4473  */
4474 void
4476  std::ostream& o, Operation& op, const std::string& operandTypes,
4477  const std::string& attrs, bool skipPattern, std::string backendPrefix) {
4478 
4479  // first without imms.
4480  writeOperationDef(o, op, operandTypes, attrs, skipPattern, backendPrefix);
4481 
4482  for (int i = 0; i < op.numberOfInputs(); i++) {
4483  bool canSwap = false;
4484 
4485  // those ops SHOULD be can-swap but are not. kludge-fix.
4486  // consider making them can-swap.
4487  if (op.name() == "ALDQ" || op.name() == "ALDQU" ||
4488  op.name() == "ALDH" || op.name() == "ALDHU" ||
4489  op.name() == "ALDW" || op.name() == "ALDD" ||
4490  op.name() == "ASTQ" || op.name() == "ASTH" ||
4491  op.name() == "ASTW" || op.name() == "ASTD" ||
4492 
4493  op.name() == "ALD8" || op.name() == "ALDU8" ||
4494  op.name() == "ALD16"|| op.name() == "ALDU16" ||
4495  op.name() == "ALD32"|| op.name() == "ALD64" ||
4496  op.name() == "AST8" || op.name() == "AST16" ||
4497  op.name() == "AST32"|| op.name() == "AST64") {
4498  canSwap = true;
4499  }
4500 
4501  for (int j = i+1 ; j < op.numberOfInputs(); j++) {
4502  if (op.canSwap(i+1, j+1)) {
4503  canSwap = true;
4504  break;
4505  }
4506  }
4507  // setcc of LLVM is not commutative and get confused if we don't generate
4508  // a pattern with immediate elsewhere than the last operand
4509  canSwap = canSwap && !(op.name().upper() == "EQ" || op.name().upper() == "NE");
4510 
4511  if (!canSwap) {
4512  std::string opTypes = operandTypes;
4513  char& c = opTypes[i + op.numberOfOutputs()];
4515  if (c) {
4516  writeOperationDef(o, op, opTypes, attrs, skipPattern, backendPrefix);
4517  }
4518  }
4519  }
4520 }
4521 
4522 
4523 /**
4524  * Writes special store patterns for i1 types.
4525  */
4526 void
4528  std::string storeOp("");
4529  auto storeOps = littleEndian_
4530  ? std::vector<std::string>{"ST8ri", "ST8rr"}
4531  : std::vector<std::string>{"STQri", "STQrr"};
4532  for (auto op : storeOps) {
4533  if (opNames_.count(op)) {
4534  storeOp = op;
4535  break;
4536  }
4537  }
4538  if (storeOp.empty()) return;
4539 
4540  // TODO: is this 32 correct for 64-bit ADFs?
4541  auto storeConstBit = [=](const std::string& bitVal) -> std::string {
4542  return std::string("(") + storeOp + " ADDRrr:$addr, " +
4543  (storeOp.back() == 'i' ? "(i32 " : "(MOVI32ri ") + bitVal +
4544  "))";
4545  };
4546 
4547  // Patterns to avoid i1 "true" values to be emitted as -1, which breaks
4548  // on, for example, BZ and BNZ if the condition is loaded later, inverted
4549  // using XOR and finally the result is bypassed: this results the -1 to be
4550  // converted to -2, which is interpreted still as true.
4551  os << "def : Pat<(store (i1 -1), ADDRrr:$addr), " << std::endl
4552  << " " << storeConstBit("1") << ">;" << std::endl;
4553  os << "def : Pat<(store (i1 1), ADDRrr:$addr), " << std::endl
4554  << " " << storeConstBit("1") << ">;" << std::endl;
4555  os << "def : Pat<(store (i1 0), ADDRrr:$addr), " << std::endl
4556  << " " << storeConstBit("0") << ">;" << std::endl;
4557 }
4558 
4559 /**
4560  * Writes single immediate operand definitions to the stream.
4561  *
4562  * @param o The output stream.
4563  * @param defName The name of the immediate operand definition.
4564  * @param operandType The target type (i.e "i32").
4565  * @param predicate The predicate expression without return statement or ';'
4566  * at the end.
4567  */
4568 void
4570  std::ostream& o,
4571  const std::string& defName,
4572  const std::string& operandType,
4573  const std::string& predicate) {
4574 
4575  o << "def " << defName << " : Operand<" << operandType
4576  << "> , ImmLeaf<" << operandType << ", [{" << std::endl
4577  << " return " << predicate << ";}]>;" << std::endl;
4578 }
4579 
4580 /**
4581  * Writes LLVM instruction definition in TCE format to the stream.
4582  *
4583  */
4584 void
4586  std::ostream& o,
4587  const std::string& instrDefName,
4588  const std::string& outs,
4589  const std::string& ins,
4590  const std::string& asmString,
4591  const std::string& pattern) {
4592 
4593  o << "def " << instrDefName << " : InstTCE<" << std::endl
4594  << " (outs " << outs << ")," << std::endl
4595  << " (ins " << ins << ")," << std::endl
4596  << " \"" << asmString << "\", " << std::endl
4597  << " [" << pattern << "]>;" << std::endl;
4598 }
4599 
4600 /**
4601  * Writes a single operation def for single operation.
4602  *
4603  * @param o Output stream to write the definition to.
4604  * @param op Operation to write definition for.
4605  * @param operandTypes value types of operands.
4606  */
4607 void
4609  std::ostream& o,
4610  Operation& op, const std::string& operandTypes, const std::string& attrs,
4611  bool skipPattern, std::string backendPrefix) {
4612  assert (operandTypes.size() > 0);
4613 
4614  // Skip definition if the operation has immediate to operand which the
4615  // machine can not transport short immediates to.
4616  if (!areImmediateOperandsLegal(op, operandTypes)) {
4620  << "Skipped writing operation pattern for: "
4621  << op.name() + operandTypes
4622  << ": Can not have immediate operand."
4623  << std::endl;
4624  }
4625  return;
4626  }
4627 
4629 
4630  std::string outputs, inputs, asmstr, pattern;
4631  outputs = "(outs" + patOutputs(op, operandTypes) + ")";
4632  inputs = "(ins " + patInputs(op, operandTypes) + ")";
4633  std::string predicatedInputs =
4634  "(ins GuardRegs:$pred, " +patInputs(op, operandTypes)+ ")";
4635 
4636  asmstr = "\"\"";
4637 
4638  if (!skipPattern) {
4639  if (llvmOperationPattern(op, operandChar) != "" ||
4640  op.dagCount() == 0) {
4641  OperationDAG* trivial = createTrivialDAG(op);
4642  pattern = operationPattern(op, *trivial, operandTypes);
4643  delete trivial;
4644  } else {
4645  auto* dagToUse = getMatchableOperationDAG(op);
4646  if (dagToUse)
4647  pattern = operationPattern(op, *dagToUse, operandTypes);
4648  }
4649  }
4650 
4651  if (attrs != "") {
4652  o << "let" << attrs << " in { " << std::endl;
4653  }
4654 
4655  std::string opcEnum =
4656  StringTools::stringToUpper(op.name()) + operandTypes;
4657 
4658  o << "def " << opcEnum << " : "
4659  << "InstTCE<"
4660  << outputs << ", "
4661  << inputs << ", "
4662  << asmstr << ", " ;
4663  if(operandTypes[0] == 'b') { //instruction can be used for comparison
4664  o << "[" << pattern << "]>"
4665  << std::endl
4666  << "{ let isCompare = 1;}" << std::endl;
4667  } else {
4668  o << "[" << pattern << "]>;"
4669  << std::endl;
4670  }
4671 
4672  bool opCanBePredicated = canBePredicated(op, operandTypes);
4673 
4674  if (opCanBePredicated) {
4675  // write predicated versions
4676  o << "def PRED_TRUE_" << opcEnum << " : "
4677  << "InstTCE<"
4678  << outputs << ", "
4679  << predicatedInputs << ", "
4680  << asmstr << ", "
4681  << "[]>;"
4682  << std::endl;
4683  // write predicated versions
4684  o << "def PRED_FALSE_" << opcEnum << " : "
4685  << "InstTCE<"
4686  << outputs << ", "
4687  << predicatedInputs << ", "
4688  << asmstr << ", "
4689  << "[]>;"
4690  << std::endl;
4691  }
4692 
4693  if (attrs != "") {
4694  o << "}" << std::endl;
4695  }
4696  opNames_[opcEnum] = backendPrefix + op.name();
4697 
4698  if (opCanBePredicated) {
4699  opNames_["PRED_TRUE_" + opcEnum] = "?" + backendPrefix + op.name();
4700  opNames_["PRED_FALSE_" + opcEnum] = "!" + backendPrefix + op.name();
4701  truePredOps_[opcEnum] = "PRED_TRUE_" + opcEnum;
4702  falsePredOps_[opcEnum] = "PRED_FALSE_" + opcEnum;
4703  }
4704 }
4705 
4706 /**
4707  *
4708  * Returns corresponding character for given operand type.
4709  *
4710  * @param operand Operand under inspection.
4711  * @return Corresponding character of operand type.
4712  */
4713 char
4715  if (operand.isVector()) {
4716  if (operand.type() == Operand::BOOL) {
4717  return OT_VREG_BOOL;
4718  } else if (operand.type() == Operand::HALF_FLOAT_WORD) {
4719  return OT_VREG_HFP;
4720  } else if (operand.type() == Operand::FLOAT_WORD) {
4721  return OT_VREG_FP;
4722  } else {
4723  if (operand.elementWidth() == 1) {
4724  return OT_VREG_BOOL;
4725  } else if (operand.elementWidth() == 8) {
4726  return OT_VREG_INT8;
4727  } else if (operand.elementWidth() == 16) {
4728  return OT_VREG_INT16;
4729  } else {
4730  return OT_VREG_INT32;
4731  }
4732  }
4733  }
4734 
4735  if (operand.type() == Operand::BOOL) {
4736  return OT_REG_BOOL;
4737  } else if (operand.type() == Operand::HALF_FLOAT_WORD) {
4738  return OT_REG_HFP;
4739  } else if (operand.type() == Operand::ULONG_WORD ||
4740  operand.type() == Operand::SLONG_WORD ||
4741  operand.type() == Operand::RAW_DATA) {
4742  return mach_.is64bit() ? OT_REG_LONG : OT_REG_INT;
4743  } else if (operand.type() != Operand::UINT_WORD &&
4744  operand.type() != Operand::SINT_WORD) {
4745  return OT_REG_FP;
4746  } else {
4747  return OT_REG_INT;
4748  }
4749 }
4750 
4751 /**
4752  * Writes operation emulation pattern in .td format to an output stream.
4753  *
4754  * @param o Output stream to write the definition to.
4755  * @param op Emulated operation.
4756  * @param dag Emulation pattern.
4757  */
4758 void
4760  std::ostream& o,
4761  const Operation& op,
4762  const OperationDAG& dag) {
4763 
4764  char operandCh = mach_.is64bit() ? OT_REG_LONG : OT_REG_INT;
4765 
4766  const OperationDAGNode* res = *(dag.endNodes().begin());
4767  if (dag.endNodes().empty()) {
4768  std::cerr << "end nodes of dag for operation: " << op.name()
4769  << " is empty!" << std::endl;
4770  assert(false);
4771  }
4772 
4773  const OperationNode* opNode = dynamic_cast<const OperationNode*>(res);
4774  if (opNode == NULL) {
4775  assert(dag.inDegree(*res) == 1);
4776  const OperationDAGEdge& edge = dag.inEdge(*res, 0);
4777  res = dynamic_cast<OperationNode*>(&dag.tailNode(edge));
4778  assert(res != NULL);
4779  }
4780 
4781  int inputCount = op.numberOfInputs();
4782 
4783  bool ok = true;
4784  std::string llvmPat = llvmOperationPattern(op, operandCh);
4785  if (llvmPat == "") {
4786  std::cerr << "unknown op: " << op.name() << std::endl;
4787  }
4788  assert(llvmPat != "" && "Unknown operation to emulate.");
4789 
4790  boost::format match1(llvmPat);
4791 
4792  int outputs = op.numberOfOutputs();
4793 
4794  std::string operandTypes;
4795  for (int i = 0; i < outputs; i++) {
4796  operandTypes += operandChar(op.operand(i+inputCount + 1));
4797  }
4798 
4799  for (int i = 0; i < op.numberOfInputs(); i++) {
4800  char inputType = operandChar(op.operand(i+1));
4801 
4802  std::string immDef = immediateOperandNameForEmulatedOperation(
4803  dag, op.operand(i + 1));
4804 
4805  operandTypes += inputType;
4806  match1 % operandToString(op.operand(i + 1), false, inputType, immDef);
4807  }
4808  if (ok) {
4809  o << "def : Pat<(" << match1.str() << "), "
4810  << dagNodeToString(op, dag, *res, true, operandTypes)
4811  << ">;" << std::endl;
4812 
4813  // need to generate emulation patterns for boolean out
4814  // for these comparison operations.
4815  if (op.name() == "LTF" || op.name() == "LTUF" ||
4816  op.name() == "EQF" || op.name() == "EQUF" ||
4817  op.name() == "GEF" || op.name() == "GEUF" ||
4818  op.name() == "LEF" || op.name() == "LEUF" ||
4819  op.name() == "GTF" || op.name() == "GTUF" ||
4820  op.name() == "NEF" || op.name() == "NEUF" ||
4821  op.name() == "EQ" || op.name() == "NE" ||
4822  op.name() == "EQ64" || op.name() == "NE64" ||
4823  op.name() == "GE" ||op.name() == "GEU" ||
4824  op.name() == "GE64" ||op.name() == "GEU64" ||
4825  op.name() == "GT" || op.name() == "GTU" ||
4826  op.name() == "GT64" || op.name() == "GTU64" ||
4827  op.name() == "LE" || op.name() == "LEU" ||
4828  op.name() == "LE64" || op.name() == "LEU64" ||
4829  op.name() == "LT" || op.name() == "LTU" ||
4830  op.name() == "LT64" || op.name() == "LTU64" ||
4831  op.name() == "LTD" || op.name() == "LTUD" ||
4832  op.name() == "EQD" || op.name() == "EQUD" ||
4833  op.name() == "GED" || op.name() == "GEUD" ||
4834  op.name() == "LED" || op.name() == "LEUD" ||
4835  op.name() == "GTD" || op.name() == "GTUD" ||
4836  op.name() == "NED" || op.name() == "NEUD" ||
4837  op.name() == "ORDD" || op.name() == "UORDD" ||
4838  op.name() == "ORDF" || op.name() == "UORDF") {
4839  std::string boolOperandTypes = operandTypes;
4840  boolOperandTypes[0] = 'b';
4841  o << "def : Pat<(" << match1.str() << "), "
4842  << dagNodeToString(op, dag, *res, true, boolOperandTypes)
4843  << ">;" << std::endl;
4844  }
4845  }
4846 }
4847 /**
4848  * Returns LLVM operation pattern for given OSAL operation.
4849  *
4850  * @param op Operation for which the LLVM pattern should be returned.
4851  * @return Operation pattern in llvm.
4852  */
4853 TCEString
4854 TDGen::llvmOperationPattern(const Operation& op, char /*operandType*/) const {
4855  TCEString opName = StringTools::stringToLower(op.name());
4856 
4857  if (opName == "add") return "add %1%, %2%";
4858  if (opName == "add64") return "add %1%, %2%";
4859  if (opName == "sub") return "sub %1%, %2%";
4860  if (opName == "sub64") return "sub %1%, %2%";
4861  if (opName == "mul") return "mul %1%, %2%";
4862  if (opName == "mul64") return "mul %1%, %2%";
4863  if (opName == "div") return "sdiv %1%, %2%";
4864  if (opName == "divu") return "udiv %1%, %2%";
4865  if (opName == "div64") return "sdiv %1%, %2%";
4866  if (opName == "divu64") return "udiv %1%, %2%";
4867  if (opName == "mod") return "srem %1%, %2%";
4868  if (opName == "modu") return "urem %1%, %2%";
4869  if (opName == "mod64") return "srem %1%, %2%";
4870  if (opName == "modu64") return "urem %1%, %2%";
4871 
4872  if (opName == "shl") return "shl %1%, %2%";
4873  if (opName == "shr") return "sra %1%, %2%";
4874  if (opName == "shru") return "srl %1%, %2%";
4875  if (opName == "rotl") return "rotl %1%, %2%";
4876  if (opName == "rotr") return "rotr %1%, %2%";
4877 
4878 
4879  if (opName == "shl64") return "shl %1%, %2%";
4880  if (opName == "shr64") return "sra %1%, %2%";
4881  if (opName == "shru64") return "srl %1%, %2%";
4882  if (opName == "rotl64") return "rotl %1%, %2%";
4883  if (opName == "rotr64") return "rotr %1%, %2%";
4884 
4885  if (opName == "and") return "and %1%, %2%";
4886  if (opName == "ior") return "or %1%, %2%";
4887  if (opName == "xor") return "xor %1%, %2%";
4888 
4889  if (opName == "and64") return "and %1%, %2%";
4890  if (opName == "ior64") return "or %1%, %2%";
4891  if (opName == "xor64") return "xor %1%, %2%";
4892 
4893  if (opName == "eq") return "seteq %1%, %2%";
4894  if (opName == "eq64") return "seteq %1%, %2%";
4895  if (opName == "ne") return "setne %1%, %2%";
4896  if (opName == "ne64") return "setne %1%, %2%";
4897  if (opName == "lt") return "setlt %1%, %2%";
4898  if (opName == "lt64") return "setlt %1%, %2%";
4899  if (opName == "le") return "setle %1%, %2%";
4900  if (opName == "le64") return "setle %1%, %2%";
4901  if (opName == "gt") return "setgt %1%, %2%";
4902  if (opName == "gt64") return "setgt %1%, %2%";
4903  if (opName == "ge") return "setge %1%, %2%";
4904  if (opName == "ge64") return "setge %1%, %2%";
4905  if (opName == "ltu") return "setult %1%, %2%";
4906  if (opName == "ltu64") return "setult %1%, %2%";
4907  if (opName == "leu") return "setule %1%, %2%";
4908  if (opName == "leu64") return "setule %1%, %2%";
4909  if (opName == "gtu") return "setugt %1%, %2%";
4910  if (opName == "gtu64") return "setugt %1%, %2%";
4911  if (opName == "geu") return "setuge %1%, %2%";
4912  if (opName == "geu64") return "setuge %1%, %2%";
4913 
4914  if (opName == "eqf" || opName == "eqd") return "setoeq %1%, %2%";
4915  if (opName == "nef" || opName == "ned") return "setone %1%, %2%";
4916  if (opName == "ltf" || opName == "ltd") return "setolt %1%, %2%";
4917  if (opName == "lef" || opName == "led") return "setole %1%, %2%";
4918  if (opName == "gtf" || opName == "gtd") return "setogt %1%, %2%";
4919  if (opName == "gef" || opName == "ged") return "setoge %1%, %2%";
4920 
4921  if (opName == "equf" || opName == "equd") return "setueq %1%, %2%";
4922  if (opName == "neuf" || opName == "neud") return "setune %1%, %2%";
4923  if (opName == "ltuf" || opName == "ltud") return "setult %1%, %2%";
4924  if (opName == "leuf" || opName == "leud") return "setule %1%, %2%";
4925  if (opName == "gtuf" || opName == "gtud") return "setugt %1%, %2%";
4926  if (opName == "geuf" || opName == "geud") return "setuge %1%, %2%";
4927 
4928  if (opName == "ordf" || opName == "ordd") return "seto %1%, %2%";
4929  if (opName == "uordf"|| opName == "uordd")return "setuo %1%, %2%";
4930 
4931  if (opName == "addf" || opName == "addd") return "fadd %1%, %2%";
4932  if (opName == "subf" || opName == "subd") return "fsub %1%, %2%";
4933  if (opName == "mulf" || opName == "muld") return "fmul %1%, %2%";
4934  if (opName == "divf" || opName == "divd") return "fdiv %1%, %2%";
4935  if (opName == "absf" || opName == "absd") return "fabs %1%";
4936  if (opName == "negf" || opName == "negd") return "fneg %1%";
4937  if (opName == "sqrtf"|| opName == "sqrtd")return "fsqrt %1%";
4938 
4939  if (opName == "cif") return "sint_to_fp %1%";
4940  if (opName == "cfi") return "fp_to_sint %1%";
4941  if (opName == "cifu") return "uint_to_fp %1%";
4942  if (opName == "cfiu") return "fp_to_uint %1%";
4943 
4944  if (opName == "cld") return "sint_to_fp %1%";
4945  if (opName == "cdl") return "fp_to_sint %1%";
4946  if (opName == "cldu") return "uint_to_fp %1%";
4947  if (opName == "cdlu") return "fp_to_uint %1%";
4948 
4949  if (opName == "cfh" || opName == "cdf") return "fpround %1%";
4950  if (opName == "chf") return "f32 (fpextend %1%)";
4951  if (opName == "cfd") return "f64 (fpextend %1%)";
4952 
4953  if (opName == "cih") return "sint_to_fp %1%";
4954  if (opName == "chi") return "i32 (fp_to_sint %1%)";
4955  if (opName == "cihu") return "uint_to_fp %1%";
4956  if (opName == "chiu") return "i32 (fp_to_uint %1%)";
4957 
4958  if (opName == "neuh") return "setune %1%, %2%";
4959  if (opName == "eqh") return "setoeq %1%, %2%";
4960  if (opName == "neh") return "setone %1%, %2%";
4961  if (opName == "lth") return "setolt %1%, %2%";
4962  if (opName == "leh") return "setole %1%, %2%";
4963  if (opName == "gth") return "setogt %1%, %2%";
4964  if (opName == "geh") return "setoge %1%, %2%";
4965 
4966  if (opName == "ordh") return "seto %1%, %2%";
4967  if (opName == "uordh") return "setuo %1%, %2%";
4968 
4969  if (opName == "addh") return "fadd %1%, %2%";
4970  if (opName == "subh") return "fsub %1%, %2%";
4971  if (opName == "mulh") return "fmul %1%, %2%";
4972  if (opName == "divh") return "fdiv %1%, %2%";
4973  if (opName == "absh") return "fabs %1%";
4974  if (opName == "negh") return "fneg %1%";
4975  if (opName == "sqrth") return "fsqrt %1%";
4976 
4977  if (opName == "cih") return "sint_to_fp %1%";
4978  if (opName == "chi") return "fp_to_sint %1%";
4979  if (opName == "cihu") return "uint_to_fp %1%";
4980  if (opName == "chiu") return "fp_to_uint %1%";
4981 
4982  if (opName == "csh") return "sint_to_fp %1%";
4983  if (opName == "cshu") return "uint_to_fp %1%";
4984  if (opName == "chs") return "fp_to_sint %1%";
4985  if (opName == "chsu") return "fp_to_uint %1%";
4986 
4987  if (littleEndian_) {
4988  if (opName == "ld8") return "sextloadi8 %1%";
4989  if (opName == "ldu8") return "zextloadi8 %1%";
4990  if (opName == "ld16") return "sextloadi16 %1%";
4991  if (opName == "ldu16") return "zextloadi16 %1%";
4992  if (mach_.is64bit()) {
4993  if (opName == "ld32") return "sextloadi32 %1%";
4994  if (opName == "ldu32") return "zextloadi32 %1%";
4995  } else {
4996  if (opName == "ld32" || opName == "ldu32") return "load %1%";
4997  }
4998  if (opName == "ld64") return "load %1%";
4999  //if (opName == "ldd") return "load";
5000 
5001  if (opName == "st8") return "truncstorei8 %2%, %1%";
5002  if (opName == "st16") return "truncstorei16 %2%, %1%";
5003  if (mach_.is64bit()) {
5004  if (opName == "st32") return "truncstorei32 %2%, %1%";
5005  } else {
5006  if (opName == "st32") return "store %2%, %1%";
5007  }
5008  if (opName == "st64") return "store %2%, %1%";
5009  } else {
5010  if (opName == "ldq") return "sextloadi8 %1%";
5011  if (opName == "ldqu") return "zextloadi8 %1%";
5012  if (opName == "ldh") return "sextloadi16 %1%";
5013  if (opName == "ldhu") return "zextloadi16 %1%";
5014  if (opName == "ldw") return "load %1%";
5015  //if (opName == "ldd") return "load";
5016 
5017  if (opName == "stq") return "truncstorei8 %2%, %1%";
5018  if (opName == "sth") return "truncstorei16 %2%, %1%";
5019  if (opName == "stw") return "store %2%, %1%";
5020  //if (opName == "std") return "load";
5021  }
5022 
5023  if (opName == "sxw64") {
5024  return "sext_inreg %1%, i32";
5025  }
5026 
5027  if (opName == "sxb64") {
5028  return "sext_inreg %1%, i1";
5029  }
5030 
5031  if (opName == "sxq64") {
5032  return "sext_inreg %1%, i8";
5033  }
5034  if (opName == "sxh64") {
5035  return "sext_inreg %1%, i16";
5036  }
5037 
5038  if (opName == "sxhw") {
5039  return "sext_inreg %1%, i16";
5040  }
5041  if (opName == "sxqw") {
5042  return "sext_inreg %1%, i8";
5043  }
5044 
5045  if (opName == "sxw")
5046  return mach_.is64bit() ? "sext_inreg %1%, i64": "sext_inreg %1%, i32";
5047 
5048  if (opName == "sxbw") return "sext_inreg %1%, i1";
5049 
5050  if (opName == "truncwh" || opName == "truncwb" || opName == "trunchb")
5051  return "trunc %1%";
5052 
5053  if (opName == "neg") return "ineg %1%";
5054  if (opName == "not") return "not %1%";
5055 
5056  if (opName == "cas") return "atomic_cmp_swap_32 %1%, %2%, %3%";
5057  if (opName == "select") return "select %3%, %1%, %2%";
5058 
5059  // Unknown operation name.
5060  return "";
5061 }
5062 
5063 /**
5064  * Returns llvm operation name for the given OSAL operation name, if any.
5065  */
5066 
5067 TCEString
5068 TDGen::llvmOperationName(const TCEString& operationName) const {
5069 
5070  TCEString opName = StringTools::stringToLower(operationName);
5071 
5072  if (opName == "add") return "add";
5073  if (opName == "sub") return "sub";
5074  if (opName == "mul") return "mul";
5075  if (opName == "div") return "sdiv";
5076  if (opName == "divu") return "udiv";
5077  if (opName == "mod") return "srem";
5078  if (opName == "modu") return "urem";
5079 
5080  if (opName == "add64") return "add";
5081  if (opName == "sub64") return "sub";
5082  if (opName == "mul64") return "mul";
5083  if (opName == "div64") return "sdiv";
5084  if (opName == "divu64") return "udiv";
5085  if (opName == "mod64") return "srem";
5086  if (opName == "modu64") return "urem";
5087 
5088  if (opName == "shl") return "shl";
5089  if (opName == "shr") return "sra";
5090  if (opName == "shru") return "srl";
5091  if (opName == "rotl") return "rotl";
5092  if (opName == "rotr") return "rotr";
5093 
5094  if (opName == "shl64") return "shl";
5095  if (opName == "shr64") return "sra";
5096  if (opName == "shru64") return "srl";
5097  if (opName == "rotl64") return "rotl";
5098  if (opName == "rotr64") return "rotr";
5099 
5100  if (opName == "and") return "and";
5101  if (opName == "ior") return "or";
5102  if (opName == "xor") return "xor";
5103 
5104  if (opName == "and64") return "and";
5105  if (opName == "ior64") return "or";
5106  if (opName == "xor64") return "xor";
5107 
5108  if (opName == "eq") return "seteq";
5109  if (opName == "eq64") return "seteq";
5110  if (opName == "ne") return "setne";
5111  if (opName == "ne64") return "setne";
5112  if (opName == "lt") return "setlt";
5113  if (opName == "lt64") return "setlt";
5114  if (opName == "le") return "setle";
5115  if (opName == "le64") return "setle";
5116  if (opName == "gt") return "setgt";
5117  if (opName == "gt64") return "setgt";
5118  if (opName == "ge") return "setge";
5119  if (opName == "ltu") return "setult";
5120  if (opName == "ltu64") return "setult";
5121  if (opName == "leu") return "setule";
5122  if (opName == "leu64") return "setule";
5123  if (opName == "gtu") return "setugt";
5124  if (opName == "gtu64") return "setugt";
5125  if (opName == "geu") return "setuge";
5126  if (opName == "geu64") return "setuge";
5127 
5128  if (opName == "eqf" || opName == "eqd") return "setoeq";
5129  if (opName == "nef" || opName == "ned") return "setone";
5130  if (opName == "ltf" || opName == "ltd") return "setolt";
5131  if (opName == "lef" || opName == "led") return "setole";
5132  if (opName == "gtf" || opName == "gtd") return "setogt";
5133  if (opName == "gef" || opName == "ged") return "setoge";
5134 
5135  if (opName == "equf" || opName == "equd") return "setueq";
5136  if (opName == "neuf" || opName == "neud") return "setune";
5137  if (opName == "ltuf" || opName == "ltud") return "setult";
5138  if (opName == "leuf" || opName == "leud") return "setule";
5139  if (opName == "gtuf" || opName == "gtud") return "setugt";
5140  if (opName == "geuf" || opName == "geud") return "setuge";
5141 
5142  if (opName == "ordf" || opName =="ordd") return "seto";
5143  if (opName == "uordf" || opName == "uordd") return "setuo";
5144 
5145  if (opName == "addf") return "fadd";
5146  if (opName == "subf") return "fsub";
5147  if (opName == "mulf") return "fmul";
5148  if (opName == "divf") return "fdiv";
5149  if (opName == "absf") return "fabs";
5150  if (opName == "negf") return "fneg";
5151  if (opName == "sqrtf") return "fsqrt";
5152 
5153  if (opName == "cif") return "sint_to_fp";
5154  if (opName == "cfi") return "fp_to_sint";
5155  if (opName == "cifu") return "uint_to_fp";
5156  if (opName == "cfiu") return "fp_to_uint";
5157 
5158  if (opName == "cfh") return "fpround";
5159  if (opName == "chf") return "fpextend";
5160 
5161  if (littleEndian_) {
5162  if (opName == "ld8") return "sextloadi8";
5163  if (opName == "ldu8") return "zextloadi8";
5164  if (opName == "ld16") return "sextloadi16";
5165  if (opName == "ldu16") return "zextloadi16";
5166  if (mach_.is64bit()) {
5167  if (opName == "ld32") return "sextloadi32";
5168  if (opName == "ldu32") return "zextloadi32";
5169  } else {
5170  if (opName == "ld32" || opName =="ldu32") return "load";
5171  }
5172  if (opName == "ld64") return "load";
5173 
5174  //if (opName == "ldd") return "load";
5175 
5176  if (opName == "st8") return "truncstorei8";
5177  if (opName == "st16") return "truncstorei16";
5178  if (opName == "st32") {
5179  if (mach_.is64bit()) {
5180  return "truncstorei32";
5181  } else {
5182  return "store";
5183  }
5184  }
5185 
5186  if (opName == "st32") return "store";
5187  if (opName == "st64") return "store";
5188  //if (opName == "std") return "load";
5189  } else { // big-endian
5190  if (opName == "ldq") return "sextloadi8";
5191  if (opName == "ldqu") return "zextloadi8";
5192  if (opName == "ldh") return "sextloadi16";
5193  if (opName == "ldhu") return "zextloadi16";
5194  if (opName == "ldw") return "load";
5195  //if (opName == "ldd") return "load";
5196 
5197  if (opName == "stq") return "truncstorei8";
5198  if (opName == "sth") return "truncstorei16";
5199  if (opName == "stw") return "store";
5200  //if (opName == "std") return "load";
5201  }
5202 
5203  if (opName.length() >2 && opName.substr(0,2) == "sx") {
5204  return "sext_inreg";
5205  }
5206 
5207  if (opName == "truncwh" || opName == "truncwb" || opName == "trunchb")
5208  return "trunc";
5209 
5210  if (opName == "neg") return "ineg";
5211  if (opName == "not") return "not";
5212  if (opName == "cas") return "atomic_cmp_swap_32";
5213 
5214  if (opName == "select") return "select";
5215 
5216  // Unknown operation name.
5217  return "";
5218 }
5219 
5220 
5221 /**
5222  * Pattern for tce generated custom op patterns.
5223  */
5224 std::string
5226  std::string opList = "";
5227  for (int i = 0; i < op.numberOfInputs(); i++) {
5228  opList += " %" + Conversion::toString(i+1) + "%";
5229  }
5230  return op.name() + opList;
5231 }
5232 
5233 /**
5234  * Check if operation can be matched with llvm pattern.
5235  *
5236  * Check if operation has llvmOperationPatters or
5237  * one of it's DAGs contain only operations, which can be matched.
5238  */
5239 bool
5241  const Operation& op, std::set<std::string>* recursionCycleCheck,
5242  bool recursionHasStore) {
5243 
5244  // LLVM does not support operations with >255 inputs.
5245  if (op.numberOfInputs() > 255) {
5246  return false;
5247  }
5248  // TODO: this should have been changed?
5250  // if operation has llvm pattern
5251  if (llvmOperationPattern(op,operandChar) != "") {
5252  return true;
5253  }
5254 
5255  std::set<std::string> useSet;
5256  if (recursionCycleCheck != NULL) {
5257  useSet = *recursionCycleCheck;
5258  }
5259  useSet.insert(op.name());
5260 
5261  // check if one of dags of operation is ok
5262  for (int i = 0; i < op.dagCount(); i++) {
5263  OperationDAG& dag = op.dag(i);
5264  if (operationDAGCanBeMatched(dag, &useSet, recursionHasStore)) {
5265  return true;
5266  }
5267  }
5268 
5269  return false;
5270 }
5271 
5272 
5273 bool
5275  const OperationDAG& opDag,
5276  std::set<std::string>* recursionCycleCheck,
5277  bool recursionHasStore) {
5278 
5279  bool hasStore = false;
5280 
5281  for (int j = 0; j < opDag.nodeCount(); j++) {
5282  OperationNode* opNode = dynamic_cast<OperationNode*>(&opDag.node(j));
5283  if (opNode) {
5284  Operation& refOp = opNode->referencedOperation();
5285  if (refOp.writesMemory()) {
5286  if (recursionHasStore || hasStore) {
5287  return false;
5288  } else {
5289  hasStore = true;
5290  }
5291  }
5292 
5293  // check that the same operation is not used recursively
5294  if (recursionCycleCheck &&
5295  recursionCycleCheck->count(refOp.name()) != 0) {
5296  return false;
5297  }
5298 
5299  // check if referenced op can be matched
5300  if (!operationCanBeMatched(refOp, recursionCycleCheck,
5301  hasStore)) {
5302  return false;
5303  }
5304  }
5305  }
5306  return true;
5307 }
5308 
5309 /**
5310  * Returns first operation DAG that can be used in LLVM pattern.
5311  *
5312  * Operation DAGs are traversed in the order of trigger-semantics in the
5313  * first .opp file found in path that defines the Operation.
5314  *
5315  * This method does not transfer ownership.
5316  *
5317  * @return The matchable operation DAG. Nullptr if could not find.
5318  */
5319 const OperationDAG*
5321  const Operation& op) {
5322 
5323  // check if one of dags of operation is ok
5324  for (int i = 0; i < op.dagCount(); i++) {
5325  OperationDAG& dag = op.dag(i);
5326  if (op.dagError(i) != "") {
5327  std::cerr << "Broken dag in operation " << op.name()
5328  << op.dagCode(i) << std::endl;
5329  assert(0);
5330  }
5331 
5332  if (operationDAGCanBeMatched(dag)) {
5333  return &dag;
5334  }
5335  }
5336  return nullptr;
5337 }
5338 
5339 
5340 /**
5341  * Returns operation pattern in llvm .td format.
5342  *
5343  * @param op Operation to return pattern for.
5344  * @param dag Operation pattern's DAG.
5345  * @param immOp Index of an operand to define as an immediate operand,
5346  * or 0, if all operands should be in registers.
5347  *
5348  * @return Pattern string.
5349  */
5350 std::string
5352  const Operation& op,
5353  const OperationDAG& dag,
5354  const std::string& operandTypes) {
5355 
5356  std::string retVal;
5357  for (OperationDAG::NodeSet::iterator i = dag.endNodes().begin();
5358  i != dag.endNodes().end(); ++i) {
5359  if (i != dag.endNodes().begin()) {
5360  retVal += ",";
5361  }
5362  const OperationDAGNode& res = **(i);
5363  retVal += dagNodeToString(op, dag, res, false, operandTypes);
5364  }
5365  return retVal;
5366 }
5367 
5368 std::string
5370  std::string operandTypes;
5371 
5372  int inputs = op.numberOfInputs();
5373  int outputs = op.numberOfOutputs();
5374 
5375  for (int i = 0; i < outputs; i++) {
5376  Operand& operand = op.operand(i + inputs +1);
5377  operandTypes += operandChar(operand);
5378  }
5379 
5380  for (int i = 0; i < inputs ; i++) {
5381  Operand& operand = op.operand(i +1);
5382  operandTypes += operandChar(operand);
5383  }
5384  return operandTypes;
5385 }
5386 
5387 /**
5388  * Return operation pattern is llvm .td format without outputs.
5389  *
5390  * This pattern can be used as sub-pattern of bigger pattern.
5391  * The operation must have only one output.
5392  *
5393  * @param op Operation to return pattern for.
5394  * @param dag Operation pattern's DAG.
5395  * @return Pattern string.
5396  */
5397 std::string
5399  const Operation& op,
5400  const OperationDAG& dag) {
5401 
5402  if (dag.endNodes().size() != 1) {
5403  throw InvalidData(
5404  __FILE__,__LINE__,__func__,
5405  "Cannot create subpattern: not exactly 1 end node!");
5406  }
5407 
5408  OperationDAG::NodeSet::iterator i = dag.endNodes().begin();
5409  const OperationDAGNode& res = **(i);
5410  OperationDAG::NodeSet preds = dag.predecessors(res);
5411  if (preds.size() != 1) {
5412  throw InvalidData(
5413  __FILE__,__LINE__,__func__,
5414  "Cannot create subpattern: not single data source for end node.");
5415  }
5416 
5417  std::string operandTypes = createDefaultOperandTypeString(op);
5418  // TODO: what about immediate operands?
5419 
5420  // TODO: size of the operand string?
5421  return dagNodeToString(
5422  op, dag, **(preds.begin()), false, operandTypes);
5423 }
5424 /**
5425  * Converts single OperationDAG node to llvm pattern fragment string.
5426  *
5427  * @param op Operation that the whole DAG is for.
5428  * @param dag Whole operation DAG.
5429  * @param node DAG node to return string for.
5430  * @param immOp Index of an operand to define as an immediate or 0 if none.
5431  * @param emulationPattern True, if the returned string should be in
5432  * emulation pattern format.
5433  * @return DAG node as a llvm .td string.
5434  */
5435 std::string
5437  const Operation& op, const OperationDAG& dag, const OperationDAGNode& node,
5438  bool emulationPattern, const std::string& operandTypes,
5439  const Operation* emulatingOp, const OperationDAGNode* successor) {
5440  const OperationNode* oNode = dynamic_cast<const OperationNode*>(&node);
5441  if (oNode != NULL) {
5442  assert(
5443  dag.inDegree(*oNode) ==
5444  oNode->referencedOperation().numberOfInputs());
5445 
5446  return operationNodeToString(
5447  op, dag, *oNode, emulationPattern, operandTypes);
5448  }
5449 
5450  const TerminalNode* tNode = dynamic_cast<const TerminalNode*>(&node);
5451  if (tNode != NULL) {
5452  const Operand& operand = op.operand(tNode->operandIndex());
5453  if (dag.inDegree(*tNode) == 0) {
5454  // Input operand for the whole operation.
5455  assert(operand.isInput());
5456 
5457  char operandType =
5458  operandTypes[operand.index()-1 + op.numberOfOutputs()];
5459  bool imm = (operandType == OT_IMM_INT ||
5460  operandType == OT_IMM_BOOL);
5461 
5462  if (imm && !canBeImmediate(dag, *tNode)) {
5463  std::string msg =
5464  "Invalid immediate operand for " + op.name() +
5465  " operand #" + Conversion::toString(tNode->operandIndex());
5466  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5467  }
5468 
5469  if (emulationPattern) {
5470  assert(emulatingOp != nullptr);
5471  return operandToString(operand, false, operandType,
5473  *emulatingOp, operand)]);
5474  } else {
5475  return operandToString(operand, false, operandType,
5476  immOperandDefs_[ImmInfo::key(op, operand)]);
5477  }
5478  } else {
5479  // Output operand for the whole operation.
5480  assert(dag.inDegree(*tNode) == 1);
5481  assert(op.operand(tNode->operandIndex()).isOutput());
5482  assert(operand.isOutput());
5483  int globalOperandIndex =
5484  tNode->operandIndex() - op.numberOfInputs();
5485  assert(globalOperandIndex == 1);
5486 
5487  const OperationDAGEdge& edge = dag.inEdge(node, 0);
5488  const OperationDAGNode& srcNode = dag.tailNode(edge);
5489 
5490  // Multiple-output operation nodes not supported in the middle
5491  // of dag:
5492  assert(dag.outDegree(srcNode) == 1);
5493 
5494  std::string dnString =
5496  op, dag, srcNode, emulationPattern, operandTypes,
5497  emulatingOp, successor);
5498 
5499  bool needTrunc = (operandTypes[globalOperandIndex-1] ==
5500  OT_REG_BOOL &&
5501  operandTypes[1] != OT_REG_BOOL &&
5502  operandTypes[1] != OT_IMM_BOOL);
5503 
5504  // handle setcc's without trunc
5505  // also loads and extends.
5506  if (needTrunc) {
5507  if (dnString.substr(0,4) == "(set" ||
5508  dnString.substr(0,5) == "(zext" ||
5509  dnString.substr(0,5) == "(load") {
5510  needTrunc = false;
5511  }
5512  }
5513 
5514  if (needTrunc) {
5515  std::string pattern =
5516  "(set " + operandToString(
5517  operand, emulationPattern, operandTypes[0])
5518  + ", (trunc " + dnString + "))";
5519  return pattern;
5520  } else {
5521  std::string pattern =
5522  "(set " + operandToString(
5523  operand, emulationPattern, operandTypes[0])
5524  + ", " + dnString + ")";
5525  return pattern;
5526  }
5527  }
5528  }
5529 
5530  // Constant values.
5531  const ConstantNode* cNode = dynamic_cast<const ConstantNode*>(&node);
5532  if (cNode != NULL) {
5533  return constantNodeString(op, dag, *cNode, operandTypes, successor);
5534  }
5535 
5536  abortWithError("Unknown OperationDAG node type.");
5537  return "";
5538 }
5539 
5540 std::string
5542  const Operation& op,
5543  const OperationDAG& dag,
5544  const ConstantNode& node,
5545  const std::string& operandTypes,
5546  const OperationDAGNode* successor) {
5547 
5548  assert(dag.inDegree(node) == 0);
5549  assert(dag.outDegree(node) == 1 || successor);
5550  const OperationDAGNode& succ = successor ?
5551  *successor : dag.headNode(dag.outEdge(node,0));
5552  const OperationNode* opn = dynamic_cast<const OperationNode*>(&succ);
5553  OperationDAG::NodeSet siblings = dag.predecessors(*opn);
5554  for (OperationDAG::NodeSet::iterator i = siblings.begin();
5555  i!= siblings.end(); i++) {
5556  const TerminalNode* tNode = dynamic_cast<const TerminalNode*>(*i);
5557  if (tNode != NULL) {
5558  const Operand& operand = op.operand(tNode->operandIndex());
5559  assert(operand.isInput());
5560  char operandType =
5561  operandTypes[operand.index()-1 + op.numberOfOutputs()];
5562  // Retrieve largest short immediate for the operand.
5563  switch (operandType) {
5564  case OT_REG_BOOL:
5565  case OT_IMM_BOOL:
5566  return "(i1 " + Conversion::toString(node.value()) + ")";
5567  case OT_REG_DOUBLE:
5568  return "(f64 " + Conversion::toString(node.value()) +")";
5569  case OT_REG_HFP:
5570  return "(f16 " + Conversion::toString(node.value()) + ")";
5571  // TODO: f16 vectors not yet implemented
5572  case OT_REG_FP:
5573  case OT_IMM_FP:
5574  return "(f32 " + Conversion::toString(node.value()) + ")";
5575  case OT_REG_LONG:
5576  case OT_IMM_LONG:
5577  return "(i64 " + Conversion::toString(node.value()) + ")";
5578  case OT_REG_INT:
5579  case OT_IMM_INT:
5580  return mach_.is64bit() ?
5581  "(i64 " + Conversion::toString(node.value()) + ")":
5582  "(i32 " + Conversion::toString(node.value()) + ")";
5583  default:
5584  break;
5585  }
5586  }
5587  }
5588  return Conversion::toString(node.value());
5589 }
5590 
5591 /**
5592  * Returns an llvm name for an operation node in an emulation dag.
5593  *
5594  * @param op the operation being emulated.
5595  * @param dag dag of the emulated operation
5596  * @param node node whose name is being asked
5597  * @param operandTypes string containing oeprand types for the emulated op.
5598  */
5599 std::string
5601  const Operation& op, const OperationDAG& dag, const OperationNode& node,
5602  const std::string& operandTypes) {
5603  const Operation& operation = node.referencedOperation();
5604  std::string operationName = StringTools::stringToUpper(operation.name());
5605 
5606 
5607  int inputs = operation.numberOfInputs();
5608 
5609  // Look at outgoing nodes. If operand goes to another op,
5610  // the value is in register.
5611  // if it's terminal, get the type from the paramete string.
5612  for (int i = 1 ; i < operation.numberOfOutputs() + 1; i++) {
5613  char c = 0;
5614  for (int e = 0; e < dag.outDegree(node); e++) {
5615  const OperationDAGEdge& edge = dag.outEdge(node, e);
5616  int dst = edge.srcOperand();
5617  if (dst == i + operation.numberOfInputs()) {
5618  TerminalNode* t =
5619  dynamic_cast<TerminalNode*>(
5620  &(dag.headNode(edge)));
5621  if (t != NULL) {
5622  int strIndex = t->operandIndex() -1 -
5623  op.numberOfInputs();
5624  assert((int)operandTypes.length() > strIndex &&
5625  strIndex >= 0);
5626  if (c != 0 && c != operandTypes[strIndex]) {
5627  throw InvalidData(__FILE__,__LINE__,__func__,
5628  "conflicting output types!");
5629  }
5630  c = operandTypes[strIndex];
5631  } else {
5632  Operand &operand =
5633  operation.operand(i+operation.numberOfInputs());
5634  char type = operandChar(operand);
5635  if (c != 0 && c!= type) {
5636  throw InvalidData(__FILE__,__LINE__,__func__,
5637  "conflicting output types!");
5638  }
5639  c = type;
5640  }
5641  }
5642  }
5643  if (c == 0) {
5644  throw InvalidData(__FILE__,__LINE__,__func__,"output not found.");
5645  }
5646  operationName += c;
5647  }
5648 
5649  // Look at incoming nodes. If operand comes from another op,
5650  // the value is in register. If operand comes from constant,
5651  // it's immediate.
5652  // if it's terminal, get the type from the parm string.
5653  for (int i = 1; i < inputs + 1; i++) {
5654  Operand &operand = operation.operand(i);
5655  for (int e = 0; e < dag.inDegree(node); e++) {
5656  const OperationDAGEdge& edge = dag.inEdge(node, e);
5657  int dst = edge.dstOperand();
5658  if (dst == i) {
5659  if (dynamic_cast<OperationNode*>(&(dag.tailNode(edge)))) {
5660  operationName += operandChar(operand);
5661  } else {
5662  if (dynamic_cast<ConstantNode*>(
5663  &(dag.tailNode(edge)))) {
5664  if (operand.type() == Operand::SINT_WORD ||
5665  operand.type() == Operand::UINT_WORD) {
5666  operationName += OT_IMM_INT;
5667  } else if (operand.type() == Operand::RAW_DATA ||
5668  operand.type() == Operand::SLONG_WORD ||
5669  operand.type() == Operand::ULONG_WORD) {
5670  operationName += mach_.is64bit() ?
5672  }
5673  } else {
5674  TerminalNode* t =
5675  dynamic_cast<TerminalNode*>(
5676  &(dag.tailNode(edge)));
5677  assert (t != NULL);
5678  int strIndex = t->operandIndex() -1 +
5679  op.numberOfOutputs();
5680  if ((int)operandTypes.length() <= strIndex ||
5681  strIndex <= 0) {
5682  std::cerr << "Invalid operand types length or"
5683  << "strIndex in operation:"
5684  << operation.name()
5685  << " OperandTypes string is: "
5686  << operandTypes
5687  << " strIndex is: " << strIndex
5688  << std::endl;
5689  assert(false);
5690  }
5691  operationName += operandTypes[strIndex];
5692  }
5693  }
5694  }
5695  }
5696  }
5697  return operationName;
5698 }
5699 
5700 /**
5701  * Converts OSAL dag operation node to llvm .td pattern fragment string.
5702  *
5703  * @param op Operation which this operation node is part of.
5704  * @param dag Parent DAG of the operation node.
5705  * @param node Node to convert to string.
5706  * @param immOp Index of an operand to define as immediate or 0 if none.
5707  * @param emulationPattern True, if the string should be in emulation pattern
5708  * format.
5709  */
5710 std::string
5712  const Operation& op, const OperationDAG& dag, const OperationNode& node,
5713  bool emulationPattern, const std::string& operandTypes) {
5714  const Operation& operation = node.referencedOperation();
5715 
5716  std::string operationPat;
5717 
5718  if (emulationPattern) {
5719  operationPat = emulatingOpNodeLLVMName(
5720  op, dag, node, operandTypes);
5721 
5722  for (int i = 0; i < operation.numberOfInputs(); i++) {
5723  if (i > 0) {
5724  operationPat += ", ";
5725  } else {
5726  operationPat += " ";
5727  }
5728  operationPat =
5729  operationPat + "%" + Conversion::toString(i + 1) + "%";
5730  }
5731  } else {
5732  operationPat = llvmOperationPattern(operation, operandTypes[0]);
5733 
5734  // generate pattern for operation if not llvmOperation (can match
5735  // custom op patterns)
5736  if (operationPat == "") {
5737  auto* dagToUse = getMatchableOperationDAG(operation);
5738  if (dagToUse) {
5739  return subPattern(operation, *dagToUse);
5740  } else {
5741  operationPat = tceOperationPattern(operation);
5742  }
5743  }
5744  }
5745 
5746  if (operationPat == "") {
5747  std::string msg("Unknown operation node in dag: " +
5748  std::string(operation.name()));
5749 
5750  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5751  }
5752 
5753  boost::format pattern(operationPat);
5754 
5755  int inputs = operation.numberOfInputs();
5756 #ifndef NDEBUG
5757  int outputs =
5758 #endif
5759  operation.numberOfOutputs();
5760 
5761  assert(outputs == 0 || outputs == 1);
5762 
5763  for (int i = 1; i < inputs + 1; i++) {
5764  for (int e = 0; e < dag.inDegree(node); e++) {
5765  const OperationDAGEdge& edge = dag.inEdge(node, e);
5766  int dst = edge.dstOperand();
5767  if (dst == i) {
5768  const OperationDAGNode& in = dag.tailNode(edge);
5769  std::string dagNodeString = dagNodeToString(
5770  op, dag, in, emulationPattern, operandTypes,
5771  &operation, &node);
5772  try {
5773  pattern % dagNodeString;
5774  } catch(...) {
5775  TCEString msg = "Boost format threw exception! ";
5776  msg << "Input format: " << operationPat;
5777  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5778  }
5779  }
5780  }
5781  }
5782 
5783  return std::string("(") + pattern.str() + ")";
5784 }
5785 
5786 /**
5787  * Returns LLVM .td format string for an operand.
5788  *
5789  * @param operand Operand to return string for.
5790  * @param match True, if the string should be in the matching pattern format.
5791  * @param operandType Character that identifies the type of the operand.
5792  * @return Operand string to be used in a llvm .td pattern.
5793  */
5794 // TODO is operandToString correct?
5795 std::string
5797  const Operand& operand,
5798  bool match,
5799  char operandType,
5800  const std::string& immDefName) {
5801  int idx = operand.index();
5802 
5803  if (operand.isVector() && !operand.isAddress()) {
5804  switch (operandType) {
5805  case OT_VREG_BOOL:
5806  case OT_VREG_INT8:
5807  case OT_VREG_INT16:
5808  case OT_VREG_INT32:
5809  case OT_VREG_FP:
5810  case OT_VREG_HFP: {
5811  TCEString regClass = associatedVectorRegisterClass(operand);
5812  return regClass + ":$op" + Conversion::toString(idx);
5813  }
5814  }
5815  }
5816 
5817  // from TDGenSIMD: if (operand.isVector && operand.isAddress()
5818  /// @todo Vector of pointers once supported. Change operand types
5819  /// for GATHER and SCATTER to be mem-data and mem-address, because
5820  /// that will direct the address operand into this if-clause.
5821 
5822  if (operand.isAddress()) {
5823  switch (operandType) {
5824  case OT_IMM_INT:
5825  case OT_IMM_LONG:
5826  if (match) {
5827  return "MEMri:$op" + Conversion::toString(idx);
5828  } else {
5829  return "ADDRri:$op" + Conversion::toString(idx);
5830  }
5831  case OT_REG_INT:
5832  case OT_REG_LONG:
5833  if (match) {
5834  return "MEMrr:$op" + Conversion::toString(idx);
5835  } else {
5836  return "ADDRrr:$op" + Conversion::toString(idx);
5837  }
5838  default:
5839  std::string msg =
5840  "invalid operation type for mem operand:";
5841  msg += operandType;
5842  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5843  }
5844  } else if (operand.type() == Operand::SINT_WORD ||
5845  operand.type() == Operand::UINT_WORD ||
5846  operand.type() == Operand::RAW_DATA ||
5847  operand.type() == Operand::BOOL) {
5848 
5849  // imm
5850  switch (operandType) {
5851  case OT_IMM_LONG:
5852  if (match) {
5853  return "i64imm:$op" + Conversion::toString(idx);
5854  } else {
5855  return "(i64 imm:$op" + Conversion::toString(idx) + ")";
5856  }
5857  case OT_IMM_INT:
5858  assert(!immDefName.empty() &&
5859  "No immediate operand defined for the operand.");
5860  return immDefName + ":$op" + Conversion::toString(idx);
5861  case OT_IMM_BOOL:
5862  if (match) {
5863  return "i1imm:$op" + Conversion::toString(idx);
5864  } else {
5865  return "(i1 imm:$op" + Conversion::toString(idx) + ")";
5866  }
5867  case OT_REG_INT:
5868  return mach_.is64bit() ?
5869  "R64IRegs:$op" + Conversion::toString(idx):
5870  "R32IRegs:$op" + Conversion::toString(idx);
5871  case OT_REG_LONG:
5872  return "R64IRegs:$op" + Conversion::toString(idx);
5873  case OT_REG_BOOL:
5874  return "R1Regs:$op" + Conversion::toString(idx);
5875  case OT_REG_FP:
5876  if (operand.type() == Operand::RAW_DATA) {
5877  return "FPRegs:$op" + Conversion::toString(idx);
5878  }
5879  /* fall through */
5880  case OT_REG_HFP:
5881  if (operand.type() == Operand::RAW_DATA) {
5882  return "HFPRegs:$op" + Conversion::toString(idx);
5883  }
5884  /* fall through */
5885  default:
5886  std::string msg =
5887  "invalid operation type for integer operand:";
5888  msg += operandType;
5889  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5890  }
5891  } else if (operand.type() == Operand::FLOAT_WORD ) {
5892 
5893  switch (operandType) {
5894  case OT_IMM_INT:
5895  case OT_IMM_FP:
5896  if (match) {
5897  return "f32imm:$op" + Conversion::toString(idx);
5898  } else {
5899  return "(f32 fpimm:$op" + Conversion::toString(idx) + ")";
5900  }
5901  case OT_REG_INT:
5902  case OT_REG_FP:
5903  return "FPRegs:$op" + Conversion::toString(idx);
5904 
5905  default:
5906  std::string msg =
5907  "invalid operation type for float operand:";
5908  msg += operandType;
5909  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5910  }
5911  } else if (operand.type() == Operand::HALF_FLOAT_WORD) {
5912 
5913  switch (operandType) {
5914  case OT_IMM_INT:
5915  case OT_IMM_FP:
5916  case OT_IMM_HFP:
5917  if (match) {
5918  return "f16imm:$op" + Conversion::toString(idx);
5919  } else {
5920  return "(f16 fpimm:$op" + Conversion::toString(idx) + ")";
5921  }
5922  case OT_REG_INT:
5923  case OT_REG_HFP:
5924  return "HFPRegs:$op" + Conversion::toString(idx);
5925  default:
5926  std::string msg =
5927  "invalid operation type for half operand:";
5928  msg += operandType;
5929  throw InvalidData(__FILE__, __LINE__, __func__, msg);
5930  }
5931  } else if (operand.type() == Operand::DOUBLE_WORD) {
5932  // TODO: immediate check??
5933  return "R64DFPRegs:$op" + Conversion::toString(idx);
5934  } else if (operand.type() == Operand::SLONG_WORD ||
5935  operand.type() == Operand::ULONG_WORD) {
5936  if (operandType == OT_REG_BOOL) {
5937  return "R1Regs:$op" + Conversion::toString(idx);
5938  }
5939  if (operandType == OT_IMM_BOOL) {
5940  if (match) {
5941  return "i1imm:$op" + Conversion::toString(idx);
5942  } else {
5943  return "(i1 imm:$op" + Conversion::toString(idx) + ")";
5944  }
5945  }
5946  if (operandType == OT_IMM_LONG) {
5947  return match ?
5948  "i64imm:$op" + Conversion::toString(idx) :
5949  "(i64 imm:$op" + Conversion::toString(idx) + ")";
5950  }
5951  return mach_.is64bit() ?
5952  "R64IRegs:$op" + Conversion::toString(idx):
5953  "R32IRegs:$op" + Conversion::toString(idx);
5954  } else {
5955  std::cerr << "Unknown operand type: " << operandType << std::endl;
5956  assert(false && "Unknown operand type.");
5957  }
5958  abortWithError("Unknown operand type on osal? Should not get here.");
5959  return "";
5960 }
5961 
5962 /**
5963  * Returns llvm input definition list for an operation.
5964  *
5965  * @param op Operation to define inputs for.
5966  * @return String defining operation inputs in llvm .td format.
5967  */
5968 std::string
5969 TDGen::patInputs(const Operation& op, const std::string& inputTypes) {
5970 
5971  std::string ins;
5972  for (int i = 0; i < op.numberOfInputs(); i++) {
5973  if (i > 0) {
5974  ins += ", ";
5975  }
5976 
5977  char inputType = inputTypes[i + op.numberOfOutputs()];
5978  std::string immDef("");
5979  // NOTE: !op.operand(i+1).isAddress() is kludge fix for MEMri/ADDri
5980  // operands. They do not have immediate operand definitions (yet).
5981  if (inputType == OT_IMM_INT && !op.operand(i+1).isAddress()) {
5982  assert(immOperandDefs_.count(
5983  ImmInfo::key(op, op.operand(i+1)))
5984  && "Missing immediate operand definition for the operand.");
5985  immDef = immOperandDefs_[ImmInfo::key(op, op.operand(i+1))];
5986  }
5987  ins += operandToString(op.operand(i + 1), true, inputType, immDef);
5988  }
5989  return ins;
5990 }
5991 
5992 
5993 /**
5994  * Returns llvm output definition list for an operation.
5995  *
5996  * @param op Operation to define outputs for.
5997  * @return String defining operation outputs in llvm .td format.
5998  */
5999 std::string
6000 TDGen::patOutputs(const Operation& op, const std::string& operandTypes) {
6001  std::string outs;
6002  for (int i = 0; i < op.numberOfOutputs(); i++) {
6003  assert(op.operand(op.numberOfInputs() + 1 + i).isOutput());
6004  outs += (i > 0) ? (",") : (" ");
6005  outs += operandToString(
6006  op.operand(op.numberOfInputs() + 1 + i), true, operandTypes[i]);
6007  }
6008  return outs;
6009 }
6010 
6011 /**
6012  * Creates a dummy dag for an OSAL operation.
6013  *
6014  * @param op Operation to create OperationDAG for.
6015  * @return OperationDAG consisting of only one operation node referencing
6016  * the given operation.
6017  */
6018 OperationDAG*
6020 
6021  OperationDAG* dag = new OperationDAG(op.impl());
6022  OperationNode* opNode = new OperationNode(op);
6023  dag->addNode(*opNode);
6024 
6025  for (int i = 0; i < op.numberOfInputs() + op.numberOfOutputs(); i++) {
6026  const Operand& operand = op.operand(i + 1);
6027  TerminalNode* t = new TerminalNode(operand.index());
6028  dag->addNode(*t);
6029  if (operand.isInput()) {
6030  OperationDAGEdge* e = new OperationDAGEdge(1, operand.index());
6031  dag->connectNodes(*t, *opNode, *e);
6032  } else {
6033  OperationDAGEdge* e = new OperationDAGEdge(operand.index(), 1);
6034  dag->connectNodes(*opNode, *t, *e);
6035  }
6036  }
6037  return dag;
6038 }
6039 
6040 
6041 /**
6042  * Returns true if the operand corresponding to the given TerminalNode in
6043  * an OperationDAG can be immediate in the llvm pattern.
6044  *
6045  * @param dag DAG of the whole operation.
6046  * @param node TerminalNode corresponding to the operand queried.
6047  */
6048 bool
6050  const OperationDAG& dag, const TerminalNode& node) {
6051 
6052  if (dag.inDegree(node) != 0) {
6053  return false;
6054  }
6055 
6056  for (int i = 0; i < dag.outDegree(node); i++) {
6057  const OperationDAGEdge& edge = dag.outEdge(node, i);
6058  const OperationDAGNode& dstNode = dag.headNode(edge);
6059  const OperationNode* opNode =
6060  dynamic_cast<const OperationNode*>(&dstNode);
6061 
6062  if (opNode == NULL) {
6063  return false;
6064  }
6065  }
6066  return true;
6067 }
6068 
6069 #if 0
6070 void
6071 TDGen::generateLoadStoreCopyGenerator(std::ostream& os) {
6072  // vector store/load generation code
6073 
6074  TCEString prefix = "&"; // address of -operator
6075  TCEString rcpf = "RegsRegClass";
6076  TCEString rapf = "TCE::RARegRegClass";
6077  TCEString boolStore = littleEndian_ ? "ST8Brb;" : "STQBrb;";
6078  TCEString intStore = littleEndian_ ? "ST32" : "STW";
6079  TCEString halfStore = littleEndian_ ? "ST16" : "STH";
6080  TCEString longStore = "ST64";
6081 
6082  os << "#include <stdio.h>" << std::endl
6083  << "int GeneratedTCEPlugin::getStore(const TargetRegisterClass *rc)"
6084  << " const {" << std::endl;
6085 
6086  os << "\tif (rc == " << prefix << rapf
6087  << ") return TCE::" << intStore << "RArr;"
6088  << std::endl;
6089 
6090  for (RegClassMap::iterator ri = regsInClasses_.begin();
6091  ri != regsInClasses_.end(); ri++) {
6092 
6093  std::cerr << "Checking reg class: " << ri->first << " for stores." << std::endl;
6094 
6095  if (ri->first.find("R1") == 0 ||
6096  ri->first.find(guardRegTemplateName) == 0) {
6097  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6098  << rcpf << ") return TCE::" << boolStore << std::endl;
6099  }
6100  if (ri->first.find("R32") == 0) {
6101  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6102  << rcpf << ") return TCE::" << intStore << "rr;" << std::endl;
6103 
6104  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6105  << "I" << rcpf << ") return TCE::" << intStore << "rr;" << std::endl;
6106 
6107  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6108  << "FP" << rcpf << ") return TCE::" << intStore << "fr;" << std::endl;
6109 
6110  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6111  << "HFP" << rcpf << ") return TCE::" << halfStore << "hr;" << std::endl;
6112  }
6113  if (mach_.is64bit()) {
6114  if (ri->first.find("R64") == 0) {
6115  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6116  << rcpf << ") return TCE::" << longStore << "ss;" << std::endl;
6117  }
6118 
6119  if (ri->first.find("R64") == 0) {
6120  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6121  << "I" << rcpf << ") return TCE::" << longStore << "ss;" << std::endl;
6122  }
6123 
6124  if (ri->first.find("R64") == 0) {
6125  os << "\tif (rc == &TCE::" << ri->first << "FP" << rcpf
6126  << ") return TCE::" << longStore << "fs;" << std::endl;
6127  }
6128 
6129  if (ri->first.find("R64") == 0) {
6130  os << "\tif (rc == &TCE::" << ri->first << "HFP" << rcpf
6131  << ") return TCE::" << longStore << "hs;" << std::endl;
6132  }
6133 
6134  if (ri->first.find("R64") == 0) {
6135  os << "\tif (rc == &TCE::" << ri->first << "DFP" << rcpf
6136  << ") return TCE::" << longStore << "ds;" << std::endl;
6137  }
6138 
6139  }
6140  }
6141 
6142  if (use64bitForFP_) {
6143  os << "\tif (rc == &TCE::FPRegsRegClass) return TCE::ST64fs;"
6144  << std::endl;
6145 
6146  os << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::ST64hs;"
6147  << std::endl;
6148  } else {
6149  os << "\tif (rc == &TCE::FPRegsRegClass) return TCE::"
6150  << intStore << "fr;" << std::endl;
6151 
6152  os << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::"
6153  << intStore << "hr;" << std::endl;
6154  }
6155 
6156  for (RegClassMap::iterator ri = regsInRFClasses_.begin();
6157  ri != regsInRFClasses_.end(); ri++) {
6158  os << "\tif (rc == "
6159  << prefix << "TCE::R32_" << ri->first << "_"
6160  << rcpf << ") return TCE::" <<intStore << "rr;" << std::endl;
6161  }
6162 
6163  TCEString boolLoad = littleEndian_ ? "LD8" : "LDQ";
6164  if (!mach_.hasOperation(boolLoad)) {
6165  boolLoad = littleEndian_ ? "LDU8" : "LDQU";
6166  if (!mach_.hasOperation(boolLoad)) {
6167  boolLoad="";
6168  }
6169  }
6170 
6171  TCEString intLoad = littleEndian_ ? "LD32" : "LDW";
6172  TCEString halfLoad = littleEndian_ ? "LD16" : "LDH";
6173  TCEString longLoad = "LD64";
6174  if (!mach_.hasOperation(halfLoad)) {
6175  halfLoad = littleEndian_ ? "LDU16;" : "LDHU";
6176  if (!mach_.hasOperation(halfLoad)) {
6177  halfLoad="";
6178  }
6179  }
6180 
6181  os << "\tprintf(\"regclass of size %d \\n\",rc->MC->RegsSize);"
6182  << std::endl
6183  << "\tassert(0&&\"Storing given regclass to stack not supported. "
6184  << "Bug in backend?\");"
6185  << std::endl
6186  << "} " << std::endl
6187  << std::endl
6188 
6189  << "int GeneratedTCEPlugin::getLoad(const TargetRegisterClass *rc)"
6190  << " const {" << std::endl;
6191 
6192  os << "\tif (rc == " << prefix << rapf << ") return TCE::" << intLoad << "RAr;"
6193  << std::endl;
6194 
6195  if (!mach_.hasOperation(intLoad) && mach_.hasOperation("LDU32")) {
6196  intLoad = "LDU32";
6197  }
6198 
6199  for (RegClassMap::iterator ri = regsInClasses_.begin();
6200  ri != regsInClasses_.end(); ri++) {
6201  std::cerr << "Checking reg class: " << ri->first << " for loads." << std::endl;
6202  if (ri->first.find("R1") == 0) {
6203  if (boolLoad != "") {
6204  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6205  << rcpf <<") return TCE::" << boolLoad << "Br;" << std::endl;
6206  } else {
6207  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6208  << rcpf <<") return TCE::" << intLoad << "Br;" << std::endl;
6209  }
6210  }
6211  if (ri->first.find("R32") == 0) {
6212  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6213  << rcpf << ") return TCE::" << intLoad << "rr;" << std::endl;
6214 
6215  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6216  << "I" << rcpf << ") return TCE::" << intLoad << "rr;" << std::endl;
6217 
6218  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6219  << "FP" << rcpf << ") return TCE::" << intLoad << "fr;" << std::endl;
6220 
6221  if (halfLoad != "") {
6222  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6223  << "HFP" << rcpf << ") return TCE::" << halfLoad << "hr;" << std::endl;
6224  }
6225  }
6226 
6227  if (mach_.is64bit()) {
6228  if (ri->first.find("R64") == 0) {
6229  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6230  << rcpf << ") return TCE::" << longLoad << "ss;" << std::endl;
6231 
6232  os << "\tif (rc == " << prefix << "TCE::" << ri->first
6233  << "I" << rcpf << ") return TCE::" << longLoad << "ss;" << std::endl;
6234 
6235  os << "\tif (rc == &TCE::" << ri->first << "FP" << rcpf
6236  << ") return TCE::" << longLoad << "fs;" << std::endl;
6237 
6238  os << "\tif (rc == &TCE::" << ri->first << "HFP" << rcpf
6239  << ") return TCE::" << longLoad << "hs;" << std::endl;
6240 
6241  os << "\tif (rc == &TCE::" << ri->first << "DFP" << rcpf
6242  << ") return TCE::" << longLoad << "ds;" << std::endl;
6243  }
6244  }
6245  // TODO: double load!
6246 
6247  }
6248 
6249  // TODO: what is this?
6250  for (RegClassMap::iterator ri = regsInRFClasses_.begin();
6251  ri != regsInRFClasses_.end(); ri++) {
6252 
6253  os << "\tif (rc == " << prefix
6254  << "TCE::R32_" << ri->first << "_"
6255  << rcpf << ") return TCE::" << intLoad << "rr;" << std::endl;
6256 
6257  }
6258 
6259  if (use64bitForFP_) {
6260  os << "\tif (rc == &TCE::FPRegsRegClass) return TCE::LD64fs;"
6261  << std::endl;
6262 
6263  os << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::LD64hs;"
6264  << std::endl;
6265  } else {
6266  os << "\tif (rc == &TCE::FPRegsRegClass) return TCE::" << intLoad << "fr;"
6267  << std::endl;
6268 
6269  os << "\tif (rc == &TCE::HFPRegsRegClass) return TCE::" << intLoad << "hr;"
6270  << std::endl;
6271  }
6272 
6273  os << "\tprintf(\"regclass of size %d \\n\",rc->MC->RegsSize);"
6274  << std::endl
6275  << "\tassert(0&&\"loading from stack to given regclass not supported."
6276  << " Bug in backend?\");"
6277  << std::endl
6278  << "} " << std::endl
6279  << std::endl;
6280  }
6281 }
6282 
6283 #endif
6284 
6285 /**
6286  * Generates implementations of getLoad() and getStore() to Backend.inc file.
6287  *
6288  * @param os Output stream to the file.
6289  */
6290 void
6294 }
6295 
6297  const TCEString& opName, const TCEString& valueName, std::ostream& os) {
6298  if (opNames_.find(opName) != opNames_.end()) {
6299  os << "\tif (vt == MVT::" << valueName << ") return TCE::"
6300  << opName << ";" << std::endl;
6301  }
6302 }
6303 
6304 
6305 void
6307  const TCEString& baseOpName,
6308  int bits,
6309  char llvmTypeChar,
6310  const TCEString& postFix,
6311  std::ostream& os) {
6312 
6313  for (int elemCount=2; elemCount <= 1024; elemCount<<=1) {
6314  TCEString opName = baseOpName;
6315  opName << bits << "X" << elemCount << postFix;
6316  TCEString vecType = "v";
6317  vecType << elemCount << (TCEString)(llvmTypeChar) << bits;
6318  createMinMaxDef(opName, vecType, os);
6319  }
6320 }
6321 
6322 
6323 void
6324 TDGen::createMinMaxGenerator(std::ostream& os) {
6325 
6326  bool is64bit = mach_.is64bit();
6327  // MIN
6328  os << "int GeneratedTCEPlugin::getMinOpcode(SDNode* n) const {" << std::endl
6329  << "\tEVT vt = n->getOperand(1).getValueType();" << std::endl;
6330  if (!is64bit) {
6331  if (opNames_.find("MINrrr") != opNames_.end()) {
6332  os << "if (vt == MVT::i32) return TCE::MINrrr;" << std::endl;
6333  }
6334  } else {
6335  if (opNames_.find("MIN64sss") != opNames_.end()) {
6336  os << "if (vt == MVT::i64) return TCE::MIN64sss;" << std::endl;
6337  }
6338  }
6339  if (opNames_.find("MINFfff") != opNames_.end()) {
6340  os << "if (vt == MVT::f32) return TCE::MINFfff;" << std::endl;
6341  }
6342 
6343  createVectorMinMaxDef("MINH", 16, 'f', "ggg", os);
6344  createVectorMinMaxDef("MINF", 32, 'f', "eee", os);
6345  createVectorMinMaxDef("MIN", 32, 'i', "uuu", os);
6346  createVectorMinMaxDef("MIN", 16, 'i', "ttt", os);
6347 
6348  os << "\treturn -1; " << std::endl << "}" << std::endl;
6349 
6350  // MAX
6351  os << "int GeneratedTCEPlugin::getMaxOpcode(SDNode* n) const {" << std::endl
6352  << "\tEVT vt = n->getOperand(1).getValueType();" << std::endl;
6353 
6354  if (!is64bit) {
6355  if (opNames_.find("MAXrrr") != opNames_.end()) {
6356  os << "if (vt == MVT::i32) return TCE::MAXrrr;" << std::endl;
6357  }
6358  } else {
6359  if (opNames_.find("MAX64sss") != opNames_.end()) {
6360  os << "if (vt == MVT::i64) return TCE::MAX64sss;" << std::endl;
6361  }
6362 
6363  }
6364  if (opNames_.find("MAXFfff") != opNames_.end()) {
6365  os << "if (vt == MVT::f32) return TCE::MAXFfff;" << std::endl;
6366  }
6367 
6368  createVectorMinMaxDef("MAXH", 16, 'f', "ggg", os);
6369  createVectorMinMaxDef("MAXF", 32, 'f', "eee", os);
6370  createVectorMinMaxDef("MAX", 32, 'i', "uuu", os);
6371  createVectorMinMaxDef("MAX", 16, 'i', "ttt", os);
6372 
6373  os << "\treturn -1; " << std::endl << "}" << std::endl;
6374 
6375  // MINU
6376  os << "int GeneratedTCEPlugin::getMinuOpcode(SDNode* n) const {" << std::endl;
6377  os << "\tEVT vt = n->getOperand(1).getValueType();" << std::endl;
6378 
6379  if (!is64bit) {
6380  if (opNames_.find("MINUrrr") != opNames_.end()) {
6381  os << "if (vt == MVT::i32) return TCE::MINUrrr;" << std::endl;
6382  }
6383  } else {
6384  if (opNames_.find("MINU64sss") != opNames_.end()) {
6385  os << "if (vt == MVT::i64) return TCE::MINU64sss;" << std::endl;
6386  }
6387  }
6388  createVectorMinMaxDef("MINU", 32, 'i', "uuu", os);
6389  createVectorMinMaxDef("MINU", 16, 'i', "ttt", os);
6390 
6391  os << "\treturn -1; " << std::endl << "}" << std::endl;
6392 
6393  // MAXU
6394  os << "int GeneratedTCEPlugin::getMaxuOpcode(SDNode* n) const {" << std::endl;
6395  os << "\tEVT vt = n->getOperand(1).getValueType();" << std::endl;
6396 
6397 
6398  if (!is64bit) {
6399  if (opNames_.find("MAXUrrr") != opNames_.end()) {
6400  os << "if (vt == MVT::i32) return TCE::MAXUrrr;" << std::endl;
6401  }
6402  } else {
6403  if (opNames_.find("MAXU64sss") != opNames_.end()) {
6404  os << "if (vt == MVT::i64) return TCE::MAXU64sss;" << std::endl;
6405  }
6406  }
6407 
6408  createVectorMinMaxDef("MAXU", 32, 'i', "uuu", os);
6409  createVectorMinMaxDef("MAXU", 16, 'i', "ttt", os);
6410  os << "\treturn -1; " << std::endl << "}" << std::endl;
6411 }
6412 
6413 void TDGen::createEndiannesQuery(std::ostream& os) {
6414  bool is64bit = mach_.is64bit();
6415  os << "bool GeneratedTCEPlugin::isLittleEndian() const {" << std::endl;
6416  os << "return " << littleEndian_ << "; }" << std::endl;
6417  os << "bool GeneratedTCEPlugin::is64bit() const {" << std::endl;
6418  os << "return " << is64bit << "; }" << std::endl;
6419 }
6420 
6421 /**
6422  * Creates query function for TCEISelLowering for testing if otherwise
6423  * unsupported constant as immediate can be materialized instead of converting
6424  * it to constant pool load.
6425  */
6426 void
6428 
6429  if (constantMaterializationPredicates_.empty()) {
6430  os << "bool GeneratedTCEPlugin::canMaterializeConstant("
6431  << "const ConstantInt&) const { " << std::endl
6432  << " return false;" << std::endl
6433  << "};" << std::endl;
6434  return;
6435  }
6436 
6437  os << "bool GeneratedTCEPlugin::canMaterializeConstant("
6438  << "const ConstantInt& ci) const {"
6439  << std::endl
6440  << " int64_t Imm = ci.getSExtValue();" << std::endl
6441  << " if (";
6442  bool first = true;
6443  for (auto& predicate : constantMaterializationPredicates_) {
6444  if (!first) {
6445  os << std::endl << " || ";
6446  }
6447  os << "(" << predicate << ")";
6448  first = false;
6449  }
6450  os << ") {"
6451  << " return true;" << std::endl
6452  << " }" << std::endl
6453  << " return false;" << std::endl
6454  << "}" << std::endl;
6455 }
6456 
6457 void TDGen::createByteExtLoadPatterns(std::ostream& os) {
6458  TCEString load = littleEndian_ ? "LD8" : "LDQ";
6459  TCEString uload = littleEndian_ ? "LDU8" : "LDQU";
6460  TCEString destSize = mach_.is64bit() ? "64" : "32";
6461  int bits = mach_.is64bit() ? 64 : 32;
6462  TCEString ANDIMM = mach_.is64bit() ? "AND64ssa" : "ANDrri";
6463  TCEString ANDREG = mach_.is64bit() ? "AND64sss" : "ANDrrr";
6464  TCEString SUBIMM = mach_.is64bit() ? "SUB64sas" : "SUBrir";
6465  TCEString EXTOP = mach_.is64bit() ? "SXQ64" : "SXQW";
6466  TCEString EXTOPC = mach_.is64bit() ? "SXQ64sr" : "SXQWrr";
6467  TCEString SHL = mach_.is64bit() ? "SHL" : "SHL64";
6468  TCEString SHR = mach_.is64bit() ? "SHR" : "SHR64";
6469  TCEString SHRU = mach_.is64bit() ? "SHRU" : "SHRU64ssa";
6470  TCEString SHLOPC = mach_.is64bit() ? "SHLrri" : "SHL64ssa";
6471  TCEString SHROPC = mach_.is64bit() ? "SHRrri" : "SHR64ssa";
6472  TCEString SHRUOPC = mach_.is64bit() ? "SHRUrri" : "SHRU64ssa";
6473  TCEString SHL4 = mach_.is64bit() ? "SHL4_32" : "SHL4_64";
6474  TCEString SHR4 = mach_.is64bit() ? "SHR4_32" : "SHR4_64";
6475  TCEString SHRU4 = mach_.is64bit() ? "SHRU4_32" : "SHRU4_64ssa";
6476  TCEString regSrcChar = mach_.is64bit() ? OT_REG_LONG : OT_REG_INT;
6477  TCEString dstTypeChar = OT_REG_INT;
6478  TCEString immSrcChar = mach_.is64bit() ? OT_IMM_LONG : OT_IMM_INT;
6479  TCEString loadOpcReg = load + dstTypeChar + regSrcChar;
6480  TCEString loadOpcImm = load + dstTypeChar + immSrcChar;
6481 
6482  if (mach_.hasOperation(load)) {
6483  if (!mach_.hasOperation(uload)) {
6484 
6485  // emulate zero ext with sing-ext and and
6486  os << "def : Pat<(i" << destSize << " (zextloadi8 ADDRrr:$addr)), "
6487  << "(" << ANDIMM << " ("
6488  << loadOpcReg << " ADDRrr:$addr), 255)>;"
6489  << std::endl;
6490  os << "def : Pat<(i" << destSize << " (zextloadi8 ADDRri:$addr)), "
6491  << "(" << ANDIMM << " ("
6492  << loadOpcImm << " ADDRri:$addr), 255)>;"
6493  << std::endl;
6494  }
6495  } else {
6496  // if no sign ext load, try zero ext load
6497  if (!mach_.hasOperation(uload)) {
6498  std::cerr << "Warning: The architecture is missing any 8-bit loads."
6499  << " All code may not compile!"
6500  << std::endl;
6501  return;
6502  }
6503  loadOpcReg = uload + dstTypeChar + regSrcChar;
6504  loadOpcImm = uload + dstTypeChar + immSrcChar;
6505 
6506  if (mach_.hasOperation(EXTOP)) {
6507  // use zextload + sext for sextload
6508  os << "def : Pat<(i" << destSize
6509  << " (sextloadi8 ADDRrr:$addr)), "
6510  << "(" << EXTOPC << " ("
6511  << loadOpcReg << " ADDRrr:$addr))>;" << std::endl;
6512  os << "def : Pat<(i" << destSize
6513  << " (sextloadi8 ADDRri:$addr)), "
6514  << "(" << EXTOPC << " ("
6515  << loadOpcImm << " ADDRri:$addr))>;" << std::endl;
6516 
6517  } else {
6518  if (mach_.hasOperation(SHL) && mach_.hasOperation(SHR)) {
6519 
6520  int sb = bits -8;
6521  os << "def : Pat<(i" << destSize
6522  << " (sextloadi16 ADDRrr:$addr)), "
6523  << "(" << SHROPC << " (" << SHLOPC << " ("
6524  << load << "rr ADDRrr:$addr), "
6525  << sb << "), " << sb << ")>;" << std::endl;
6526 
6527  os << "def : Pat<(i" << destSize
6528  << " (sextloadi16 ADDRri:$addr)), "
6529  << "(" << SHROPC << " (" << SHLOPC << " ("
6530  << load << "ri ADDRri:$addr), "
6531  << sb << "), " << sb << ")>;" << std::endl;
6532  } else if (mach_.hasOperation(SHL4) &&
6533  mach_.hasOperation(SHR4)) {
6534  if (!mach_.is64bit()) {
6535  os << "def : Pat<(i32 (sextloadi8 ADDRrr:$addr)), "
6536  << "(SHR4_32rr (SHR4_32rr (SHR4_32rr (SHR4_32rr "
6537  << "(SHR4_32rr (SHR4_32rr "
6538  << "(SHL4_32rr (SHL4_32rr (SHL4_32rr (SHL4_32rr "
6539  << "(SHL4_32rr (SHL4_32rr ("
6540  << load << "rr ADDRrr:$addr)))))))))))))>;"
6541  << std::endl;
6542 
6543  os << "def : Pat<(i32 (sextloadi8 ADDRri:$addr)), "
6544  << "(SHR4_32rr (SHR4_32rr (SHR4_32rr (SHR4_32rr "
6545  << "(SHR4_32rr (SHR4_32rr "
6546  << "(SHL4_32rr (SHL4_32rr (SHL4_32rr (SHL4_32rr "
6547  << "(SHL4_32rr (SHL4_32rr ("
6548  << load << "ri ADDRri:$addr)))))))))))))>;"
6549  << std::endl;
6550  } else {
6551  os << "def : Pat<(i64 (sextloadi8 ADDRrr:$addr)), "
6552  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6553  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6554  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6555  << "(SHR4_64ss (SHR4_64ss "
6556  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6557  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6558  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6559  << "(SHL4_64ss (SHL4_64ss ("
6560  << load << "rr ADDRrr:$addr)))))))))))))>;"
6561  << std::endl;
6562 
6563  os << "def : Pat<(i64 (sextloadi8 ADDRri:$addr)), "
6564  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6565  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6566  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6567  << "(SHR4_64ss (SHR4_64ss "
6568  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6569  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6570  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6571  << "(SHL4_64ss (SHL4_64ss ("
6572  << load << "ri ADDRri:$addr)))))))))))))>;"
6573  << std::endl;
6574  }
6575  } else {
6576  std::cerr << "Warning: no sign-extending 8-bit loads,"
6577  << " 8-bit sign extension instruction or suitable"
6578  << " shifts for sext-emulation in the processor."
6579  << " All code may not compile!" << std::endl;
6580  }
6581  }
6582  }
6583 
6584  // TODO: is there a more capable version of this code
6585  // commented out above???
6586 
6587  os << "def : Pat<(i" << destSize << " (zextloadi1 ADDRrr:$addr)), ("
6588  << loadOpcReg << " ADDRrr:$addr)>;"
6589  << std::endl
6590  << "def : Pat<(i" << destSize << " (zextloadi1 ADDRri:$addr)), ("
6591  << loadOpcImm << " ADDRri:$addr)>;"
6592  << std::endl;
6593 
6594  os << "def : Pat<(i" << destSize << " (sextloadi1 ADDRrr:$addr)), "
6595  << "(" << SUBIMM << " 0, "
6596  << "(" << ANDREG << " ("
6597  << loadOpcReg << " ADDRrr:$addr), 1))>;"
6598  << std::endl
6599  << "def : Pat<(i" << destSize << " (sextloadi1 ADDRri:$addr)), "
6600  << "(" << SUBIMM << " 0, "
6601  << "(" << ANDREG << " ("
6602  << loadOpcImm << " ADDRri:$addr), 1))>;"
6603  << std::endl
6604  << "// anyextloads" << std::endl;
6605 
6606  os << "def : Pat<(i" << destSize << " (extloadi1 ADDRrr:$src)), ("
6607  << loadOpcReg << " ADDRrr:$src)>;" << std::endl
6608  << "def : Pat<(i" << destSize << " (extloadi1 ADDRri:$src)), ("
6609  << loadOpcImm << " ADDRri:$src)>;" << std::endl
6610  << "def : Pat<(i" << destSize << " (extloadi8 ADDRrr:$src)), ("
6611  << loadOpcReg << " ADDRrr:$src)>;" << std::endl
6612  << "def : Pat<(i" << destSize << " (extloadi8 ADDRri:$src)), ("
6613  << loadOpcImm << " ADDRri:$src)>;" << std::endl
6614  << std::endl;
6615 }
6616 
6617 void TDGen::createShortExtLoadPatterns(std::ostream& os) {
6618  TCEString load = littleEndian_ ? "LD16" : "LDH";
6619  TCEString destSize = mach_.is64bit() ? "64" : "32";
6620  int bits = mach_.is64bit() ? 64 : 32;
6621  TCEString ANDOPC = mach_.is64bit() ? "AND64ssa" : "ANDrri";
6622  TCEString uload = littleEndian_ ? "LDU16" : "LDHU";
6623  TCEString EXTOP = mach_.is64bit() ? "SXH64" : "SXHW";
6624  TCEString EXTOPC = mach_.is64bit() ? "SXH64sr" : "SXHWrr";
6625  TCEString regSrcChar = mach_.is64bit() ? OT_REG_LONG : OT_REG_INT;
6626  TCEString dstTypeChar = OT_REG_INT;
6627  TCEString immSrcChar = mach_.is64bit() ? OT_IMM_LONG : OT_IMM_INT;
6628  TCEString loadOpcReg = load + dstTypeChar + regSrcChar;
6629  TCEString loadOpcImm = load + dstTypeChar + immSrcChar;
6630 
6631  TCEString SHL = mach_.is64bit() ? "SHL" : "SHL64";
6632  TCEString SHR = mach_.is64bit() ? "SHR" : "SHR64";
6633  TCEString SHRU = mach_.is64bit() ? "SHRU" : "SHRU64ssa";
6634  TCEString SHLOPC = mach_.is64bit() ? "SHLrri" : "SHL64ssa";
6635  TCEString SHROPC = mach_.is64bit() ? "SHRrri" : "SHR64ssa";
6636  TCEString SHRUOPC = mach_.is64bit() ? "SHRUrri" : "SHRU64ssa";
6637  TCEString SHL4 = mach_.is64bit() ? "SHL4_32" : "SHL4_64";
6638  TCEString SHR4 = mach_.is64bit() ? "SHR4_32" : "SHR4_64";
6639  TCEString SHRU4 = mach_.is64bit() ? "SHRU4_32" : "SHRU4_64ssa";
6640 
6641  if (mach_.hasOperation(load)) {
6642  if (!mach_.hasOperation(uload)) {
6643  // emulate zero ext with sing-ext and and
6644  os << "def : Pat<(i" << destSize
6645  << " (zextloadi16 ADDRrr:$addr)), "
6646  << "(" << ANDOPC << " (" << loadOpcReg
6647  << " ADDRrr:$addr), 65535)>;" << std::endl;
6648  os << "def : Pat<(i" << destSize
6649  << " (zextloadi16 ADDRri:$addr)), "
6650  << "(" << ANDOPC << " ("
6651  << loadOpcImm << " ADDRri:$addr), 65535)>;" << std::endl;
6652  }
6653  } else {
6654  if (!mach_.hasOperation(uload)) {
6655  std::cerr << "Warning: The architecture is missing any 16-bit loads."
6656  << std::endl;
6657  return;
6658  }
6659  loadOpcReg = uload + dstTypeChar + regSrcChar;
6660  loadOpcImm = uload + dstTypeChar + immSrcChar;
6661 
6662  if (mach_.hasOperation(EXTOP)) {
6663  // use zextload + sext for sextload
6664  os << "def : Pat<(i" << destSize
6665  << " (sextloadi16 ADDRrr:$addr)), "
6666  << "(" << EXTOPC
6667  << " (" << loadOpcReg << " ADDRrr:$addr))>;" << std::endl;
6668  os << "def : Pat<(i" << destSize
6669  << " (sextloadi16 ADDRri:$addr)), "
6670  << "(" << EXTOPC
6671  << " (" << loadOpcImm << " ADDRri:$addr))>;" << std::endl;
6672  } else {
6673  if (mach_.hasOperation(SHL) && mach_.hasOperation(SHR)) {
6674  int sb = bits -16;
6675  os << "def : Pat<(i" << destSize
6676  << " (sextloadi16 ADDRrr:$addr)), "
6677  << "(" << SHROPC << " (" << SHLOPC << " ("
6678  << load << "rr ADDRrr:$addr), "
6679  << sb << "), " << sb << ")>;" << std::endl;
6680 
6681  os << "def : Pat<(i" << destSize
6682  << " (sextloadi16 ADDRri:$addr)), "
6683  << "(" << SHROPC << " (" << SHLOPC << " ("
6684  << load << "ri ADDRri:$addr), "
6685  << sb << "), " << sb << ")>;" << std::endl;
6686  } else if (mach_.hasOperation(SHL4) &&
6687  mach_.hasOperation(SHR4)) {
6688  if (!mach_.is64bit()) {
6689  os << "def : Pat<(i32 (sextloadi16 ADDRrr:$addr)), "
6690  << "(SHR4_32rr (SHR4_32rr (SHR4_32rr (SHR4_32rr "
6691  << "(SHL4_32rr (SHL4_32rr (SHL4_32rr (SHL4_32rr ("
6692  << load << "rr ADDRrr:$addr)))))))))>;" << std::endl;
6693 
6694  os << "def : Pat<(i32 (sextloadi16 ADDRri:$addr)), "
6695  << "(SHR4_32rr (SHR4_32rr (SHR4_32rr (SHR4_32rr "
6696  << "(SHL4_32rr (SHL4_32rr (SHL4_32rr (SHL4_32rr ("
6697  << load << "ri ADDRri:$addr)))))))))>;" << std::endl;
6698  } else {
6699  os << "def : Pat<(i64 (sextloadi8 ADDRrr:$addr)), "
6700  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6701  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6702  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6703  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6704  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6705  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss ("
6706  << load << "rr ADDRrr:$addr)))))))))))))>;"
6707  << std::endl;
6708 
6709  os << "def : Pat<(i64 (sextloadi8 ADDRri:$addr)), "
6710  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6711  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6712  << "(SHR4_64ss (SHR4_64ss (SHR4_64ss (SHR4_64ss "
6713  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6714  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss "
6715  << "(SHL4_64ss (SHL4_64ss (SHL4_64ss (SHL4_64ss ("
6716  << load << "ri ADDRri:$addr)))))))))))))>;"
6717  << std::endl;
6718  }
6719  } else {
6720  std::cerr << "Warning: no sign-extending 16-bit loads,"
6721  << " 16-bit sign extension instruction or suitable"
6722  << " shifts for sext-emulation in the processor."
6723  << " All code may not compile!" << std::endl;
6724  }
6725  }
6726  }
6727  // anyext
6728  os << "def : Pat<(i" << destSize << " (extloadi16 ADDRrr:$src)), ("
6729  << loadOpcReg << " ADDRrr:$src)>;" << std::endl
6730  << "def : Pat<(i" << destSize << " (extloadi16 ADDRri:$src)), ("
6731  << loadOpcImm << " ADDRri:$src)>;" << std::endl;
6732 }
6733 
6734 void TDGen::create32BitExtLoadPatterns(std::ostream& os) {
6735  TCEString load = "LD32";
6736  const TCEString uload = "LDU32";
6737  TCEString ZXOP = "ZXW64";
6738  TCEString ZXOPC = "ZXW64ss";
6739 
6740  if (mach_.hasOperation(load)) {
6741  if (!mach_.hasOperation(uload)) {
6742  if (!mach_.hasOperation(ZXOP)) {
6743  // emulate zero ext with sing-ext and and
6744  os << "def : Pat<(i64 (zextloadi32 ADDRrr:$addr)), "
6745  << "(AND64ssa (LD32ss ADDRrr:$addr),"
6746  << "0xffffffff)>;" << std::endl;
6747 
6748  os << "def : Pat<(i64 (zextloadi32 ADDRri:$addr)), "
6749  << "(AND64ssa (LD32sa ADDRri:$addr),"
6750  << "0xffffffff)>;" << std::endl;
6751  } else {
6752  // use zxw64 instr for zext
6753  os << "def : Pat<(i64 (zextloadi32 ADDRrr:$addr)), "
6754  << "(" << ZXOPC << " (LD32ss ADDRrr:$addr))>;" <<std::endl;
6755 
6756  os << "def : Pat<(i64 (zextloadi32 ADDRri:$addr)), "
6757  << "(" << ZXOPC << " (LD32sa ADDRri:$addr))>;" <<std::endl;
6758  }
6759  }
6760  } else {
6761  if (!mach_.hasOperation(uload)) {
6762  std::cerr << "Warning: The architecture is missing any 16-bit loads."
6763  << std::endl;
6764  return;
6765  }
6766  load = uload;
6767 
6768  if (mach_.hasOperation("SXW64")) {
6769  // use zextload + sext for sextload
6770  os << "def : Pat<(i64 (sextloadi32 ADDRrr:$addr)), "
6771  << "(SXW64ss (LDU32ss ADDRrr:$addr))>;" << std::endl;
6772 
6773  os << "def : Pat<(i64 (sextloadi32 ADDRri:$addr)), "
6774  << "(SXW64ss (LDU32sa ADDRri:$addr))>;" << std::endl;
6775  } else {
6776  std::cerr << "Warning: no sign-extending 32-bit loads or"
6777  << " 32-bit sign extension instruction!"
6778  << " in the processor. All code may not compile!"
6779  << std::endl;
6780  }
6781  }
6782  // anyext.
6783  os << "def : Pat<(i64 (extloadi32 ADDRrr:$src)), "
6784  << "(" << load << "ss ADDRrr:$src)>;" << std::endl
6785 
6786  << "def : Pat<(i64 (extloadi32 ADDRri:$src)), "
6787  << "(" << load << "sa ADDRrr:$src)>;" << std::endl;
6788 }
6789 
6790 /**
6791  * Writes details about function arguments and returns values.
6792  *
6793  * @param o Output stream to the file.
6794  */
6795 void
6796 TDGen::writeCallingConv(std::ostream& os) {
6798 
6799  int bits = mach_.is64bit() ? 64 : 32;
6800  int bytes = mach_.is64bit() ? 8 : 4;
6801  // Function return value types.
6802  os << "// Function return value types." << endl;
6803  os << "def RetCC_TCE : CallingConv<[" << endl;
6804  if (mach_.is64bit()) {
6805  os << " CCIfType<[i1], CCPromoteToType<i64>>," << endl
6806  << " CCIfType<[i32], CCPromoteToType<i64>>," << endl
6807  << " CCIfType<[i64], CCAssignToReg<[IRES0]>>," << endl
6808  << " CCIfType<[f64], CCAssignToReg<[IRES0]>>," << endl << endl;
6809  } else {
6810  os << " CCIfType<[i1], CCPromoteToType<i32>>," << endl;
6811  os << " CCIfType<[i32], CCAssignToReg<[IRES0]>>," << endl;
6812  }
6813 
6814  os << " CCIfType<[f16], CCAssignToReg<[IRES0]>>," << endl
6815  << " CCIfType<[f32], CCAssignToReg<[IRES0]>>," << endl << endl;
6816 
6817  os << " // Vector value types." << endl;
6818  std::map<TCEString, RegisterClass>::const_iterator rcIt;
6819  for (rcIt = vRegClasses_.begin(); rcIt != vRegClasses_.end(); ++rcIt) {
6820  const TCEString& vtStr = rcIt->first;
6821  const RegisterClass& regClass = rcIt->second;
6822 
6823  if (regClass.numberOfRegisters() > 0) {
6824  os << " CCIfType<[" << vtStr << "], CCAssignToReg<[";
6825  if (regClass.valueType().width() <= bits) {
6826  os << "IRES0";
6827  } else {
6828  os << regClass.registerInfo(0).regName_;
6829  }
6830  os << "]>>," << endl;
6831  } else {
6832  verbose("ValueType " + vtStr + " can not be a return value");
6833  }
6834  }
6835 
6836  os << " CCAssignToStack<" << bytes << ", " << bytes << ">" << endl
6837  << "]>;" << endl << endl;
6838 
6839  // Function argument value types.
6840  os << "// Function argument value types." << endl;
6841  os << "def CC_TCE : CallingConv<[" << endl;
6842  if (mach_.is64bit()) {
6843  os << " CCIfType<[i1, i8, i16, i32], CCPromoteToType<i64>>," << endl
6844  << " CCIfType<[i64], CCAssignToReg<[IRES0]>>," << endl << endl;
6845 
6846  for (unsigned int i = 4; i < (3 + argRegCount_); i++) {
6847  os << " CCIfType<[i64], CCAssignToReg<[A" << i << "]>>," << endl;
6848  }
6849 
6850  } else {
6851  os << " CCIfType<[i1, i8, i16], CCPromoteToType<i32>>," << endl
6852  << " CCIfType<[i32], CCAssignToReg<[IRES0]>>," << endl << endl;
6853 
6854  for (unsigned int i = 4; i < (3 + argRegCount_); i++) {
6855  os << " CCIfType<[i32], CCAssignToReg<[A" << i << "]>>," << endl;
6856  }
6857  }
6858 
6859  if (mach_.is64bit()) {
6860  os << " // 64-bit integer values get stored in stack slots that are"
6861  << endl
6862  << " // 8 bytes insize and 8-byte aligned." << endl
6863  << " CCIfType<[i64, f64, f32], CCAssignToStack<8, 8>>,"
6864  << endl << endl;
6865  } else {
6866  os << " // Integer values get stored in stack slots that are" << endl
6867  << " // 4 bytes insize and 4-byte aligned." << endl
6868  << " CCIfType<[i32, f32], CCAssignToStack<4, 4>>," << endl << endl;
6869  }
6870  os << " // Double values get stored in stack slots that are" << endl
6871  << " // 8 bytes in size and 8-byte aligned." << endl
6872  << " CCIfType<[f64], CCAssignToStack<8, 8>>";
6873 
6874  if (vRegClasses_.size() > 0) {
6875  os << ",";
6876  }
6877  os << endl << endl;
6878 
6879  os << " // Vector value types." << endl;
6880  for (rcIt = vRegClasses_.begin(); rcIt != vRegClasses_.end(); ++rcIt) {
6881  const TCEString& vtStr = rcIt->first;
6882  const RegisterClass& regClass = rcIt->second;
6883 
6884  int byteAlignment = regClass.alignment() / 8;
6885  if (byteAlignment < bytes) {
6886  byteAlignment = bytes;
6887  }
6888 
6889  os << " CCIfType<[" << vtStr << "], CCAssignToStack<"
6890  << byteAlignment << ", " << byteAlignment << ">>";
6891  if (rcIt != --vRegClasses_.end()) {
6892  os << ",";
6893  }
6894  os << endl;
6895  }
6896 
6897  os << "]>;" << endl;
6898 }
6899 
6900 void
6902  os << "//===- GenCallingConv.td - Calling Conventions TCE ---------*- "
6903  << "tablegen -*-===//" << std::endl
6904  << "// " << std::endl
6905  << "// The LLVM Compiler Infrastructure" << std::endl
6906  << "//" << std::endl
6907  << "// This file is distributed under the University of "
6908  << "Illinois Open Source" << std::endl
6909  << "// License. See LICENSE.TXT for details." << std::endl
6910  << "// " << std::endl
6911  << "//===--------------------------------------------------------"
6912  << "--------------===//" << std::endl
6913  << "//" << std::endl
6914  << "// This describes the calling conventions for the TCE "
6915  << "architectures." << std::endl
6916  << "//" << std::endl
6917  << "//===--------------------------------------------------------"
6918  << "--------------===//" << std::endl << std::endl;
6919 }
6920 
6921 void
6922 TDGen::writeArgRegsArray(std::ostream& os) {
6923  os << "#ifndef ARGREGS_HH" << std::endl
6924  << "#define ARGREGS_HH" << std::endl << std::endl
6925  << "static const unsigned ArgRegs[] = { TCE::IRES0" << std::endl;
6926  for (unsigned int i = 4; i < (3 + argRegCount_); i++) {
6927  os << ",TCE::A" << i;
6928  }
6929  os << "};" << std::endl;
6930 
6931  os << "static const int argRegCount = " << argRegCount_ <<";" << std::endl
6932  << "#endif" << std::endl;
6933 }
6934 
6935 void
6936 TDGen::createParamDRegNums(std::ostream& os) {
6937  os <<
6938  "std::vector<unsigned>" << std::endl <<
6939  "GeneratedTCEPlugin::getParamDRegNums() const {" << std::endl <<
6940  "std::vector<unsigned> res;" << std::endl;
6941  for (unsigned int i = 4; i < argRegCount_ + 3; i++) {
6942  os << "res.push_back(TCE::A" << i << ");" << std::endl;
6943  }
6944  os << "return res;}" << std::endl;
6945 }
6946 
6947 void
6949  os <<
6950  "std::vector<unsigned>" << std::endl <<
6951  "GeneratedTCEPlugin::getVectorRVDRegNums() const {" << std::endl <<
6952  "std::vector<unsigned> res;" << std::endl;
6953 
6954  std::set<TCEString> processedRegs;
6955  for (auto rcIt : vRegClasses_) {
6956  const RegisterClass& regClass = rcIt.second;
6957 
6958  int width = regClass.valueType().width();
6959  if (regClass.numberOfRegisters() > 0) {
6960  const TCEString& name = regClass.registerInfo(0).regName_;
6961  if (processedRegs.find(name) == processedRegs.end() &&
6962  width > maxScalarWidth_) {
6963  processedRegs.insert(name);
6964 
6965  os << "res.push_back(TCE::" << name << ");" << std::endl;
6966  }
6967  }
6968  }
6969  os << "return res;}" << std::endl;
6970 }
6971 
6972 // TODO: this should be based on vector widths???
6973 void
6974 TDGen::createGetMaxMemoryAlignment(std::ostream& os) const {
6975  if (mach_.is64bit()) {
6976  os << std::endl
6977  << "unsigned GeneratedTCEPlugin::getMaxMemoryAlignment() const {"
6978  << std::endl
6979  << "\treturn 8;"
6980  << std::endl << "}" << std::endl;
6981  } else {
6982  os << std::endl
6983  << "unsigned GeneratedTCEPlugin::getMaxMemoryAlignment() const {"
6984  << std::endl
6985  << "\treturn 4;"
6986  << std::endl << "}" << std::endl;
6987  }
6988 }
6989 
6990 
6991 void TDGen::createSelectPatterns(std::ostream& os) {
6992  os << "// Creating select patterns. " << std::endl;
6993  if (!hasSelect_) {
6994  os << "// Does not have select instr. " << std::endl;
6995  if (!hasConditionalMoves_) {
6996  std::string NEG = mach_.is64bit() ? "NEG64" : "NEG";
6997  std::string NEGOPC = mach_.is64bit() ? "NEG64ss" : "NEGrr";
6998  std::string gprRegs = mach_.is64bit() ? "R64IRegs" : "R32IRegs";
6999  std::string typeStr = mach_.is64bit() ? "ssa" : "rri";
7000  std::string typeStrInv = mach_.is64bit() ? "sas" : "rir";
7001 
7002  const char* sub = mach_.is64bit() ? "SUB64" : "SUB";
7003  const char* iand = mach_.is64bit() ? "AND64" : "AND";
7004  std::string ior = mach_.is64bit() ? "IOR64" : "IOR";
7005  std::string defType = mach_.is64bit() ? "i64" : "i32";
7006  std::string andReg = mach_.is64bit() ? "AND64sss" : "ANDrrr";
7007  std::string iorReg = mach_.is64bit() ? "IOR64sss" : "IORrrr";
7008 
7009  std::string iorBool = mach_.is64bit() ? "IOR64bbb" : "IORbbb";
7010  std::string andBool = mach_.is64bit() ? "AND64bbb" : "ANDbbb";
7011  std::string xorBooli = mach_.is64bit() ? "XOR64bbj" : "XORbbj";
7012 
7013  bool hasNeg = opNames_.count("NEGrr");
7014 
7015  std::string condRC = regs1bit_.empty() ? gprRegs : "R1Regs";
7016  std::string truncOp = regs1bit_.empty() ? std::string(iand) + typeStr : "ANDext";
7017  OperationPool opPool;
7018  std::string truncPattern = regs1bit_.empty()
7019  ? std::string("$c")
7020  : std::string("(") + truncOp + " " + condRC + ":$c" + ", 1)";
7021  std::string falseMask = getLLVMPatternWithConstants(
7022  opPool.operation(sub), typeStr, truncPattern, "1");
7023 
7024  std::string trueMask = hasNeg ?
7025  std::string("(" + NEGOPC + " ") + truncPattern +
7026  std::string(")")
7028  opPool.operation(sub), typeStrInv, "0", truncPattern);
7029 
7030  std::string applyTrueMaskOnImm = getLLVMPatternWithConstants(
7031  opPool.operation(iand), typeStr, trueMask, "imm:$t");
7032  std::string applyFalseMaskOnImm = getLLVMPatternWithConstants(
7033  opPool.operation(iand), typeStr, falseMask, "imm:$f");
7034 
7035 #if 0 // TODO: why is this commented out???
7036  if (mach_.is64bit()) {
7037  os << std::endl
7038  << "def : Pat<(i64 (select R1Regs:$c, R64Regs:$t, R64Regs:$f)), "
7039  << "(IOR64sss (AND64sss R32Regs:$t, (SUB64sas 0, (ANDext R1Regs:$c, 1))),"
7040  << "(AND64sss R32Regs:$f, (SUB64ssa (ANDext R1Regs:$c, 1), 1)))>;"
7041  << std::endl << std::endl
7042 
7043  << "def : Pat<(i64 (select R1Regs:$c, (i64 imm:$t),(i64 imm:$f))),"
7044  << "(IOR64sss (AND64ssa (SUB64sas 0, (ANDext R1Regs:$c, 1)), imm:$t),"
7045  << "(AND64ssa (SUB64ssa (ANDext R1Regs:$c, 1), 1), imm:$f))>;"
7046  << std::endl << std::endl
7047 
7048  << "def : Pat<(i64 (select R1Regs:$c, R64Regs:$t, (i64 imm:$f))),"
7049  << "(IOR64sss (AND64sss (SUB64sas 0, (ANDext R1Regs:$c, 1)), R32Regs:$t),"
7050  << "(AND64ssa (SUB64ssa (ANDext R1Regs:$c, 1), 1), imm:$f))>;"
7051  << std::endl << std::endl
7052 
7053  << "def : Pat<(i64 (select R1Regs:$c, (i64 imm:$t), R64Regs:$f)),"
7054  << "(IOR64sss (AND64ssa (SUB64sas 0, (ANDext R1Regs:$c, 1)), imm:$t),"
7055  << "(AND64sss (SUB64ssa (ANDext R1Regs:$c, 1), 1), R32Regs:$f))>;"
7056  << std::endl << std::endl;
7057 
7058  os << std::endl
7059  << "def : Pat<(i64 (select R1Regs:$c, R64Regs:$t, R64Regs:$f)), "
7060  << "(IOR64sss (AND64sss R64Regs:$t, (SUB64sas 0, (ANDext R1Regs:$c, 1))),"
7061  << "(AND64sss R64Regs:$f, (SUB64ssa (ANDext R1Regs:$c, 1), 1)))>;"
7062  << std::endl << std::endl
7063 
7064  << "def : Pat<(i64 (select R1Regs:$c, (i64 imm:$t),(i64 imm:$f))),"
7065  << "(IOR64sss (AND64ssa (SUB64sas 0, (ANDext R1Regs:$c, 1)), imm:$t),"
7066  << "(AND64ssa (SUB64ssa (ANDext R1Regs:$c, 1), 1), imm:$f))>;"
7067  << std::endl << std::endl
7068 
7069  << "def : Pat<(i64 (select R1Regs:$c, R64Regs:$t, (i64 imm:$f))),"
7070  << "(IOR64sss (AND64sss (SUB64sas 0, (ANDext R1Regs:$c, 1)), R64Regs:$t),"
7071  << "(AND64ssa (SUB64ssa (ANDext R1Regs:$c, 1), 1), imm:$f))>;"
7072  << std::endl << std::endl
7073 
7074  << "def : Pat<(i64 (select R1Regs:$c, (i64 imm:$t), R64Regs:$f)),"
7075  << "(IOR64sss (ANDssa (SUB64sas 0, (ANDext R1Regs:$c, 1)), imm:$t),"
7076  << "(ANDsss (SUBssa (ANDext R1Regs:$c, 1), 1), R64Regs:$f))>;"
7077  << std::endl << std::endl
7078 
7079  << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$t, R1Regs:$f)),"
7080  << "(IOR64bbb (AND64bbb R1Regs:$c, R1Regs:$t), "
7081  << "(AND64bbb (XOR64bbj R1Regs:$c, 1), R1Regs:$f))>;"
7082  << std::endl << std::endl
7083 
7084  << "def : Pat<(i1 (select R1Regs:$c, (i1 0), R1Regs:$f)),"
7085  << "(AND64bbb (XOR64bbj R1Regs:$c, 1), R1Regs:$f)>;"
7086  << std::endl << std::endl
7087 
7088  << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$t, (i1 -1))),"
7089  << "(IOR64bbb (AND64bbb R1Regs:$c, R1Regs:$t),"
7090  << "(XOR64bbj R1Regs:$c, 1))>;"
7091  << std::endl << std::endl;
7092  } //else {
7093 #endif
7094 
7095  if (mach_.is64bit()) {
7096  // optimize select with zero.
7097  os << "def : Pat<(i64 (select "
7098  << condRC << ":$c, R64Regs:$t, (i64 0)))," << std::endl
7099  << " (AND64sss "
7100  << trueMask << ", R64Regs:$t)>;"
7101  << std::endl << std::endl
7102 
7103  << "def : Pat<(i64 (select "
7104  << condRC << ":$c, (i64 0), R64Regs:$f))," << std::endl
7105  << "(AND64sss " << falseMask << ", R64Regs:$f)>;"
7106  << std::endl << std::endl;
7107 
7108  // also select with zero and some other imm
7109  os << "def : Pat<(i64 (select "
7110  << condRC << ":$c, (i64 imm:$t),(i64 0)))," << std::endl
7111  << " " << applyTrueMaskOnImm << ">;"
7112  << std::endl << std::endl;
7113 
7114  os << "def : Pat<(i64 (select "
7115  << condRC << ":$c, (i64 0),(i64 imm:$f)))," << std::endl
7116  << " " << applyFalseMaskOnImm << ">;"
7117  << std::endl << std::endl;
7118  } else {
7119  // optimize select with zero.
7120  os << "def : Pat<(i32 (select "
7121  << condRC << ":$c, R32Regs:$t, (i32 0)))," << std::endl
7122  << " (ANDrrr "
7123  << trueMask << ", R32Regs:$t)>;"
7124  << std::endl << std::endl
7125 
7126  << "def : Pat<(i32 (select "
7127  << condRC << ":$c, (i32 0), R32Regs:$f))," << std::endl
7128  << "(ANDrrr " << falseMask << ", R32Regs:$f)>;"
7129  << std::endl << std::endl;
7130 
7131  // also select with zero and some other imm
7132  os << "def : Pat<(i32 (select "
7133  << condRC << ":$c, (i32 imm:$t),(i32 0)))," << std::endl
7134  << " " << applyTrueMaskOnImm << ">;"
7135  << std::endl << std::endl;
7136 
7137  os << "def : Pat<(i32 (select "
7138  << condRC << ":$c, (i32 0),(i32 imm:$f)))," << std::endl
7139  << " " << applyFalseMaskOnImm << ">;"
7140  << std::endl << std::endl;
7141  }
7142 
7143 
7144  // TODO: similar patterns could be made with -1, avoiding one AND?
7145 
7146  // then the more generic ones
7147  os << std::endl
7148  << "def : Pat<(" << defType << " (select "
7149  << condRC << ":$c, " << gprRegs << ":$t, " << gprRegs << ":$f)), " << std::endl
7150  << " (" << iorReg << " (" << andReg << " " << gprRegs << ":$t, "
7151  << trueMask << "),"
7152  << "(" << andReg << " " << gprRegs << ":$f, " << falseMask << "))>;"
7153  << std::endl << std::endl
7154 
7155  << "def : Pat<(" << defType << " (select "
7156  << condRC << ":$c, (" << defType << " imm:$t),(" << defType << " imm:$f)))," << std::endl
7157  << " (" << iorReg << " " << applyTrueMaskOnImm << ","
7158  << applyFalseMaskOnImm << ")>;"
7159  << std::endl << std::endl
7160 
7161  << "def : Pat<(" << defType << " (select "
7162  << condRC << ":$c, " << gprRegs << ":$t, (" << defType << " imm:$f)))," << std::endl
7163  << " (" << iorReg << " (" << andReg << " "
7164  << trueMask << ", " << gprRegs << ":$t)," << applyFalseMaskOnImm << ")>;"
7165  << std::endl << std::endl
7166 
7167  << "def : Pat<(" << defType << " (select "
7168  << condRC << ":$c, (" << defType << " imm:$t), " << gprRegs << ":$f))," << std::endl
7169  << " (" << iorReg << " " << applyTrueMaskOnImm << ","
7170  << "(" << andReg << " " << falseMask << ", " << gprRegs << ":$f))>;"
7171  << std::endl << std::endl;
7172 
7173  if (!regs1bit_.empty()) {
7174  os << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$t, R1Regs:$f)),"
7175  << std::endl
7176  << " (" << iorBool << " (" << andBool << " R1Regs:$c, R1Regs:$t), "
7177  << "(" << andBool << " (" << xorBooli << " R1Regs:$c, 1), R1Regs:$f))>;"
7178  << std::endl << std::endl
7179 
7180  << "def : Pat<(i1 (select R1Regs:$c, (i1 0), R1Regs:$f)),"
7181  << std::endl
7182  << " (" << andBool << " (" << xorBooli << " R1Regs:$c, 1), R1Regs:$f)>;"
7183  << std::endl << std::endl
7184 
7185  << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$t, (i1 -1))),"
7186  << std::endl
7187  << " (" << iorBool << " (" << andBool << " R1Regs:$c, R1Regs:$t),"
7188  << "(" << xorBooli << " R1Regs:$c, 1))>;"
7189  << std::endl << std::endl;
7190  }
7191 
7192  os << "def : Pat<(f32 (select " << condRC << ":$c, "
7193  "FPRegs:$t,FPRegs:$f))," << std::endl
7194  << " (IORfff (ANDfff FPRegs:$t, (SUBfir 0, "
7195  << truncPattern << ")),"
7196  << "(ANDfff FPRegs:$f, (SUBfri "
7197  << truncPattern << ",1)))>;"
7198  << std::endl << std::endl
7199 
7200  << "def : Pat<(f16 (select " << condRC << ":$c, "
7201  "R32HFPRegs:$t, R32HFPRegs:$f))," << std::endl
7202  << " (IORhhh (ANDhhh R32HFPRegs:$t, (SUBhir 0, "
7203  << truncPattern << ")),"
7204  << "(ANDhhh R32HFPRegs:$f, (SUBhri "
7205  << truncPattern << ",1)))>;"
7206  << std::endl << std::endl;
7207 // }
7208  } else { // has conditional moves.
7209  opNames_["SELECT_I1bb"] = "CMOV_SELECT";
7210  opNames_["SELECT_I1bj"] = "CMOV_SELECT";
7211  opNames_["SELECT_I1jb"] = "CMOV_SELECT";
7212  opNames_["SELECT_I1jj"] = "CMOV_SELECT";
7213  opNames_["SELECT_I32rr"] = "CMOV_SELECT";
7214  opNames_["SELECT_I32ir"] = "CMOV_SELECT";
7215  opNames_["SELECT_I32ri"] = "CMOV_SELECT";
7216  opNames_["SELECT_I32ii"] = "CMOV_SELECT";
7217  opNames_["SELECT_F32"] = "CMOV_SELECT";
7218  opNames_["SELECT_F16"] = "CMOV_SELECT";
7219 
7220  // TODO: why does this break??
7221  os << " let isSelect = 1 in {" << std::endl;
7222 
7223  if (mach_.is64bit()) {
7224  opNames_["SELECT_I64rr"] = "CMOV_SELECT";
7225  opNames_["SELECT_I64ir"] = "CMOV_SELECT";
7226  opNames_["SELECT_I64ri"] = "CMOV_SELECT";
7227  opNames_["SELECT_I64ii"] = "CMOV_SELECT";
7228  opNames_["SELECT_F64"] = "CMOV_SELECT";
7229 
7230 
7231 
7232  os << "def SELECT_I64rr : InstTCE<(outs R64IRegs:$dst),"
7233  << "(ins R1Regs:$c, R64IRegs:$T, R64IRegs:$F),"
7234  << "\"# SELECT_I64 PSEUDO!\","
7235  << "[(set R64IRegs:$dst,"
7236  << "(select R1Regs:$c, R64IRegs:$T, R64IRegs:$F))]>;"
7237  << std::endl << std::endl
7238 
7239  << "def SELECT_I64ri : InstTCE<(outs R64IRegs:$dst),"
7240  << "(ins R64IRegs:$c, R64IRegs:$T, i64imm:$F),"
7241  << "\"# SELECT_I64 PSEUDO!\","
7242  << "[(set R64IRegs:$dst,"
7243  << "(select R64IRegs:$c, R64IRegs:$T, (i64 imm:$F)))]>;"
7244  << std::endl << std::endl
7245 
7246  << "def SELECT_I64ir : InstTCE<(outs R64IRegs:$dst),"
7247  << "(ins R64IRegs:$c, i64imm:$T, R64IRegs:$F),"
7248  << "\"# SELECT_I64 PSEUDO!\","
7249  << "[(set R64IRegs:$dst,"
7250  << "(select R64IRegs:$c, (i64 imm:$T), R64IRegs:$F))]>;"
7251  << std::endl << std::endl
7252 
7253  << "def SELECT_I64ii : InstTCE<(outs R64IRegs:$dst),"
7254  << "(ins R64IRegs:$c, i64imm:$T, i64imm:$F),"
7255  << "\"# SELECT_I64 PSEUDO!\","
7256  << "[(set R64IRegs:$dst,"
7257  << "(select R64IRegs:$c, (i64 imm:$T), (i64 imm:$F)))]>;"
7258  << std::endl << std::endl
7259 
7260  << "def SELECT_F64 : InstTCE<(outs R64DFPRegs:$dst),"
7261  << "(ins R1Regs:$c, R64DFPRegs:$T, R64DFPRegs:$F),"
7262  << "\"# SELECT_F64 PSEUDO!\","
7263  << "[(set R64DFPRegs:$dst,"
7264  << "(select R1Regs:$c, R64DFPRegs:$T, R64DFPRegs:$F))]>;"
7265  << std::endl << std::endl;
7266  }
7267 
7268  os << "def SELECT_I1bb : InstTCE<(outs R1Regs:$dst),"
7269  << "(ins GuardRegs:$c, R1Regs:$T, R1Regs:$F),"
7270  << "\"# SELECT_I1 PSEUDO!\","
7271  << " [(set R1Regs:$dst,"
7272  << "(select GuardRegs:$c, R1Regs:$T, R1Regs:$F))]>;"
7273  << std::endl << std::endl
7274 
7275  << "def SELECT_I1bj : InstTCE<(outs R1Regs:$dst),"
7276  << " (ins GuardRegs:$c, R1Regs:$T, i1imm:$F),"
7277  << "\"# SELECT_I1 PSEUDO!\","
7278  << "[(set R1Regs:$dst,"
7279  << "(select GuardRegs:$c, R1Regs:$T, (i1 imm:$F)))]>;"
7280  << std::endl << std::endl
7281 
7282  << "def SELECT_I1jb : InstTCE<(outs R1Regs:$dst),"
7283  << "(ins GuardRegs:$c, i1imm:$T, R1Regs:$F),"
7284  << "\"# SELECT_I1 PSEUDO!\","
7285  << "[(set R1Regs:$dst,"
7286  << "(select GuardRegs:$c, (i1 imm:$T), R1Regs:$F))]>;"
7287  << std::endl << std::endl
7288 
7289  << "def SELECT_I1jj : InstTCE<(outs R1Regs:$dst),"
7290  << "(ins GuardRegs:$c, i1imm:$T, i1imm:$F),"
7291  << "\"# SELECT_I1 PSEUDO!\","
7292  << "[(set R1Regs:$dst,"
7293  << "(select GuardRegs:$c, (i1 imm:$T), (i1 imm:$F)))]>;"
7294  << std::endl << std::endl
7295 
7296  << "def SELECT_I32rr : InstTCE<(outs R32IRegs:$dst),"
7297  << "(ins GuardRegs:$c, R32IRegs:$T, R32IRegs:$F),"
7298  << "\"# SELECT_I32 PSEUDO!\","
7299  << "[(set R32IRegs:$dst,"
7300  << "(select GuardRegs:$c, R32IRegs:$T, R32IRegs:$F))]>;"
7301  << std::endl << std::endl
7302 // select with the cond in an i32 (produced by expanded vselects with i32 cond vectors)
7303 
7304  << "def SELECT_I32ri : InstTCE<(outs R32IRegs:$dst),"
7305  << "(ins R32IRegs:$c, R32IRegs:$T, i32imm:$F),"
7306  << "\"# SELECT_I32 PSEUDO!\","
7307  << "[(set R32IRegs:$dst,"
7308  << "(select R32IRegs:$c, R32IRegs:$T, i32MoveImm:$F))]>;"
7309  << std::endl << std::endl
7310 
7311  << "def SELECT_I32ir : InstTCE<(outs R32IRegs:$dst),"
7312  << "(ins R32IRegs:$c, i32imm:$T, R32IRegs:$F),"
7313  << "\"# SELECT_I32 PSEUDO!\","
7314  << "[(set R32IRegs:$dst,"
7315  << "(select R32IRegs:$c, i32MoveImm:$T, R32IRegs:$F))]>;"
7316  << std::endl << std::endl
7317 
7318  << "def SELECT_I32ii : InstTCE<(outs R32IRegs:$dst),"
7319  << "(ins R32IRegs:$c, i32imm:$T, i32imm:$F),"
7320  << "\"# SELECT_I32 PSEUDO!\","
7321  << "[(set R32IRegs:$dst,"
7322  << "(select R32IRegs:$c, i32MoveImm:$T, i32MoveImm:$F))]>;"
7323  << std::endl << std::endl
7324 
7325  << "def SELECT_F32 : InstTCE<(outs FPRegs:$dst),"
7326  << "(ins GuardRegs:$c, FPRegs:$T, FPRegs:$F),"
7327  << "\"# SELECT_F32 PSEUDO!\","
7328  << "[(set FPRegs:$dst,"
7329  << "(select GuardRegs:$c, FPRegs:$T, FPRegs:$F))]>;"
7330  << std::endl << std::endl
7331 
7332  << "def SELECT_F16 : InstTCE<(outs HFPRegs:$dst),"
7333  << "(ins GuardRegs:$c, HFPRegs:$T, HFPRegs:$F),"
7334  << "\"# SELECT_F16 PSEUDO!\","
7335  << "[(set HFPRegs:$dst, "
7336  << "(select GuardRegs:$c, HFPRegs:$T, HFPRegs:$F))]>;"
7337  << std::endl << std::endl;
7338 
7339  os << "}" << std::endl << std::endl;
7340 
7341  if (mach_.is64bit()) {
7342  os << "def : Pat<(i64 (select R64IRegs:$c, R64IRegs:$T, R64IRegs:$F)),"
7343  << "(SELECT_I64rr (MOVI64I1ss R64Regs:$c),"
7344  << "R64IRegs:$T, R64IRegs:$F)>;"
7345  << std::endl << std::endl;
7346  }
7347 
7348  os << "def : Pat<(i32 (select R32IRegs:$c, R32IRegs:$T, R32IRegs:$F)),"
7349  << "(SELECT_I32rr (MOVI32I1rr R32Regs:$c),"
7350  << "R32IRegs:$T, R32IRegs:$F)>;"
7351  << std::endl << std::endl;
7352 
7353  }
7354  } else {
7355  os << "// Has select instr!. " << std::endl;
7356  }
7357  std::map<TCEString, RegisterClass>::const_iterator it;
7358  for (it = vRegClasses_.begin(); it != vRegClasses_.end(); ++it) {
7359  const RegisterClass& regClass = it->second;
7360  TCEString regClassName = regClass.name();
7361  ValueType valType = regClass.valueType();
7362  TCEString valTypeName = valType.valueTypeStr();
7363 
7364  os << "def SELECT_" << valTypeName << " : InstTCE<(outs "
7365  << regClassName << ":$dst), (ins R1Regs:$c, " << regClassName
7366  << ":$T, " << regClassName << ":$F), \"\","
7367  << "[(set " << regClassName << ":$dst,"
7368  << "(select R1Regs:$c, " << regClassName << ":$T, " << regClassName
7369  << ":$F))]>;" << std::endl
7370  << std::endl;
7371 
7372  opNames_["SELECT_" + valTypeName] = "CMOV_SELECT";
7373  }
7374 }
7375 
7376 /**
7377  * Generates llvm patterns for constants which are not supported directly as
7378  * immediates by the target machine.
7379  *
7380  * For example, if a target does not sign extending immediates, a pattern is
7381  * generated that transforms negative constants C to (SUB 0, -C).
7382  */
7383 void
7385 
7386  // TODO: this is used when when not needed!
7387  // creating unnecessary NEG operations!
7388 
7389  // LLVM XForm fragments //
7390 
7391  // Transformation functions definitions that creates new constants
7392  // from unsupported constants.
7393  os << std::endl << "// Arithmetic negation XForm fragment."
7394  << std::endl << "def aneg_xform : SDNodeXForm<imm, [{"
7395  << std::endl << " return CurDAG->getTargetConstant("
7396  << std::endl << " -(N->getZExtValue()), SDLoc(N), MVT::i32);"
7397  << std::endl << "}]>;"
7398  << std::endl << std::endl;
7399 
7400  // Constant select operand definitions //
7401 
7402  // Used in Constant materialization patterns to select the constant values
7403  // that are valid for the pattern transformation. The predicate must
7404  // test that the original constant can be accepted by the materialization
7405  // pattern itself and test that the resulted constants by XForms are
7406  // supported too by the target machine.
7407 
7408  // Negative constant materialization: C -> NEG(-C) or C -> SUB(0, -C)
7409  // selecting the cheapest.
7410  std::vector<std::string> ops;
7411  if (opNames_.count("NEGri")) ops.push_back("NEG");
7412  if (opNames_.count("SUBrri")) ops.push_back("SUB");
7413  for (auto op : ops) {
7414  // Predicate that accepts the negative constants
7415  std::string predicate = "Imm < 0";
7416  std::pair<int64_t, int64_t> tmp = immInfo_->immediateValueBounds(
7417  ImmInfoKey{op , 1} , 32);
7418  if (tmp.second < 2) continue;
7419 
7420  predicate += " && Imm >= -" + Conversion::toString(tmp.second-1);
7421 
7422  writeImmediateDef(os, "minus_i32imm", "i32", predicate);
7423  // store predicates for the materialization queries by ISelLowering,
7424  // where decisions to bail unsupported constants to constant pool are
7425  // made. The stored predicates are written to Backend.inc later on.
7426  constantMaterializationPredicates_.push_back(predicate);
7427 
7428  os << std::endl << "def : Pat<(i32 minus_i32imm:$imm)," << std::endl;
7429  if (op == "NEG") {
7430  os << " (NEGri (aneg_xform imm:$imm))>;";
7431  } else if (op == "SUB") {
7432  os << " (SUBrri (MOVI32ri 0), (aneg_xform imm:$imm))>;";
7433  }
7434  os << std::endl;
7435  break; // We need only the cheapest materialization pattern.
7436  }
7437 }
7438 
7439 /**
7440  * Writes query method for retrieving LLVM instruction for pointer adjustment
7441  * and suitable offset value.
7442  *
7443  * Some machines may not SUBrri definition (second operand can not take an
7444  * immediate) and, therefore, pointer adjustments must use other operation
7445  * for it.
7446  */
7447 void
7448 TDGen::writeGetPointerAdjustmentQuery(std::ostream& os) const {
7449 
7450  TCEString ADDIMM = mach_.is64bit() ? "ADD64ssa" : "ADDrri";
7451  TCEString SUBIMM = mach_.is64bit() ? "SUB64ssa" : "SUBrri";
7452 
7453 
7454 
7455  boost::format queryTmpl(
7456  "// <MI opcode, adjusted offset>\n"
7457  "std::tuple<int, int> GeneratedTCEPlugin::getPointerAdjustment(\n"
7458  " int offset) const {\n"
7459  " if (offset > 0) // Adjust pointer up.\n"
7460  " return std::make_tuple(TCE::%1%, offset);\n"
7461  " else\n"
7462  " return std::make_tuple(TCE::%2%, %3%);\n"
7463  "}\n");
7464 
7465  // Prefer non-negative offset
7466  if (opNames_.count(SUBIMM)) {
7467  os << queryTmpl % ADDIMM % SUBIMM % "-offset" << std::endl;
7468  return;
7469  } else if (opNames_.count("ADDrri")) {
7470  os << queryTmpl % ADDIMM % ADDIMM % "offset" << std::endl;
7471  return;
7472  }
7473 
7475  InvalidData,
7476  "The machine is missing ADD or SUB operation with direct\n"
7477  "immediate source for pointer adjustment operations.");
7478  return;
7479 }
7480 
7481 
7482 /**
7483  * Returns llvm predicate expression for short immediate constraint.
7484  */
7485 std::string
7487  int64_t lowerBoundInclusive,
7488  uint64_t upperBoundInclusive) {
7489 
7490  // If can transport any 64-bit imm, no need for any checks.
7491  if (upperBoundInclusive == UINT64_MAX ||
7492  lowerBoundInclusive == INT64_MIN) {
7493  return std::string("(true)");
7494  }
7495 
7496  return std::string("(")
7497  + Conversion::toString(lowerBoundInclusive) + "ll"
7498  + " <= Imm && Imm <= "
7499  + Conversion::toString(upperBoundInclusive) + "ll)";
7500 }
7501 
7502 /**
7503  * Returns corresponding immediate operand name for the emulated operation.
7504  *
7505  * @param dag The emulation code of the emulated operation.
7506  * @param operand The operand.
7507  * @return The operand immediate name if found. Otherwise return empty string.
7508  */
7509 std::string
7511  const OperationDAG& dag,
7512  const Operand& operand) {
7513 
7514  for (const auto& sourceNode : dag.rootNodes()) {
7515  const TerminalNode* sourceTerminal =
7516  dynamic_cast<TerminalNode*>(sourceNode);
7517 
7518  if (sourceTerminal == nullptr) continue;
7519 
7520  for (const auto& destEdge : dag.outEdges(*sourceTerminal)) {
7521  const OperationNode* opNode =
7522  dynamic_cast<OperationNode*>(&dag.headNode(*destEdge));
7523 
7524  assert(opNode != nullptr &&
7525  "TerminalNode points to other than OperandNode.");
7526  const Operation& operation = opNode->referencedOperation();
7527  ImmInfoKey key = ImmInfo::key(operation, operand);
7528  if (immOperandDefs_.count(key)) {
7529  return immOperandDefs_.at(key);
7530  } else {
7531  return "";
7532  }
7533  }
7534  }
7535  return "";
7536 }
7537 
7538 /**
7539  * Checks if the operation can have the specified immediate operands.
7540  *
7541  */
7542 bool
7544  const Operation& operation,
7545  const std::string& operandTypes) const {
7546 
7547  assert(static_cast<int>(operandTypes.size()) >= operation.operandCount());
7548 
7549  for (int i = 0 ; i < operation.numberOfInputs(); i++) {
7550  if (operandTypes.at(i + operation.numberOfOutputs()) != OT_IMM_INT) {
7551  continue;
7552  }
7553 
7554  const Operand& operand = operation.operand(i+1);
7555 
7556  // Kludge fix for ADDri/MEMri operands. LLVM wants some times to select
7557  // store/load instruction, where the address operand is immediate.
7558  // However, the machine may not have capability to directly transport
7559  // immediate to the address operand. Considering the case as illegal
7560  // will reject operation definitions using ADDri/MEMri operands and
7561  // breaks the instruction selection later on. Temporarily accept
7562  // ADDri/MEMri operands until the issue is fixed.
7563  if (operand.isAddress()) {
7564  continue;
7565  }
7566 
7567  if (immInfo_->count(operation, operand) == 0) {
7568  for (int swappableWith : operand.swap()) {
7569  const Operand& otherOperand = operation.operand(swappableWith);
7570  if (immInfo_->count(operation, otherOperand)
7571  && operation.name() != "EQ"
7572  && operation.name() != "NE") {
7573  // ^ EQ and NE are not commutative in LLVM
7574  return true;
7575  }
7576  }
7577  return false;
7578  }
7579  }
7580 
7581  return true;
7582 }
7583 
7584 
7585 /**
7586  * Returns true if the instruction can be predicated.
7587  *
7588  * TODO
7589  */
7590 bool
7591 TDGen::canBePredicated(Operation& /*op*/, const std::string& operandTypes) {
7592 
7593  // Predicating operands with immediates can currently lead to
7594  // unschedulable code in case there's no bus that has both the
7595  // predicate and the immediate transfer capability. Disable
7596  // generating the predicated versions for immediate operand
7597  // patterns for now.
7598  if (operandTypes.find(OT_IMM_INT) != std::string::npos) return false;
7599 
7600  if (hasConditionalMoves_) return true;
7601 
7602  return false;
7603 }
7604 
7605 /**
7606  * Returns OSAL operation names valid for stack accesses.
7607  *
7608  * @param mach The target machine.
7609  */
7610 std::vector<std::string>
7612 
7613  using namespace TTAMachine;
7614 
7615  std::vector<std::string> opcodes;
7616 
7617  auto collectMemoryOps = [](
7618  std::vector<std::string>& newOpcodes,
7619  const FunctionUnit& fu) -> void {
7620 
7621  for (int i = 0; i < fu.operationCount(); i++) {
7622  const Operation& op = MachineInfo::osalOperation(*fu.operation(i));
7623  if (!op.readsMemory() && !op.writesMemory()) {
7624  continue;
7625  }
7626  newOpcodes.push_back(StringTools::stringToUpper(op.name()));
7627  }
7628  };
7629 
7630  std::map<const AddressSpace*, std::set<const FunctionUnit*>>
7631  addrSpaceLsuMap;
7632  for (const FunctionUnit* fu : mach.functionUnitNavigator()) {
7633  if (fu->hasAddressSpace()) {
7634  addrSpaceLsuMap[fu->addressSpace()].insert(fu);
7635  }
7636  }
7637 
7638  const int stackAddressSpaceId = 0;
7639  if (addrSpaceLsuMap.size() == 1) {
7640  // Only one data address space. Stack resides there.
7641  for (auto lsu : addrSpaceLsuMap.begin()->second) {
7642  collectMemoryOps(opcodes, *lsu);
7643  }
7644  } else {
7645  // Multiple data address spaces. Find LSUs having the stack address
7646  // space ID.
7647  for (auto asLsusPair : addrSpaceLsuMap) {
7648  if (asLsusPair.first->hasNumericalId(stackAddressSpaceId)) {
7649  for (auto lsu : asLsusPair.second) {
7650  collectMemoryOps(opcodes, *lsu);
7651  }
7652  break;
7653  }
7654  }
7655  }
7656 
7657  return opcodes;
7658 }
7659 
7660 /**
7661  * Returns LLVM pattern for the expression with constant value(s) supported by
7662  * target machine.
7663  *
7664  * For example, for pattern (SUBrri (foo ...), 123) the method returns
7665  * (SUBrrr (foo ...), (MOVI32ri 123)) if the target machine can not supply
7666  * the constant "123" as an immediate.
7667  *
7668  * The method should be called after all operation definitions have been
7669  * created (after all calls to writeOperationDef()).
7670  *
7671  * Return empty string if the given pattern can not be handled because:
7672  * - Operation is not supported by target machine.
7673  *
7674  * @param op The operation.
7675  * @param operandTypes The preferred operand types.
7676  * @param operand0 The pattern for the first operand or constant indicated by
7677  * operandTypes.
7678  * @param operand1 The pattern for the second operand or constant indicated by
7679  * operandTypes.
7680  */
7681 TCEString
7683  const Operation& op, const std::string& operandTypes,
7684  const std::string& operand0,
7685  const std::string& operand1) const {
7686 
7687  //TODO If operation is not supported, try to replace it with an emulation
7688  // pattern first and then deal with the new patterns with constant
7689  // operands (and take account possible infinite recursion).
7690  //TODO Cache the calculated results?
7691 
7692  assert(op.numberOfInputs() == 2);
7693 
7694  auto makePattern = [](
7695  const std::string& opc,
7696  const std::string& opdTypes,
7697  const std::string& operand0,
7698  const std::string& operand1) -> TCEString {
7699  return std::string("(") + opc + opdTypes + " " + operand0
7700  + ", " + operand1 + ")";
7701  };
7702 
7703  std::string opc = StringTools::stringToUpper(op.name());
7704  const std::string outputOpdTypes = operandTypes.substr(
7705  0, op.numberOfOutputs());
7706  const std::string inputOpdTypes = operandTypes.substr(
7707  op.numberOfOutputs());
7708  assert(inputOpdTypes.size() == 2);
7709  const auto regOperandsOnly = operandTypesToRegisters(operandTypes);
7710  if (!opNames_.count(opc + regOperandsOnly)) {
7711  // Operation is not supported at all by the target machine.
7712  return "";
7713  }
7714 
7715  if (opNames_.count(opc + operandTypes)) {
7716  // Supported as is.
7717  return makePattern(opc, operandTypes, operand0, operand1);
7718  }
7719 
7720  std::vector<std::string> supportedOperandTypes;
7721  for (auto i = 0u; i < inputOpdTypes.size(); i++) {
7722  std::string oneInputChanged = inputOpdTypes;
7723  oneInputChanged[i] = operandTypeToRegister(oneInputChanged[i]);
7724  if (oneInputChanged == inputOpdTypes) continue;
7725  if (opNames_.count(opc + outputOpdTypes + oneInputChanged)) {
7726  supportedOperandTypes.push_back(oneInputChanged);
7727  }
7728  }
7729 
7730  supportedOperandTypes.push_back(regOperandsOnly);
7731 
7732  std::vector<const std::string*> inputOpdValues{&operand0, &operand1};
7733 
7734  // Now legalize pattern by changing unsupported immediate operands with
7735  // immediate moves.
7736  for (const auto& supportedOpdType : supportedOperandTypes) {
7737 
7738  // Loop throught immediate opd types. Check if constant is encodable
7739  // for the operation.
7740  bool isSupported = true;
7741  for (auto i = 0u; i < supportedOpdType.size(); i++) {
7742  auto& opdType = supportedOpdType.at(i);
7743  auto osalOpdIdx = i - op.numberOfInputs() + 1;
7744 
7745  bool ok = false;
7746  switch (opdType) {
7747  default:
7748  ok = true; // Ok. Not immediate type.
7749  break;
7750  case OT_IMM_INT: {
7751  bool isOperandReference =
7752  inputOpdValues.at(i)->find(":$") != std::string::npos;
7753  if (isOperandReference) {
7754  // Size of the constant is not known, must expect the
7755  // worst.
7756  ok = false;
7757  break;
7758  }
7759  int64_t value = Conversion::toInt(
7760  *inputOpdValues.at(i));
7761  ok = immInfo_->canTakeImmediate(op, osalOpdIdx, value,
7762  32);
7763  }
7764  break;
7765  case OT_IMM_FP:
7767  op, osalOpdIdx, 32);
7768  break;
7769  case OT_IMM_HFP:
7771  op, osalOpdIdx, 16);
7772  break;
7773  case OT_IMM_BOOL:
7775  op, osalOpdIdx, 1);
7776  break;
7777  }
7778  if (!ok) {
7779  isSupported = false;
7780  break;
7781  }
7782  }
7783 
7784  if (!isSupported) continue;
7785 
7786  std::string result = std::string("(") + opc + outputOpdTypes
7787  + supportedOpdType + " ";
7788  if (supportedOpdType.at(0) == inputOpdTypes.at(0)) {
7789  result += *inputOpdValues.at(0);
7790  } else {
7791  result += getMovePattern(
7792  inputOpdTypes.at(0), *inputOpdValues.at(0));
7793  }
7794  for (auto i = 1u; i < supportedOpdType.size(); i++) {
7795  result += ", ";
7796  if (supportedOpdType.at(i) == inputOpdTypes.at(i)) {
7797  result += *inputOpdValues.at(i);
7798  } else {
7799  result += getMovePattern(
7800  inputOpdTypes.at(i), *inputOpdValues.at(i));
7801  }
7802  }
7803  result += ")";
7804  return result;
7805  }
7806 
7807  return "";
7808 }
7809 
7810 std::string
7811 TDGen::operandTypesToRegisters(const std::string& opdTypes) const {
7812  std::string result(opdTypes);
7813  for (char& type : result) {
7814  type = operandTypeToRegister(type);
7815  }
7816  return result;
7817 }
7818 
7819 char
7820 TDGen::operandTypeToRegister(const char& opdType) const {
7821  switch (opdType) {
7822  case OT_IMM_INT: return OT_REG_INT; // Integer immediate.
7823  case OT_IMM_BOOL: return OT_REG_BOOL; // Boolean immediate.
7824  case OT_IMM_FP: return OT_REG_FP; // 32-bit floating point immediate.
7825  case OT_IMM_HFP: return OT_REG_HFP; // 15-bi floating point immediate.
7826  // TODO: vector immediate types.
7827  default:
7828  break;
7829  }
7830  return opdType; // Return as is (should be register type).
7831 }
7832 
7833 
7834 TCEString
7836  const char& opdType, const std::string& inputPattern) const {
7837 
7838  TCEString pat = "(MOV";
7839  // Note: This listing is incomplete.
7840  switch (opdType) {
7841  case OT_IMM_INT: // Integer immediate.
7842  pat += std::string("I32") + operandTypeToRegister(opdType) + opdType;
7843  break;
7844  case OT_REG_INT: // Integer register.
7845  pat += std::string("I32") + operandTypeToRegister(opdType) + opdType;
7846  break;
7847  case OT_IMM_BOOL: // Boolean immediate.
7848  pat += "I1ri"; //TODO: this is inconsistent
7849  break;
7850  case OT_REG_BOOL: // Boolean register.
7851  pat += "I1rr"; //TODO: this is inconsistent
7852  break;
7853  case OT_IMM_FP: // Single precision floating point immediate.
7854  case OT_REG_FP: // -||- register.
7855  pat += std::string("F32") + operandTypeToRegister(opdType) + opdType;
7856  break;
7857  case OT_IMM_HFP: // Half precision floating point immediate.
7858  case OT_REG_HFP: // -||- register.
7859  pat += std::string("F16") + operandTypeToRegister(opdType) + opdType;
7860  break;
7861  // TODO: vector register and immediate types.
7862  default:
7863  assert(false && "Handling for a type not implemented");
7864  break;
7865  }
7866  pat += " " + inputPattern + ")";
7867  return pat;
7868 }
7869 
7870 void TDGen::writeCallSeqStart(std::ostream& os) {
7871 
7872  bool is64bit = mach_.is64bit();
7873 
7874  if (!is64bit) {
7875  os << "def SDT_TCECallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,"
7876  << "SDTCisVT<1, i32> ]>;" << std::endl << std::endl;
7877  } else {
7878  os << "def SDT_TCECallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i64>,"
7879  << "SDTCisVT<1, i64> ]>;" << std::endl << std::endl;
7880  }
7881  os << "def callseq_start : SDNode<\"ISD::CALLSEQ_START\", "
7882  << "SDT_TCECallSeqStart, [SDNPHasChain, SDNPOutGlue]>;" << std::endl
7883  << std::endl
7884  << "let Defs = [SP], Uses = [SP] in {" << std::endl
7885  << "def ADJCALLSTACKDOWN : Pseudo<(outs),";
7886  if (!is64bit) {
7887  os << "(ins i32imm:$amt1, i32imm:$amt2),";
7888  } else {
7889  os << "(ins i64imm:$amt1, i64imm:$amt2),";
7890  }
7891  os << "\"# ADJCALLSTACKDOWN $amt1, $amt2\","
7892  << "[(callseq_start timm:$amt1, timm:$amt2)]>;}"
7893  << std::endl << std::endl;
7894 }
7895 
7896 void TDGen::createBranchAnalysis(std::ostream& os) {
7897  os << "bool GeneratedTCEPlugin::analyzeCCBranch(" << std::endl
7898  << "\tllvm::MachineInstr& i," << std::endl
7899  << "\tllvm::SmallVectorImpl<llvm::MachineOperand>& cond) const {"
7900  << std::endl
7901  << std::endl;
7902 
7905 
7906  os << "\tif (i.getOpcode() == TCE::EQ_JUMP) {" << std::endl
7907  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7908  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7909  << "\t\tcond.push_back(MachineOperand::CreateImm(2));"
7910  << std::endl
7911  << "\t\treturn false; }" << std::endl;
7912 
7913  os << "\tif (i.getOpcode() == TCE::NE_JUMP) {" << std::endl
7914  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7915  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7916  << "\t\tcond.push_back(MachineOperand::CreateImm(3));"
7917  << std::endl
7918  << "\t\treturn false; }" << std::endl;
7919 
7920  os << "\tif (i.getOpcode() == TCE::GT_JUMP) {" << std::endl
7921  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7922  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7923  << "\t\tcond.push_back(MachineOperand::CreateImm(4));"
7924  << std::endl
7925  << "\t\treturn false; }" << std::endl;
7926 
7927  os << "\tif (i.getOpcode() == TCE::LE_JUMP) {" << std::endl
7928  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7929  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7930  << "\t\tcond.push_back(MachineOperand::CreateImm(5));"
7931  << std::endl
7932  << "\t\treturn false; }" << std::endl;
7933 
7934  os << "\tif (i.getOpcode() == TCE::GTU_JUMP) {" << std::endl
7935  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7936  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7937  << "\t\tcond.push_back(MachineOperand::CreateImm(6));"
7938  << std::endl
7939  << "\t\treturn false; }" << std::endl;
7940 
7941  os << "\tif (i.getOpcode() == TCE::LEU_JUMP) {" << std::endl
7942  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7943  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7944  << "\t\tcond.push_back(MachineOperand::CreateImm(7));"
7945  << std::endl
7946  << "\t\treturn false; }" << std::endl;
7947 
7948  if (opNames_.find("EQF_JUMP") != opNames_.end()) {
7949  os << "\tif (i.getOpcode() == TCE::EQF_JUMP) {" << std::endl
7950  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7951  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7952  << "\t\tcond.push_back(MachineOperand::CreateImm(8));"
7953  << std::endl
7954  << "\t\treturn false; }" << std::endl;
7955  }
7956 
7957  if (opNames_.find("NEF_JUMP") != opNames_.end()) {
7958  os << "\tif (i.getOpcode() == TCE::NEF_JUMP) {" << std::endl
7959  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7960  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7961  << "\t\tcond.push_back(MachineOperand::CreateImm(9));"
7962  << std::endl
7963  << "\t\treturn false; }" << std::endl;
7964  }
7965 
7966  if (opNames_.find("LEF_JUMP") != opNames_.end()) {
7967  os << "\tif (i.getOpcode() == TCE::LEF_JUMP) {" << std::endl
7968  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7969  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7970  << "\t\tcond.push_back(MachineOperand::CreateImm(10));"
7971  << std::endl
7972  << "\t\treturn false; }" << std::endl;
7973  }
7974 
7975  if (opNames_.find("GEF_JUMP") != opNames_.end()) {
7976  os << "\tif (i.getOpcode() == TCE::GEF_JUMP) {" << std::endl
7977  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7978  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7979  << "\t\tcond.push_back(MachineOperand::CreateImm(10));"
7980  << std::endl
7981  << "\t\treturn false; }" << std::endl;
7982  }
7983 
7984  if (opNames_.find("LTF_JUMP") != opNames_.end()) {
7985  os << "\tif (i.getOpcode() == TCE::LTF_JUMP) {" << std::endl
7986  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7987  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7988  << "\t\tcond.push_back(MachineOperand::CreateImm(12));"
7989  << std::endl
7990  << "\t\treturn false; }" << std::endl;
7991  }
7992 
7993  if (opNames_.find("GTF_JUMP") != opNames_.end()) {
7994  os << "\tif (i.getOpcode() == TCE::GTF_JUMP) {" << std::endl
7995  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
7996  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
7997  << "\t\tcond.push_back(MachineOperand::CreateImm(13));"
7998  << std::endl
7999  << "\t\treturn false; }" << std::endl;
8000  }
8001  }
8002 
8005  if (opNames_.count("TCEBREQrr")) {
8006  os << "\tif (i.getOpcode() == TCE::TCEBREQrr) {" << std::endl
8007  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8008  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8009  << "\t\tcond.push_back(MachineOperand::CreateImm(2));"
8010  << std::endl
8011  << "\t\treturn false;" << std::endl
8012  << "\t}" << std::endl;
8013 
8014  os << "\tif (i.getOpcode() == TCE::TCEBREQri) {" << std::endl
8015  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8016  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8017  << "\t\tcond.push_back(MachineOperand::CreateImm(102));"
8018  << std::endl
8019  << "\t\treturn false;" << std::endl
8020  << "\t}" << std::endl;
8021  }
8022 
8023  if (opNames_.count("TCEBRNErr")) {
8024  os << "\tif (i.getOpcode() == TCE::TCEBRNErr) {" << std::endl
8025  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8026  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8027  << "\t\tcond.push_back(MachineOperand::CreateImm(3));"
8028  << std::endl
8029  << "\t\treturn false;" << std::endl
8030  << "\t}" << std::endl;
8031 
8032  os << "\tif (i.getOpcode() == TCE::TCEBRNEri) {" << std::endl
8033  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8034  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8035  << "\t\tcond.push_back(MachineOperand::CreateImm(103));"
8036  << std::endl
8037  << "\t\treturn false;" << std::endl
8038  << "\t}" << std::endl;
8039  }
8040 
8041  if (opNames_.count("TCEBRGTrr")) {
8042  os << "\tif (i.getOpcode() == TCE::TCEBRGTrr) {" << std::endl
8043  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8044  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8045  << "\t\tcond.push_back(MachineOperand::CreateImm(4));"
8046  << std::endl
8047  << "\t\treturn false;" << std::endl
8048  << "\t}" << std::endl;
8049 
8050  os << "\tif (i.getOpcode() == TCE::TCEBRGTri) {" << std::endl
8051  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8052  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8053  << "\t\tcond.push_back(MachineOperand::CreateImm(104));"
8054  << std::endl
8055  << "\t\treturn false;" << std::endl
8056  << "\t}" << std::endl;
8057  }
8058 
8059  if (opNames_.count("TCEBRGTUrr")) {
8060  os << "\tif (i.getOpcode() == TCE::TCEBRGTUrr) {" << std::endl
8061  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8062  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8063  << "\t\tcond.push_back(MachineOperand::CreateImm(6));"
8064  << std::endl
8065  << "\t\treturn false;" << std::endl
8066  << "\t}" << std::endl;
8067 
8068  os << "\tif (i.getOpcode() == TCE::TCEBRGTUri) {" << std::endl
8069  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8070  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8071  << "\t\tcond.push_back(MachineOperand::CreateImm(106));"
8072  << std::endl
8073  << "\t\treturn false;" << std::endl
8074  << "\t}" << std::endl;
8075  }
8076 
8077  if (opNames_.count("TCEBRLTrr")) {
8078  os << "\tif (i.getOpcode() == TCE::TCEBRLTrr) {" << std::endl
8079  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8080  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8081  << "\t\tcond.push_back(MachineOperand::CreateImm(14));"
8082  << std::endl
8083  << "\t\treturn false;" << std::endl
8084  << "\t}" << std::endl;
8085 
8086  os << "\tif (i.getOpcode() == TCE::TCEBRLTri) {" << std::endl
8087  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8088  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8089  << "\t\tcond.push_back(MachineOperand::CreateImm(114));"
8090  << std::endl
8091  << "\t\treturn false;" << std::endl
8092  << "\t}" << std::endl;
8093  }
8094 
8095  if (opNames_.count("TCEBRLTUrr")) {
8096  os << "\tif (i.getOpcode() == TCE::TCEBRLTUrr) {" << std::endl
8097  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8098  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8099  << "\t\tcond.push_back(MachineOperand::CreateImm(15));"
8100  << std::endl
8101  << "\t\treturn false;" << std::endl
8102  << "\t}" << std::endl;
8103 
8104  os << "\tif (i.getOpcode() == TCE::TCEBRLTUri) {" << std::endl
8105  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8106  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8107  << "\t\tcond.push_back(MachineOperand::CreateImm(115));"
8108  << std::endl
8109  << "\t\treturn false;" << std::endl
8110  << "\t}" << std::endl;
8111  }
8112 
8113  if (opNames_.count("TCEBRLErr")) {
8114  os << "\tif (i.getOpcode() == TCE::TCEBRLErr) {" << std::endl
8115  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8116  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8117  << "\t\tcond.push_back(MachineOperand::CreateImm(5));"
8118  << std::endl
8119  << "\t\treturn false;" << std::endl
8120  << "\t}" << std::endl;
8121 
8122  os << "\tif (i.getOpcode() == TCE::TCEBRLEri) {" << std::endl
8123  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8124  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8125  << "\t\tcond.push_back(MachineOperand::CreateImm(105));"
8126  << std::endl
8127  << "\t\treturn false;" << std::endl
8128  << "\t}" << std::endl;
8129  }
8130 
8131  if (opNames_.count("TCEBRLEUrr")) {
8132  os << "\tif (i.getOpcode() == TCE::TCEBRLEUrr) {" << std::endl
8133  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8134  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8135  << "\t\tcond.push_back(MachineOperand::CreateImm(7));"
8136  << std::endl
8137  << "\t\treturn false;" << std::endl
8138  << "\t}" << std::endl;
8139 
8140  os << "\tif (i.getOpcode() == TCE::TCEBRLEUri) {" << std::endl
8141  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8142  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8143  << "\t\tcond.push_back(MachineOperand::CreateImm(107));"
8144  << std::endl
8145  << "\t\treturn false;" << std::endl
8146  << "\t}" << std::endl;
8147  }
8148 
8149  if (opNames_.count("TCEBRGErr")) {
8150  os << "\tif (i.getOpcode() == TCE::TCEBRGErr) {" << std::endl
8151  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8152  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8153  << "\t\tcond.push_back(MachineOperand::CreateImm(16));"
8154  << std::endl
8155  << "\t\treturn false;" << std::endl
8156  << "\t}" << std::endl;
8157 
8158  os << "\tif (i.getOpcode() == TCE::TCEBRGEri) {" << std::endl
8159  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8160  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8161  << "\t\tcond.push_back(MachineOperand::CreateImm(116));"
8162  << std::endl
8163  << "\t\treturn false;" << std::endl
8164  << "\t}" << std::endl;
8165  }
8166 
8167  if (opNames_.count("TCEBRGEUrr")) {
8168  os << "\tif (i.getOpcode() == TCE::TCEBRGEUrr) {" << std::endl
8169  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8170  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8171  << "\t\tcond.push_back(MachineOperand::CreateImm(17));"
8172  << std::endl
8173  << "\t\treturn false;" << std::endl
8174  << "\t}" << std::endl;
8175 
8176  os << "\tif (i.getOpcode() == TCE::TCEBRGEUri) {" << std::endl
8177  << "\t\tcond.push_back(i.getOperand(0));" << std::endl
8178  << "\t\tcond.push_back(i.getOperand(1));" << std::endl
8179  << "\t\tcond.push_back(MachineOperand::CreateImm(117));"
8180  << std::endl
8181  << "\t\treturn false;" << std::endl
8182  << "\t}" << std::endl;
8183  }
8184  }
8185  os << "\treturn true;"
8186  << "}" << std::endl << std::endl;
8187 
8188  // insert branch
8189 
8190  os << "#include <llvm/CodeGen/MachineInstrBuilder.h>" << std::endl
8191  << std::endl;
8192 
8193  os << "void TCEInstrInfo::insertCCBranch( " << std::endl
8194  << "\tMachineBasicBlock& mbb," << std::endl
8195  << "\tMachineBasicBlock& tbb," << std::endl
8196  << "\tArrayRef<MachineOperand> cond," << std::endl
8197  << "const DebugLoc& dl) const {" << std::endl
8198  << "\tassert(cond.size() == 3);" << std::endl;
8199 
8200  os << "\tint opcode;" << std::endl;
8201 
8204  os << "\tswitch (cond[2].getImm()) {" << std::endl
8205  << "\t\tcase 2: opcode = TCE::EQ_JUMP;break;" << std::endl
8206  << "\t\tcase 3: opcode = TCE::NE_JUMP;break;" << std::endl
8207  << "\t\tcase 4: opcode = TCE::GT_JUMP;break;" << std::endl
8208  << "\t\tcase 5: opcode = TCE::LE_JUMP;break;" << std::endl
8209  << "\t\tcase 6: opcode = TCE::GTU_JUMP;break;" << std::endl
8210  << "\t\tcase 7: opcode = TCE::LEU_JUMP;break;" << std::endl;
8211 
8212  if (opNames_.find("EQF_JUMP") != opNames_.end()) {
8213  os << "\t\tcase 8: opcode = TCE::EQF_JUMP;break;" << std::endl;
8214  }
8215  if (opNames_.find("NEF_JUMP") != opNames_.end()) {
8216  os << "\t\tcase 9: opcode = TCE::NEF_JUMP;break;" << std::endl;
8217  }
8218  if (opNames_.find("LEF_JUMP") != opNames_.end()) {
8219  os << "\t\tcase 10: opcode = TCE::LEF_JUMP;break;" << std::endl;
8220  }
8221  if (opNames_.find("GEF_JUMP") != opNames_.end()) {
8222  os << "\t\tcase 11: opcode = TCE::GEF_JUMP;break;" << std::endl;
8223  }
8224  if (opNames_.find("LTF_JUMP") != opNames_.end()) {
8225  os << "\t\tcase 12: opcode = TCE::LTF_JUMP;break;" << std::endl;
8226  }
8227  if (opNames_.find("GEF_JUMP") != opNames_.end()) {
8228  os << "\t\tcase 13: opcode = TCE::GTF_JUMP;break;" << std::endl;
8229  }
8230 
8231  os << "\t\tdefault: assert(false && \"Unknown condition code\");}"
8232  << std::endl;
8235  os << "\tswitch (cond[2].getImm()) {" << std::endl;
8236  if (opNames_.count("TCEBREQrr")) {
8237  os << "\t\tcase 2: opcode = TCE::TCEBREQrr; break;" << std::endl
8238  << "\t\tcase 102: opcode = TCE::TCEBREQri; break;"
8239  << std::endl;
8240  }
8241  if (opNames_.count("TCEBRNErr")) {
8242  os << "\t\tcase 3: opcode = TCE::TCEBRNErr; break;" << std::endl
8243  << "\t\tcase 103: opcode = TCE::TCEBRNEri; break;"
8244  << std::endl;
8245  }
8246  if (opNames_.count("TCEBRGTrr")) {
8247  os << "\t\tcase 4: opcode = TCE::TCEBRGTrr; break;" << std::endl
8248  << "\t\tcase 104: opcode = TCE::TCEBRGTri; break;"
8249  << std::endl;
8250  }
8251  if (opNames_.count("TCEBRGTUrr")) {
8252  os << "\t\tcase 6: opcode = TCE::TCEBRGTUrr; break;" << std::endl
8253  << "\t\tcase 106: opcode = TCE::TCEBRGTUri; break;"
8254  << std::endl;
8255  }
8256  if (opNames_.count("TCEBRLTrr")) {
8257  os << "\t\tcase 14: opcode = TCE::TCEBRLTrr; break;" << std::endl
8258  << "\t\tcase 114: opcode = TCE::TCEBRLTri; break;"
8259  << std::endl;
8260  }
8261  if (opNames_.count("TCEBRLTUrr")) {
8262  os << "\t\tcase 15: opcode = TCE::TCEBRLTUrr; break;" << std::endl
8263  << "\t\tcase 115: opcode = TCE::TCEBRLTUri; break;"
8264  << std::endl;
8265  }
8266  if (opNames_.count("TCEBRLErr")) {
8267  os << "\t\tcase 5: opcode = TCE::TCEBRLErr; break;" << std::endl
8268  << "\t\tcase 105: opcode = TCE::TCEBRLEri; break;"
8269  << std::endl;
8270  }
8271  if (opNames_.count("TCEBRLEUrr")) {
8272  os << "\t\tcase 7: opcode = TCE::TCEBRLEUrr; break;" << std::endl
8273  << "\t\tcase 107: opcode = TCE::TCEBRLEUri; break;"
8274  << std::endl;
8275  }
8276  if (opNames_.count("TCEBRGErr")) {
8277  os << "\t\tcase 16: opcode = TCE::TCEBRGErr; break;" << std::endl
8278  << "\t\tcase 116: opcode = TCE::TCEBRGEri; break;"
8279  << std::endl;
8280  }
8281  if (opNames_.count("TCEBRGEUrr")) {
8282  os << "\t\tcase 17: opcode = TCE::TCEBRGEUrr; break;" << std::endl
8283  << "\t\tcase 117: opcode = TCE::TCEBRGEUri; break;"
8284  << std::endl;
8285  }
8286  os << "\t\tdefault: assert(false && \"Unknown condition code\");}"
8287  << std::endl;
8288  } else {
8289  os << "\tassert(false && \"Unknown condition code\");" << std::endl;
8290  }
8291 
8292  os << "\tif (cond[1].isReg()) {" << std::endl
8293  << "\t\tBuildMI(&mbb, dl, get(opcode)).addReg(cond[0].getReg())"
8294  << std::endl
8295  << "\t\t .addReg(cond[1].getReg()).addMBB(&tbb);" << std::endl
8296  << "\t} else {" << std::endl
8297  << "\t\tBuildMI(&mbb, dl, get(opcode)).addReg(cond[0].getReg())"
8298  << std::endl
8299  << "\t\t .addImm(cond[1].getImm()).addMBB(&tbb);" << std::endl
8300  << "\t}" << std::endl;
8301  os << "}";
8302 }
8303 
8304 void TDGen::write64bitMoveDefs(std::ostream& o) {
8305  o << std::endl << "// 64-bit register->register move definitions."
8306  << std::endl << "let isAsCheapAsAMove = 1 in {" << std::endl;
8307 
8308  o << "def MOV64rr : InstTCE<(outs R64Regs:$dst), (ins R64Regs:$src),"
8309  << " \"$src -> $dst;\", []>;" << std::endl;
8310 
8311  o << "def PRED_TRUE_MOV64rr : InstTCE<(outs R64Regs:$dst), "
8312  << "(ins R1Regs:$pred, R64Regs:$src), \"$src -> $dst;\", []>;"
8313  << std::endl;
8314 
8315  o << "def PRED_FALSE_MOV64rr : InstTCE<(outs R64Regs:$dst), "
8316  << "(ins R1Regs:$pred, R64Regs:$src), \"$src -> $dst;\", []>;"
8317  << std::endl;
8318 
8319  o << "} // end of is as cheap as move" << std::endl;
8320 }
8321 
8322 void TDGen::genTCEInstrInfo_copyPhys64bitReg(std::ostream&o) const {
8323  o << std::endl
8324  << "#include <llvm/CodeGen/MachineInstrBuilder.h>" << std::endl
8325  << "// copies 64-bit reg to a another" << std::endl
8326  << "bool TCEInstrInfo::copyPhys64bitReg(" << std::endl
8327  << "\tMachineBasicBlock& mbb," << std::endl
8328  << "\tMachineBasicBlock::iterator mbbi," << std::endl
8329  << "const DebugLoc& dl," << std::endl
8330  << "\tunsigned destReg, unsigned srcReg," << std::endl
8331  << "\tbool killSrc) const {" << std::endl
8332  << std::endl;
8333 
8334  if (mach_.is64bit()) {
8335  o << "\tif (TCE::R64RegsRegClass.contains(destReg, srcReg)) {\n"
8336  << "\t\tBuildMI(mbb, mbbi, dl, get(TCE::MOV64rr), destReg)\n"
8337  << "\t\t\t.addReg(srcReg, getKillRegState(killSrc));" << std::endl
8338  << "\t\treturn true;" << std::endl
8339  << "}" << std::endl;
8340  }
8341  o << "\treturn false;" << std::endl
8342  << "}";
8343 }
8344 
8345 void TDGen::writeAddressingModeDefs(std::ostream& o) {
8346  if (!mach_.is64bit()) {
8347  o << std::endl
8348  << "// Addressing modes." << std::endl
8349  << "def ADDRrr : ComplexPattern<i32, 2, \"SelectADDRrr\", [], []>;" << std::endl
8350  << "def ADDRri : ComplexPattern<i32, 2, \"SelectADDRri\", [frameindex], []>;" << std::endl
8351  << std::endl
8352  << "// Address operands" << std::endl
8353  << "def MEMrr : Operand<i32> {" << std::endl
8354  << "let PrintMethod = \"printMemOperand\";" << std::endl
8355  << "let MIOperandInfo = (ops R32IRegs, R32IRegs);" << std::endl
8356  << "}" << std::endl
8357  << "def MEMri : Operand<i32> {" << std::endl
8358  << "let PrintMethod = \"printMemOperand\";" << std::endl
8359  << "let MIOperandInfo = (ops R32IRegs, i32imm);" << std::endl
8360  << "}" << std::endl
8361  << std::endl
8362  << "// Branch targets have OtherVT type." << std::endl
8363  << "def brtarget : Operand<OtherVT>; " << std::endl
8364  << "def calltarget : Operand<i32>;" << std::endl;
8365 
8366  o << "def SDT_TCECall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;" << std::endl;
8367  } else {
8368  o << std::endl
8369  << "// Addressing modes." << std::endl
8370  << "def ADDRrr : ComplexPattern<i64, 2, \"SelectADDRrr\", [], []>;" << std::endl
8371  << "def ADDRri : ComplexPattern<i64, 2, \"SelectADDRri\", [frameindex], []>;" << std::endl
8372  << std::endl
8373  << "// Address operands" << std::endl
8374  << "def MEMrr : Operand<i64> {" << std::endl
8375  << "let PrintMethod = \"printMemOperand\";" << std::endl
8376  << "let MIOperandInfo = (ops R64IRegs, R64IRegs);" << std::endl
8377  << "}" << std::endl
8378  << "def MEMri : Operand<i64> {" << std::endl
8379  << "let PrintMethod = \"printMemOperand\";" << std::endl
8380  << "let MIOperandInfo = (ops R64IRegs, i64imm);" << std::endl
8381  << "}" << std::endl
8382  << std::endl
8383  << "// Branch targets have OtherVT type." << std::endl
8384  << "def brtarget : Operand<OtherVT>; " << std::endl
8385  << "def calltarget : Operand<i64>;" << std::endl;
8386 
8387  o << "def SDT_TCECall : SDTypeProfile<0, 1, [SDTCisVT<0, i64>]>;" << std::endl;
8388  }
8389 }
8390 
8391 void TDGen::writeMiscPatterns(std::ostream& o) {
8392  if (!mach_.is64bit()) {
8393  o << "// zero extending moves used in some patterns" << std::endl
8394  << "def ANDext : InstTCE<(outs R32IRegs:$dst), (ins R1Regs:$src, i32imm:$val), \"\", []>;" << std::endl
8395  << "def PRED_TRUE_ANDext : InstTCE<(outs R32IRegs:$dst),"
8396  << " (ins R1Regs:$pred, R1Regs:$src, i32imm:$val), \"\", []>;" << std::endl
8397  << "def PRED_FALSE_ANDext : InstTCE<(outs R32IRegs:$dst),"
8398  << " (ins R1Regs:$pred, R1Regs:$src, i32imm:$val),\"\", []>;" << std::endl
8399  << "def XORbicmp: InstTCE<(outs R1Regs:$dst),"
8400  << " (ins R1Regs:$src, i32imm:$val), \"\", []>;" << std::endl
8401  << "def PRED_TRUE_XORbicmp: InstTCE<(outs R1Regs:$dst),"
8402  << " (ins R1Regs:$pred, R1Regs:$src, i32imm:$val), \"\", []>;" << std::endl
8403  << "def PRED_FALSE_XORbicmp: InstTCE<(outs R1Regs:$dst),"
8404  << " (ins R1Regs:$pred, R1Regs:$src, i32imm:$val), \"\", []>;" << std::endl;
8405 
8406  o << "def: Pat <(i32 (anyext R1Regs:$src)), (ANDext R1Regs:$src, 1)>;" << std::endl
8407  << "def: Pat <(i32 (zext R1Regs:$src)), (ANDext R1Regs:$src, 1)>;" << std::endl;
8408 
8409  o << "// select of 1 or 0." << std::endl
8410  << "def : Pat<(i32 (select R1Regs:$c, (i32 1), (i32 0))),"
8411  << " (ANDext R1Regs:$c, 1)>;" << std::endl;
8412 
8413  o << std::endl
8414  << "def: Pat <(i32 (sext R1Regs:$src)), (SUBrir 0,(ANDext R1Regs:$src, 1))>;"
8415  << std::endl;
8416 
8417  o << "// ------ Shift (emulation) patterns. " << std::endl
8418  << "def: Pat <(i32 (shl R32IRegs:$val, (i32 1))),"
8419  << " (ADDrrr R32Regs:$val, R32Regs:$val)>;" << std::endl
8420  << "def: Pat <(i32 (TCESHLConst R32IRegs:$val, (i32 1))),"
8421  << " (ADDrrr R32IRegs:$val, R32IRegs:$val)>;" << std::endl;
8422 
8423  o << "// ----- Global addresses, constant pool entries ------" << std::endl
8424  << "def TCEGlobalAddr : SDNode<\"TCEISD::GLOBAL_ADDR\", SDTIntUnaryOp>;" << std::endl
8425  << "def TCEConstPool : SDNode<\"TCEISD::CONST_POOL\", SDTIntUnaryOp>;" << std::endl
8426  << "def : Pat<(TCEGlobalAddr tglobaladdr:$in), (MOVI32ri tglobaladdr:$in)>;" << std::endl
8427  << "def : Pat<(TCEGlobalAddr tconstpool:$in), (MOVI32ri tconstpool:$in)>;" << std::endl
8428  << "def : Pat<(TCEConstPool tglobaladdr:$in), (MOVI32ri tglobaladdr:$in)>;" << std::endl
8429  << "def : Pat<(TCEConstPool tconstpool:$in), (MOVI32ri tconstpool:$in)>;" << std::endl;
8430 
8431 
8432  o << "// some peephole patterns." << std::endl
8433  << "// 1-bit select with imm values - xor or mov." << std::endl
8434  << "def : Pat<(i1 (select R1Regs:$c, (i1 0), (i1 -1))), (XORbbj R1Regs:$c, 1)>;" << std::endl
8435  << "def : Pat<(i1 (select R1Regs:$c, (i1 -1), (i1 0))), (MOVI1rr R1Regs:$c)>;" << std::endl
8436  << "def : Pat<(i1 (select R1Regs:$c, (i1 -1), R1Regs:$F)), (IORbbb R1Regs:$c, R1Regs:$F)>;" << std::endl
8437  << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$T, (i1 0))), (ANDbbb R1Regs:$c, R1Regs:$T)>;" << std::endl;
8438 
8439  o << "// 1-bit comparison between booleans - xor or xnor(implemented with 2 xors)" << std::endl
8440  << "def : Pat<(i1 (setne R1Regs:$op1, R1Regs:$op2)), (XORbbb R1Regs:$op1, R1Regs:$op2)>;" << std::endl
8441  << "// TODO: should the temp values be converted to i32? usually more i32 regs." << std::endl
8442  << "def : Pat<(i1 (seteq R1Regs:$op1, R1Regs:$op2)), (XORbbj (XORbbb R1Regs:$op1, R1Regs:$op2), 1)>;" << std::endl;
8443 
8444  o << "def TCEBlockAddress : SDNode<\"TCEISD::BLOCK_ADDR\", SDTIntUnaryOp>;" << std::endl
8445  << "def : Pat<(TCEBlockAddress tblockaddress:$src1), (MOVI32ri tblockaddress:$src1)>;" << std::endl;
8446 
8447  } else {
8448  o << "// zero extending moves used in some patterns" << std::endl
8449  << "def ANDext : InstTCE<(outs R64IRegs:$dst),"
8450  << " (ins R1Regs:$src, i64imm:$val), \"\", []>;" << std::endl
8451  << "def PRED_TRUE_ANDext : InstTCE<(outs R64IRegs:$dst),"
8452  << " (ins R1Regs:$pred, R1Regs:$src, i64imm:$val), \"\", []>;" << std::endl
8453  << "def PRED_FALSE_ANDext : InstTCE<(outs R64IRegs:$dst),"
8454  << " (ins R1Regs:$pred, R1Regs:$src, i64imm:$val),\"\", []>;" << std::endl
8455  << "def XORbicmp: InstTCE<(outs R1Regs:$dst),"
8456  << " (ins R1Regs:$src, i64imm:$val), \"\", []>;" << std::endl
8457  << "def PRED_TRUE_XORbicmp: InstTCE<(outs R1Regs:$dst),"
8458  << " (ins R1Regs:$pred, R1Regs:$src, i64imm:$val), \"\", []>;" << std::endl
8459  << "def PRED_FALSE_XORbicmp: InstTCE<(outs R1Regs:$dst),"
8460  << " (ins R1Regs:$pred, R1Regs:$src, i64imm:$val), \"\", []>;" << std::endl;
8461 
8462  o << "def: Pat <(i64 (anyext R1Regs:$src)), (ANDext R1Regs:$src, 1)>;" << std::endl
8463  << "def: Pat <(i64 (zext R1Regs:$src)), (ANDext R1Regs:$src, 1)>;" << std::endl;
8464 
8465  o << "// select of 1 or 0." << std::endl
8466  << "def : Pat<(i64 (select R1Regs:$c, (i64 1), (i64 0))), (ANDext R1Regs:$c, 1)>;" << std::endl;
8467 
8468  o << std::endl
8469  << "def: Pat <(i64 (sext R1Regs:$src)), (SUB64sas 0,(ANDext R1Regs:$src, 1))>;"
8470  << std::endl;
8471 
8472  o << "// ------ Shift (emulation) patterns. " << std::endl
8473  << "def: Pat <(i64 (shl R64IRegs:$val, (i64 1))),"
8474  << " (ADD64sss R64Regs:$val, R64Regs:$val)>;" << std::endl
8475  << "def: Pat <(i64 (TCESHLConst R64IRegs:$val, (i64 1))),"
8476  << " (ADD64sss R64IRegs:$val, R64IRegs:$val)>;" << std::endl;
8477 
8478  o << "// ----- Global addresses, constant pool entries ------" << std::endl
8479  << "def TCEGlobalAddr : SDNode<\"TCEISD::GLOBAL_ADDR\", SDTIntUnaryOp>;" << std::endl
8480  << "def TCEConstPool : SDNode<\"TCEISD::CONST_POOL\", SDTIntUnaryOp>;" << std::endl
8481  << "def : Pat<(TCEGlobalAddr tglobaladdr:$in), (MOVI64sa tglobaladdr:$in)>;" << std::endl
8482  << "def : Pat<(TCEGlobalAddr tconstpool:$in), (MOVI64sa tconstpool:$in)>;" << std::endl
8483  << "def : Pat<(TCEConstPool tglobaladdr:$in), (MOVI64sa tglobaladdr:$in)>;" << std::endl
8484  << "def : Pat<(TCEConstPool tconstpool:$in), (MOVI64sa tconstpool:$in)>;" << std::endl;
8485 
8486  o << "// some peephole patterns." << std::endl
8487  << "// 1-bit select with imm values - xor or mov." << std::endl
8488  << "def : Pat<(i1 (select R1Regs:$c, (i1 0), (i1 -1))), (XOR64bbj R1Regs:$c, 1)>;" << std::endl
8489  << "def : Pat<(i1 (select R1Regs:$c, (i1 -1), (i1 0))), (MOVI1rr R1Regs:$c)>;" << std::endl
8490  << "def : Pat<(i1 (select R1Regs:$c, (i1 -1), R1Regs:$F)), (IOR64bbb R1Regs:$c, R1Regs:$F)>;" << std::endl
8491  << "def : Pat<(i1 (select R1Regs:$c, R1Regs:$T, (i1 0))), (AND64bbb R1Regs:$c, R1Regs:$T)>;" << std::endl;
8492 
8493  o << "// 1-bit comparison between booleans - xor or xnor(implemented with 2 xors)" << std::endl
8494  << "def : Pat<(i1 (setne R1Regs:$op1, R1Regs:$op2)), (XOR64bbb R1Regs:$op1, R1Regs:$op2)>;" << std::endl
8495  << "// TODO: should the temp values be converted to i64? usually more i64 regs." << std::endl
8496  << "def : Pat<(i1 (seteq R1Regs:$op1, R1Regs:$op2)), (XOR64bbj (XOR64bbb R1Regs:$op1, R1Regs:$op2), 1)>;" << std::endl;
8497 
8498  o << "def TCEBlockAddress : SDNode<\"TCEISD::BLOCK_ADDR\", SDTIntUnaryOp>;" << std::endl
8499  << "def : Pat<(TCEBlockAddress tblockaddress:$src1), (MOVI64sa tblockaddress:$src1)>;" << std::endl;
8500  }
8501 }
8502 
8503 void TDGen::writeConstShiftPat(std::ostream& os,
8504  const TCEString& nodeName,
8505  const TCEString& opNameBase, int i) {
8506 
8507  if (!mach_.is64bit()) {
8508  TCEString opName = opNameBase; opName << i << "_32rr";
8509  if (opNames_.find(opName) != opNames_.end()) {
8510  os << "def : Pat<(i32 (" << nodeName
8511  << " R32IRegs:$val, (i32 " << i << "))), ("
8512  << opName << " R32IRegs:$val)>;" << std::endl;
8513  }
8514  } else {
8515  TCEString opName = opNameBase; opName << i << "_64rr";
8516  if (opNames_.find(opName) != opNames_.end()) {
8517  os << "def : Pat<(i64 (" << nodeName
8518  << " R64IRegs:$val, (i64 " << i << "))), ("
8519  << opName << " R64IRegs:$val)>;" << std::endl;
8520  }
8521  }
8522 }
8523 
8524 
8525 void TDGen::createConstShiftPatterns(std::ostream& os) {
8526  int bits = mach_.is64bit() ? 64: 32;
8527  for (int i = 1; i < bits; i++) {
8528  writeConstShiftPat(os, "TCESRAConst", "SHR", i);
8529  writeConstShiftPat(os, "TCESRLConst", "SHRU", i);
8530  writeConstShiftPat(os, "TCESHLConst", "SHL", i);
8531  }
8532 }
8533 
8535 
8536  // TODO: what about true/false versions of these ops?
8537 
8538  TCEString load = littleEndian_ ? "LD8" : "LDQ";
8539  TCEString uload = littleEndian_ ? "LDU8" : "LDQU";
8540  TCEString wload = littleEndian_ ?
8541  (mach_.is64bit() ? "LD64" : "LD32") : "LDW";
8542  if (mach_.hasOperation(load)) {
8543  os << "def " << load
8544  << "Br : InstTCE<(outs R1Regs:$op2), (ins MEMrr:$op1), \"\", "
8545  << "[(set R1Regs:$op2, (sextloadi1 ADDRrr:$op1))]>;" << std::endl
8546  << "def " << load
8547  << "Bi : InstTCE<(outs R1Regs:$op2), (ins MEMri:$op1), \"\", "
8548  << "[(set R1Regs:$op2, (sextloadi1 ADDRri:$op1))]>; " << std::endl;
8549 
8550  opNames_[load + "Br"] = load;
8551  opNames_[load + "Bi"] = load;
8552 
8553  }
8554  if (mach_.hasOperation(uload)) {
8555  os << "def " << uload
8556  << "Br : InstTCE<(outs R1Regs:$op2), (ins MEMrr:$op1), \"\", "
8557  << "[(set R1Regs:$op2, (zextloadi1 ADDRrr:$op1))]>;" << std::endl
8558  << "def " << uload
8559  << "Bi : InstTCE<(outs R1Regs:$op2), (ins MEMri:$op1), \"\", "
8560  << "[(set R1Regs:$op2, (zextloadi1 ADDRri:$op1))]>;" << std::endl;
8561  opNames_[uload + "Br"] = uload;
8562  opNames_[uload + "Bi"] = uload;
8563 
8564  os << "def : Pat<(i1 (load ADDRrr:$addr)), ("
8565  << uload << "Br ADDRrr:$addr)>;" << std::endl;
8566  os << "def : Pat<(i1 (load ADDRri:$addr)), ("
8567  << uload << "Bi ADDRri:$addr)>;" << std::endl;
8568  } else {
8569  if (mach_.hasOperation(load)) {
8570  os << "def : Pat<(i1 (load ADDRrr:$addr)), ("
8571  << load << "Br ADDRrr:$addr)>;" << std::endl;
8572  os << "def : Pat<(i1 (load ADDRri:$addr)), ("
8573  << load << "Bi ADDRri:$addr)>;" << std::endl;
8574  }
8575  }
8576 
8577  // if no 8-bit loads, create 32/64-bit loads for stack access but
8578  // no patterns for isel as only the stack is 32/64-bit aligned.
8579  // 1- and 8-bit loads on isel will be handled by lowering.
8580  if (!mach_.hasOperation(load) &&
8581  !mach_.hasOperation(uload) &&
8582  mach_.hasOperation(wload)) {
8583  os << "def " << wload
8584  << "Br : InstTCE<(outs R1Regs:$op2), (ins MEMrr:$op1), \"\", "
8585  << "[]>;" << std::endl
8586  << "def " << wload
8587  << "Bi : InstTCE<(outs R1Regs:$op2), (ins MEMri:$op1), \"\", "
8588  << "[]>;" << std::endl;
8589 
8590  opNames_[wload + "Br"] = wload;
8591  opNames_[wload + "Bi"] = wload;
8592  }
8593 
8594  TCEString halfLoad = littleEndian_ ? "LD16" : "LDH";
8595  if (!mach_.hasOperation(halfLoad)) {
8596  TCEString halfULoad = littleEndian_ ? "LDU16" : "LDHU";
8597  if (mach_.hasOperation(halfULoad)) {
8598  halfLoad = halfULoad;
8599  } else {
8600  return;
8601  }
8602  }
8603 
8604  os << "def " << halfLoad << "hr : InstTCE<(outs HFPRegs:$op2), "
8605  << "(ins MEMrr:$op1), \"\", [(set HFPRegs:$op2, "
8606  << "(load ADDRrr:$op1))]>;" << std::endl;
8607 
8608  os << "def " << halfLoad << "hi : InstTCE<(outs HFPRegs:$op2), "
8609  << "(ins MEMri:$op1), \"\", [(set HFPRegs:$op2, "
8610  << "(load ADDRri:$op1))]>;" << std::endl;
8611 
8612  opNames_[halfLoad + "hr"] = halfLoad;
8613  opNames_[halfLoad + "hi"] = halfLoad;
8614 
8615  // TODO: what about 32-bit?
8616 }
8617 
8618 // ---------------------------------------------------------------------------
8619 // ValueType implementation.
8620 
8621 /**
8622  * Constructor.
8623  *
8624  * @param subwWidth Subword width.
8625  * @param subwCount Subword count.
8626  * @param isFloat True, if is a floating point type.
8627  */
8628 ValueType::ValueType(int subwWidth, int subwCount, bool isFloat)
8629  : subwWidth_(subwWidth), subwCount_(subwCount), isFloat_(isFloat) {
8630  assert(subwWidth > 0 && "Invalid value type.");
8631  assert(subwCount > 0 && "Invalid value type.");
8632 }
8633 
8634 /**
8635  * Constructor.
8636  *
8637  * @param vtStr Value type string in LLVM format.
8638  */
8640  ValueType vt = valueType(vtStr);
8641  this->subwWidth_ = vt.subwWidth_;
8642  this->subwCount_ = vt.subwCount_;
8643  this->isFloat_ = vt.isFloat_;
8644 }
8645 
8646 /**
8647  * Constructor.
8648  *
8649  * @param opnd Operand to be converted to ValueType.
8650  */
8652  ValueType vt = valueType(opnd);
8653  this->subwWidth_ = vt.subwWidth_;
8654  this->subwCount_ = vt.subwCount_;
8655  this->isFloat_ = vt.isFloat_;
8656 }
8657 
8658 /**
8659  * Copy constructor.
8660  *
8661  * @param other Value to be copied.
8662  */
8664  : subwWidth_(other.subwWidth_),
8665  subwCount_(other.subwCount_),
8666  isFloat_(other.isFloat_) {}
8667 
8668 /**
8669  * Value assignment.
8670  *
8671  * @param other Value to be assigned.
8672  * @return Reference with the assigned values.
8673  */
8674 ValueType&
8676  this->subwWidth_ = other.subwWidth_;
8677  this->subwCount_ = other.subwCount_;
8678  this->isFloat_ = other.isFloat_;
8679  return *this;
8680 }
8681 
8682 /**
8683  * Tells whether ValueType is supported by LLVM or not.
8684  *
8685  * @return True, if ValueType is supported by LLVM.
8686  */
8687 bool
8691  return true;
8692  }
8693  return false;
8694 }
8695 
8696 /**
8697  * Returns ValueType's whole bitwidth.
8698  *
8699  * @return ValueType's whole bitwidth.
8700  */
8701 int
8703  return subwWidth_ * subwCount_;
8704 }
8705 
8706 /**
8707  * Returns ValueType's subword bitwidth.
8708  *
8709  * @return ValueType's subword bitwidth.
8710  */
8711 int
8713  return subwWidth_;
8714 }
8715 
8716 /**
8717  * Returns ValueType's subword count.
8718  *
8719  * @return ValueType's subword count.
8720  */
8721 int
8723  return subwCount_;
8724 }
8725 
8726 /**
8727  * Tells whether ValueType is a floating point type or not.
8728  *
8729  * @return True, is ValueType is a float type.
8730  */
8731 bool
8733  return isFloat_;
8734 }
8735 
8736 /**
8737  * Tells whether ValueType is a vector type or not.
8738  *
8739  * @return True, is ValueType is a vector type.
8740  */
8741 bool
8743  return subwCount_ > 1;
8744 }
8745 
8746 /**
8747  * Returns the Operand::OperandType of ValueType.
8748  *
8749  * @return OperandType of ValueType.
8750  */
8753  if (!isFloat_ && subwWidth_ == 1) {
8754  return Operand::BOOL;
8755  } else if (isFloat_ && subwWidth_ == 16) {
8756  return Operand::HALF_FLOAT_WORD;
8757  } else if (isFloat_ && subwWidth_ == 32) {
8758  return Operand::FLOAT_WORD;
8759  } else if (!isFloat_) {
8760  return Operand::UINT_WORD;
8761  }
8762 
8763  return Operand::UINT_WORD;
8764 }
8765 
8766 /**
8767  * Returns ValueType in LLVM value type string format, e.g. "v2i32".
8768  *
8769  * @return Value type string in LLVM format.
8770  */
8771 TCEString
8773  const TCEString subwWidthStr = Conversion::toString(subwWidth_);
8774 
8775  // Check if the value type is a scalar.
8776  if (subwCount_ == 1) {
8777  if (isFloat_) {
8778  return "f" + subwWidthStr;
8779  } else {
8780  return "i" + subwWidthStr;
8781  }
8782  }
8783 
8784  // The value type is a vector.
8785  if (isFloat_) {
8786  return "v" + Conversion::toString(subwCount_) + "f" + subwWidthStr;
8787  } else {
8788  return "v" + Conversion::toString(subwCount_) + "i" + subwWidthStr;
8789  }
8790 }
8791 
8792 /**
8793  * Returns Operand in LLVM value type string format, e.g. "v2i32".
8794  *
8795  * @param operand Operand that will be transformed to value type string.
8796  * @return Value type string in LLVM format.
8797  */
8798 TCEString
8800  if (operand.type() == Operand::FLOAT_WORD ||
8801  operand.type() == Operand::HALF_FLOAT_WORD) {
8802  ValueType vt(operand.elementWidth(), operand.elementCount(), true);
8803  return vt.valueTypeStr();
8804  } else {
8805  ValueType vt(operand.elementWidth(), operand.elementCount(), false);
8806  return vt.valueTypeStr();
8807  }
8808 }
8809 
8810 /**
8811  * Returns given LLVM value type string (e.g. "v2i32") as ValueType.
8812  *
8813  * @param vtStr LLVM value type string to be converted to ValueType.
8814  * @return ValueType object of the LLVM value type string.
8815  */
8816 ValueType
8818  assert(vtStr.size() > 1);
8819 
8820  // Check if the value type is a scalar.
8821  if (vtStr[0] != 'v') {
8822  int subwWidthStr = Conversion::toInt(vtStr.substr(1));
8823 
8824  if (vtStr[0] == TDGen::OT_REG_FP) {
8825  return ValueType(subwWidthStr, 1, true);
8826  } else {
8827  return ValueType(subwWidthStr, 1, false);
8828  }
8829  }
8830 
8831  // The value type is a vector, find float/integer type ("f"/"i")
8832  // indicator.
8833  size_t vtI = vtStr.length() - 1;
8834  while (vtI > 0 && std::isdigit(vtStr[vtI])) --vtI;
8835 
8836  int subwCount = Conversion::toInt(vtStr.substr(1, vtI - 1));
8837  int subwWidth = Conversion::toInt(vtStr.substr(vtI + 1));
8838 
8839  if (vtStr[vtI] == TDGen::OT_REG_FP) {
8840  return ValueType(subwWidth, subwCount, true);
8841  } else {
8842  return ValueType(subwWidth, subwCount, false);
8843  }
8844 }
8845 
8846 /**
8847  * Returns given Operand as a value type object.
8848  *
8849  * @param operand Operand to be converted to ValueType.
8850  * @return ValueType presentation of the Operand.
8851  */
8852 ValueType
8854  return valueType(valueTypeStr(operand));
8855 }
8856 
8857 /**
8858  * Returns a list of vector value types that match the given width.
8859  *
8860  * Currently filters out unsupported LLVM value types.
8861  *
8862  * @param width The width of the desired value types.
8863  * @param onlyInts If true, floating point types are not included to output.
8864  * @return Value types for given width in a container.
8865  */
8866 std::vector<ValueType>
8867 ValueType::vectorTypesOfWidth(int width, bool onlyInts) {
8868  std::vector<ValueType> vts;
8869 
8870  int subwCount = 2;
8871  int subwWidth = width / subwCount;
8872 
8873  while (subwWidth > 0) {
8874  ValueType intVt(subwWidth, subwCount, false);
8875  if (intVt.isSupportedByLLVM()) {
8876  vts.push_back(intVt);
8877  }
8878 
8879  if (!onlyInts) {
8880  ValueType floatVt(subwWidth, subwCount, true);
8881  if (floatVt.isSupportedByLLVM()) {
8882  vts.push_back(floatVt);
8883  }
8884  }
8885 
8886  subwWidth /= 2;
8887  subwCount *= 2;
8888  }
8889 
8890  return vts;
8891 }
8892 
8893 /**
8894  * Returns a list of vector value types that match the given subword width.
8895  *
8896  * Currently filters out unsupported LLVM value types.
8897  *
8898  * @param subwordWidth The subword width of the desired value types.
8899  * @param onlyInts If true, floating point types are not included to output.
8900  * @return Value types for given subword width in a container.
8901  */
8902 std::vector<ValueType>
8903 ValueType::vectorTypesOfSubwordWidth(int subwordWidth, bool onlyInts) {
8904  std::vector<ValueType> vts;
8905 
8906  int subwCount = 2;
8907  int subwWidth = subwordWidth;
8908  int MAX_SUBW_COUNT = SIMD_WORD_WIDTH / BYTE_BITWIDTH;
8909 
8910  while (subwWidth * subwCount <= SIMD_WORD_WIDTH &&
8911  subwCount <= MAX_SUBW_COUNT) {
8912  ValueType intVt(subwWidth, subwCount, false);
8913  if (intVt.isSupportedByLLVM()) {
8914  vts.push_back(intVt);
8915  }
8916 
8917  if (!onlyInts) {
8918  ValueType floatVt(subwWidth, subwCount, true);
8919  if (floatVt.isSupportedByLLVM()) {
8920  vts.push_back(floatVt);
8921  }
8922  }
8923 
8924  subwCount *= 2;
8925  }
8926 
8927  return vts;
8928 }
8929 
8930 // ---------------------------------------------------------------------------
8931 // RegisterClass implementation.
8932 
8933 /**
8934  * Constructor.
8935  *
8936  * @param vt ValueType that is supported by the RegisterClass.
8937  * @param name Name of the RegisterClass.
8938  */
8940  : name_(name), vt_(vt), registers_(std::vector<RegisterInfo>()) {
8941  if (vt.width() < 8) {
8942  alignment_ = 8;
8943  } else {
8944  alignment_ = vt.width();
8945  }
8946 }
8947 
8948 /**
8949  * Copy constructor.
8950  *
8951  * @param other RegisterClass to be copied.
8952  */
8954  : name_(other.name_),
8955  vt_(other.vt_),
8956  alignment_(other.alignment_),
8957  registers_(other.registers_) {}
8958 
8959 /**
8960  * Value assignment.
8961  *
8962  * @param other RegisterClass to be assigned.
8963  * @return Reference with the assigned values.
8964  */
8967  this->name_ = other.name_;
8968  this->vt_ = other.vt_;
8969  this->alignment_ = other.alignment_;
8970  this->registers_ = other.registers_;
8971  return *this;
8972 }
8973 
8974 /**
8975  * Returns RegisterClass's name.
8976  *
8977  * @return Name of the RegisterClass.
8978  */
8979 TCEString
8981  return name_;
8982 }
8983 
8984 /**
8985  * Returns the supported ValueType.
8986  *
8987  * @return Supported ValueType.
8988  */
8989 ValueType
8991  return vt_;
8992 }
8993 
8994 /**
8995  * Returns the RegisterClass's alignment in bits.
8996  *
8997  * @return Alignment of RegisterClass in bits.
8998  */
8999 int
9001  return alignment_;
9002 }
9003 
9004 /**
9005  * Returns RegisterInfo pointed by the index.
9006  *
9007  * @return RegisterInfo pointed by the index.
9008  */
9011  assert(
9012  index >= static_cast<int>(0) &&
9013  index < static_cast<int>(registers_.size()));
9014  return registers_[index];
9015 }
9016 
9017 /**
9018  * Returns how many registers is used by this RegisterClass.
9019  *
9020  * @return A number of registers used by this RegisterClass.
9021  */
9022 size_t
9024  return registers_.size();
9025 }
9026 
9027 /**
9028  * Sets the registers used by this RegisterClass.
9029  *
9030  * @param registers The new registers used by this RegisterClass.
9031  */
9032 void
9033 RegisterClass::addRegisters(const std::vector<RegisterInfo>& registers) {
9034  registers_.insert(registers_.end(), registers.begin(), registers.end());
9035 }
Operand
Definition: Operand.hh:52
TDGen::requiredI64Regs_
unsigned int requiredI64Regs_
Definition: TDGen.hh:616
OperationDAGEdge::dstOperand
int dstOperand() const
Definition: OperationDAGEdge.cc:54
ImmediateAnalyzer.hh
TDGen::gprRegNames_
std::vector< std::string > gprRegNames_
Definition: TDGen.hh:592
ADDIMM
#define ADDIMM
Definition: TCEFrameInfo.cc:62
TDGen::createEndiannesQuery
void createEndiannesQuery(std::ostream &os)
Definition: TDGen.cc:6413
TDGenerator::RegisterInfo::regFileName_
TCEString regFileName_
Name of the register file the register belongs to, e.g. "RF".
Definition: TDGen.hh:656
TDGen::writePortGuardedJumpDefPair
bool writePortGuardedJumpDefPair(std::ostream &os, const TCEString &tceop1, const TCEString &tceop2, bool fp=false)
Definition: TDGen.cc:3841
TDGenerator::RegisterClass
Definition: TDGen.hh:721
BoostGraph::predecessors
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
TDGen::OT_REG_FP
static const char OT_REG_FP
Definition: TDGen.hh:485
TDGen::write16bitRegisterInfo
void write16bitRegisterInfo(std::ostream &o)
Definition: TDGen.cc:1155
TDGen::RESULT
@ RESULT
Definition: TDGen.hh:100
TDGen::genTCETargetLoweringSIMD_associatedVectorRegClass
void genTCETargetLoweringSIMD_associatedVectorRegClass(std::ostream &o) const
Definition: TDGen.cc:3042
ImmInfo::immediateValueBounds
std::pair< int64_t, int64_t > immediateValueBounds(const ImmInfoKey &key, int destWidth) const
Definition: ImmInfo.cc:219
BoostGraph::connectNodes
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
BoostGraph::outEdge
virtual Edge & outEdge(const Node &node, const int index) const
Operation::writesMemory
virtual bool writesMemory() const
Definition: Operation.cc:252
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
TDGen::OT_REG_INT
static const char OT_REG_INT
Definition: TDGen.hh:483
TDGen::getMatchableOperationDAG
const OperationDAG * getMatchableOperationDAG(const Operation &op)
Definition: TDGen.cc:5320
TDGen::maxScalarWidth_
int maxScalarWidth_
Definition: TDGen.hh:610
TDGen::writeHWLoopDef
void writeHWLoopDef(std::ostream &o)
Definition: TDGen.cc:3571
TDGen::writeBooleanStorePatterns
void writeBooleanStorePatterns(std::ostream &os)
Definition: TDGen.cc:4527
TDGenerator::RegisterInfo::regIndex_
unsigned regIndex_
Register index in the register file.
Definition: TDGen.hh:658
TTAMachine::Machine::hasOperation
bool hasOperation(const TCEString &opName) const
Definition: Machine.cc:1048
TDGen::checkRequiredRegisters
bool checkRequiredRegisters()
Definition: TDGen.cc:3280
TDGen::resRegNames_
std::vector< std::string > resRegNames_
Definition: TDGen.hh:591
TDGen::createConstantMaterializationQuery
void createConstantMaterializationQuery(std::ostream &os)
Definition: TDGen.cc:6427
TDGen::writeConstShiftPat
void writeConstShiftPat(std::ostream &os, const TCEString &nodeName, const TCEString &opNameBase, int i)
Definition: TDGen.cc:8503
TDGen::writeVectorRegisterClasses
void writeVectorRegisterClasses(std::ostream &o) const
Definition: TDGen.cc:2046
Operand::setElementCount
virtual void setElementCount(int elementCount)
Definition: Operand.cc:308
Operand::BOOL
@ BOOL
Definition: Operand.hh:64
MachineConnectivityCheck
Definition: MachineConnectivityCheck.hh:69
TDGen::OT_IMM_HFP
static const char OT_IMM_HFP
Definition: TDGen.hh:491
TDGen::OT_VREG_INT32
static const char OT_VREG_INT32
Definition: TDGen.hh:496
TDGenerator::RegisterClass::RegisterClass
RegisterClass(const ValueType &vt, const TCEString &name)
Definition: TDGen.cc:8939
BoostGraph::tailNode
virtual Node & tailNode(const Edge &edge) const
ImmInfo::canTakeImmediateByWidth
bool canTakeImmediateByWidth(const Operation &operation, int inputOperandId, int bitWidth)
Definition: ImmInfo.cc:275
TDGen::canBeImmediate
bool canBeImmediate(const OperationDAG &dag, const TerminalNode &node)
Definition: TDGen.cc:6049
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
NumberFormatException
Definition: Exception.hh:421
TDGen::immediateStores_
std::map< TCEString, TDGenerator::InstructionInfo > immediateStores_
All immediate store operations (<ValueType, InstrInfo>).
Definition: TDGen.hh:527
TTAMachine::RegisterFile::isReserved
virtual bool isReserved() const
Definition: RegisterFile.cc:184
TDGen.hh
MachineConnectivityCheck.hh
TDGen::write64bitRegisterInfo
void write64bitRegisterInfo(std::ostream &o)
Definition: TDGen.cc:1307
BoostGraph::headNode
virtual Node & headNode(const Edge &edge) const
Operand::OperandType
OperandType
Definition: Operand.hh:58
Operation::output
virtual Operand & output(int index) const
Definition: Operation.cc:526
Operand::HALF_FLOAT_WORD
@ HALF_FLOAT_WORD
Definition: Operand.hh:63
TDGenerator::RegisterClass::registerInfo
RegisterInfo registerInfo(int index) const
Definition: TDGen.cc:9010
TDGenerator::RegisterClass::valueType
ValueType valueType() const
Definition: TDGen.cc:8990
TDGen::requiredI32Regs_
unsigned int requiredI32Regs_
Minimum number of 32 bit registers.
Definition: TDGen.hh:615
BoostGraph::node
Node & node(const int index) const
ImmInfo::count
size_t count(const ImmInfoKey &key) const
Definition: ImmInfo.hh:87
TTAMachine::RegisterGuard::registerIndex
int registerIndex() const
TDGen::immInfo_
ImmInfo * immInfo_
Definition: TDGen.hh:430
TDGen::OT_VREG_BOOL
static const char OT_VREG_BOOL
Definition: TDGen.hh:493
Operand::elementCount
virtual int elementCount() const
Definition: Operand.cc:298
TDGen::writeVectorBitConversions
void writeVectorBitConversions(std::ostream &o) const
Definition: TDGen.cc:2362
TDGen::OT_IMM_INT
static const char OT_IMM_INT
Definition: TDGen.hh:489
Operation::dagError
virtual TCEString dagError(int index) const
Definition: Operation.cc:182
TDGenerator::ValueType::SUPPORTED_LLVM_VALUE_TYPES
static const std::set< TCEString > SUPPORTED_LLVM_VALUE_TYPES
Contains all supported LLVM value types (<ValueType>).
Definition: TDGen.hh:715
TDGen::tceOperationPattern
std::string tceOperationPattern(const Operation &op)
Definition: TDGen.cc:5225
TDGenerator::RegisterClass::registers
std::vector< RegisterInfo > registers() const
TDGen::operationPattern
std::string operationPattern(const Operation &op, const OperationDAG &dag, const std::string &operandTypes)
Definition: TDGen.cc:5351
TDGen::createDefaultOperandTypeString
std::string createDefaultOperandTypeString(const Operation &op)
Definition: TDGen.cc:5369
TDGen::createByteExtLoadPatterns
void createByteExtLoadPatterns(std::ostream &os)
Definition: TDGen.cc:6457
TDGen::writeVectorRegisterNames
void writeVectorRegisterNames(std::ostream &o)
Definition: TDGen.cc:2014
AssocTools::containsKey
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
BoostGraph< OperationDAGNode, OperationDAGEdge >::NodeSet
std::set< OperationDAGNode *, typename OperationDAGNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
TDGen::writeCallDef
void writeCallDef(std::ostream &o)
Definition: TDGen.cc:3899
TDGen::genGeneratedTCEPlugin_getIorOpcode
void genGeneratedTCEPlugin_getIorOpcode(std::ostream &o) const
Definition: TDGen.cc:3259
TDGenerator::ValueType::subwCount_
int subwCount_
Subword count of the value type.
Definition: TDGen.hh:710
TDGen::regs16bit_
std::vector< RegInfo > regs16bit_
Definition: TDGen.hh:578
REG_RENAMER_PART
static const unsigned REG_RENAMER_PART
Definition: TDGen.cc:332
TTAMachine::Bus
Definition: Bus.hh:53
TDGen::associatedVectorRegisterClass
TCEString associatedVectorRegisterClass(const Operand &operand) const
Definition: TDGen.cc:1786
TDGenerator::RegisterClass::addRegisters
void addRegisters(const std::vector< RegisterInfo > &registers)
Definition: TDGen.cc:9033
TDGen::truePredOps_
std::map< std::string, std::string > truePredOps_
Definition: TDGen.hh:596
ImmInfoKey
std::pair< std::string, int > ImmInfoKey
Definition: ImmInfo.hh:53
Operand::UINT_WORD
@ UINT_WORD
Definition: Operand.hh:60
TDGen::subwordWidthOfRawData
int subwordWidthOfRawData(const Operation &op) const
Definition: TDGen.cc:1722
TDGen::BOOL_SUBW_WIDTH
static const int BOOL_SUBW_WIDTH
Bool type subword width.
Definition: TDGen.hh:469
SUBIMM
#define SUBIMM
Definition: TCEFrameInfo.cc:63
TTAMachine::Machine::is64bit
bool is64bit() const
Definition: Machine.hh:260
TDGen::writeOperationDefs
void writeOperationDefs(std::ostream &o, Operation &op, bool skipPattern)
Definition: TDGen.cc:4271
Operand::width
virtual int width() const
Definition: Operand.cc:318
Operand::setType
virtual void setType(OperandType type)
Definition: Operand.cc:175
TDGen::writeCallSeqStart
void writeCallSeqStart(std::ostream &os)
Definition: TDGen.cc:7870
Application::VERBOSE_LEVEL_DEFAULT
static const int VERBOSE_LEVEL_DEFAULT
Default verbose level - do not print anything unnecessary.
Definition: Application.hh:222
MachineInfo.hh
MachineInfo::osalOperation
static Operation & osalOperation(const TTAMachine::HWOperation &hwOp)
Definition: MachineInfo.cc:794
TDGen::writeInstrInfo
void writeInstrInfo(std::ostream &o)
Definition: TDGen.cc:3328
TerminalNode
Definition: TerminalNode.hh:47
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
TDGen::writeVectorImmediateWriteDefs
void writeVectorImmediateWriteDefs(std::ostream &instrInfoTD)
Definition: TDGen.cc:3160
Operand::setElementWidth
virtual void setElementWidth(int elementWidth)
Definition: Operand.cc:288
TDGen::analyzeMachineRegisters
void analyzeMachineRegisters()
Definition: TDGen.cc:1422
TDGen::falsePredOps_
std::map< std::string, std::string > falsePredOps_
Definition: TDGen.hh:597
TDGenerator::RegisterClass::name
TCEString name() const
Definition: TDGen.cc:8980
TDGen::argRegCount_
unsigned int argRegCount_
Definition: TDGen.hh:613
TDGen::createVectorRVDRegNums
virtual void createVectorRVDRegNums(std::ostream &os)
Definition: TDGen.cc:6948
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
OperationNode::referencedOperation
Operation & referencedOperation() const
Definition: OperationNode.cc:70
TDGen::scalarOps_
std::map< TCEString, Operation * > scalarOps_
Contains all scalar operations (<Name, Operation>).
Definition: TDGen.hh:508
TDGenerator::RegisterInfo
Definition: TDGen.hh:644
TDGen::llvmOperationPattern
virtual TCEString llvmOperationPattern(const Operation &op, char operandType=' ') const
Definition: TDGen.cc:4854
TDGen::OT_REG_BOOL
static const char OT_REG_BOOL
Definition: TDGen.hh:482
TDGen::supportedStackAccessOperations
static std::vector< std::string > supportedStackAccessOperations(const TTAMachine::Machine &mach)
Definition: TDGen.cc:7611
TDGen::OT_VREG_HFP
static const char OT_VREG_HFP
Definition: TDGen.hh:498
Operand::elementWidth
virtual int elementWidth() const
Definition: Operand.cc:278
TDGen::write32bitRegisterInfo
void write32bitRegisterInfo(std::ostream &o)
Definition: TDGen.cc:965
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
BoostGraph::addNode
virtual void addNode(Node &node)
OperationNode
Definition: OperationNode.hh:47
TDGen::orderEqualWidthRegistersToRoundRobin
void orderEqualWidthRegistersToRoundRobin()
Definition: TDGen.cc:1618
TTAMachine::Machine::Navigator::count
int count() const
TDGen::guardedRegs_
std::set< RegInfo > guardedRegs_
List of register that are associated with a guard on a bus.
Definition: TDGen.hh:621
TDGen::OT_REG_LONG
static const char OT_REG_LONG
Definition: TDGen.hh:484
TCEString::upper
TCEString upper() const
Definition: TCEString.cc:86
Operand::isOutput
virtual bool isOutput() const
Definition: Operand.cc:155
NullOperation::instance
static NullOperation & instance()
TDGen::writeScalarToVectorDefs
void writeScalarToVectorDefs(std::ostream &o) const
Definition: TDGen.cc:2332
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
TDGen::writeVectorRegisterMoveDefs
void writeVectorRegisterMoveDefs(std::ostream &o)
Definition: TDGen.cc:2214
TDGen::writeVectorOperationDefs
void writeVectorOperationDefs(std::ostream &o, Operation &op, bool skipPattern)
Definition: TDGen.cc:2108
OperationDAGEdge
Definition: OperationDAGEdge.hh:38
MachineConnectivityCheck::hasConditionalMoves
static bool hasConditionalMoves(const TTAMachine::Machine &mach, const std::set< int > &rfWidths)
Definition: MachineConnectivityCheck.cc:1876
TDGen::OT_VREG_INT8
static const char OT_VREG_INT8
Definition: TDGen.hh:494
TDGen::genGeneratedTCEPlugin_getLoad
void genGeneratedTCEPlugin_getLoad(std::ostream &o) const
Definition: TDGen.cc:2883
Conversion::toString
static std::string toString(const T &source)
TDGen::writeInstrDef
void writeInstrDef(std::ostream &o, const std::string &instrDefName, const std::string &outs, const std::string &ins, const std::string &asmString, const std::string &pattern)
Definition: TDGen.cc:4585
TDGen::writeVectorMemoryOperationDefs
void writeVectorMemoryOperationDefs(std::ostream &o, Operation &op, bool skipPattern)
Definition: TDGen.cc:2205
TDGen::write64bitMoveDefs
void write64bitMoveDefs(std::ostream &o)
Definition: TDGen.cc:8304
TDGen::regs8bit_
std::vector< RegInfo > regs8bit_
Definition: TDGen.hh:576
TDGen::RegInfo::idx
unsigned idx
Definition: TDGen.hh:112
TDGen::vbcastOperations_
std::map< TCEString, TCEString > vbcastOperations_
Contains machine's VBCAST instructions (<ValueType, InstrName>).
Definition: TDGen.hh:534
TDGen::isVectorStoreOperation
bool isVectorStoreOperation(const Operation &op) const
Definition: TDGen.cc:1921
TDGen::shlOperations_
std::map< TCEString, TCEString > shlOperations_
Contains machine's shl instructions (<ValueType, InstrName>).
Definition: TDGen.hh:566
TDGen::generateBackend
void generateBackend(std::string &path)
Definition: TDGen.cc:388
TDGen::areImmediateOperandsLegal
bool areImmediateOperandsLegal(const Operation &operation, const std::string &operandTypes) const
Definition: TDGen.cc:7543
Operation::dagCode
virtual TCEString dagCode(int index) const
Definition: Operation.cc:159
TDGen::isVectorLoadOperation
bool isVectorLoadOperation(const Operation &op) const
Definition: TDGen.cc:1909
TDGen::writeGetPointerAdjustmentQuery
void writeGetPointerAdjustmentQuery(std::ostream &os) const
Definition: TDGen.cc:7448
TDGenerator::RegisterClass::alignment_
int alignment_
RegisterClass alignment in bits, at least 8.
Definition: TDGen.hh:743
OperationDAG::endNodes
const OperationDAG::NodeSet & endNodes() const
Definition: OperationDAG.cc:137
TDGenerator::ValueType
Definition: TDGen.hh:679
ImmInfo::key
static ImmInfoKey key(const Operation &operation, int inputOperandId)
Definition: ImmInfo.cc:57
BoostGraph::outDegree
virtual int outDegree(const Node &node) const
TDGen::allOpNames_
OperationDAGSelector::OperationSet allOpNames_
Contains all operation names in upper case.
Definition: TDGen.hh:505
Operation::canSwap
virtual bool canSwap(int id1, int id2) const
Definition: Operation.cc:470
TCEString.hh
TDGen::OT_VREG_INT16
static const char OT_VREG_INT16
Definition: TDGen.hh:495
TDGenerator::ValueType::valueType
static ValueType valueType(const TCEString &vtStr)
Definition: TDGen.cc:8817
StringTools::stringToUpper
static std::string stringToUpper(const std::string &source)
Definition: StringTools.cc:143
ImmInfo.hh
TDGen::writeOperandDefs
void writeOperandDefs(std::ostream &o)
Definition: TDGen.cc:566
TDGen::hasRegisterClassSupport
bool hasRegisterClassSupport(const Operation &op) const
Definition: TDGen.cc:1749
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
TTAMachine::FunctionUnit
Definition: FunctionUnit.hh:55
TDGen::ARGUMENT
@ ARGUMENT
Definition: TDGen.hh:99
Operand::isVector
virtual bool isVector() const
Definition: Operand.cc:268
TDGen::hasConditionalMoves_
bool hasConditionalMoves_
Definition: TDGen.hh:608
numbersToAscending
bool numbersToAscending(const TCEString &lhs, const TCEString &rhs)
Definition: TDGen.cc:292
TDGen::genTCETargetLoweringSIMD_addVectorRegisterClasses
void genTCETargetLoweringSIMD_addVectorRegisterClasses(std::ostream &o) const
Definition: TDGen.cc:2997
TDGen::createTrivialDAG
OperationDAG * createTrivialDAG(Operation &op)
Definition: TDGen.cc:6019
TDGen::vRegClasses_
std::map< TCEString, TDGenerator::RegisterClass > vRegClasses_
Contains required vector register classes (<ValueType, RegClass>).
Definition: TDGen.hh:520
TDGen::writeStartOfRegisterInfo
void writeStartOfRegisterInfo(std::ostream &o)
Definition: TDGen.cc:539
TDGen::writeTopLevelTD
void writeTopLevelTD(std::ostream &o)
Definition: TDGen.cc:4190
TDGen::registerStores_
std::map< TCEString, TDGenerator::InstructionInfo > registerStores_
All register store operations (<ValueType, InstrInfo>).
Definition: TDGen.hh:523
TDGenerator::ValueType::vectorTypesOfSubwordWidth
static std::vector< ValueType > vectorTypesOfSubwordWidth(int subwordWidth, bool onlyInt=false)
Definition: TDGen.cc:8903
TDGen::dregNum_
unsigned dregNum_
Definition: TDGen.hh:462
OperationDAGSelector::findDags
static OperationDAGList findDags(const std::string &opName, OperationSet opSet, const ImmInfo *immInfo=nullptr)
Definition: OperationDAGSelector.cc:57
TDGen::writeCallingConvLicenceText
void writeCallingConvLicenceText(std::ostream &os)
Definition: TDGen.cc:6901
TDGen::createMinMaxGenerator
virtual void createMinMaxGenerator(std::ostream &os)
Definition: TDGen.cc:6324
OperationDAGEdge.hh
TDGen::tempRegFiles_
std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > tempRegFiles_
Register files whose last reg reserved for temp reg copies.
Definition: TDGen.hh:626
TDGenerator::RegisterClass::alignment
int alignment() const
Definition: TDGen.cc:9000
TDGen::immediatePredicate
std::string immediatePredicate(int64_t lowerBoundInclusive, uint64_t upperBoundInclusive)
Definition: TDGen.cc:7486
TTAMachine::Machine::controlUnit
virtual ControlUnit * controlUnit() const
Definition: Machine.cc:345
TDGen::writeIntegerImmediateDefs
void writeIntegerImmediateDefs(std::ostream &o, const ImmInfo &iivis)
Definition: TDGen.cc:594
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
HWOperation.hh
TDGen::regsInRFClasses_
RegClassMap regsInRFClasses_
Definition: TDGen.hh:632
TTAMachine::HWOperation::name
const std::string & name() const
Definition: HWOperation.cc:141
TDGen::getLLVMPatternWithConstants
TCEString getLLVMPatternWithConstants(const Operation &op, const std::string &operandTypes, const std::string &operand0, const std::string &operand1) const
Definition: TDGen.cc:7682
InvalidData
Definition: Exception.hh:149
MachineInfo::supportsPortGuardedJump
static bool supportsPortGuardedJump(const TTAMachine::Machine &machine, bool inverted, const TCEString &opName)
Definition: MachineInfo.cc:703
OperationDAGEdge::srcOperand
int srcOperand() const
Definition: OperationDAGEdge.cc:49
TDGen::addOperations_
std::map< TCEString, TCEString > addOperations_
Contains machine's add instructions (<ValueType, InstrName>).
Definition: TDGen.hh:564
TDGen::hasSelect_
bool hasSelect_
Definition: TDGen.hh:606
TDGen::writeAddressingModeDefs
void writeAddressingModeDefs(std::ostream &o)
Definition: TDGen.cc:8345
regOperandCharToImmOperandChar
char regOperandCharToImmOperandChar(char c)
Definition: TDGen.cc:4450
OperationDAGNode
Definition: OperationDAGNode.hh:45
TDGen::operationNodeToString
std::string operationNodeToString(const Operation &op, const OperationDAG &dag, const OperationNode &node, bool emulationPattern, const std::string &operandTypes)
Definition: TDGen.cc:5711
TDGenerator::ValueType::operator=
ValueType & operator=(const ValueType &other)
Definition: TDGen.cc:8675
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
Conversion.hh
Operand::SLONG_WORD
@ SLONG_WORD
Definition: Operand.hh:66
TDGenerator::ValueType::subwordWidth
int subwordWidth() const
Definition: TDGen.cc:8712
TDGen::saveAdditionalVectorOperationInfo
void saveAdditionalVectorOperationInfo(const Operation &op, const TCEString &valueTypes, bool isRegisterOp)
Definition: TDGen.cc:2190
TDGenerator::ValueType::subwWidth_
int subwWidth_
Subword width of the value type.
Definition: TDGen.hh:708
LLVMTCECmdLineOptions.hh
TDGen::writeGuardRegisterClassInfo
void writeGuardRegisterClassInfo(std::ostream &o)
Definition: TDGen.cc:1952
TTAMachine::RegisterGuard
Definition: Guard.hh:137
BoostGraph::inEdge
virtual Edge & inEdge(const Node &node, const int index) const
TDGen::canBePredicated
bool canBePredicated(Operation &op, const std::string &operandTypes)
Definition: TDGen.cc:7591
TDGen::writeVectorLoadStoreOperationExploitations
void writeVectorLoadStoreOperationExploitations(std::ostream &o)
Definition: TDGen.cc:2648
TDGen::isWrongEndianessVectorOp
bool isWrongEndianessVectorOp(const Operation &op) const
Definition: TDGen.cc:1927
ADFSerializer
Definition: ADFSerializer.hh:49
TDGen::operandToString
virtual std::string operandToString(const Operand &operand, bool match, char operandType, const std::string &immDefName="")
Definition: TDGen.cc:5796
TDGen::writeOperationDef
void writeOperationDef(std::ostream &o, Operation &op, const std::string &operandTypes, const std::string &attrs, bool skipPattern, std::string backendPrefix="")
Definition: TDGen.cc:4608
TDGen::FP_SUBW_WIDTH
static const int FP_SUBW_WIDTH
Float type subword width.
Definition: TDGen.hh:465
TDGen::baseClasses_
std::map< int, TCEString > baseClasses_
Contains vector base classes for register files (<Width, Name>).
Definition: TDGen.hh:514
OperationDAG.hh
Application.hh
TDGen::genTCERegisterInfo_setReservedVectorRegs
void genTCERegisterInfo_setReservedVectorRegs(std::ostream &os) const
Definition: TDGen.cc:4162
OperationDAG
Definition: OperationDAG.hh:43
ImmediateAnalyzer::analyze
static ImmInfo * analyze(const TTAMachine::Machine &mach)
Definition: ImmediateAnalyzer.cc:60
TDGenerator::RegisterClass::registers_
std::vector< RegisterInfo > registers_
Register file registers that this RegisterClass uses.
Definition: TDGen.hh:745
TDGenerator::ValueType::width
int width() const
Definition: TDGen.cc:8702
ImmInfo::canTakeImmediate
bool canTakeImmediate(const Operation &operation, int inputOperandId, int64_t value, int destWidth)
Definition: ImmInfo.cc:252
TDGenerator::RegisterClass::operator=
RegisterClass & operator=(const RegisterClass &other)
Definition: TDGen.cc:8966
TDGen::writeArgRegsArray
void writeArgRegsArray(std::ostream &os)
Definition: TDGen.cc:6922
__func__
#define __func__
Definition: Application.hh:67
TDGen::subPattern
std::string subPattern(const Operation &op, const OperationDAG &dag)
Definition: TDGen.cc:5398
TDGen::OPERATION_PATTERNS_
static const std::map< TCEString, TCEString > OPERATION_PATTERNS_
Contains <BaseOpName, OpPattern> key-value pairs.
Definition: TDGen.hh:502
Operand::FLOAT_WORD
@ FLOAT_WORD
Definition: Operand.hh:61
TTAMachine::Machine::functionUnitNavigator
virtual FunctionUnitNavigator functionUnitNavigator() const
Definition: Machine.cc:380
TDGen::gatherOperations_
std::map< TCEString, TCEString > gatherOperations_
Contains machine's GATHER instructions (<ValueType, InstrName>).
Definition: TDGen.hh:562
TDGen::genGeneratedTCEPlugin_getLoadOpcode
void genGeneratedTCEPlugin_getLoadOpcode(std::ostream &o) const
Definition: TDGen.cc:3215
TDGen::registers_
std::map< int, std::vector< TDGenerator::RegisterInfo > > registers_
Contains registers fit for being vector registers (<Width, Registers>).
Definition: TDGen.hh:517
ConstantNode
Definition: ConstantNode.hh:43
TDGenerator::ValueType::isSupportedByLLVM
bool isSupportedByLLVM() const
Definition: TDGen.cc:8688
Operand::index
virtual int index() const
Definition: Operand.cc:135
TDGen::genGeneratedTCEPlugin_getStore
void genGeneratedTCEPlugin_getStore(std::ostream &o) const
Definition: TDGen.cc:2783
OperationDAGSelector::OperationDAGList
Definition: OperationDAGSelector.hh:56
TDGen::mach_
const TTAMachine::Machine & mach_
Definition: TDGen.hh:459
MachineInfo::getOpset
static OperationSet getOpset(const TTAMachine::Machine &mach)
Definition: MachineInfo.cc:65
TDGenerator::RegisterInfo::regName_
TCEString regName_
Register name in GenRegisterInfo.td, e.g. "KLUDGE_REGISTER".
Definition: TDGen.hh:654
Guard.hh
TTAMachine::FunctionUnit::operationCount
virtual int operationCount() const
Definition: FunctionUnit.cc:419
Operation.hh
TDGen::writeOperationDefUsingGivenOperandTypes
void writeOperationDefUsingGivenOperandTypes(std::ostream &o, Operation &op, bool skipPattern, std::vector< TDGenerator::ValueType > inputs, std::vector< TDGenerator::ValueType > outputs, TCEString instrSuffix="")
Definition: TDGen.cc:1840
OperationDAGSelector.hh
Operation::readsMemory
virtual bool readsMemory() const
Definition: Operation.cc:242
TDGen::hasRawOperands
bool hasRawOperands(const Operation &op) const
Definition: TDGen.cc:1699
TDGen::opNames_
std::map< std::string, std::string > opNames_
Definition: TDGen.hh:594
TDGen::createBranchAnalysis
void createBranchAnalysis(std::ostream &os)
Definition: TDGen.cc:7896
TDGenerator::ValueType::isFloat_
bool isFloat_
If true, the value type is a floating point type.
Definition: TDGen.hh:712
TDGen::writeWiderVectorOperationExploitations
void writeWiderVectorOperationExploitations(std::ostream &o)
Definition: TDGen.cc:2775
TDGen::MAX_SCALAR_WIDTH
static const int MAX_SCALAR_WIDTH
Distincts wide vs scalar registers.
Definition: TDGen.hh:471
TDGenerator::ValueType::isFloat
bool isFloat() const
Definition: TDGen.cc:8732
Operand::SINT_WORD
@ SINT_WORD
Definition: Operand.hh:59
TTAMachine::FunctionUnit::hasOperation
virtual bool hasOperation(const std::string &name) const
Definition: FunctionUnit.cc:330
TDGen::EXPLOIT_BIGGER_REGISTERS
static const bool EXPLOIT_BIGGER_REGISTERS
If set to true, smaller vector value types can be stored to larger register files,...
Definition: TDGen.hh:478
TDGen::guardRegTemplateName
static const std::string guardRegTemplateName
Definition: TDGen.hh:636
Machine.hh
OperationDAGSelector::OperationSet
TCETools::CIStringSet OperationSet
Definition: OperationDAGSelector.hh:88
TDGen::writeRegisterDef
void writeRegisterDef(std::ostream &o, const RegInfo &reg, const std::string regName, const std::string regTemplate, const std::string aliases, RegType type)
Definition: TDGen.cc:448
Operation::isVectorOperation
virtual bool isVectorOperation() const
Definition: Operation.cc:222
Operand::ULONG_WORD
@ ULONG_WORD
Definition: Operand.hh:67
Operation::impl
OperationPimpl & impl()
Definition: Operation.hh:170
Bus.hh
TDGen::prebypassStackIndeces_
bool prebypassStackIndeces_
Definition: TDGen.hh:617
TDGen::RegInfo
Definition: TDGen.hh:110
TDGen::operandChar
virtual char operandChar(Operand &operand)
Definition: TDGen.cc:4714
BoostGraph::inDegree
virtual int inDegree(const Node &node) const
Operand::RAW_DATA
@ RAW_DATA
Definition: Operand.hh:65
TDGenerator::ValueType::ValueType
ValueType(int subwWidth, int subwCount, bool isFloat)
Definition: TDGen.cc:8628
TTAMachine::Bus::guardCount
int guardCount() const
Definition: Bus.cc:441
TTAMachine::Port::isOutput
virtual bool isOutput() const
Definition: Port.cc:308
TDGen::TDGen
TDGen(const TTAMachine::Machine &mach)
Definition: TDGen.cc:341
TDGen::writeImmediateDef
virtual void writeImmediateDef(std::ostream &o, const std::string &defName, const std::string &operandType, const std::string &predicate)
Definition: TDGen.cc:4569
TTAMachine::Bus::guard
Guard * guard(int index) const
Definition: Bus.cc:456
TTAMachine::Unit::portCount
virtual int portCount() const
Definition: Unit.cc:135
Operation
Definition: Operation.hh:59
TDGen::regsInClasses_
RegClassMap regsInClasses_
All registers in certain group.
Definition: TDGen.hh:630
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
Operation::operandCount
virtual int operandCount() const
Definition: Operation.cc:212
TDGen::regs32bit_
std::vector< RegInfo > regs32bit_
Definition: TDGen.hh:580
TDGen::HFP_SUBW_WIDTH
static const int HFP_SUBW_WIDTH
Half float type subword width.
Definition: TDGen.hh:467
TDGen::getMovePattern
TCEString getMovePattern(const char &opdType, const std::string &inputPattern) const
Definition: TDGen.cc:7835
TDGen::create32BitExtLoadPatterns
void create32BitExtLoadPatterns(std::ostream &os)
Definition: TDGen.cc:6734
TDGen::writeControlFlowInstrDefs
void writeControlFlowInstrDefs(std::ostream &os)
Definition: TDGen.cc:3560
MachineConnectivityCheck::tempRegisterFiles
static std::set< const TTAMachine::RegisterFile *, TTAMachine::MachinePart::Comparator > tempRegisterFiles(const TTAMachine::Machine &machine)
Definition: MachineConnectivityCheck.cc:1038
TDGen::createGetMaxMemoryAlignment
void createGetMaxMemoryAlignment(std::ostream &os) const
Definition: TDGen.cc:6974
TDGen::writeRARegisterInfo
void writeRARegisterInfo(std::ostream &o)
Definition: TDGen.cc:3101
TDGen::writeRegisterInfo
bool writeRegisterInfo(std::ostream &o)
Definition: TDGen.cc:496
TDGen::writePatternReplacement
void writePatternReplacement(std::ostream &o, const TCEString &origPat, const TCEString &replacerPat) const
Definition: TDGen.cc:1819
TDGen::createMinMaxDef
void createMinMaxDef(const TCEString &opName, const TCEString &valueName, std::ostream &os)
Definition: TDGen.cc:6296
Operand.hh
TDGen::vectorOps_
std::map< TCEString, Operation * > vectorOps_
Contains all vector operations (<Name, Operation>).
Definition: TDGen.hh:511
OperationDAGSelector::OperationDAGList::smallestNodeCount
OperationDAG & smallestNodeCount() const
Definition: OperationDAGSelector.hh:64
TDGen::analyzeRegisters
void analyzeRegisters()
Definition: TDGen.cc:783
TDGen::OT_IMM_LONG
static const char OT_IMM_LONG
Definition: TDGen.hh:492
Operation::input
virtual Operand & input(int index) const
Definition: Operation.cc:503
TDGen::writeVectorRegisterBaseClasses
void writeVectorRegisterBaseClasses(std::ostream &o) const
Definition: TDGen.cc:1991
TDGen::writeCallingConv
void writeCallingConv(std::ostream &os)
Definition: TDGen.cc:6796
BoostGraph::outEdges
virtual EdgeSet outEdges(const Node &node) const
TDGen::writeVectorTruncStoreDefs
void writeVectorTruncStoreDefs(std::ostream &o) const
Definition: TDGen.cc:2262
Operand::DOUBLE_WORD
@ DOUBLE_WORD
Definition: Operand.hh:62
Operation::operand
virtual Operand & operand(int id) const
Definition: Operation.cc:541
TDGen::analyzeMachineVectorRegisterClasses
void analyzeMachineVectorRegisterClasses()
Definition: TDGen.cc:1226
TDGen::RegInfo::rf
std::string rf
Definition: TDGen.hh:111
TDGen::verbose
void verbose(const TCEString &msg) const
Definition: TDGen.cc:1806
XMLSerializer::setDestinationString
void setDestinationString(std::string &destination)
Definition: XMLSerializer.cc:156
TTAMachine::BaseRegisterFile::port
virtual RFPort * port(const std::string &name) const
Definition: BaseRegisterFile.cc:129
Operation::dagCount
virtual int dagCount() const
Definition: Operation.cc:134
TDGen::~TDGen
virtual ~TDGen()
Definition: TDGen.cc:379
TDGen::OT_REG_DOUBLE
static const char OT_REG_DOUBLE
Definition: TDGen.hh:487
TDGen::writeBackendCode
void writeBackendCode(std::ostream &o)
Definition: TDGen.cc:3941
TTAMachine::Machine::registerFileNavigator
virtual RegisterFileNavigator registerFileNavigator() const
Definition: Machine.cc:450
TDGen::writeCondBranchDefs
void writeCondBranchDefs(std::ostream &os)
Definition: TDGen.cc:3605
TDGen::writeMoveImmediateDefs
void writeMoveImmediateDefs(std::ostream &o)
Definition: TDGen.cc:701
TDGen::immediateOperandNameForEmulatedOperation
std::string immediateOperandNameForEmulatedOperation(const OperationDAG &, const Operand &operand)
Definition: TDGen.cc:7510
IllegalMachine
Definition: Exception.hh:878
TDGen::writeVectorOperationDef
void writeVectorOperationDef(std::ostream &o, Operation &op, TCEString valueTypes, const TCEString &attributes, bool skipPattern)
Definition: TDGen.cc:2125
TDGen::OT_VREG_FP
static const char OT_VREG_FP
Definition: TDGen.hh:497
TDGen::writeRegisterClasses
void writeRegisterClasses(std::ostream &o)
Definition: TDGen.cc:761
ADFSerializer.hh
ConstantNode::value
virtual long value() const
Definition: ConstantNode.cc:60
TDGen::createConstantMaterializationPatterns
virtual void createConstantMaterializationPatterns(std::ostream &os)
Definition: TDGen.cc:7384
Operand::type
virtual OperandType type() const
Definition: Operand.cc:165
TDGen::regs1bit_
std::vector< RegInfo > regs1bit_
Definition: TDGen.hh:574
TDGen::regs_
std::map< std::string, RegInfo > regs_
Map of generated llvm register names to physical register in the machine.
Definition: TDGen.hh:588
BYTE_BITWIDTH
const Byte BYTE_BITWIDTH
Definition: BaseType.hh:136
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
TDGen::dagNodeToString
std::string dagNodeToString(const Operation &op, const OperationDAG &dag, const OperationDAGNode &node, bool emulationPattern, const std::string &operandTypes, const Operation *emulatingOp=nullptr, const OperationDAGNode *successor=nullptr)
Definition: TDGen.cc:5436
TDGen::maxVectorSize_
int maxVectorSize_
Definition: TDGen.hh:599
TDGenerator::RegisterClass::vt_
ValueType vt_
Value type that is supported by this RegisterClass, e.g. v4i32.
Definition: TDGen.hh:741
TDGenerator::RegisterClass::numberOfRegisters
size_t numberOfRegisters() const
Definition: TDGen.cc:9023
TCEString
Definition: TCEString.hh:53
TDGenerator::ValueType::vectorTypesOfWidth
static std::vector< ValueType > vectorTypesOfWidth(int width, bool onlyInts=false)
Definition: TDGen.cc:8867
FUPort.hh
sub
#define sub
Definition: ConstantTransformer.cc:63
ControlUnit.hh
TDGen::isVectorBitwiseOperation
bool isVectorBitwiseOperation(const Operation &op) const
Definition: TDGen.cc:1939
TTAMachine::Machine::busNavigator
virtual BusNavigator busNavigator() const
Definition: Machine.cc:356
TDGen::genGeneratedTCEPlugin_getShlOpcode
void genGeneratedTCEPlugin_getShlOpcode(std::ostream &o) const
Definition: TDGen.cc:3244
TDGen::RegType
RegType
Definition: TDGen.hh:96
TDGen::patOutputs
std::string patOutputs(const Operation &op, const std::string &oprTypes)
Definition: TDGen.cc:6000
TerminalNode.hh
TDGen::writeInstrFormats
void writeInstrFormats(std::ostream &o)
Definition: TDGen.cc:4214
TDGen::createVectorMinMaxDef
void createVectorMinMaxDef(const TCEString &opName, int bits, char llvmTypeChar, const TCEString &postFix, std::ostream &os)
Definition: TDGen.cc:6306
TDGen::writeCallDefRegs
virtual void writeCallDefRegs(std::ostream &o)
Definition: TDGen.cc:3524
ADFSerializer::writeMachine
void writeMachine(const TTAMachine::Machine &machine)
Definition: ADFSerializer.cc:259
TDGenerator::ValueType::subwordCount
int subwordCount() const
Definition: TDGen.cc:8722
MachineInfo::supportsPortGuardedJumps
static bool supportsPortGuardedJumps(const TTAMachine::Machine &machine)
Definition: MachineInfo.cc:663
TDGen::RESERVED
@ RESERVED
Definition: TDGen.hh:98
TDGen::gatherAllMachineOperations
void gatherAllMachineOperations()
Definition: TDGen.cc:941
TDGen::createShortExtLoadPatterns
void createShortExtLoadPatterns(std::ostream &os)
Definition: TDGen.cc:6617
TTAMachine::Port::isInput
virtual bool isInput() const
Definition: Port.cc:298
TDGen::constantNodeString
std::string constantNodeString(const Operation &op, const OperationDAG &dag, const ConstantNode &node, const std::string &operandTypes, const OperationDAGNode *successor=nullptr)
Definition: TDGen.cc:5541
TDGen::constantMaterializationPredicates_
std::vector< std::string > constantMaterializationPredicates_
All predicates used in constant materialization patterns.
Definition: TDGen.hh:634
TDGen::genGeneratedTCEPlugin_getGatherOpcode
void genGeneratedTCEPlugin_getGatherOpcode(std::ostream &o) const
Definition: TDGen.cc:3199
TDGen::writeScalarOperationExploitations
void writeScalarOperationExploitations(std::ostream &o)
Definition: TDGen.cc:2419
TDGen::registerLoads_
std::map< TCEString, TDGenerator::InstructionInfo > registerLoads_
All register load operations (<ValueType, InstrInfo>).
Definition: TDGen.hh:525
TDGen::argRegNames_
std::vector< std::string > argRegNames_
Definition: TDGen.hh:590
ConstantNode.hh
TDGen::patInputs
std::string patInputs(const Operation &op, const std::string &oprTypes)
Definition: TDGen.cc:5969
TDGen::operationDAGCanBeMatched
bool operationDAGCanBeMatched(const OperationDAG &op, std::set< std::string > *recursionCycleCheck=NULL, bool recursionHasStore=false)
Definition: TDGen.cc:5274
TDGen::iorOperations_
std::map< TCEString, TCEString > iorOperations_
Contains machine's shl instructions (<ValueType, InstrName>).
Definition: TDGen.hh:568
TTAMachine::Machine::Navigator::item
ComponentType * item(int index) const
TTAMachine::FunctionUnit::operation
virtual HWOperation * operation(const std::string &name) const
Definition: FunctionUnit.cc:363
Operand::isAddress
virtual bool isAddress() const
Definition: Operand.cc:328
OperationNode.hh
TTAMachine::RegisterFile
Definition: RegisterFile.hh:47
TDGen::createParamDRegNums
void createParamDRegNums(std::ostream &os)
Definition: TDGen.cc:6936
Conversion::toInt
static int toInt(const T &source)
TDGenerator::ValueType::isVector
bool isVector() const
Definition: TDGen.cc:8742
TDGenerator::ValueType::valueTypeStr
TCEString valueTypeStr() const
Definition: TDGen.cc:8772
TDGen::genGeneratedTCEPlugin_getVectorImmediateOpcode
void genGeneratedTCEPlugin_getVectorImmediateOpcode(std::ostream &o) const
Definition: TDGen.cc:3179
TDGen::writeVectorBitwiseOperationDefs
void writeVectorBitwiseOperationDefs(std::ostream &o, Operation &op, bool skipPattern)
Definition: TDGen.cc:2601
TDGen::truncOperations_
std::vector< std::pair< const Operation *, TCEString > > truncOperations_
Contains machine's TRUNCxx/CFH instructions (<ValueType, InstrName>).
Definition: TDGen.hh:536
TDGen::llvmGuardRegs_
std::vector< std::string > llvmGuardRegs_
The LLVM register defs used as guards.
Definition: TDGen.hh:584
TDGen::createBoolAndHalfLoadPatterns
void createBoolAndHalfLoadPatterns(std::ostream &os)
Definition: TDGen.cc:8534
MathTools.hh
TDGen::emulatingOpNodeLLVMName
std::string emulatingOpNodeLLVMName(const Operation &op, const OperationDAG &dag, const OperationNode &node, const std::string &operandTypes)
Definition: TDGen.cc:5600
OperationPool
Definition: OperationPool.hh:52
TDGen::operandTypeToRegister
char operandTypeToRegister(const char &opdType) const
Definition: TDGen.cc:7820
TDGen::immOperandDefs_
std::map< ImmInfoKey, std::string > immOperandDefs_
Maps (operation, operand) pairs to i32 immediate operand definition names.
Definition: TDGen.hh:433
TDGen::associateRegistersWithVectorRegisterClasses
void associateRegistersWithVectorRegisterClasses()
Definition: TDGen.cc:1653
TDGenerator::ValueType::operandType
Operand::OperandType operandType() const
Definition: TDGen.cc:8752
TTAMachine
Definition: Assembler.hh:48
TDGen::writeMiscPatterns
void writeMiscPatterns(std::ostream &o)
Definition: TDGen.cc:8391
TDGen::operationCanBeMatched
bool operationCanBeMatched(const Operation &op, std::set< std::string > *recursionCycleCheck=NULL, bool recursionHasStore=false)
Definition: TDGen.cc:5240
TTAMachine::BaseRegisterFile::size
virtual int size() const
TDGen::createConstShiftPatterns
void createConstShiftPatterns(std::ostream &os)
Definition: TDGen.cc:8525
BoostGraph::rootNodes
virtual NodeSet rootNodes() const
useful utility functions
Operand::isInput
virtual bool isInput() const
Definition: Operand.cc:145
TDGen::genTCEInstrInfoSIMD_copyPhysVectorReg
void genTCEInstrInfoSIMD_copyPhysVectorReg(std::ostream &o) const
Definition: TDGen.cc:3131
TDGen::llvmOperationName
virtual TCEString llvmOperationName(const TCEString &opName) const
Definition: TDGen.cc:5068
TTAMachine::Machine::instructionTemplateNavigator
virtual InstructionTemplateNavigator instructionTemplateNavigator() const
Definition: Machine.cc:428
ImmInfo
Definition: ImmInfo.hh:82
TTAMachine::BaseRegisterFile::width
virtual int width() const
BoostGraph::nodeCount
int nodeCount() const
LLVMBackend::llvmRequiredOpset
static OperationDAGSelector::OperationSet llvmRequiredOpset(bool includeFloatOps, bool isLittleEndian, bool bits64)
Definition: LLVMBackend.cc:150
TTAMachine::RegisterGuard::registerFile
const RegisterFile * registerFile() const
TDGen::GPR
@ GPR
Definition: TDGen.hh:97
OperationPool.hh
MachineInfo::supportsBoolRegisterGuardedJumps
static bool supportsBoolRegisterGuardedJumps(const TTAMachine::Machine &machine)
Definition: MachineInfo.cc:616
TDGen::writeEmulationPattern
void writeEmulationPattern(std::ostream &o, const Operation &op, const OperationDAG &dag)
Definition: TDGen.cc:4759
Operation::numberOfOutputs
virtual int numberOfOutputs() const
Definition: Operation.cc:202
TTAMachine::Machine::Navigator
Definition: Machine.hh:186
SIMD_WORD_WIDTH
#define SIMD_WORD_WIDTH
Definition: SimValue.hh:42
TDGen::write1bitRegisterInfo
void write1bitRegisterInfo(std::ostream &o)
Definition: TDGen.cc:905
Operand::defaultElementWidth
static int defaultElementWidth(OperandType type)
Definition: Operand.cc:557
TDGen::genTCEInstrInfo_copyPhys64bitReg
void genTCEInstrInfo_copyPhys64bitReg(std::ostream &o) const
Definition: TDGen.cc:8322
Operation::dag
virtual OperationDAG & dag(int index) const
Definition: Operation.cc:148
TDGenerator::RegisterClass::name_
TCEString name_
RegisterClass name.
Definition: TDGen.hh:739
StringTools::stringToLower
static std::string stringToLower(const std::string &source)
Definition: StringTools.cc:160
TDGen::movOperations_
std::set< TCEString > movOperations_
Contains all moves between register classes (<InstrName>).
Definition: TDGen.hh:571
TerminalNode::operandIndex
virtual int operandIndex() const
Definition: TerminalNode.cc:60
TDGen::genGeneratedTCEPlugin_getAddOpcode
void genGeneratedTCEPlugin_getAddOpcode(std::ostream &o) const
Definition: TDGen.cc:3229
TDGen::regs64bit_
std::vector< RegInfo > regs64bit_
Definition: TDGen.hh:582
TDGen::generateLoadStoreCopyGenerator
void generateLoadStoreCopyGenerator(std::ostream &os)
Definition: TDGen.cc:6291
TDGen::createSelectPatterns
virtual void createSelectPatterns(std::ostream &os)
Definition: TDGen.cc:6991
TTAMachine::RegisterFile::zeroRegister
virtual bool zeroRegister() const
Definition: RegisterFile.cc:629
TDGen::operandTypesToRegisters
std::string operandTypesToRegisters(const std::string &opdTypes) const
Definition: TDGen.cc:7811
TTAMachine::Machine
Definition: Machine.hh:73
TDGen::OT_IMM_BOOL
static const char OT_IMM_BOOL
Definition: TDGen.hh:488
TDGen::littleEndian_
bool littleEndian_
Definition: TDGen.hh:612
TDGen::use64bitForFP_
bool use64bitForFP_
Definition: TDGen.hh:618
TDGen::OT_IMM_FP
static const char OT_IMM_FP
Definition: TDGen.hh:490
TDGen::MAX_SUBW_COUNT
static const int MAX_SUBW_COUNT
Maximum number of subwords that any SIMD operation can have.
Definition: TDGen.hh:473
Operand::swap
virtual const std::set< int > & swap() const
Definition: Operand.cc:361
TDGen::OT_REG_HFP
static const char OT_REG_HFP
Definition: TDGen.hh:486
TDGen::genTCETargetLoweringSIMD_getSetCCResultVT
void genTCETargetLoweringSIMD_getSetCCResultVT(std::ostream &o) const
Definition: TDGen.cc:3072
TDGenerator
Definition: TDGen.hh:63
LLVMBackend.hh