From c2039da7b885b04a3136b371e08b790237002a61 Mon Sep 17 00:00:00 2001 From: Vsevolod Livinskiy Date: Fri, 17 Apr 2015 11:20:39 +0300 Subject: [PATCH] Support of *-generic-16 target --- func.cpp | 10 +++++-- ispc.cpp | 19 ++++++++++-- ispc.h | 7 ++++- module.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 98 insertions(+), 23 deletions(-) diff --git a/func.cpp b/func.cpp index a624b699..d6c8c340 100644 --- a/func.cpp +++ b/func.cpp @@ -515,8 +515,14 @@ Function::GenerateIR() { llvm::FunctionType *ftype = type->LLVMFunctionType(g->ctx, true); llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage; std::string functionName = sym->name; - if (g->mangleFunctionsWithTarget) - functionName += std::string("_") + g->target->GetISAString(); + if (g->mangleFunctionsWithTarget) { + // If we treat generic as smth, we should have appropriate mangling + if (g->target->getISA() == Target::GENERIC && + !g->target->getTreatGenericAsSmth().empty()) + functionName += std::string("_") + g->target->getTreatGenericAsSmth(); + else + functionName += std::string("_") + g->target->GetISAString(); + } #ifdef ISPC_NVPTX_ENABLED if (g->target->getISA() == Target::NVPTX) { diff --git a/ispc.cpp b/ispc.cpp index f5a5ec59..0367fbc6 100644 --- a/ispc.cpp +++ b/ispc.cpp @@ -416,12 +416,13 @@ public: }; -Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) : +Target::Target(const char *arch, const char *cpu, const char *isa, bool pic, std::string genericAsSmth) : m_target(NULL), m_targetMachine(NULL), m_dataLayout(NULL), m_valid(false), m_isa(SSE2), + m_treatGenericAsSmth(genericAsSmth), m_arch(""), m_is32Bit(true), m_cpu(""), @@ -660,8 +661,20 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) : CPUfromISA = CPU_Generic; } else if (!strcasecmp(isa, "generic-16") || - !strcasecmp(isa, "generic-x16")) { + !strcasecmp(isa, "generic-x16") || + // We treat *-generic-16 as generic-16, but with special name mangling + strstr(isa, "-generic-16") || + strstr(isa, "-generic-x16")) { this->m_isa = Target::GENERIC; + if (strstr(isa, "-generic-16") || + strstr(isa, "-generic-x16")) { + // It is used for appropriate name mangling and dispatch function during multitarget compilation + this->m_treatGenericAsSmth = isa; + // We need to create appropriate name for mangling. + // Remove "-x16" or "-16" and replace "-" with "_". + this->m_treatGenericAsSmth = this->m_treatGenericAsSmth.substr(0, this->m_treatGenericAsSmth.find_last_of("-")); + std::replace(this->m_treatGenericAsSmth.begin(), this->m_treatGenericAsSmth.end(), '-', '_'); + } this->m_nativeVectorWidth = 16; this->m_nativeVectorAlignment = 64; this->m_vectorWidth = 16; @@ -1065,7 +1078,7 @@ Target::SupportedTargets() { "avx1.1-i32x8, avx1.1-i32x16, avx1.1-i64x4 " "avx2-i32x8, avx2-i32x16, avx2-i64x4, " "generic-x1, generic-x4, generic-x8, generic-x16, " - "generic-x32, generic-x64" + "generic-x32, generic-x64, *-generic-x16" #ifdef ISPC_ARM_ENABLED ", neon-i8x16, neon-i16x8, neon-i32x4" #endif diff --git a/ispc.h b/ispc.h index 5af265fe..00eadbd6 100644 --- a/ispc.h +++ b/ispc.h @@ -196,7 +196,7 @@ public: /** Initializes the given Target pointer for a target of the given name, if the name is a known target. Returns true if the target was initialized and false if the name is unknown. */ - Target(const char *arch, const char *cpu, const char *isa, bool pic); + Target(const char *arch, const char *cpu, const char *isa, bool pic, std::string genenricAsSmth = ""); /** Returns a comma-delimited string giving the names of the currently supported compilation targets. */ @@ -255,6 +255,8 @@ public: ISA getISA() const {return m_isa;} + std::string getTreatGenericAsSmth() const {return m_treatGenericAsSmth;} + std::string getArch() const {return m_arch;} bool is32Bit() const {return m_is32Bit;} @@ -316,6 +318,9 @@ private: /** Instruction set being compiled to. */ ISA m_isa; + /** The variable shows if we use special mangling with generic target. */ + std::string m_treatGenericAsSmth; + /** Target system architecture. (e.g. "x86-64", "x86"). */ std::string m_arch; diff --git a/module.cpp b/module.cpp index 95be7352..c1d766a0 100644 --- a/module.cpp +++ b/module.cpp @@ -975,8 +975,14 @@ Module::AddFunctionDeclaration(const std::string &name, std::string functionName = name; if (storageClass != SC_EXTERN_C) { functionName += functionType->Mangle(); - if (g->mangleFunctionsWithTarget) - functionName += g->target->GetISAString(); + // If we treat generic as smth, we should have appropriate mangling + if (g->mangleFunctionsWithTarget) { + if (g->target->getISA() == Target::GENERIC && + !g->target->getTreatGenericAsSmth().empty()) + functionName += g->target->getTreatGenericAsSmth(); + else + functionName += g->target->GetISAString(); + } } llvm::Function *function = llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(), @@ -2569,7 +2575,7 @@ Module::execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostre // "avx", return a string with the ISA name inserted before the original // filename's suffix, like "foo_avx.obj". static std::string -lGetTargetFileName(const char *outFileName, const char *isaString) { +lGetTargetFileName(const char *outFileName, const char *isaString, bool forceCXX) { char *targetOutFileName = new char[strlen(outFileName) + 16]; if (strrchr(outFileName, '.') != NULL) { // Copy everything up to the last '.' @@ -2581,8 +2587,11 @@ lGetTargetFileName(const char *outFileName, const char *isaString) { strcat(targetOutFileName, "_"); strcat(targetOutFileName, isaString); - // And finish with the original file suffiz - strcat(targetOutFileName, strrchr(outFileName, '.')); + // And finish with the original file suffix if it is not *-generic target + if (!forceCXX) + strcat(targetOutFileName, strrchr(outFileName, '.')); + else + strcat(targetOutFileName, ".cpp"); } else { // Can't find a '.' in the filename, so just append the ISA suffix @@ -2590,6 +2599,10 @@ lGetTargetFileName(const char *outFileName, const char *isaString) { strcpy(targetOutFileName, outFileName); strcat(targetOutFileName, "_"); strcat(targetOutFileName, isaString); + + // Append ".cpp" suffix to the original file if it is *-generic target + if (forceCXX) + strcat(targetOutFileName, ".cpp"); } return targetOutFileName; } @@ -2890,11 +2903,26 @@ lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, continue; // Emit code to see if the system can run the current candidate - // variant successfully--"is the system's ISA enuemrant value >= + // variant successfully--"is the system's ISA enumerant value >= // the enumerant value of the current candidate?" + + // dispatchNum is needed to separate generic from *-generic target + int dispatchNum = i; + if ((Target::ISA)(i == Target::GENERIC) && + !g->target->getTreatGenericAsSmth().empty()) { + if (g->target->getTreatGenericAsSmth() == "knl_generic") + dispatchNum = Target::KNL; + else if (g->target->getTreatGenericAsSmth() == "skx_generic") + dispatchNum = Target::SKX; + else { + Error(SourcePos(), "*-generic target can be called only with knl or skx"); + exit(1); + } + } + llvm::Value *ok = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, - systemISA, LLVMInt32(i), "isa_ok", bblock); + systemISA, LLVMInt32(dispatchNum), "isa_ok", bblock); llvm::BasicBlock *callBBlock = llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc); llvm::BasicBlock *nextBBlock = @@ -3076,14 +3104,16 @@ Module::CompileAndOutput(const char *srcFile, } #endif /* ISPC_NVPTX_ENABLED */ if (outputType == CXX) { - if (target == NULL || strncmp(target, "generic-", 8) != 0) { + if (target == NULL || strncmp(target, "generic-", 8) != 0 + || strstr(target, "-generic-") == NULL) { Error(SourcePos(), "When generating C++ output, one of the \"generic-*\" " "targets must be used."); return 1; } } else if (outputType == Asm || outputType == Object) { - if (target != NULL && strncmp(target, "generic-", 8) == 0) { + if (target != NULL && + (strncmp(target, "generic-", 8) == 0 || strstr(target, "-generic-") != NULL)) { Error(SourcePos(), "When using a \"generic-*\" compilation target, " "%s output can not be used.", (outputType == Asm) ? "assembly" : "object file"); @@ -3174,12 +3204,18 @@ Module::CompileAndOutput(const char *srcFile, DHI.EmitBackMatter = false; } + // Variable is needed later for approptiate dispatch function. + // It indicates if we have *-generic target. + std::string treatGenericAsSmth = ""; for (unsigned int i = 0; i < targets.size(); ++i) { g->target = new Target(arch, cpu, targets[i].c_str(), generatePIC); if (!g->target->isValid()) return 1; + if (!g->target->getTreatGenericAsSmth().empty()) + treatGenericAsSmth = g->target->getTreatGenericAsSmth(); + // Issue an error if we've already compiled to a variant of // this target ISA. (It doesn't make sense to compile to both // avx and avx-x2, for example.) @@ -3200,11 +3236,21 @@ Module::CompileAndOutput(const char *srcFile, lExtractAndRewriteGlobals(m->module, &globals[i]); if (outFileName != NULL) { - const char *isaName = g->target->GetISAString(); - std::string targetOutFileName = - lGetTargetFileName(outFileName, isaName); - if (!m->writeOutput(outputType, targetOutFileName.c_str())) - return 1; + std::string targetOutFileName; + // We always generate cpp file for *-generic target during multitarget compilation + if (g->target->getISA() == Target::GENERIC && + !g->target->getTreatGenericAsSmth().empty()) { + targetOutFileName = lGetTargetFileName(outFileName, + g->target->getTreatGenericAsSmth().c_str(), true); + if (!m->writeOutput(CXX, targetOutFileName.c_str(), includeFileName)) + return 1; + } + else { + const char *isaName = g->target->GetISAString(); + targetOutFileName = lGetTargetFileName(outFileName, isaName, false); + if (!m->writeOutput(outputType, targetOutFileName.c_str())) + return 1; + } } } errorCount += m->errorCount; @@ -3217,9 +3263,14 @@ Module::CompileAndOutput(const char *srcFile, DHI.EmitBackMatter = true; } - const char *isaName = g->target->GetISAString(); + const char *isaName; + if (g->target->getISA() == Target::GENERIC && + !g->target->getTreatGenericAsSmth().empty()) + isaName = g->target->getTreatGenericAsSmth().c_str(); + else + isaName = g->target->GetISAString(); std::string targetHeaderFileName = - lGetTargetFileName(headerFileName, isaName); + lGetTargetFileName(headerFileName, isaName, false); // write out a header w/o target name for the first target only if (!m->writeOutput(Module::Header, headerFileName, "", &DHI)) { return 1; @@ -3253,7 +3304,7 @@ Module::CompileAndOutput(const char *srcFile, } Assert(firstTargetMachine != NULL); - g->target = new Target(arch, cpu, firstISA, generatePIC); + g->target = new Target(arch, cpu, firstISA, generatePIC, treatGenericAsSmth); if (!g->target->isValid()) { return 1; }