Added structure alignment in headers; extended the test system to support alignment tests

This commit is contained in:
Andrey Guskov
2015-02-17 17:58:34 +03:00
parent 7477a95a59
commit ef9315200c
5 changed files with 118 additions and 22 deletions

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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
View 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
View 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);
}