Implement new naming scheme for --target.

Now targets are named like "<isa>-i<mask size>x<gang size>", e.g.
"sse4-i8x16", or "avx2-i32x16".

The old target names are still supported.
This commit is contained in:
Matt Pharr
2013-08-08 19:23:44 -07:00
parent 1d76f74b16
commit 0c5742b6f8
7 changed files with 163 additions and 100 deletions

View File

@@ -489,54 +489,72 @@ on which you're running ``ispc`` is used to determine the target CPU.
ispc foo.ispc -o foo.obj --cpu=corei7-avx ispc foo.ispc -o foo.obj --cpu=corei7-avx
Finally, ``--target`` selects the target instruction set. The following Finally, ``--target`` selects the target instruction set. The target
targets are currently supported: string is of the form ``[ISA]-i[mask size]x[gang size]``. For example,
``--target=avx2-i32x16`` specifies a target with the AVX2 instruction set,
a mask size of 32 bits, and a gang size of 16.
=========== ========= ======================================= The following target ISAs are supported:
Target Gang Size Description
----------- --------- --------------------------------------- ============ ==========================================
avx 8 AVX (2010-2011 era Intel CPUs) Target Description
avx-x2 16 "Double-pumped" AVX target, running ------------ ------------------------------------------
twice as many program instances as the avx, avx1 AVX (2010-2011 era Intel CPUs)
native vector width. avx1.1 AVX 1.1 (2012 era "Ivybridge" Intel CPUs)
avx1.1 8 AVX 1.1 target (2012 era "Ivybridge" avx2 AVX 2 target (2013- Intel "Haswell" CPUs)
Intel CPUs). neon ARM NEON
avx1.1-x2 16 Double-pumped AVX 1.1 target. sse2 SSE2 (early 2000s era x86 CPUs)
avx2 8 AVX 2 target (2013- Intel "Haswell" sse4 SSE4 (generally 2008-2010 Intel CPUs)
CPUs.) ============ ==========================================
avx2-x2 16 Double-pumped AVX 2 target.
neon-8 16 ARM NEON target, targeting computation Consult your CPU's manual for specifics on which vector instruction set it
on 8-bit data types. supports.
neon-16 8 ARM NEON target, targeting computation
on 16-bit data types. The mask size may be 8, 16, or 32 bits, though not all combinations of ISAs
neon-32 4 ARM NEON target, targeting computation and mask sizes are supported. For best performance, the best general
on 32-bit data types. approach is to choose a mask size equal to the size of the most common
sse2 4 SSE2 (early 2000s era x86 CPUs). datatype in your programs. For example, if most of your computation is on
sse2-x2 8 Double-pumped SSE2. 32-bit floating-point values, an ``i32`` target is appropriate. However,
sse4 4 SSE4 (generally 2008-2010 Intel CPUs). if you're mostly doing computation on 8-bit images, ``i8`` is a better choice.
sse4-x2 8 Double-pumped SSE4.
sse4-8 16 SSE4 target targeting computation on
8-bit data types.
sse4-16 8 SSE4 target targeting computation on
16-bit data types.
=========== ========= =======================================
See `Basic Concepts: Program Instances and Gangs of Program Instances`_ for See `Basic Concepts: Program Instances and Gangs of Program Instances`_ for
more discussion of the "gang size" and its implications for program more discussion of the "gang size" and its implications for program
execution. execution.
instruction sets. (As general context, SSE2 was first introduced in Running ``ispc --help`` and looking at the output for the ``--target``
processors that shipped in 2001, SSE4 was introduced in 2007, and option gives the most up-to-date documentation about which targets your
processors with AVX were introduced in 2010, and AVX2 arrived in 2013. compiler binary supports.
Consult your CPU's
manual for specifics on which vector instruction set it supports.) The naming scheme for compilation targets changed in August 2013; the
following table shows the relationship between names in the old scheme and
in the new scheme:
============= ===========
Target Former Name
------------- -----------
avx1-i32x8 avx, avx1
avx1-i32x16 avx-x2
avx1.1-i32x8 avx1.1
avx1.1-i32x16 avx1.1-x2
avx2-i32x8 avx2
avx2-i32x16 avx2-x2
neon-8 n/a
neon-16 n/a
neon-32 n/a
sse2-i32x4 sse2
sse2-i32x8 sse2-x2
sse4-i32x4 sse4
sse4-i32x8 sse4-x2
sse4-i8x16 n/a
sse4-i16x8 n/a
============= ===========
By default, the target instruction set is chosen based on the most capable By default, the target instruction set is chosen based on the most capable
one supported by the system on which you're running ``ispc``. You can one supported by the system on which you're running ``ispc``. You can
override this choice with the ``--target`` flag; for example, to select override this choice with the ``--target`` flag; for example, to select
Intel® SSE2, use ``--target=sse2``. (As with the other options in this Intel® SSE2 with a 32-bit mask and 4 program instances in a gang, use
section, see the output of ``ispc --help`` for a full list of supported ``--target=sse2-i32x4``. (As with the other options in this section, see
targets.) the output of ``ispc --help`` for a full list of supported targets.)
Generating Generic C++ Output Generating Generic C++ Output
----------------------------- -----------------------------

