Added structure alignment in headers; extended the test system to support alignment tests
This commit is contained in:
63
module.cpp
63
module.cpp
@@ -1486,22 +1486,49 @@ lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedSt
|
||||
fprintf(file, "#ifndef __ISPC_STRUCT_%s__\n",st->GetCStructName().c_str());
|
||||
fprintf(file, "#define __ISPC_STRUCT_%s__\n",st->GetCStructName().c_str());
|
||||
|
||||
fprintf(file, "struct %s", st->GetCStructName().c_str());
|
||||
char sSOA[48];
|
||||
bool pack, needsAlign = false;
|
||||
llvm::Type *stype = st->LLVMType(g->ctx);
|
||||
llvm::DataLayout *DL = g->target->getDataLayout();
|
||||
|
||||
if (!(pack = llvm::dyn_cast<llvm::StructType>(stype)->isPacked()))
|
||||
for (int i = 0; !needsAlign && (i < st->GetElementCount()); ++i) {
|
||||
const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
|
||||
needsAlign |= ftype->IsVaryingType()
|
||||
&& (CastType<StructType>(ftype) == NULL);
|
||||
}
|
||||
if (st->GetSOAWidth() > 0)
|
||||
// This has to match the naming scheme in
|
||||
// StructType::GetCDeclaration().
|
||||
fprintf(file, "_SOA%d", st->GetSOAWidth());
|
||||
fprintf(file, " {\n");
|
||||
|
||||
sprintf(sSOA, "_SOA%d", st->GetSOAWidth());
|
||||
else
|
||||
*sSOA = '\0';
|
||||
if (!needsAlign)
|
||||
fprintf(file, "%sstruct %s%s {\n", (pack)? "packed " : "",
|
||||
st->GetCStructName().c_str(), sSOA);
|
||||
else {
|
||||
unsigned uABI = DL->getABITypeAlignment(stype);
|
||||
fprintf(file, "__ISPC_ALIGNED_STRUCT__(%u) %s%s {\n", uABI,
|
||||
st->GetCStructName().c_str(), sSOA);
|
||||
}
|
||||
for (int i = 0; i < st->GetElementCount(); ++i) {
|
||||
const Type *type = st->GetElementType(i)->GetAsNonConstType();
|
||||
std::string d = type->GetCDeclaration(st->GetElementName(i));
|
||||
// Don't expand struct members as their insides will be expanded.
|
||||
if (type->IsVaryingType() && (CastType<StructType>(type) == NULL)) {
|
||||
fprintf(file, " %s[%d];\n", d.c_str(), g->target->getVectorWidth());
|
||||
const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
|
||||
std::string d = ftype->GetCDeclaration(st->GetElementName(i));
|
||||
|
||||
fprintf(file, " ");
|
||||
if (needsAlign && ftype->IsVaryingType() &&
|
||||
(CastType<StructType>(ftype) == NULL)) {
|
||||
unsigned uABI = DL->getABITypeAlignment(ftype->LLVMType(g->ctx));
|
||||
fprintf(file, "__ISPC_ALIGN__(%u) ", uABI);
|
||||
}
|
||||
// Don't expand arrays, pointers and structures:
|
||||
// their insides will be expanded automatically.
|
||||
if (!ftype->IsArrayType() && !ftype->IsPointerType() &&
|
||||
ftype->IsVaryingType() && (CastType<StructType>(ftype) == NULL)) {
|
||||
fprintf(file, "%s[%d];\n", d.c_str(), g->target->getVectorWidth());
|
||||
}
|
||||
else {
|
||||
fprintf(file, " %s;\n", d.c_str());
|
||||
fprintf(file, "%s;\n", d.c_str());
|
||||
}
|
||||
}
|
||||
fprintf(file, "};\n");
|
||||
@@ -1515,8 +1542,22 @@ lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedSt
|
||||
static void
|
||||
lEmitStructDecls(std::vector<const StructType *> &structTypes, FILE *file, bool emitUnifs=true) {
|
||||
std::vector<const StructType *> emittedStructs;
|
||||
|
||||
fprintf(file,
|
||||
"\n#ifndef __ISPC_ALIGN__\n"
|
||||
"#if defined(__clang__) || !defined(_MSC_VER)\n"
|
||||
"// Clang, GCC, ICC\n"
|
||||
"#define __ISPC_ALIGN__(s) __attribute__((aligned(s)))\n"
|
||||
"#define __ISPC_ALIGNED_STRUCT__(s) struct __ISPC_ALIGN__(s)\n"
|
||||
"#else\n"
|
||||
"// Visual Studio\n"
|
||||
"#define __ISPC_ALIGN__(s) __declspec(align(s))\n"
|
||||
"#define __ISPC_ALIGNED_STRUCT__(s) __ISPC_ALIGN__(s) struct\n"
|
||||
"#endif\n"
|
||||
"#endif\n\n");
|
||||
|
||||
for (unsigned int i = 0; i < structTypes.size(); ++i)
|
||||
lEmitStructDecl(structTypes[i], &emittedStructs, file, emitUnifs);
|
||||
lEmitStructDecl(structTypes[i], &emittedStructs, file, emitUnifs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
run_tests.py
10
run_tests.py
@@ -194,8 +194,8 @@ def run_test(testname):
|
||||
|
||||
# We need to figure out the signature of the test
|
||||
# function that this test has.
|
||||
sig2def = { "f_v(" : 0, "f_f(" : 1, "f_fu(" : 2, "f_fi(" : 3,
|
||||
"f_du(" : 4, "f_duf(" : 5, "f_di(" : 6 }
|
||||
sig2def = { "f_v(" : 0, "f_f(" : 1, "f_fu(" : 2, "f_fi(" : 3,
|
||||
"f_du(" : 4, "f_duf(" : 5, "f_di(" : 6, "f_sz" : 7 }
|
||||
file = open(filename, 'r')
|
||||
match = -1
|
||||
for line in file:
|
||||
@@ -310,16 +310,16 @@ def run_test(testname):
|
||||
ispc_cmd = ispc_exe_rel + " --woff %s -o %s -O3 --emit-asm --target=%s" % \
|
||||
(filename4ptx, obj_name, options.target)
|
||||
|
||||
|
||||
|
||||
|
||||
# compile the ispc code, make the executable, and run it...
|
||||
ispc_cmd += " -h " + filename + ".h"
|
||||
cc_cmd += " -DTEST_HEADER=<" + filename + ".h>"
|
||||
(compile_error, run_error) = run_cmds([ispc_cmd, cc_cmd],
|
||||
options.wrapexe + " " + exe_name, \
|
||||
testname, should_fail)
|
||||
|
||||
# clean up after running the test
|
||||
try:
|
||||
os.unlink(filename + ".h")
|
||||
if not options.save_bin:
|
||||
if not run_error:
|
||||
os.unlink(exe_name)
|
||||
|
||||
@@ -51,6 +51,16 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if (TEST_SIG == 7)
|
||||
#define varying_f_sz f_sz
|
||||
#define v1_varying_f_sz f_sz
|
||||
#define v2_varying_f_sz f_sz
|
||||
#define v4_varying_f_sz f_sz
|
||||
#define v8_varying_f_sz f_sz
|
||||
#define v16_varying_f_sz f_sz
|
||||
#include TEST_HEADER
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern int width();
|
||||
extern void f_v(float *result);
|
||||
@@ -103,7 +113,7 @@ void *ISPCAlloc(void **handle, int64_t size, int32_t alignment) {
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define ALIGN
|
||||
#define ALIGN __declspec(align(64))
|
||||
#else
|
||||
#define ALIGN __attribute__((aligned(64)))
|
||||
#endif
|
||||
@@ -112,11 +122,11 @@ int main(int argc, char *argv[]) {
|
||||
int w = width();
|
||||
assert(w <= 64);
|
||||
|
||||
float returned_result[64] ALIGN;
|
||||
float vfloat[64] ALIGN;
|
||||
double vdouble[64] ALIGN;
|
||||
int vint[64] ALIGN;
|
||||
int vint2[64] ALIGN;
|
||||
ALIGN float returned_result[64];
|
||||
ALIGN float vfloat[64];
|
||||
ALIGN double vdouble[64];
|
||||
ALIGN int vint[64];
|
||||
ALIGN int vint2[64];
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
returned_result[i] = -1e20;
|
||||
@@ -142,6 +152,8 @@ int main(int argc, char *argv[]) {
|
||||
f_duf(returned_result, vdouble, 5.f);
|
||||
#elif (TEST_SIG == 6)
|
||||
f_di(returned_result, vdouble, vint2);
|
||||
#elif (TEST_SIG == 7)
|
||||
*returned_result = sizeof(ispc::f_sz);
|
||||
#else
|
||||
#error "Unknown or unset TEST_SIG value"
|
||||
#endif
|
||||
|
||||
22
tests/align1.ispc
Normal file
22
tests/align1.ispc
Normal file
@@ -0,0 +1,22 @@
|
||||
struct InnerUniform {
|
||||
uniform int i;
|
||||
};
|
||||
|
||||
struct f_sz {
|
||||
uniform int type, temp[5];
|
||||
int k[3];
|
||||
InnerUniform u;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export void keep_struct_declared(varying f_sz * uniform s) {
|
||||
}
|
||||
|
||||
export uniform int width() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[0] = sizeof(f_sz);
|
||||
}
|
||||
21
tests/align2.ispc
Normal file
21
tests/align2.ispc
Normal file
@@ -0,0 +1,21 @@
|
||||
struct InnerVec {
|
||||
int i;
|
||||
};
|
||||
|
||||
struct f_sz {
|
||||
InnerVec u;
|
||||
uniform int tail;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export void keep_struct_declared(varying f_sz * uniform s) {
|
||||
}
|
||||
|
||||
export uniform int width() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[0] = sizeof(f_sz);
|
||||
}
|
||||
Reference in New Issue
Block a user