Fixed issue with aliasing local variables

ISPC++ now produces valid code, or an appropriate error message, for all
of my test cases.
This commit is contained in:
2017-05-11 15:42:11 -04:00
parent bfe723e1b7
commit 5e6f06cf59
12 changed files with 135 additions and 25 deletions

View File

@@ -8099,6 +8099,11 @@ SymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
if (!symbol) if (!symbol)
return NULL; return NULL;
Symbol *tmp = m->symbolTable->LookupVariable(symbol->name.c_str());
if (tmp) {
tmp->parentFunction = symbol->parentFunction;
symbol = tmp;
}
if (Type::EqualForReplacement(symbol->type->GetBaseType(), from)) { if (Type::EqualForReplacement(symbol->type->GetBaseType(), from)) {
symbol->type = PolyType::ReplaceType(symbol->type, to); symbol->type = PolyType::ReplaceType(symbol->type, to);
@@ -8176,6 +8181,14 @@ FunctionSymbolExpr::Optimize() {
return this; return this;
} }
Expr *
FunctionSymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
// force re-evaluation of overloaded type
this->triedToResolve = false;
return this;
}
int int
FunctionSymbolExpr::EstimateCost() const { FunctionSymbolExpr::EstimateCost() const {
@@ -8422,6 +8435,16 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype,
cost[i] += 8 * costScale; cost[i] += 8 * costScale;
continue; continue;
} }
if (callTypeNC->IsPolymorphicType()) {
const PolyType *callTypeP =
CastType<PolyType>(callTypeNC->GetBaseType());
if (callTypeP->CanBeType(fargTypeNC->GetBaseType()) &&
callTypeNC->IsArrayType() == fargTypeNC->IsArrayType() &&
callTypeNC->IsPointerType() == fargTypeNC->IsPointerType()){
cost[i] += 8 * costScale;
continue;
}
}
if (fargType->IsVaryingType() && callType->IsUniformType()) { if (fargType->IsVaryingType() && callType->IsUniformType()) {
// Here we deal with brodcasting uniform to varying. // Here we deal with brodcasting uniform to varying.
// callType - varying and fargType - uniform is forbidden. // callType - varying and fargType - uniform is forbidden.
@@ -8548,6 +8571,12 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos,
return true; return true;
} }
else if (matches.size() > 1) { else if (matches.size() > 1) {
for (size_t i=0; i<argTypes.size(); i++) {
if (argTypes[i]->IsPolymorphicType()) {
matchingFunc = matches[0];
return true;
}
}
// Multiple matches: ambiguous // Multiple matches: ambiguous
std::string candidateMessage = std::string candidateMessage =
lGetOverloadCandidateMessage(matches, argTypes, argCouldBeNULL); lGetOverloadCandidateMessage(matches, argTypes, argCouldBeNULL);

1
expr.h
View File

@@ -761,6 +761,7 @@ public:
Symbol *GetBaseSymbol() const; Symbol *GetBaseSymbol() const;
Expr *TypeCheck(); Expr *TypeCheck();
Expr *Optimize(); Expr *Optimize();
Expr *ReplacePolyType(const PolyType *from, const Type *to);
void Print() const; void Print() const;
int EstimateCost() const; int EstimateCost() const;
llvm::Constant *GetConstant(const Type *type) const; llvm::Constant *GetConstant(const Type *type) const;

View File

@@ -90,7 +90,7 @@
#endif #endif
#include <llvm/Support/ToolOutputFile.h> #include <llvm/Support/ToolOutputFile.h>
Function::Function(Symbol *s, Stmt *c) { Function::Function(Symbol *s, Stmt *c, bool typecheck) {
sym = s; sym = s;
code = c; code = c;
@@ -98,6 +98,7 @@ Function::Function(Symbol *s, Stmt *c) {
Assert(maskSymbol != NULL); Assert(maskSymbol != NULL);
if (code != NULL) { if (code != NULL) {
if (typecheck) {
code = TypeCheck(code); code = TypeCheck(code);
if (code != NULL && g->debugPrint) { if (code != NULL && g->debugPrint) {
@@ -106,6 +107,7 @@ Function::Function(Symbol *s, Stmt *c) {
code->Print(0); code->Print(0);
printf("---------------------\n"); printf("---------------------\n");
} }
}
if (code != NULL) { if (code != NULL) {
code = Optimize(code); code = Optimize(code);
@@ -641,7 +643,6 @@ Function::IsPolyFunction() const {
return false; return false;
} }
std::vector<Function *> * std::vector<Function *> *
Function::ExpandPolyArguments(SymbolTable *symbolTable) const { Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
Assert(symbolTable != NULL); Assert(symbolTable != NULL);
@@ -659,30 +660,57 @@ Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
} }
const FunctionType *ft = CastType<FunctionType>(versions[i]->type); const FunctionType *ft = CastType<FunctionType>(versions[i]->type);
symbolTable->PushScope();
Symbol *s = symbolTable->LookupFunction(versions[i]->name.c_str(), ft);
Stmt *ncode = (Stmt*)CopyAST(code); Stmt *ncode = (Stmt*)CopyAST(code);
Function *f = new Function(s, ncode, false);
for (size_t j=0; j<args.size(); j++) {
f->args[j] = new Symbol(*args[j]);
symbolTable->AddVariable(f->args[j], false);
}
for (int j=0; j<ft->GetNumParameters(); j++) { for (int j=0; j<ft->GetNumParameters(); j++) {
if (func->GetParameterType(j)->IsPolymorphicType()) { if (func->GetParameterType(j)->IsPolymorphicType()) {
const PolyType *from = CastType<PolyType>( const PolyType *from = CastType<PolyType>(
func->GetParameterType(j)->GetBaseType()); func->GetParameterType(j)->GetBaseType());
ncode = (Stmt*)TranslatePoly(ncode, from, f->code = (Stmt*)TranslatePoly(f->code, from,
ft->GetParameterType(j)->GetBaseType()); ft->GetParameterType(j)->GetBaseType());
if (g->debugPrint) { if (g->debugPrint) {
printf("%s after replacing %s with %s:\n\n", printf("%s after replacing %s with %s:\n\n",
sym->name.c_str(), from->GetString().c_str(), sym->name.c_str(), from->GetString().c_str(),
ft->GetParameterType(j)->GetBaseType()->GetString().c_str()); ft->GetParameterType(j)->GetBaseType()->GetString().c_str());
ncode->Print(0); f->code->Print(0);
printf("------------------------------------------\n\n"); printf("------------------------------------------\n\n");
} }
} }
} }
Symbol *s = symbolTable->LookupFunction(versions[i]->name.c_str(), ft); // we didn't typecheck before, now we can
f->code = TypeCheck(f->code);
expanded->push_back(new Function(s, ncode)); f->code = Optimize(f->code);
if (g->debugPrint) {
printf("After optimizing expanded function \"%s\":\n",
f->sym->name.c_str());
f->code->Print(0);
printf("---------------------\n");
}
symbolTable->PopScope();
expanded->push_back(f);
} }
return expanded; return expanded;

2
func.h
View File

@@ -44,7 +44,7 @@
class Function { class Function {
public: public:
Function(Symbol *sym, Stmt *code); Function(Symbol *sym, Stmt *code, bool typecheck=true);
const Type *GetReturnType() const; const Type *GetReturnType() const;
const FunctionType *GetType() const; const FunctionType *GetType() const;

View File

@@ -559,7 +559,8 @@ DeclStmt::TypeCheck() {
// an int as the constValue later... // an int as the constValue later...
const Type *type = vars[i].sym->type; const Type *type = vars[i].sym->type;
if (CastType<AtomicType>(type) != NULL || if (CastType<AtomicType>(type) != NULL ||
CastType<EnumType>(type) != NULL) { CastType<EnumType>(type) != NULL ||
CastType<PolyType>(type) != NULL) {
// If it's an expr list with an atomic type, we'll later issue // If it's an expr list with an atomic type, we'll later issue
// an error. Need to leave vars[i].init as is in that case so // an error. Need to leave vars[i].init as is in that case so
// it is in fact caught later, though. // it is in fact caught later, though.
@@ -577,9 +578,15 @@ DeclStmt::TypeCheck() {
Stmt * Stmt *
DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) { DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) {
for (size_t i = 0; i < vars.size(); i++) { for (size_t i = 0; i < vars.size(); i++) {
vars[i].sym = new Symbol(*vars[i].sym);
m->symbolTable->AddVariable(vars[i].sym, false);
Symbol *s = vars[i].sym; Symbol *s = vars[i].sym;
if (Type::EqualForReplacement(s->type->GetBaseType(), from)) { if (Type::EqualForReplacement(s->type->GetBaseType(), from)) {
s->type = PolyType::ReplaceType(s->type, to); s->type = PolyType::ReplaceType(s->type, to);
// this typecast *should* be valid after typechecking
vars[i].init = TypeConvertExpr(vars[i].init, s->type,
"initializer");
} }
} }

View File

@@ -95,14 +95,14 @@ SymbolTable::PopScope() {
bool bool
SymbolTable::AddVariable(Symbol *symbol) { SymbolTable::AddVariable(Symbol *symbol, bool issueScopeWarning) {
Assert(symbol != NULL); Assert(symbol != NULL);
// Check to see if a symbol of the same name has already been declared. // Check to see if a symbol of the same name has already been declared.
for (int i = (int)variables.size() - 1; i >= 0; --i) { for (int i = (int)variables.size() - 1; i >= 0; --i) {
SymbolMapType &sm = *(variables[i]); SymbolMapType &sm = *(variables[i]);
if (sm.find(symbol->name) != sm.end()) { if (sm.find(symbol->name) != sm.end()) {
if (i == (int)variables.size()-1) { if (i == (int)variables.size()-1 && issueScopeWarning) {
// If a symbol of the same name was declared in the // If a symbol of the same name was declared in the
// same scope, it's an error. // same scope, it's an error.
Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".", Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".",
@@ -112,9 +112,11 @@ SymbolTable::AddVariable(Symbol *symbol) {
else { else {
// Otherwise it's just shadowing something else, which // Otherwise it's just shadowing something else, which
// is legal but dangerous.. // is legal but dangerous..
if (issueScopeWarning) {
Warning(symbol->pos, Warning(symbol->pos,
"Symbol \"%s\" shadows symbol declared in outer scope.", "Symbol \"%s\" shadows symbol declared in outer scope.",
symbol->name.c_str()); symbol->name.c_str());
}
(*variables.back())[symbol->name] = symbol; (*variables.back())[symbol->name] = symbol;
return true; return true;
} }

2
sym.h
View File

@@ -141,7 +141,7 @@ public:
with a symbol defined at the same scope. (Symbols may shaodow with a symbol defined at the same scope. (Symbols may shaodow
symbols in outer scopes; a warning is issued in this case, but this symbols in outer scopes; a warning is issued in this case, but this
method still returns true.) */ method still returns true.) */
bool AddVariable(Symbol *symbol); bool AddVariable(Symbol *symbol, bool issueScopeWarning=true);
/** Looks for a variable with the given name in the symbol table. This /** Looks for a variable with the given name in the symbol table. This
method searches outward from the innermost scope to the outermost, method searches outward from the innermost scope to the outermost,

View File

@@ -1,5 +1,5 @@
CXX=g++ CXX=g++
CXXFLAGS=-std=c++11 CXXFLAGS=-std=c++11 -O2
ISPC=../ispc ISPC=../ispc
ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64 ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64

View File

@@ -1,7 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include "hello.ispc.h" #include "hello.h"
int main() { int main() {
float A[100]; float A[100];

27
tests_ispcpp/varying.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include <stdlib.h>
#include <stdio.h>
#include "varying.h"
int main() {
float A[256];
double B[256];
double outA[256];
double outB[256];
for (int i=0; i<256; i++) {
A[i] = 1. / (i+1);
B[i] = 1. / (i+1);
}
ispc::square(256, (float*)&A, (double*)&outA);
ispc::square(256, (double*)&B, (double*)&outB);
for (int i=0; i<256; i++) {
printf("float: %.16f\tdouble: %.16f\n", outA[i], outB[i]);
}
return 0;
}

14
tests_ispcpp/varying.ispc Normal file
View File

@@ -0,0 +1,14 @@
floating foo(const uniform int a, floating b) {
floating out = b;
for (int i = 1; i<a; i++) {
out *= b;
}
return out;
}
export void square(uniform int N, uniform floating b[], uniform double out[]) {
foreach (i = 0 ... N) {
out[i] = foo(2, b[i]);
}
}

View File

@@ -721,9 +721,11 @@ PolyType::ReplaceType(const Type *from, const Type *to) {
if (from->IsVaryingType()) if (from->IsVaryingType())
t = t->GetAsVaryingType(); t = t->GetAsVaryingType();
if (g->debugPrint) {
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n", fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
from->GetString().c_str(), from->GetString().c_str(),
t->GetString().c_str()); t->GetString().c_str());
}
return t; return t;
} }