116
ispc.cpp
View File

@@ -106,7 +106,7 @@ static void __cpuidex(int info[4], int level, int count) {
static const char * static const char *
lGetSystemISA() { lGetSystemISA() {
#ifdef __arm__ #ifdef __arm__
return "neon-32"; return "neon-i32x4";
#else #else
int info[4]; int info[4];
__cpuid(info, 1); __cpuid(info, 1);
@@ -121,19 +121,19 @@ lGetSystemISA() {
int info2[4]; int info2[4];
__cpuidex(info2, 7, 0); __cpuidex(info2, 7, 0);
if ((info2[1] & (1 << 5)) != 0) if ((info2[1] & (1 << 5)) != 0)
return "avx2"; return "avx2-i32x8";
else else
return "avx1.1"; return "avx1.1-i32x8";
} }
// Regular AVX // Regular AVX
return "avx"; return "avx-i32x8";
} }
else if ((info[2] & (1 << 19)) != 0) else if ((info[2] & (1 << 19)) != 0)
return "sse4"; return "sse4-i32x4";
else if ((info[3] & (1 << 26)) != 0) else if ((info[3] & (1 << 26)) != 0)
return "sse2"; return "sse2-i32x4";
else { else {
fprintf(stderr, "Unable to detect supported SSE/AVX ISA. Exiting.\n"); Error(SourcePos(), "Unable to detect supported SSE/AVX ISA. Exiting.");
exit(1); exit(1);
} }
#endif #endif
@@ -186,22 +186,22 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
// If a CPU was specified explicitly, try to pick the best // If a CPU was specified explicitly, try to pick the best
// possible ISA based on that. // possible ISA based on that.
if (!strcmp(cpu, "core-avx2")) if (!strcmp(cpu, "core-avx2"))
isa = "avx2"; isa = "avx2-i32x8";
#ifdef ISPC_ARM_ENABLED #ifdef ISPC_ARM_ENABLED
else if (!strcmp(cpu, "cortex-a9") || else if (!strcmp(cpu, "cortex-a9") ||
!strcmp(cpu, "cortex-a15")) !strcmp(cpu, "cortex-a15"))
isa = "neon-32"; isa = "neon-i32x4";
#endif #endif
else if (!strcmp(cpu, "core-avx-i")) else if (!strcmp(cpu, "core-avx-i"))
isa = "avx1.1"; isa = "avx1.1-i32x8";
else if (!strcmp(cpu, "sandybridge") || else if (!strcmp(cpu, "sandybridge") ||
!strcmp(cpu, "corei7-avx")) !strcmp(cpu, "corei7-avx"))
isa = "avx"; isa = "avx-i32x8";
else if (!strcmp(cpu, "corei7") || else if (!strcmp(cpu, "corei7") ||
!strcmp(cpu, "penryn")) !strcmp(cpu, "penryn"))
isa = "sse4"; isa = "sse4-i32x4";
else else
isa = "sse2"; isa = "sse2-i32x4";
Warning(SourcePos(), "No --target specified on command-line. " Warning(SourcePos(), "No --target specified on command-line. "
"Using ISA \"%s\" based on specified CPU \"%s\".", isa, "Using ISA \"%s\" based on specified CPU \"%s\".", isa,
cpu); cpu);
@@ -211,7 +211,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
// supports. // supports.
isa = lGetSystemISA(); isa = lGetSystemISA();
Warning(SourcePos(), "No --target specified on command-line. " Warning(SourcePos(), "No --target specified on command-line. "
"Using system ISA \"%s\".", isa); "Using default system target \"%s\".", isa);
} }
} }
@@ -241,8 +241,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
} }
} }
if (foundCPU == false) { if (foundCPU == false) {
fprintf(stderr, "Error: CPU type \"%s\" unknown. Supported CPUs: " Error(SourcePos(), "Error: CPU type \"%s\" unknown. Supported CPUs: "
"%s.\n", cpu, SupportedTargetCPUs().c_str()); "%s.", cpu, SupportedCPUs().c_str());
return; return;
} }
} }
@@ -283,7 +283,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
} }
// Check default LLVM generated targets // Check default LLVM generated targets
if (!strcasecmp(isa, "sse2")) { if (!strcasecmp(isa, "sse2") ||
!strcasecmp(isa, "sse2-i32x4")) {
this->m_isa = Target::SSE2; this->m_isa = Target::SSE2;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 4; this->m_vectorWidth = 4;
@@ -291,7 +292,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "sse2-x2")) { else if (!strcasecmp(isa, "sse2-x2") ||
!strcasecmp(isa, "sse2-i32x8")) {
this->m_isa = Target::SSE2; this->m_isa = Target::SSE2;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -299,7 +301,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "sse4")) { else if (!strcasecmp(isa, "sse4") ||
!strcasecmp(isa, "sse4-i32x4")) {
this->m_isa = Target::SSE4; this->m_isa = Target::SSE4;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 4; this->m_vectorWidth = 4;
@@ -308,7 +311,9 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "sse4x2") || !strcasecmp(isa, "sse4-x2")) { else if (!strcasecmp(isa, "sse4x2") ||
!strcasecmp(isa, "sse4-x2") ||
!strcasecmp(isa, "sse4-i32x8")) {
this->m_isa = Target::SSE4; this->m_isa = Target::SSE4;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -316,7 +321,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "sse4-8")) { else if (!strcasecmp(isa, "sse4-i8x16")) {
this->m_isa = Target::SSE4; this->m_isa = Target::SSE4;
this->m_nativeVectorWidth = 16; this->m_nativeVectorWidth = 16;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -324,7 +329,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 8; this->m_maskBitCount = 8;
} }
else if (!strcasecmp(isa, "sse4-16")) { else if (!strcasecmp(isa, "sse4-i16x8")) {
this->m_isa = Target::SSE4; this->m_isa = Target::SSE4;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -332,7 +337,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 16; this->m_maskBitCount = 16;
} }
else if (!strcasecmp(isa, "generic-4")) { else if (!strcasecmp(isa, "generic-4") ||
!strcasecmp(isa, "generic-x4")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 4; this->m_vectorWidth = 4;
@@ -342,7 +348,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasTranscendentals = true; this->m_hasTranscendentals = true;
this->m_hasGather = this->m_hasScatter = true; this->m_hasGather = this->m_hasScatter = true;
} }
else if (!strcasecmp(isa, "generic-8")) { else if (!strcasecmp(isa, "generic-8") ||
!strcasecmp(isa, "generic-x8")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -352,7 +359,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasTranscendentals = true; this->m_hasTranscendentals = true;
this->m_hasGather = this->m_hasScatter = true; this->m_hasGather = this->m_hasScatter = true;
} }
else if (!strcasecmp(isa, "generic-16")) { else if (!strcasecmp(isa, "generic-16") ||
!strcasecmp(isa, "generic-x16")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 16; this->m_nativeVectorWidth = 16;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -362,7 +370,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasTranscendentals = true; this->m_hasTranscendentals = true;
this->m_hasGather = this->m_hasScatter = true; this->m_hasGather = this->m_hasScatter = true;
} }
else if (!strcasecmp(isa, "generic-32")) { else if (!strcasecmp(isa, "generic-32") ||
!strcasecmp(isa, "generic-x32")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 32; this->m_nativeVectorWidth = 32;
this->m_vectorWidth = 32; this->m_vectorWidth = 32;
@@ -372,7 +381,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasTranscendentals = true; this->m_hasTranscendentals = true;
this->m_hasGather = this->m_hasScatter = true; this->m_hasGather = this->m_hasScatter = true;
} }
else if (!strcasecmp(isa, "generic-64")) { else if (!strcasecmp(isa, "generic-64") ||
!strcasecmp(isa, "generic-x64")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 64; this->m_nativeVectorWidth = 64;
this->m_vectorWidth = 64; this->m_vectorWidth = 64;
@@ -382,14 +392,17 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasTranscendentals = true; this->m_hasTranscendentals = true;
this->m_hasGather = this->m_hasScatter = true; this->m_hasGather = this->m_hasScatter = true;
} }
else if (!strcasecmp(isa, "generic-1")) { else if (!strcasecmp(isa, "generic-1") ||
!strcasecmp(isa, "generic-x1")) {
this->m_isa = Target::GENERIC; this->m_isa = Target::GENERIC;
this->m_nativeVectorWidth = 1; this->m_nativeVectorWidth = 1;
this->m_vectorWidth = 1; this->m_vectorWidth = 1;
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "avx") || !strcasecmp(isa, "avx1")) { else if (!strcasecmp(isa, "avx") ||
!strcasecmp(isa, "avx1") ||
!strcasecmp(isa, "avx1-i32x8")) {
this->m_isa = Target::AVX; this->m_isa = Target::AVX;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -397,7 +410,9 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "avx-x2") || !strcasecmp(isa, "avx1-x2")) { else if (!strcasecmp(isa, "avx-x2") ||
!strcasecmp(isa, "avx1-x2") ||
!strcasecmp(isa, "avx1-i32x16")) {
this->m_isa = Target::AVX; this->m_isa = Target::AVX;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -405,7 +420,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 32; this->m_maskBitCount = 32;
} }
else if (!strcasecmp(isa, "avx1.1")) { else if (!strcasecmp(isa, "avx1.1") ||
!strcasecmp(isa, "avx1.1-i32x8")) {
this->m_isa = Target::AVX11; this->m_isa = Target::AVX11;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -418,7 +434,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasRand = true; this->m_hasRand = true;
#endif #endif
} }
else if (!strcasecmp(isa, "avx1.1-x2")) { else if (!strcasecmp(isa, "avx1.1-x2") ||
!strcasecmp(isa, "avx1.1-i32x16")) {
this->m_isa = Target::AVX11; this->m_isa = Target::AVX11;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -431,7 +448,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasRand = true; this->m_hasRand = true;
#endif #endif
} }
else if (!strcasecmp(isa, "avx2")) { else if (!strcasecmp(isa, "avx2") ||
!strcasecmp(isa, "avx2-i32x8")) {
this->m_isa = Target::AVX2; this->m_isa = Target::AVX2;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -449,7 +467,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_hasGather = true; this->m_hasGather = true;
#endif #endif
} }
else if (!strcasecmp(isa, "avx2-x2")) { else if (!strcasecmp(isa, "avx2-x2") ||
!strcasecmp(isa, "avx2-i32x16")) {
this->m_isa = Target::AVX2; this->m_isa = Target::AVX2;
this->m_nativeVectorWidth = 16; this->m_nativeVectorWidth = 16;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -468,7 +487,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
#endif #endif
} }
#ifdef ISPC_ARM_ENABLED #ifdef ISPC_ARM_ENABLED
else if (!strcasecmp(isa, "neon-8")) { else if (!strcasecmp(isa, "neon-i8x16")) {
this->m_isa = Target::NEON8; this->m_isa = Target::NEON8;
this->m_nativeVectorWidth = 16; this->m_nativeVectorWidth = 16;
this->m_vectorWidth = 16; this->m_vectorWidth = 16;
@@ -477,7 +496,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 8; this->m_maskBitCount = 8;
} }
else if (!strcasecmp(isa, "neon-16")) { else if (!strcasecmp(isa, "neon-i16x8")) {
this->m_isa = Target::NEON16; this->m_isa = Target::NEON16;
this->m_nativeVectorWidth = 8; this->m_nativeVectorWidth = 8;
this->m_vectorWidth = 8; this->m_vectorWidth = 8;
@@ -486,7 +505,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
this->m_maskingIsFree = false; this->m_maskingIsFree = false;
this->m_maskBitCount = 16; this->m_maskBitCount = 16;
} }
else if (!strcasecmp(isa, "neon-32") || !strcasecmp(isa, "neon")) { else if (!strcasecmp(isa, "neon") ||
!strcasecmp(isa, "neon-i32x4")) {
this->m_isa = Target::NEON32; this->m_isa = Target::NEON32;
this->m_nativeVectorWidth = 4; this->m_nativeVectorWidth = 4;
this->m_vectorWidth = 4; this->m_vectorWidth = 4;
@@ -497,8 +517,8 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
} }
#endif #endif
else { else {
fprintf(stderr, "Target ISA \"%s\" is unknown. Choices are: %s\n", Error(SourcePos(), "Target \"%s\" is unknown. Choices are: %s.",
isa, SupportedTargetISAs()); isa, SupportedTargets());
error = true; error = true;
} }
@@ -592,7 +612,7 @@ Target::Target(const char *arch, const char *cpu, const char *isa, bool pic) :
std::string std::string
Target::SupportedTargetCPUs() { Target::SupportedCPUs() {
std::string ret; std::string ret;
int count = sizeof(supportedCPUs) / sizeof(supportedCPUs[0]); int count = sizeof(supportedCPUs) / sizeof(supportedCPUs[0]);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
@@ -605,7 +625,7 @@ Target::SupportedTargetCPUs() {
const char * const char *
Target::SupportedTargetArchs() { Target::SupportedArchs() {
return return
#ifdef ISPC_ARM_ENABLED #ifdef ISPC_ARM_ENABLED
"arm, " "arm, "
@@ -615,14 +635,18 @@ Target::SupportedTargetArchs() {
const char * const char *
Target::SupportedTargetISAs() { Target::SupportedTargets() {
return return
#ifdef ISPC_ARM_ENABLED #ifdef ISPC_ARM_ENABLED
"neon-8, neon-16, neon-32, " "neon-i8x16, neon-16x8, neon-32x4, "
#endif #endif
"sse2, sse2-x2, sse4, sse4-8, sse4-16, sse4-x2, " "sse2-i32x4, sse2-i32x8, "
"avx, avx-x2, avx1.1, avx1.1-x2, avx2, avx2-x2, " "sse4-i32x4, sse4-i32x8, sse4-i16x8, sse4-i8x16, "
"generic-1, generic-4, generic-8, generic-16, generic-32"; "avx1-i32x8, avx1-i32x16, "
"avx1.1-i32x8, avx1.1-i32x16, "
"avx2-i32x8, avx2-i32x16, "
"generic-x1, generic-x4, generic-x8, generic-x16, "
"generic-x32, generic-x64";
} }

12
ispc.h
View File

@@ -192,16 +192,16 @@ public:
Target(const char *arch, const char *cpu, const char *isa, bool pic); Target(const char *arch, const char *cpu, const char *isa, bool pic);
/** Returns a comma-delimited string giving the names of the currently /** Returns a comma-delimited string giving the names of the currently
supported target ISAs. */ supported compilation targets. */
static const char *SupportedTargetISAs(); static const char *SupportedTargets();
/** Returns a comma-delimited string giving the names of the currently /** Returns a comma-delimited string giving the names of the currently
supported target CPUs. */ supported CPUs. */
static std::string SupportedTargetCPUs(); static std::string SupportedCPUs();
/** Returns a comma-delimited string giving the names of the currently /** Returns a comma-delimited string giving the names of the currently
supported target architectures. */ supported architectures. */
static const char *SupportedTargetArchs(); static const char *SupportedArchs();
/** Returns a triple string specifying the target architecture, vendor, /** Returns a triple string specifying the target architecture, vendor,
and environment. */ and environment. */

View File

@@ -85,13 +85,16 @@ usage(int ret) {
printf(" \t\taddressing calculations are done by default, even\n"); printf(" \t\taddressing calculations are done by default, even\n");
printf(" \t\ton 64-bit target architectures.)\n"); printf(" \t\ton 64-bit target architectures.)\n");
printf(" [--arch={%s}]\t\tSelect target architecture\n", printf(" [--arch={%s}]\t\tSelect target architecture\n",
Target::SupportedTargetArchs()); Target::SupportedArchs());
printf(" [--c++-include-file=<name>]\t\tSpecify name of file to emit in #include statement in generated C++ code.\n"); printf(" [--c++-include-file=<name>]\t\tSpecify name of file to emit in #include statement in generated C++ code.\n");
#ifndef ISPC_IS_WINDOWS #ifndef ISPC_IS_WINDOWS
printf(" [--colored-output]\t\tAlways use terminal colors in error/warning messages.\n"); printf(" [--colored-output]\t\tAlways use terminal colors in error/warning messages.\n");
#endif #endif
printf(" [--cpu=<cpu>]\t\t\tSelect target CPU type\n"); printf(" ");
printf(" <cpu>={%s}\n", Target::SupportedTargetCPUs().c_str()); char cpuHelp[2048];
sprintf(cpuHelp, "[--cpu=<cpu>]\t\t\tSelect target CPU type\n<cpu>={%s}\n",
Target::SupportedCPUs().c_str());
PrintWithWordBreaks(cpuHelp, 16, TerminalWidth(), stdout);
printf(" [-D<foo>]\t\t\t\t#define given value when running preprocessor\n"); printf(" [-D<foo>]\t\t\t\t#define given value when running preprocessor\n");
printf(" [--dev-stub <filename>]\t\tEmit device-side offload stub functions to file\n"); printf(" [--dev-stub <filename>]\t\tEmit device-side offload stub functions to file\n");
printf(" [--emit-asm]\t\t\tGenerate assembly language file as output\n"); printf(" [--emit-asm]\t\t\tGenerate assembly language file as output\n");
@@ -126,7 +129,11 @@ usage(int ret) {
printf(" [--pic]\t\t\t\tGenerate position-independent code\n"); printf(" [--pic]\t\t\t\tGenerate position-independent code\n");
#endif // !ISPC_IS_WINDOWS #endif // !ISPC_IS_WINDOWS
printf(" [--quiet]\t\t\t\tSuppress all output\n"); printf(" [--quiet]\t\t\t\tSuppress all output\n");
printf(" [--target=<isa>]\t\t\tSelect target ISA. <isa>={%s}\n", Target::SupportedTargetISAs()); printf(" ");
char targetHelp[2048];
sprintf(targetHelp, "[--target=<t>]\t\t\tSelect target ISA and width.\n"
"<t>={%s}", Target::SupportedTargets());
PrintWithWordBreaks(targetHelp, 24, TerminalWidth(), stdout);
printf(" [--version]\t\t\t\tPrint ispc version\n"); printf(" [--version]\t\t\t\tPrint ispc version\n");
printf(" [--werror]\t\t\t\tTreat warnings as errors\n"); printf(" [--werror]\t\t\t\tTreat warnings as errors\n");
printf(" [--woff]\t\t\t\tDisable warnings\n"); printf(" [--woff]\t\t\t\tDisable warnings\n");

View File

@@ -37,7 +37,7 @@ parser.add_option("-g", "--generics-include", dest="include_file", help="Filenam
parser.add_option("-f", "--ispc-flags", dest="ispc_flags", help="Additional flags for ispc (-g, -O1, ...)", parser.add_option("-f", "--ispc-flags", dest="ispc_flags", help="Additional flags for ispc (-g, -O1, ...)",
default="") default="")
parser.add_option('-t', '--target', dest='target', parser.add_option('-t', '--target', dest='target',
help='Set compilation target (neon8, neon16, neon32, sse2, sse2-x2, sse4, sse4-x2, sse4-8, sse4-16, avx, avx-x2, generic-4, generic-8, generic-16, generic-32)', help='Set compilation target (sse2-i32x4, sse2-i32x8, sse4-i32x4, sse4-i32x8, sse4-i16x8, sse4-i8x16, avx1-i32x8, avx1-i32x16, avx1.1-i32x8, avx1.1-i32x16, avx2-i32x8, avx2-i32x16, generic-x1, generic-x4, generic-x8, generic-x16, generic-x32, generic-x64)',
default="sse4") default="sse4")
parser.add_option('-a', '--arch', dest='arch', parser.add_option('-a', '--arch', dest='arch',
help='Set architecture (arm, x86, x86-64)', help='Set architecture (arm, x86, x86-64)',

View File

@@ -79,8 +79,8 @@
compiler under a debuffer; in this case, just return a reasonable compiler under a debuffer; in this case, just return a reasonable
default. default.
*/ */
static int int
lTerminalWidth() { TerminalWidth() {
if (g->disableLineWrap) if (g->disableLineWrap)
return 1<<30; return 1<<30;
@@ -228,8 +228,8 @@ lFindIndent(int numColons, const char *buf) {
/** Print the given string to the given FILE, assuming the given output /** Print the given string to the given FILE, assuming the given output
column width. Break words as needed to avoid words spilling past the column width. Break words as needed to avoid words spilling past the
last column. */ last column. */
static void void
lPrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out) { PrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out) {
#ifdef ISPC_IS_WINDOWS #ifdef ISPC_IS_WINDOWS
fputs(buf, out); fputs(buf, out);
fputs("\n", out); fputs("\n", out);
@@ -375,7 +375,7 @@ lPrint(const char *type, bool isError, SourcePos p, const char *fmt,
return; return;
printed.insert(formattedBuf); printed.insert(formattedBuf);
lPrintWithWordBreaks(formattedBuf, indent, lTerminalWidth(), stderr); PrintWithWordBreaks(formattedBuf, indent, TerminalWidth(), stderr);
lPrintFileLineContext(p); lPrintFileLineContext(p);
free(errorBuf); free(errorBuf);

14
util.h
View File

@@ -156,4 +156,18 @@ void GetDirectoryAndFileName(const std::string &currentDir,
bool VerifyDataLayoutCompatibility(const std::string &module_dl, bool VerifyDataLayoutCompatibility(const std::string &module_dl,
const std::string &lib_dl); const std::string &lib_dl);
/** Print the given string to the given FILE, assuming the given output
column width. Break words as needed to avoid words spilling past the
last column. */
void PrintWithWordBreaks(const char *buf, int indent, int columnWidth,
FILE *out);
/** Returns the width of the terminal where the compiler is running.
Finding this out may fail in a variety of reasonable situations (piping
compiler output to 'less', redirecting output to a file, running the
compiler under a debuffer; in this case, just return a reasonable
default.
*/
int TerminalWidth();
#endif // ISPC_UTIL_H #endif // ISPC_UTIL_H