OpenASIP  2.0
LowerMissingInstructions.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2015 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file LowerMissingInstructions.cc
26  *
27  * Convert instruction which are not supported by the machine to
28  * function calls.
29  *
30  * NOTE: Right now system is limited to replace only those operations, which
31  * use only one bitwidth integers for example i1.icmp.i32.i32 cannot
32  * be lowered to function call.
33  * However i16.mul.i16.i16 works.
34  *
35  * Maybe better way would be to take llvm footprints which must be
36  * emulated and create function prototype directly for them.
37  * @author Mikael Lepisto 2008-2009 (mikael.lepisto-no.spam-tut.fi)
38  * @author Pekka Jaaskelainen 2010
39  * @note reting: red
40  */
41 
42 #include "CompilerWarnings.hh"
43 IGNORE_COMPILER_WARNING("-Wunused-parameter")
44 
45 #define DEBUG_TYPE "lowermissing"
46 
47 #include "llvm/Transforms/Scalar.h"
48 #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
49 #include "tce_config.h"
50 #include "llvm/IR/LLVMContext.h"
51 #include "llvm/IR/Module.h"
52 #include "llvm/IR/DerivedTypes.h"
53 #include "llvm/IR/Instructions.h"
54 #include "llvm/IR/Constants.h"
55 #include "llvm/ADT/Statistic.h"
56 #include "llvm/Support/Compiler.h"
57 #include "llvm/IR/AbstractCallSite.h"
58 #include "llvm/IR/InstrTypes.h" // CreateIntegerCast()
59 #include "llvm/ADT/Twine.h"
60 
61 #include "llvm/ADT/STLExtras.h" // array_endof
62 #include "llvm/Support/CommandLine.h" // cl::opt
63 
64 
65 // TCE headers
66 // tce_config.h defines these. this undef to avoid warning.
67 // TODO: how to do this in tce_config.h???
68 #ifdef LLVM_LIBDIR
69 #undef LLVM_LIBDIR
70 #endif
71 
72 #include "Machine.hh"
73 #include "OperationDAGSelector.hh"
74 #include "MachineInfo.hh"
75 #include "Operand.hh"
76 #include "Operation.hh"
77 #include "OperationPool.hh"
78 #include "TCEString.hh"
80 
81 #include "LLVMBackend.hh" // llvmRequiredOps()
82 
84 
85 using namespace llvm;
86 
87 STATISTIC(NumLowered, "Number of instructions lowered");
88 
89 #include <iostream>
90 
91 #define ARGLIST_CONST
92 #define TYPE_CONST
93 
94 namespace {
95  class LowerMissingInstructions : public FunctionPass {
96  std::map< std::string, Function*> replaceFunctions;
97  const TTAMachine::Machine* mach_;
98  Module* dstModule_;
99 
100  public:
101  static char ID; // Pass ID, replacement for typeid
102  LowerMissingInstructions(const TTAMachine::Machine& mach);
103 
104 
105  // from llvm::Pass:
106  bool doInitialization(Module &M) override;
107  bool doFinalization (Module &M) override;
108 
109  // to suppress Clang warnings
110  using llvm::FunctionPass::doInitialization;
111  using llvm::FunctionPass::doFinalization;
112 
113  bool runOnBasicBlock(BasicBlock &BB);
114  bool runOnFunction(Function &F);
115 
116  virtual StringRef getPassName() const override {
117  return "TCE: LowerMissingInstructions";
118  }
119 
120  void addFunctionForFootprints(
121  Module& M, FunctionType* fType, Operation& op,
122  std::string suffix);
123 
124  private:
125  std::string stringType(const Type* type) const;
126 
127  ARGLIST_CONST Type* getLLVMType(
128  Operand::OperandType type, ARGLIST_CONST Type* llvmIntegerType);
129 
130  std::string getFootprint(Instruction& I);
131 
132  // getGlobalContext() was removed form LLVM.
133  LLVMContext& getGlobalContext() const {
134  return dstModule_->getContext();
135  }
136  };
137 
138  char LowerMissingInstructions::ID = 0;
139 
140 // When we got another way than parameter
141 // for passing machine we can register pass to manager
142 // RegisterPass<LowerMissingInstructions>
143 // X("lowermissing", "Lower missing instructions to libcalls");
144 }
145 
146 // - Interface to this file...
148  return new LowerMissingInstructions(mach);
149 }
150 
151 LowerMissingInstructions::LowerMissingInstructions(
152  const TTAMachine::Machine& mach) :
153  FunctionPass(ID),
154  mach_(&mach) {
155 }
156 
157 // convert type name to string
158 std::string
159 LowerMissingInstructions::stringType(const Type* type) const {
160  LLVMContext& context = getGlobalContext();
161  if (type == Type::getInt64Ty(context)) {
162  return "i64";
163  } else if (type == Type::getInt32Ty(context)) {
164  return "i32";
165  } else if (type == Type::getInt16Ty(context)) {
166  return "i16";
167  } else if (type == Type::getInt8Ty(context)) {
168  return "i8";
169  } else if (type == Type::getInt1Ty(context)) {
170  return "i1";
171  } else if (type == Type::getHalfTy(context)) {
172  return "f16";
173  } else if (type == Type::getFloatTy(context)) {
174  return "f32";
175  } else if (type == Type::getDoubleTy(context)) {
176  return "f64";
177  } else if (type == Type::getLabelTy(context)) {
178  return "label";
179  } else if (type == Type::getVoidTy(context)) {
180  return "void";
181  } else {
182  return "unknown";
183  }
184 }
185 
186 ARGLIST_CONST Type*
187 LowerMissingInstructions::getLLVMType(
188  Operand::OperandType type, ARGLIST_CONST Type* llvmIntegerType) {
189  switch (type) {
190  case Operand::SINT_WORD:
191  return llvmIntegerType;
192  case Operand::UINT_WORD:
193  return llvmIntegerType;
194  case Operand::SLONG_WORD:
195  return Type::getInt64Ty(getGlobalContext());
196  case Operand::ULONG_WORD:
197  return Type::getInt64Ty(getGlobalContext());
198  case Operand::FLOAT_WORD:
199  return Type::getFloatTy(getGlobalContext());
201  return Type::getHalfTy(getGlobalContext());
203  return Type::getDoubleTy(getGlobalContext());
204  default:
205  return Type::getVoidTy(getGlobalContext());
206  }
207 }
208 
209 const std::vector<std::string>& llvmFootprints(std::string tceOp) {
210  static bool init = true;
211  static std::map<std::string, std::vector<std::string> > footprints;
212 
213  // NOTE: .i32 is default footprint suffix if there is no i16, i8 or i1
214  // versions.. e.g. .i32 is suffix for f32.fadd.f32.f32
215  if (init) {
216 // footprints["DIVU.i32"].push_back("i32.udiv.i32.i32");
217 // footprints["DIVU.i16"].push_back("i16.udiv.i16.i16");
218 // footprints["DIVU.i8"].push_back("i8.udiv.i8.i8");
219 
220 // footprints["DIV.i32"].push_back("i32.sdiv.i32.i32");
221 // footprints["DIV.i16"].push_back("i16.sdiv.i16.i16");
222 // footprints["DIV.i8"].push_back("i8.sdiv.i8.i8");
223 
224 // footprints["MODU.i32"].push_back("i32.urem.i32.i32");
225 // footprints["MODU.i16"].push_back("i16.urem.i16.i16");
226 // footprints["MODU.i8"].push_back("i8.urem.i8.i8");
227 
228 // footprints["MOD.i32"].push_back("i32.rem.i32.i32");
229 // footprints["MOD.i16"].push_back("i16.rem.i16.i16");
230 // footprints["MOD.i8"].push_back("i8.rem.i8.i8");
231 
232 // footprints["MUL.i32"].push_back("i32.mul.i32.i32");
233 // footprints["MUL.i16"].push_back("i16.mul.i16.i16");
234 // footprints["MUL.i8"].push_back("i8.mul.i8.i8");
235  footprints["ADDH.i32"].push_back("f16.fadd.f16.f16");
236  footprints["SUBH.i32"].push_back("f16.fsub.f16.f16");
237  footprints["NEGH.i32"].push_back("f16.fneg.f16");
238  footprints["MULH.i32"].push_back("f16.fmul.f16.f16");
239  footprints["DIVH.i32"].push_back("f16.fdiv.f16.f16");
240  footprints["SQRTH.i32"].push_back("f16.sqrt.f16");
241 
242  footprints["ADDF.i32"].push_back("f32.fadd.f32.f32");
243  footprints["SUBF.i32"].push_back("f32.fsub.f32.f32");
244  footprints["NEGF.i32"].push_back("f32.fneg.f32");
245  footprints["MULF.i32"].push_back("f32.fmul.f32.f32");
246  footprints["DIVF.i32"].push_back("f32.fdiv.f32.f32");
247  footprints["SQRTF.i32"].push_back("f32.sqrt.f32");
248 
249  footprints["ADDD.i64"].push_back("f64.fadd.f64.f64");
250  footprints["SUBD.i64"].push_back("f64.fsub.f64.f64");
251  footprints["NEGD.i64"].push_back("f64.fneg.f64");
252  footprints["MULD.i64"].push_back("f64.fmul.f64.f64");
253  footprints["DIVD.i64"].push_back("f64.fdiv.f64.f64");
254  footprints["SQRTD.i64"].push_back("f64.sqrt.f64");
255 
256  footprints["CFI.i32"].push_back("i32.fptosi.f32");
257  footprints["CFIU.i32"].push_back("i32.fptoui.f32");
258  footprints["CIF.i32"].push_back("f32.sitofp.i32");
259  footprints["CIFU.i32"].push_back("f32.uitofp.i32");
260 
261  footprints["CFI.i16"].push_back("i16.fptosi.f32");
262  footprints["CFIU.i16"].push_back("i16.fptoui.f32");
263  footprints["CIF.i16"].push_back("f32.sitofp.i16");
264  footprints["CIFU.i16"].push_back("f32.uitofp.i16");
265 
266  footprints["CFI.i8"].push_back("i8.fptosi.f32");
267  footprints["CFIU.i8"].push_back("i8.fptoui.f32");
268  footprints["CIF.i8"].push_back("f32.sitofp.i8");
269  footprints["CIFU.i8"].push_back("f32.uitofp.i8");
270 
271  footprints["CDL.i64"].push_back("i64.fptosi.f64");
272  footprints["CDLU.i64"].push_back("i64.fptoui.f64");
273  footprints["CLD.i64"].push_back("f64.sitofp.i64");
274  footprints["CLDU.i64"].push_back("f64.uitofp.i64");
275 
276  footprints["CDL.i32"].push_back("i32.fptosi.f64");
277  footprints["CDLU.i32"].push_back("i32.fptoui.f64");
278  footprints["CLD.i32"].push_back("f64.sitofp.i32");
279  footprints["CLDU.i32"].push_back("f64.uitofp.i32");
280 
281  footprints["CDL.i16"].push_back("i16.fptosi.f64");
282  footprints["CDLU.i16"].push_back("i16.fptoui.f64");
283  footprints["CLD.i16"].push_back("f64.sitofp.i16");
284  footprints["CLDU.i16"].push_back("f64.uitofp.i16");
285 
286  footprints["CDL.i8"].push_back("i8.fptosi.f64");
287  footprints["CDLU.i8"].push_back("i8.fptoui.f64");
288  footprints["CLD.i8"].push_back("f64.sitofp.i8");
289  footprints["CLDU.i8"].push_back("f64.uitofp.i8");
290 
291  footprints["EQF.i1"].push_back("i1.fcmp.oeq.f32.f32");
292  footprints["NEF.i1"].push_back("i1.fcmp.one.f32.f32");
293  footprints["LTF.i1"].push_back("i1.fcmp.olt.f32.f32");
294  footprints["LEF.i1"].push_back("i1.fcmp.ole.f32.f32");
295  footprints["GTF.i1"].push_back("i1.fcmp.ogt.f32.f32");
296  footprints["GEF.i1"].push_back("i1.fcmp.oge.f32.f32");
297 
298  footprints["EQUF.i1"].push_back("i1.fcmp.ueq.f32.f32");
299  footprints["NEUF.i1"].push_back("i1.fcmp.une.f32.f32");
300  footprints["LTUF.i1"].push_back("i1.fcmp.ult.f32.f32");
301  footprints["LEUF.i1"].push_back("i1.fcmp.ule.f32.f32");
302  footprints["GTUF.i1"].push_back("i1.fcmp.ugt.f32.f32");
303  footprints["GEUF.i1"].push_back("i1.fcmp.uge.f32.f32");
304 
305  footprints["EQF.i32"].push_back("i32.fcmp.oeq.f32.f32");
306  footprints["NEF.i32"].push_back("i32.fcmp.one.f32.f32");
307  footprints["LTF.i32"].push_back("i32.fcmp.olt.f32.f32");
308  footprints["LEF.i32"].push_back("i32.fcmp.ole.f32.f32");
309  footprints["GTF.i32"].push_back("i32.fcmp.ogt.f32.f32");
310  footprints["GEF.i32"].push_back("i32.fcmp.oge.f32.f32");
311 
312  footprints["EQUF.i32"].push_back("i32.fcmp.ueq.f32.f32");
313  footprints["NEUF.i32"].push_back("i32.fcmp.une.f32.f32");
314  footprints["LTUF.i32"].push_back("i32.fcmp.ult.f32.f32");
315  footprints["LEUF.i32"].push_back("i32.fcmp.ule.f32.f32");
316  footprints["GTUF.i32"].push_back("i32.fcmp.ugt.f32.f32");
317  footprints["GEUF.i32"].push_back("i32.fcmp.uge.f32.f32");
318 
319  footprints["ORDF.i1"].push_back("i1.fcmp.ord.f32.f32");
320  footprints["ORDF.i32"].push_back("i32.fcmp.ord.f32.f32");
321  footprints["UORDF.i1"].push_back("i1.fcmp.uno.f32.f32");
322  footprints["UORDF.i32"].push_back("i32.fcmp.uno.f32.f32");
323 
324  footprints["CFD.i64"].push_back("f64.fpext.f32");
325 
326  footprints["EQD.i1"].push_back("i1.fcmp.oeq.f64.f64");
327  footprints["NED.i1"].push_back("i1.fcmp.one.f64.f64");
328  footprints["LTD.i1"].push_back("i1.fcmp.olt.f64.f64");
329  footprints["GED.i1"].push_back("i1.fcmp.oge.f64.f64");
330  footprints["LED.i1"].push_back("i1.fcmp.ole.f64.f64");
331  footprints["GTD.i1"].push_back("i1.fcmp.ogt.f64.f64");
332 
333  footprints["EQD.i64"].push_back("i64.fcmp.oeq.f64.f64");
334  footprints["NED.i64"].push_back("i64.fcmp.one.f64.f64");
335  footprints["LTD.i64"].push_back("i64.fcmp.olt.f64.f64");
336  footprints["GED.i64"].push_back("i64.fcmp.oge.f64.f64");
337  footprints["LED.i64"].push_back("i64.fcmp.ole.f64.f64");
338  footprints["GTD.i64"].push_back("i64.fcmp.ogt.f64.f64");
339 
340  footprints["EQUD.i1"].push_back("i1.fcmp.ueq.f64.f64");
341  footprints["NEUD.i1"].push_back("i1.fcmp.une.f64.f64");
342  footprints["GEUD.i1"].push_back("i1.fcmp.uge.f64.f64");
343  footprints["LEUD.i1"].push_back("i1.fcmp.ule.f64.f64");
344  footprints["LTUD.i1"].push_back("i1.fcmp.ult.f64.f64");
345  footprints["GTUD.i1"].push_back("i1.fcmp.ugt.f64.f64");
346 
347  footprints["EQUD.i64"].push_back("i64.fcmp.ueq.f64.f64");
348  footprints["NEUD.i64"].push_back("i64.fcmp.une.f64.f64");
349  footprints["LEUD.i64"].push_back("i64.fcmp.ule.f64.f64");
350  footprints["GEUD.i64"].push_back("i64.fcmp.uge.f64.f64");
351  footprints["LTUD.i64"].push_back("i64.fcmp.ult.f64.f64");
352  footprints["GTUD.i64"].push_back("i64.fcmp.ugt.f64.f64");
353 
354  footprints["ORDD.i1"].push_back("i1.fcmp.ord.f64.f64");
355  footprints["ORDD.i64"].push_back("i64.fcmp.ord.f64.f64");
356  footprints["UORDD.i1"].push_back("i1.fcmp.uno.f64.f64");
357  footprints["UORDD.i64"].push_back("i64.fcmp.uno.f64.f64");
358 
359  init = false;
360  }
361 
362  return footprints[tceOp];
363 }
364 
365 std::string
366 LowerMissingInstructions::getFootprint(Instruction& I) {
367 
368  std::string footPrint = stringType(I.getType());
369 
370  switch (I.getOpcode()) {
371 
372  case Instruction::FCmp: {
373  FCmpInst* cmpInst = dyn_cast<FCmpInst>(&I);
374  footPrint += std::string(".") + cmpInst->getOpcodeName() + ".";
375 
376  switch (cmpInst->getPredicate()) {
377  case FCmpInst::FCMP_FALSE:
378  footPrint += "false";
379  break;
380  case FCmpInst::FCMP_OEQ:
381  footPrint += "oeq";
382  break;
383  case FCmpInst::FCMP_OGT:
384  footPrint += "ogt";
385  break;
386  case FCmpInst::FCMP_OGE:
387  footPrint += "oge";
388  break;
389  case FCmpInst::FCMP_OLT:
390  footPrint += "olt";
391  break;
392  case FCmpInst::FCMP_OLE:
393  footPrint += "ole";
394  break;
395  case FCmpInst::FCMP_ONE:
396  footPrint += "one";
397  break;
398  case FCmpInst::FCMP_ORD:
399  footPrint += "ord";
400  break;
401  case FCmpInst::FCMP_UNO:
402  footPrint += "uno";
403  break;
404  case FCmpInst::FCMP_UEQ:
405  footPrint += "ueq";
406  break;
407  case FCmpInst::FCMP_UGT:
408  footPrint += "ugt";
409  break;
410  case FCmpInst::FCMP_UGE:
411  footPrint += "uge";
412  break;
413  case FCmpInst::FCMP_ULT:
414  footPrint += "ult";
415  break;
416  case FCmpInst::FCMP_ULE:
417  footPrint += "ule";
418  break;
419  case FCmpInst::FCMP_UNE:
420  footPrint += "une";
421  break;
422  case FCmpInst::FCMP_TRUE:
423  footPrint += "true";
424  break;
425  default:
426  footPrint += "PREDFAIL";
427  }
428  } break;
429 
430  case Instruction::Call: {
431  if (!isa<CallInst>(&I) ||
432  dyn_cast<CallInst>(&I)->getCalledFunction() == NULL)
433  break;
434  std::string calledName =
435  dyn_cast<CallInst>(&I)->getCalledFunction()->getName().str();
436  if (calledName == "llvm.sqrt.f32") {
437  return "f32.sqrt.f32";
438  }
439 
440  } break;
441 
442  default:
443  footPrint += std::string(".") + I.getOpcodeName();
444  }
445 
446  for (unsigned int i = 0; i < I.getNumOperands();i++) {
447  footPrint += "." + stringType(I.getOperand(i)->getType());
448  }
449 
450  return footPrint;
451 }
452 
453 void LowerMissingInstructions::addFunctionForFootprints(
454  Module& M, FunctionType* /*fType*/, Operation& op, std::string suffix) {
455 
456  // set replace footprints for operations to emulate
457  // (there might be multiple different footprints for the same
458  // emulation function)
459  const std::vector<std::string>&
460  footprints = llvmFootprints(op.name() + suffix);
461 
462  for (unsigned int j = 0; j < footprints.size(); j++) {
463  Function* func = M.getFunction(op.emulationFunctionName());
464  replaceFunctions[footprints[j]] = func;
465 
466 #if 0
467  std::cerr << "Operation: " << op.name()
468  << " is emulated with: " << op.emulationFunctionName()
469  << " footprint: " << footprints[j]
470  << std::endl;
471 #endif
472  }
473 }
474 
475 bool LowerMissingInstructions::doInitialization(Module &M) {
476 
479  << std::endl
480  << "---- LowerMissingInstructions ----"
481  << std::endl;
482  }
483 
484  dstModule_ = &M;
485 
486  bool retVal = true;
487 
489  opSet = MachineInfo::getOpset(*mach_);
490 
492  requiredSet = LLVMBackend::llvmRequiredOpset(true, mach_->isLittleEndian(), mach_->is64bit());
493 
494  OperationPool osal;
495 
496  // Check required set, which must be lowered to function calls..
497  for (OperationDAGSelector::OperationSet::iterator i = requiredSet.begin();
498  i != requiredSet.end(); i++) {
499 
500  if (opSet.find(*i) == opSet.end() &&
501  OperationDAGSelector::findDags(*i, opSet).empty()) {
502 
503  Operation& op = osal.operation((*i).c_str());
504 
505  if (&op == &NullOperation::instance()) {
506  std::cerr << "Error: Cant find operation: " << *i
507  << " from OSAL"
508  << std::endl;
509 
510  return false;
511  }
512 
513  if (op.numberOfOutputs() != 1) {
514  if (Application::verboseLevel() > 0) {
515  Application::errorStream() << "Cannot lower missing instruction:"
516  << *i << std::endl;
517  }
518  continue;
519  }
520 
521  // Make parameter list for operation with all needed integer
522  // widths. If pure floating point just i32 is used.
523  //
524  // If there is also
525  // IntWord or UIntWord parameters all vectors are filled.
526  std::vector<ARGLIST_CONST Type*> argList_i64;
527  TYPE_CONST Type* retVal_i64 = NULL;
528 
529  std::vector<ARGLIST_CONST Type*> argList_i32;
530  TYPE_CONST Type* retVal_i32 = NULL;
531 
532  std::vector<ARGLIST_CONST Type*> argList_i16;
533  TYPE_CONST Type* retVal_i16 = NULL;
534 
535  std::vector<ARGLIST_CONST Type*> argList_i8;
536  TYPE_CONST Type* retVal_i8 = NULL;
537 
538  std::vector<ARGLIST_CONST Type*> argList_i1;
539  TYPE_CONST Type* retVal_i1 = NULL;
540 
541  TYPE_CONST Type* defaultIntegerType =
542  mach_->is64bit() ?
543  Type::getInt64Ty(getGlobalContext()) :
544  Type::getInt32Ty(getGlobalContext());
545 
546  std::vector<ARGLIST_CONST Type*>& argList_default =
547  mach_->is64bit() ? argList_i64 : argList_i32;
548 
549  TYPE_CONST Type*& retVal_default =
550  mach_->is64bit() ? retVal_i64 : retVal_i32;
551 
552  const char* defaultIntegerSuffix =
553  mach_->is64bit() ? ".i64" : ".i32";
554 
555  bool useInt = false;
556  for (int j = 1; j <= op.numberOfInputs(); j++) {
557  Operand& operand = op.operand(j);
558  ARGLIST_CONST Type* llvmOp = getLLVMType(
559  operand.type(), //Type::getInt32Ty(getGlobalContext()));
560  defaultIntegerType);
561 
562  argList_default.push_back(llvmOp);
563 
564  if (llvmOp == defaultIntegerType) {
565  useInt = true;
566  }
567  }
568 
569  Operand& outputOperand = op.operand(op.numberOfInputs() + 1);
570  retVal_default = getLLVMType(outputOperand.type(), defaultIntegerType);
571 
572  // TODO: should also create smaller bit widths for long type operands??
573  if (retVal_default == defaultIntegerType) { //Type::getInt32Ty(getGlobalContext())) {
574  useInt = true;
575  }
576 
577  FunctionType* fType_default =
578  FunctionType::get(retVal_default, argList_default, false);
579 
580  if (retVal_default == Type::getInt32Ty(getGlobalContext()) ||
581  retVal_default == Type::getFloatTy(getGlobalContext())) {
582 
583  FunctionType* fType_i32 =
584  FunctionType::get(Type::getInt32Ty(getGlobalContext()), argList_i32, false);
585  addFunctionForFootprints(M, fType_i32, op, ".i32"); //".i32");
586  } else {
587  addFunctionForFootprints(M, fType_default, op, defaultIntegerSuffix); //".i32");
588  }
589 
590  // create other function protos for other integer bitwidths
591  if (useInt) {
592  if (retVal_default == defaultIntegerType) {
593  if (mach_->is64bit()) {
594  retVal_i32 = Type::getInt32Ty(getGlobalContext());
595  }
596  retVal_i16 = Type::getInt16Ty(getGlobalContext());
597  retVal_i8 = Type::getInt8Ty(getGlobalContext());
598  retVal_i1 = Type::getInt1Ty(getGlobalContext());
599  } else {
600  if (mach_->is64bit()) {
601  retVal_i32 = retVal_default;
602  }
603  retVal_i16 = retVal_default;
604  retVal_i8 = retVal_default;
605  retVal_i1 = retVal_default;
606  }
607 
608  for (unsigned int j = 0; j < argList_default.size(); j++) {
609  ARGLIST_CONST Type* currArg = argList_default[j];
610  if (currArg == defaultIntegerType) {
611  if (mach_->is64bit()) {
612  argList_i32.push_back(Type::getInt32Ty(getGlobalContext()));
613  }
614  argList_i16.push_back(Type::getInt16Ty(getGlobalContext()));
615  argList_i8.push_back(Type::getInt8Ty(getGlobalContext()));
616  argList_i1.push_back(Type::getInt1Ty(getGlobalContext()));
617  } else {
618  if (mach_->is64bit()) {
619  argList_i16.push_back(currArg);
620  }
621  argList_i16.push_back(currArg);
622  argList_i8.push_back(currArg);
623  argList_i1.push_back(currArg);
624  }
625  }
626 
627  if (mach_->is64bit()) {
628  FunctionType* fType_i32 =
629  FunctionType::get(retVal_i32, argList_i32, false);
630  addFunctionForFootprints(M, fType_i32, op, ".i32");
631  }
632 
633  FunctionType* fType_i16 =
634  FunctionType::get(retVal_i16, argList_i16, false);
635 
636  FunctionType* fType_i8 =
637  FunctionType::get(retVal_i8, argList_i8, false);
638 
639  FunctionType* fType_i1 =
640  FunctionType::get(retVal_i1, argList_i1, false);
641 
642  addFunctionForFootprints(M, fType_i16, op, ".i16");
643  addFunctionForFootprints(M, fType_i8, op, ".i8");
644  addFunctionForFootprints(M, fType_i1, op, ".i1");
645 
646  }
647  }
648  }
649 
650  return retVal;
651 }
652 
653 bool LowerMissingInstructions::doFinalization(Module& /* M */) {
656  << std::endl
657  << "---- DONE: LowerMissingInstructions ----"
658  << std::endl;
659  }
660  return true;
661 }
662 
663 // runOnBasicBlock - This method does the actual work of converting
664 // instructions over, assuming that the pass has already been initialized.
665 //
666 bool LowerMissingInstructions::runOnBasicBlock(BasicBlock &BB) {
667  bool Changed = false;
668  BasicBlock::InstListType &BBIL = BB.getInstList();
669 
670  // Loop over all of the instructions, looking for instructions to lower
671  // instructions
672  for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
673 
674  // get footprint of instruction
675  std::string footPrint = getFootprint(*I);
676 
677  std::map<std::string, Function*>::iterator
678  replaceFunc = replaceFunctions.find(footPrint);
679 
680  // std::cerr << "Footprint: " << footPrint << "\n";
681 
682  if (replaceFunc != replaceFunctions.end()) {
683  if (replaceFunc->second == NULL) {
684  // this should leak down to llvm-tce
685  std::cerr
686  << (boost::format(
687  "ERROR: emulation function for footprint"
688  "'%s' wasn't found. Floating point"
689  " emulation required but --swfp was not given?") %
690  footPrint).str() << std::endl;
691  /* TODO: we have to exit() here as the Exception does not
692  propagate down to the llvm-tce with all distributions.
693  Should fail more gracefully as this is library code. */
694  exit(1);
695  }
699  << "Replacing: " << footPrint
700  << " with emulation function." << std::endl;
701  }
702  std::vector<Value*> args;
703 
704  for (unsigned j = 0; j < I->getNumOperands(); j++) {
705 
706  if (I->getOperand(j)->getType() == Type::getInt16Ty(getGlobalContext()) ||
707  I->getOperand(j)->getType() == Type::getInt8Ty(getGlobalContext()) ||
708  (I->getOperand(j)->getType() == Type::getInt32Ty(getGlobalContext()) &&
709  mach_->is64bit())) {
710 
711  // Emulated operations with i1/i8/i16 operands need
712  // their operands extended to 32 bits. However, there's
713  // no easy way to see if the llvm operand requires
714  // sign or zero extension, so the correct extension is
715  // currently determined directly from the footprint.
716  if (footPrint == "f32.sitofp.i16" ||
717  footPrint == "f32.sitofp.i8") {
718 
719  // sign extension needed
720  args.push_back(
721  llvm::CastInst::CreateIntegerCast(
722  I->getOperand(j),
723  Type::getInt32Ty(getGlobalContext()),
724  true, "", &(*I)));
725  } else if (footPrint == "f32.uitofp.i16" ||
726  footPrint == "f32.uitofp.i8") {
727  // zero extension needed
728  args.push_back(
729  llvm::CastInst::CreateIntegerCast(
730  I->getOperand(j),
731  Type::getInt32Ty(getGlobalContext()),
732  false, "", &(*I)));
733  } else if (footPrint == "f64.sitofp.i32" && mach_->is64bit()) {
734  args.push_back(
735  llvm::CastInst::CreateIntegerCast(
736  I->getOperand(j),
737  Type::getInt64Ty(getGlobalContext()),
738  true, "", &(*I)));
739 
740  } else if (footPrint == "f64.uitofp.i32" && mach_->is64bit()) {
741  args.push_back(
742  llvm::CastInst::CreateIntegerCast(
743  I->getOperand(j),
744  Type::getInt64Ty(getGlobalContext()),
745  false, "", &(*I)));
746  } else {
747  // might not need ext after all.
748  args.push_back(I->getOperand(j));
749  }
750  } else if (I->getOpcode() == llvm::Instruction::Call
751  && j == 0) {
752  // the first operand of a Call is the called function pointer,
753  // ignore it
754  continue;
755  } else {
756  args.push_back(I->getOperand(j));
757  }
758  }
759  CallInst *NewCall =
760  CallInst::Create(
761  FunctionCallee(replaceFunc->second), args, Twine(""), &(*I));
762  NewCall->setTailCall();
763 
764  // Replace all uses of the instruction with call instruction
765  if (I->getType() != NewCall->getType()) {
766 
767  Value *MCast;
768  Instruction::CastOps castOps =
769  llvm::CastInst::getCastOpcode(
770  NewCall, false, I->getType(), false);
771  MCast = llvm::CastInst::Create(
772  castOps, NewCall, I->getType(), Twine(""),
773  &(*I));
774  I->replaceAllUsesWith(MCast);
775 
776  } else {
777  I->replaceAllUsesWith(NewCall);
778  }
779 
780 
781  I = --BBIL.erase(I);
782  Changed = true;
783 
784  NumLowered++;
785  }
786  }
787  return Changed;
788 }
789 
790 bool
791 LowerMissingInstructions::runOnFunction(Function &F) {
792  for (BasicBlock &BB : F) {
793  runOnBasicBlock(BB);
794  }
795  return true;
796 }
Operand
Definition: Operand.hh:52
llvm
Definition: InlineAsmParser.hh:49
OperationPool::operation
Operation & operation(const char *name)
Definition: OperationPool.cc:99
createLowerMissingInstructionsPass
Pass * createLowerMissingInstructionsPass(const TTAMachine::Machine &mach)
Definition: LowerMissingInstructions.cc:147
Operand::OperandType
OperandType
Definition: Operand.hh:58
Operand::HALF_FLOAT_WORD
@ HALF_FLOAT_WORD
Definition: Operand.hh:63
Operand::UINT_WORD
@ UINT_WORD
Definition: Operand.hh:60
BlocksTranslator::FU_TYPE::ID
@ ID
Application::VERBOSE_LEVEL_DEFAULT
static const int VERBOSE_LEVEL_DEFAULT
Default verbose level - do not print anything unnecessary.
Definition: Application.hh:222
MachineInfo.hh
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
Application::verboseLevel
static int verboseLevel()
Definition: Application.hh:176
Application::logStream
static std::ostream & logStream()
Definition: Application.cc:155
NullOperation::instance
static NullOperation & instance()
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
TCEString.hh
OperationDAGSelector::findDags
static OperationDAGList findDags(const std::string &opName, OperationSet opSet, const ImmInfo *immInfo=nullptr)
Definition: OperationDAGSelector.cc:57
Operand::SLONG_WORD
@ SLONG_WORD
Definition: Operand.hh:66
Operation::emulationFunctionName
TCEString emulationFunctionName() const
Definition: Operation.cc:623
llvmFootprints
const std::vector< std::string > & llvmFootprints(std::string tceOp)
Definition: LowerMissingInstructions.cc:209
Operand::FLOAT_WORD
@ FLOAT_WORD
Definition: Operand.hh:61
MachineInfo::getOpset
static OperationSet getOpset(const TTAMachine::Machine &mach)
Definition: MachineInfo.cc:65
Operation.hh
OperationDAGSelector.hh
Operand::SINT_WORD
@ SINT_WORD
Definition: Operand.hh:59
Machine.hh
OperationDAGSelector::OperationSet
TCETools::CIStringSet OperationSet
Definition: OperationDAGSelector.hh:88
Operand::ULONG_WORD
@ ULONG_WORD
Definition: Operand.hh:67
Operation
Definition: Operation.hh:59
TYPE_CONST
#define TYPE_CONST
Definition: LowerMissingInstructions.cc:92
STATISTIC
STATISTIC(NumLowered, "Number of instructions lowered")
Operand.hh
Operand::DOUBLE_WORD
@ DOUBLE_WORD
Definition: Operand.hh:62
Operation::operand
virtual Operand & operand(int id) const
Definition: Operation.cc:541
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
Operand::type
virtual OperandType type() const
Definition: Operand.cc:165
Application::errorStream
static std::ostream & errorStream()
Definition: Application.cc:171
POP_COMPILER_DIAGS
#define POP_COMPILER_DIAGS
Definition: CompilerWarnings.hh:68
ARGLIST_CONST
#define ARGLIST_CONST
Definition: LowerMissingInstructions.cc:91
OperationPool
Definition: OperationPool.hh:52
LLVMBackend::llvmRequiredOpset
static OperationDAGSelector::OperationSet llvmRequiredOpset(bool includeFloatOps, bool isLittleEndian, bool bits64)
Definition: LLVMBackend.cc:150
OperationPool.hh
Operation::numberOfOutputs
virtual int numberOfOutputs() const
Definition: Operation.cc:202
CompilerWarnings.hh
TTAMachine::Machine
Definition: Machine.hh:73
LLVMBackend.hh