Merge pull request #1024 from Vsevolod-Livinskij/multitarget
Support of *-generic-16 target
This commit is contained in:
8
func.cpp
8
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)
|
||||
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)
|
||||
{
|
||||
|
||||
19
ispc.cpp
19
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
|
||||
|
||||
7
ispc.h
7
ispc.h
@@ -207,7 +207,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. */
|
||||
@@ -266,6 +266,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;}
|
||||
@@ -327,6 +329,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;
|
||||
|
||||
|
||||
75
module.cpp
75
module.cpp
@@ -973,9 +973,15 @@ Module::AddFunctionDeclaration(const std::string &name,
|
||||
std::string functionName = name;
|
||||
if (storageClass != SC_EXTERN_C) {
|
||||
functionName += functionType->Mangle();
|
||||
if (g->mangleFunctionsWithTarget)
|
||||
// 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(),
|
||||
module);
|
||||
@@ -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
|
||||
// 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 '.'
|
||||
@@ -2579,8 +2585,11 @@ lGetTargetFileName(const char *outFileName, const char *isaString) {
|
||||
strcat(targetOutFileName, "_");
|
||||
strcat(targetOutFileName, isaString);
|
||||
|
||||
// And finish with the original file suffiz
|
||||
// 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
|
||||
@@ -2588,6 +2597,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;
|
||||
}
|
||||
@@ -2897,11 +2910,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 =
|
||||
@@ -3082,14 +3110,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");
|
||||
@@ -3180,12 +3210,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.)
|
||||
@@ -3206,13 +3242,23 @@ Module::CompileAndOutput(const char *srcFile,
|
||||
lExtractAndRewriteGlobals(m->module, &globals[i]);
|
||||
|
||||
if (outFileName != NULL) {
|
||||
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();
|
||||
std::string targetOutFileName =
|
||||
lGetTargetFileName(outFileName, isaName);
|
||||
targetOutFileName = lGetTargetFileName(outFileName, isaName, false);
|
||||
if (!m->writeOutput(outputType, targetOutFileName.c_str()))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
errorCount += m->errorCount;
|
||||
|
||||
// Only write the generate header file, if desired, the first
|
||||
@@ -3223,9 +3269,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;
|
||||
@@ -3259,7 +3310,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user