Merge pull request #1024 from Vsevolod-Livinskij/multitarget

Support of *-generic-16 target
This commit is contained in:
Dmitry Babokin
2015-04-24 18:16:45 +03:00
4 changed files with 98 additions and 23 deletions

View File

@@ -515,8 +515,14 @@ Function::GenerateIR() {
llvm::FunctionType *ftype = type->LLVMFunctionType(g->ctx, true); llvm::FunctionType *ftype = type->LLVMFunctionType(g->ctx, true);
llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage; llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage;
std::string functionName = sym->name; std::string functionName = sym->name;
if (g->mangleFunctionsWithTarget) if (g->mangleFunctionsWithTarget) {
functionName += std::string("_") + g->target->GetISAString(); // 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 #ifdef ISPC_NVPTX_ENABLED
if (g->target->getISA() == Target::NVPTX) if (g->target->getISA() == Target::NVPTX)
{ {

View File

@@ -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_target(NULL),
m_targetMachine(NULL), m_targetMachine(NULL),
m_dataLayout(NULL), m_dataLayout(NULL),
m_valid(false), m_valid(false),
m_isa(SSE2), m_isa(SSE2),
m_treatGenericAsSmth(genericAsSmth),
m_arch(""), m_arch(""),
m_is32Bit(true), m_is32Bit(true),
m_cpu(""), m_cpu(""),
@@ -660,8 +661,20 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
CPUfromISA = CPU_Generic; CPUfromISA = CPU_Generic;
} }
else if (!strcasecmp(isa, "generic-16") || 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; 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_nativeVectorWidth = 16;
this->m_nativeVectorAlignment = 64; this->m_nativeVectorAlignment = 64;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -1065,7 +1078,7 @@ Target::SupportedTargets() {
"avx1.1-i32x8, avx1.1-i32x16, avx1.1-i64x4 " "avx1.1-i32x8, avx1.1-i32x16, avx1.1-i64x4 "
"avx2-i32x8, avx2-i32x16, avx2-i64x4, " "avx2-i32x8, avx2-i32x16, avx2-i64x4, "
"generic-x1, generic-x4, generic-x8, generic-x16, " "generic-x1, generic-x4, generic-x8, generic-x16, "
"generic-x32, generic-x64" "generic-x32, generic-x64, *-generic-x16"
#ifdef ISPC_ARM_ENABLED #ifdef ISPC_ARM_ENABLED
", neon-i8x16, neon-i16x8, neon-i32x4" ", neon-i8x16, neon-i16x8, neon-i32x4"
#endif #endif

7
ispc.h
View File

@@ -207,7 +207,7 @@ public:
/** Initializes the given Target pointer for a target of the given /** Initializes the given Target pointer for a target of the given
name, if the name is a known target. Returns true if the name, if the name is a known target. Returns true if the
target was initialized and false if the name is unknown. */ 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 /** Returns a comma-delimited string giving the names of the currently
supported compilation targets. */ supported compilation targets. */
@@ -266,6 +266,8 @@ public:
ISA getISA() const {return m_isa;} ISA getISA() const {return m_isa;}
std::string getTreatGenericAsSmth() const {return m_treatGenericAsSmth;}
std::string getArch() const {return m_arch;} std::string getArch() const {return m_arch;}
bool is32Bit() const {return m_is32Bit;} bool is32Bit() const {return m_is32Bit;}
@@ -327,6 +329,9 @@ private:
/** Instruction set being compiled to. */ /** Instruction set being compiled to. */
ISA m_isa; 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"). */ /** Target system architecture. (e.g. "x86-64", "x86"). */
std::string m_arch; std::string m_arch;

View File

@@ -973,8 +973,14 @@ Module::AddFunctionDeclaration(const std::string &name,
std::string functionName = name; std::string functionName = name;
if (storageClass != SC_EXTERN_C) { if (storageClass != SC_EXTERN_C) {
functionName += functionType->Mangle(); functionName += functionType->Mangle();
if (g->mangleFunctionsWithTarget) // If we treat generic as smth, we should have appropriate mangling
functionName += g->target->GetISAString(); 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 *function =
llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(), llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(),
@@ -2567,7 +2573,7 @@ Module::execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostre
// "avx", return a string with the ISA name inserted before the original // "avx", return a string with the ISA name inserted before the original
// filename's suffix, like "foo_avx.obj". // filename's suffix, like "foo_avx.obj".
static std::string 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]; char *targetOutFileName = new char[strlen(outFileName) + 16];
if (strrchr(outFileName, '.') != NULL) { if (strrchr(outFileName, '.') != NULL) {
// Copy everything up to the last '.' // Copy everything up to the last '.'
@@ -2579,8 +2585,11 @@ lGetTargetFileName(const char *outFileName, const char *isaString) {
strcat(targetOutFileName, "_"); strcat(targetOutFileName, "_");
strcat(targetOutFileName, isaString); strcat(targetOutFileName, isaString);
// And finish with the original file suffiz // And finish with the original file suffix if it is not *-generic target
strcat(targetOutFileName, strrchr(outFileName, '.')); if (!forceCXX)
strcat(targetOutFileName, strrchr(outFileName, '.'));
else
strcat(targetOutFileName, ".cpp");
} }
else { else {
// Can't find a '.' in the filename, so just append the ISA suffix // Can't find a '.' in the filename, so just append the ISA suffix
@@ -2588,6 +2597,10 @@ lGetTargetFileName(const char *outFileName, const char *isaString) {
strcpy(targetOutFileName, outFileName); strcpy(targetOutFileName, outFileName);
strcat(targetOutFileName, "_"); strcat(targetOutFileName, "_");
strcat(targetOutFileName, isaString); strcat(targetOutFileName, isaString);
// Append ".cpp" suffix to the original file if it is *-generic target
if (forceCXX)
strcat(targetOutFileName, ".cpp");
} }
return targetOutFileName; return targetOutFileName;
} }
@@ -2897,11 +2910,26 @@ lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc,
continue; continue;
// Emit code to see if the system can run the current candidate // 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?" // 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::Value *ok =
llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, 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 *callBBlock =
llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc); llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc);
llvm::BasicBlock *nextBBlock = llvm::BasicBlock *nextBBlock =
@@ -3082,14 +3110,16 @@ Module::CompileAndOutput(const char *srcFile,
} }
#endif /* ISPC_NVPTX_ENABLED */ #endif /* ISPC_NVPTX_ENABLED */
if (outputType == CXX) { 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-*\" " Error(SourcePos(), "When generating C++ output, one of the \"generic-*\" "
"targets must be used."); "targets must be used.");
return 1; return 1;
} }
} }
else if (outputType == Asm || outputType == Object) { 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, " Error(SourcePos(), "When using a \"generic-*\" compilation target, "
"%s output can not be used.", "%s output can not be used.",
(outputType == Asm) ? "assembly" : "object file"); (outputType == Asm) ? "assembly" : "object file");
@@ -3180,12 +3210,18 @@ Module::CompileAndOutput(const char *srcFile,
DHI.EmitBackMatter = false; 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) { for (unsigned int i = 0; i < targets.size(); ++i) {
g->target = new Target(arch, cpu, targets[i].c_str(), generatePIC); g->target = new Target(arch, cpu, targets[i].c_str(), generatePIC);
if (!g->target->isValid()) if (!g->target->isValid())
return 1; return 1;
if (!g->target->getTreatGenericAsSmth().empty())
treatGenericAsSmth = g->target->getTreatGenericAsSmth();
// Issue an error if we've already compiled to a variant of // Issue an error if we've already compiled to a variant of
// this target ISA. (It doesn't make sense to compile to both // this target ISA. (It doesn't make sense to compile to both
// avx and avx-x2, for example.) // avx and avx-x2, for example.)
@@ -3206,11 +3242,21 @@ Module::CompileAndOutput(const char *srcFile,
lExtractAndRewriteGlobals(m->module, &globals[i]); lExtractAndRewriteGlobals(m->module, &globals[i]);
if (outFileName != NULL) { if (outFileName != NULL) {
const char *isaName = g->target->GetISAString(); std::string targetOutFileName;
std::string targetOutFileName = // We always generate cpp file for *-generic target during multitarget compilation
lGetTargetFileName(outFileName, isaName); if (g->target->getISA() == Target::GENERIC &&
if (!m->writeOutput(outputType, targetOutFileName.c_str())) !g->target->getTreatGenericAsSmth().empty()) {
return 1; 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; errorCount += m->errorCount;
@@ -3223,9 +3269,14 @@ Module::CompileAndOutput(const char *srcFile,
DHI.EmitBackMatter = true; 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 = std::string targetHeaderFileName =
lGetTargetFileName(headerFileName, isaName); lGetTargetFileName(headerFileName, isaName, false);
// write out a header w/o target name for the first target only // write out a header w/o target name for the first target only
if (!m->writeOutput(Module::Header, headerFileName, "", &DHI)) { if (!m->writeOutput(Module::Header, headerFileName, "", &DHI)) {
return 1; return 1;
@@ -3259,7 +3310,7 @@ Module::CompileAndOutput(const char *srcFile,
} }
Assert(firstTargetMachine != NULL); Assert(firstTargetMachine != NULL);
g->target = new Target(arch, cpu, firstISA, generatePIC); g->target = new Target(arch, cpu, firstISA, generatePIC, treatGenericAsSmth);
if (!g->target->isValid()) { if (!g->target->isValid()) {
return 1; return 1;
} }