llvm_common.cc 3.83 KB
Newer Older
1 2 3 4 5 6 7 8
/*!
 *  Copyright (c) 2017 by Contributors
 * \file llvm_common.cc
 */
#ifdef TVM_LLVM_VERSION

#include <tvm/base.h>
#include <mutex>
9
#include "llvm_common.h"
10 11 12 13 14 15

namespace tvm {
namespace codegen {

struct LLVMEnv {
  std::mutex mu;
16
  bool all_initialized{false};
17 18 19 20 21 22 23 24 25

  static LLVMEnv* Global() {
    static LLVMEnv inst;
    return &inst;
  }
};

void InitializeLLVM() {
  LLVMEnv* e = LLVMEnv::Global();
26
  if (!e->all_initialized) {
27
    std::lock_guard<std::mutex> lock(e->mu);
28 29 30 31 32 33 34
    if (!e->all_initialized) {
      e->all_initialized = true;
      llvm::InitializeAllTargetInfos();
      llvm::InitializeAllTargets();
      llvm::InitializeAllTargetMCs();
      llvm::InitializeAllAsmParsers();
      llvm::InitializeAllAsmPrinters();
35 36 37 38
    }
  }
}

39 40 41 42 43
void ParseLLVMTargetOptions(const std::string& target_str,
                            std::string* triple,
                            std::string* mcpu,
                            std::string* mattr,
                            llvm::TargetOptions* options) {
44
  // setup target triple
45 46 47 48 49
  size_t start = 0;
  if (target_str.length() >= 4 &&
      target_str.substr(0, 4) == "llvm") {
    start = 4;
  }
50
  // simple parser
51 52 53 54
  triple->resize(0);
  mcpu->resize(0);
  mattr->resize(0);

55
  bool soft_float_abi = false;
56
  std::string key, value;
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
  std::istringstream is(target_str.substr(start, target_str.length() - start));

  while (is >> key) {
    if (key == "--system-lib" || key == "-system-lib") {
      continue;
    }
    size_t pos = key.find('=');
    if (pos != std::string::npos) {
      CHECK_GE(key.length(), pos + 1)
          << "inavlid argument " << key;
      value = key.substr(pos + 1, key.length() - 1);
      key = key.substr(0, pos);
    } else {
      CHECK(is >> value)
          << "Unspecified value for option " << key;
    }
    if (key == "-target" ||
        key == "-mtriple") {
75
      *triple = value;
76
    } else if (key == "-mcpu") {
77
      *mcpu = value;
78
    } else if (key == "-mattr") {
79
      *mattr = value;
80 81 82 83 84
    } else if (key == "-mfloat-abi") {
      if (value == "hard") {
        soft_float_abi = false;
      } else if (value == "soft") {
        soft_float_abi = true;
85
      } else {
86
        LOG(FATAL) << "invalid -mfloat-abi option " << value;
87
      }
88
    } else if (key == "-device" || key == "-libs" || key == "-model") {
89
      // pass
90 91
    } else {
      LOG(FATAL) << "unknown option " << key;
92
    }
93
  }
94

95 96 97
  if (triple->length() == 0 ||
      *triple == "default") {
    *triple = llvm::sys::getDefaultTargetTriple();
98
  }
99
  // set target option
100 101
  llvm::TargetOptions& opt = *options;
  opt = llvm::TargetOptions();
102
  #if TVM_LLVM_VERSION < 50
103
  opt.LessPreciseFPMADOption = true;
104
  #endif
105 106 107 108 109 110 111 112 113
  opt.AllowFPOpFusion = llvm::FPOpFusion::Fast;
  opt.UnsafeFPMath = true;
  opt.NoInfsFPMath = true;
  opt.NoNaNsFPMath = true;
  if (soft_float_abi) {
    opt.FloatABIType = llvm::FloatABI::Soft;
  } else {
    opt.FloatABIType = llvm::FloatABI::Hard;
  }
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
}


llvm::TargetMachine*
GetLLVMTargetMachine(const std::string& target_str,
                     bool allow_null) {
  std::string target_triple, mcpu, mattr;
  llvm::TargetOptions opt;

  ParseLLVMTargetOptions(target_str,
                         &target_triple,
                         &mcpu,
                         &mattr,
                         &opt);

  if (target_triple.length() == 0 ||
      target_triple == "default") {
    target_triple = llvm::sys::getDefaultTargetTriple();
  }
  if (mcpu.length() == 0) {
    mcpu = "generic";
  }

  std::string err;
  const llvm::Target* target =
      llvm::TargetRegistry::lookupTarget(target_triple, err);
  if (target == nullptr) {
    CHECK(allow_null) << err << " target_triple=" << target_triple;
    return nullptr;
  }
144
  llvm::TargetMachine* tm = target->createTargetMachine(
145
      target_triple, mcpu, mattr, opt, llvm::Reloc::PIC_);
146
  return tm;
147 148
}

149 150 151
}  // namespace codegen
}  // namespace tvm
#endif  // TVM_LLVM_VERSION