45 #define DEBUG_TYPE "lowermissing"
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"
59 #include "llvm/ADT/Twine.h"
61 #include "llvm/ADT/STLExtras.h"
62 #include "llvm/Support/CommandLine.h"
87 STATISTIC(NumLowered,
"Number of instructions lowered");
95 class LowerMissingInstructions :
public FunctionPass {
96 std::map< std::string, Function*> replaceFunctions;
106 bool doInitialization(Module &M)
override;
107 bool doFinalization (Module &M)
override;
110 using llvm::FunctionPass::doInitialization;
111 using llvm::FunctionPass::doFinalization;
113 bool runOnBasicBlock(BasicBlock &BB);
114 bool runOnFunction(Function &F);
116 virtual StringRef getPassName()
const override {
117 return "TCE: LowerMissingInstructions";
120 void addFunctionForFootprints(
121 Module& M, FunctionType* fType,
Operation& op,
125 std::string stringType(
const Type* type)
const;
130 std::string getFootprint(Instruction& I);
133 LLVMContext& getGlobalContext()
const {
134 return dstModule_->getContext();
138 char LowerMissingInstructions::ID = 0;
148 return new LowerMissingInstructions(mach);
151 LowerMissingInstructions::LowerMissingInstructions(
159 LowerMissingInstructions::stringType(
const Type* type)
const {
160 LLVMContext& context = getGlobalContext();
161 if (type == Type::getInt64Ty(context)) {
163 }
else if (type == Type::getInt32Ty(context)) {
165 }
else if (type == Type::getInt16Ty(context)) {
167 }
else if (type == Type::getInt8Ty(context)) {
169 }
else if (type == Type::getInt1Ty(context)) {
171 }
else if (type == Type::getHalfTy(context)) {
173 }
else if (type == Type::getFloatTy(context)) {
175 }
else if (type == Type::getDoubleTy(context)) {
177 }
else if (type == Type::getLabelTy(context)) {
179 }
else if (type == Type::getVoidTy(context)) {
187 LowerMissingInstructions::getLLVMType(
191 return llvmIntegerType;
193 return llvmIntegerType;
195 return Type::getInt64Ty(getGlobalContext());
197 return Type::getInt64Ty(getGlobalContext());
199 return Type::getFloatTy(getGlobalContext());
201 return Type::getHalfTy(getGlobalContext());
203 return Type::getDoubleTy(getGlobalContext());
205 return Type::getVoidTy(getGlobalContext());
210 static bool init =
true;
211 static std::map<std::string, std::vector<std::string> > footprints;
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
324 footprints[
"CFD.i64"].push_back(
"f64.fpext.f32");
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");
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");
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");
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");
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");
362 return footprints[tceOp];
366 LowerMissingInstructions::getFootprint(Instruction& I) {
368 std::string footPrint = stringType(I.getType());
370 switch (I.getOpcode()) {
372 case Instruction::FCmp: {
373 FCmpInst* cmpInst = dyn_cast<FCmpInst>(&I);
374 footPrint += std::string(
".") + cmpInst->getOpcodeName() +
".";
376 switch (cmpInst->getPredicate()) {
377 case FCmpInst::FCMP_FALSE:
378 footPrint +=
"false";
380 case FCmpInst::FCMP_OEQ:
383 case FCmpInst::FCMP_OGT:
386 case FCmpInst::FCMP_OGE:
389 case FCmpInst::FCMP_OLT:
392 case FCmpInst::FCMP_OLE:
395 case FCmpInst::FCMP_ONE:
398 case FCmpInst::FCMP_ORD:
401 case FCmpInst::FCMP_UNO:
404 case FCmpInst::FCMP_UEQ:
407 case FCmpInst::FCMP_UGT:
410 case FCmpInst::FCMP_UGE:
413 case FCmpInst::FCMP_ULT:
416 case FCmpInst::FCMP_ULE:
419 case FCmpInst::FCMP_UNE:
422 case FCmpInst::FCMP_TRUE:
426 footPrint +=
"PREDFAIL";
430 case Instruction::Call: {
431 if (!isa<CallInst>(&I) ||
432 dyn_cast<CallInst>(&I)->getCalledFunction() == NULL)
434 std::string calledName =
435 dyn_cast<CallInst>(&I)->getCalledFunction()->getName().str();
436 if (calledName ==
"llvm.sqrt.f32") {
437 return "f32.sqrt.f32";
443 footPrint += std::string(
".") + I.getOpcodeName();
446 for (
unsigned int i = 0; i < I.getNumOperands();i++) {
447 footPrint +=
"." + stringType(I.getOperand(i)->getType());
453 void LowerMissingInstructions::addFunctionForFootprints(
454 Module& M, FunctionType* ,
Operation& op, std::string suffix) {
459 const std::vector<std::string>&
462 for (
unsigned int j = 0; j < footprints.size(); j++) {
464 replaceFunctions[footprints[j]] = func;
467 std::cerr <<
"Operation: " << op.
name()
469 <<
" footprint: " << footprints[j]
475 bool LowerMissingInstructions::doInitialization(Module &M) {
480 <<
"---- LowerMissingInstructions ----"
497 for (OperationDAGSelector::OperationSet::iterator i = requiredSet.begin();
498 i != requiredSet.end(); i++) {
500 if (opSet.find(*i) == opSet.end() &&
506 std::cerr <<
"Error: Cant find operation: " << *i
526 std::vector<ARGLIST_CONST Type*> argList_i64;
529 std::vector<ARGLIST_CONST Type*> argList_i32;
532 std::vector<ARGLIST_CONST Type*> argList_i16;
535 std::vector<ARGLIST_CONST Type*> argList_i8;
538 std::vector<ARGLIST_CONST Type*> argList_i1;
543 Type::getInt64Ty(getGlobalContext()) :
544 Type::getInt32Ty(getGlobalContext());
546 std::vector<ARGLIST_CONST Type*>& argList_default =
547 mach_->is64bit() ? argList_i64 : argList_i32;
550 mach_->is64bit() ? retVal_i64 : retVal_i32;
552 const char* defaultIntegerSuffix =
553 mach_->is64bit() ?
".i64" :
".i32";
562 argList_default.push_back(llvmOp);
564 if (llvmOp == defaultIntegerType) {
570 retVal_default = getLLVMType(outputOperand.
type(), defaultIntegerType);
573 if (retVal_default == defaultIntegerType) {
577 FunctionType* fType_default =
578 FunctionType::get(retVal_default, argList_default,
false);
580 if (retVal_default == Type::getInt32Ty(getGlobalContext()) ||
581 retVal_default == Type::getFloatTy(getGlobalContext())) {
583 FunctionType* fType_i32 =
584 FunctionType::get(Type::getInt32Ty(getGlobalContext()), argList_i32,
false);
585 addFunctionForFootprints(M, fType_i32, op,
".i32");
587 addFunctionForFootprints(M, fType_default, op, defaultIntegerSuffix);
592 if (retVal_default == defaultIntegerType) {
593 if (mach_->is64bit()) {
594 retVal_i32 = Type::getInt32Ty(getGlobalContext());
596 retVal_i16 = Type::getInt16Ty(getGlobalContext());
597 retVal_i8 = Type::getInt8Ty(getGlobalContext());
598 retVal_i1 = Type::getInt1Ty(getGlobalContext());
600 if (mach_->is64bit()) {
601 retVal_i32 = retVal_default;
603 retVal_i16 = retVal_default;
604 retVal_i8 = retVal_default;
605 retVal_i1 = retVal_default;
608 for (
unsigned int j = 0; j < argList_default.size(); j++) {
610 if (currArg == defaultIntegerType) {
611 if (mach_->is64bit()) {
612 argList_i32.push_back(Type::getInt32Ty(getGlobalContext()));
614 argList_i16.push_back(Type::getInt16Ty(getGlobalContext()));
615 argList_i8.push_back(Type::getInt8Ty(getGlobalContext()));
616 argList_i1.push_back(Type::getInt1Ty(getGlobalContext()));
618 if (mach_->is64bit()) {
619 argList_i16.push_back(currArg);
621 argList_i16.push_back(currArg);
622 argList_i8.push_back(currArg);
623 argList_i1.push_back(currArg);
627 if (mach_->is64bit()) {
628 FunctionType* fType_i32 =
629 FunctionType::get(retVal_i32, argList_i32,
false);
630 addFunctionForFootprints(M, fType_i32, op,
".i32");
633 FunctionType* fType_i16 =
634 FunctionType::get(retVal_i16, argList_i16,
false);
636 FunctionType* fType_i8 =
637 FunctionType::get(retVal_i8, argList_i8,
false);
639 FunctionType* fType_i1 =
640 FunctionType::get(retVal_i1, argList_i1,
false);
642 addFunctionForFootprints(M, fType_i16, op,
".i16");
643 addFunctionForFootprints(M, fType_i8, op,
".i8");
644 addFunctionForFootprints(M, fType_i1, op,
".i1");
653 bool LowerMissingInstructions::doFinalization(Module& ) {
657 <<
"---- DONE: LowerMissingInstructions ----"
666 bool LowerMissingInstructions::runOnBasicBlock(BasicBlock &BB) {
667 bool Changed =
false;
668 BasicBlock::InstListType &BBIL = BB.getInstList();
672 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
675 std::string footPrint = getFootprint(*I);
677 std::map<std::string, Function*>::iterator
678 replaceFunc = replaceFunctions.find(footPrint);
682 if (replaceFunc != replaceFunctions.end()) {
683 if (replaceFunc->second == NULL) {
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;
699 <<
"Replacing: " << footPrint
700 <<
" with emulation function." << std::endl;
702 std::vector<Value*> args;
704 for (
unsigned j = 0; j < I->getNumOperands(); j++) {
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()) &&
716 if (footPrint ==
"f32.sitofp.i16" ||
717 footPrint ==
"f32.sitofp.i8") {
721 llvm::CastInst::CreateIntegerCast(
723 Type::getInt32Ty(getGlobalContext()),
725 }
else if (footPrint ==
"f32.uitofp.i16" ||
726 footPrint ==
"f32.uitofp.i8") {
729 llvm::CastInst::CreateIntegerCast(
731 Type::getInt32Ty(getGlobalContext()),
733 }
else if (footPrint ==
"f64.sitofp.i32" && mach_->is64bit()) {
735 llvm::CastInst::CreateIntegerCast(
737 Type::getInt64Ty(getGlobalContext()),
740 }
else if (footPrint ==
"f64.uitofp.i32" && mach_->is64bit()) {
742 llvm::CastInst::CreateIntegerCast(
744 Type::getInt64Ty(getGlobalContext()),
748 args.push_back(I->getOperand(j));
750 }
else if (I->getOpcode() == llvm::Instruction::Call
756 args.push_back(I->getOperand(j));
761 FunctionCallee(replaceFunc->second), args, Twine(
""), &(*I));
762 NewCall->setTailCall();
765 if (I->getType() != NewCall->getType()) {
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(
""),
774 I->replaceAllUsesWith(MCast);
777 I->replaceAllUsesWith(NewCall);
791 LowerMissingInstructions::runOnFunction(Function &F) {
792 for (BasicBlock &BB : F) {