10 Commits

Author SHA1 Message Date
1633d50b34 AVX2 2020-02-27 21:09:45 -08:00
b8453b4a3a update bison 2019-07-14 12:48:50 -07:00
1eb64a13e1 A an array of tests 2017-05-12 12:33:51 -04:00
2921430e45 Cleaning up tests and printing for demo 2017-05-11 21:16:08 -04:00
34d26554bf use correct abs function for doubles 2017-05-11 16:28:11 -04:00
5c0911c2a8 add missing dependency for timing test 2017-05-11 16:25:07 -04:00
f513e085ea Add sqrt tests from assignment 1 2017-05-11 16:22:18 -04:00
a47cab4dfa Replicates all needed state between expanded functions
commit 5e6f06cf59
Author: Aaron Gutierrez <gutierrez.aaron.m@gmail.com>
Date:   Thu May 11 15:42:11 2017 -0400

    Fixed issue with aliasing local variables

    ISPC++ now produces valid code, or an appropriate error message, for all
    of my test cases.

commit bfe723e1b7
Author: Aaron Gutierrez <gutierrez.aaron.m@gmail.com>
Date:   Thu May 11 03:09:38 2017 -0400

    Actually copy the AST.

    Type replacement works except for function parameters.

commit f65b3e6300
Author: Aaron Gutierrez <gutierrez.aaron.m@gmail.com>
Date:   Thu May 11 01:19:50 2017 -0400

    [WIP] Remove cases for ForeachStmt and SymbolExpr

commit 2e28640860
Merge: 6a91c5d d020107
Author: Aaron Gutierrez <gutierrez.aaron.m@gmail.com>
Date:   Wed May 10 23:13:40 2017 -0400

    Merge branch 'master' into copy_ast

commit 6a91c5d5ac
Author: Aaron Gutierrez <gutierrez.aaron.m@gmail.com>
Date:   Wed May 10 11:11:39 2017 -0400

    Attempt to replicate AST when expanding polytypes
2017-05-11 15:43:29 -04:00
d020107d91 Typechecking fixes, moved some printing behind debug flag 2017-05-10 23:12:48 -04:00
ab29965d75 force add cpp file for test 2017-05-10 14:25:39 -04:00
27 changed files with 1015 additions and 183 deletions

120
ast.cpp
View File

@@ -86,7 +86,7 @@ AST::GenerateIR() {
ASTNode *
WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
void *data) {
void *data, ASTPostCallBackFunc preUpdate) {
if (node == NULL)
return node;
@@ -97,6 +97,10 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
return node;
}
if (preUpdate != NULL) {
node = preUpdate(node, data);
}
////////////////////////////////////////////////////////////////////////////
// Handle Statements
if (llvm::dyn_cast<Stmt>(node) != NULL) {
@@ -120,54 +124,54 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
UnmaskedStmt *ums;
if ((es = llvm::dyn_cast<ExprStmt>(node)) != NULL)
es->expr = (Expr *)WalkAST(es->expr, preFunc, postFunc, data);
es->expr = (Expr *)WalkAST(es->expr, preFunc, postFunc, data, preUpdate);
else if ((ds = llvm::dyn_cast<DeclStmt>(node)) != NULL) {
for (unsigned int i = 0; i < ds->vars.size(); ++i)
ds->vars[i].init = (Expr *)WalkAST(ds->vars[i].init, preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if ((is = llvm::dyn_cast<IfStmt>(node)) != NULL) {
is->test = (Expr *)WalkAST(is->test, preFunc, postFunc, data);
is->test = (Expr *)WalkAST(is->test, preFunc, postFunc, data, preUpdate);
is->trueStmts = (Stmt *)WalkAST(is->trueStmts, preFunc,
postFunc, data);
postFunc, data, preUpdate);
is->falseStmts = (Stmt *)WalkAST(is->falseStmts, preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if ((dos = llvm::dyn_cast<DoStmt>(node)) != NULL) {
dos->testExpr = (Expr *)WalkAST(dos->testExpr, preFunc,
postFunc, data);
postFunc, data, preUpdate);
dos->bodyStmts = (Stmt *)WalkAST(dos->bodyStmts, preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if ((fs = llvm::dyn_cast<ForStmt>(node)) != NULL) {
fs->init = (Stmt *)WalkAST(fs->init, preFunc, postFunc, data);
fs->test = (Expr *)WalkAST(fs->test, preFunc, postFunc, data);
fs->step = (Stmt *)WalkAST(fs->step, preFunc, postFunc, data);
fs->stmts = (Stmt *)WalkAST(fs->stmts, preFunc, postFunc, data);
fs->init = (Stmt *)WalkAST(fs->init, preFunc, postFunc, data, preUpdate);
fs->test = (Expr *)WalkAST(fs->test, preFunc, postFunc, data, preUpdate);
fs->step = (Stmt *)WalkAST(fs->step, preFunc, postFunc, data, preUpdate);
fs->stmts = (Stmt *)WalkAST(fs->stmts, preFunc, postFunc, data, preUpdate);
}
else if ((fes = llvm::dyn_cast<ForeachStmt>(node)) != NULL) {
for (unsigned int i = 0; i < fes->startExprs.size(); ++i)
fes->startExprs[i] = (Expr *)WalkAST(fes->startExprs[i], preFunc,
postFunc, data);
postFunc, data, preUpdate);
for (unsigned int i = 0; i < fes->endExprs.size(); ++i)
fes->endExprs[i] = (Expr *)WalkAST(fes->endExprs[i], preFunc,
postFunc, data);
fes->stmts = (Stmt *)WalkAST(fes->stmts, preFunc, postFunc, data);
postFunc, data, preUpdate);
fes->stmts = (Stmt *)WalkAST(fes->stmts, preFunc, postFunc, data, preUpdate);
}
else if ((fas = llvm::dyn_cast<ForeachActiveStmt>(node)) != NULL) {
fas->stmts = (Stmt *)WalkAST(fas->stmts, preFunc, postFunc, data);
fas->stmts = (Stmt *)WalkAST(fas->stmts, preFunc, postFunc, data, preUpdate);
}
else if ((fus = llvm::dyn_cast<ForeachUniqueStmt>(node)) != NULL) {
fus->expr = (Expr *)WalkAST(fus->expr, preFunc, postFunc, data);
fus->stmts = (Stmt *)WalkAST(fus->stmts, preFunc, postFunc, data);
fus->expr = (Expr *)WalkAST(fus->expr, preFunc, postFunc, data, preUpdate);
fus->stmts = (Stmt *)WalkAST(fus->stmts, preFunc, postFunc, data, preUpdate);
}
else if ((cs = llvm::dyn_cast<CaseStmt>(node)) != NULL)
cs->stmts = (Stmt *)WalkAST(cs->stmts, preFunc, postFunc, data);
cs->stmts = (Stmt *)WalkAST(cs->stmts, preFunc, postFunc, data, preUpdate);
else if ((defs = llvm::dyn_cast<DefaultStmt>(node)) != NULL)
defs->stmts = (Stmt *)WalkAST(defs->stmts, preFunc, postFunc, data);
defs->stmts = (Stmt *)WalkAST(defs->stmts, preFunc, postFunc, data, preUpdate);
else if ((ss = llvm::dyn_cast<SwitchStmt>(node)) != NULL) {
ss->expr = (Expr *)WalkAST(ss->expr, preFunc, postFunc, data);
ss->stmts = (Stmt *)WalkAST(ss->stmts, preFunc, postFunc, data);
ss->expr = (Expr *)WalkAST(ss->expr, preFunc, postFunc, data, preUpdate);
ss->stmts = (Stmt *)WalkAST(ss->stmts, preFunc, postFunc, data, preUpdate);
}
else if (llvm::dyn_cast<BreakStmt>(node) != NULL ||
llvm::dyn_cast<ContinueStmt>(node) != NULL ||
@@ -175,22 +179,22 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
// nothing
}
else if ((ls = llvm::dyn_cast<LabeledStmt>(node)) != NULL)
ls->stmt = (Stmt *)WalkAST(ls->stmt, preFunc, postFunc, data);
ls->stmt = (Stmt *)WalkAST(ls->stmt, preFunc, postFunc, data, preUpdate);
else if ((rs = llvm::dyn_cast<ReturnStmt>(node)) != NULL)
rs->expr = (Expr *)WalkAST(rs->expr, preFunc, postFunc, data);
rs->expr = (Expr *)WalkAST(rs->expr, preFunc, postFunc, data, preUpdate);
else if ((sl = llvm::dyn_cast<StmtList>(node)) != NULL) {
std::vector<Stmt *> &sls = sl->stmts;
for (unsigned int i = 0; i < sls.size(); ++i)
sls[i] = (Stmt *)WalkAST(sls[i], preFunc, postFunc, data);
sls[i] = (Stmt *)WalkAST(sls[i], preFunc, postFunc, data, preUpdate);
}
else if ((ps = llvm::dyn_cast<PrintStmt>(node)) != NULL)
ps->values = (Expr *)WalkAST(ps->values, preFunc, postFunc, data);
ps->values = (Expr *)WalkAST(ps->values, preFunc, postFunc, data, preUpdate);
else if ((as = llvm::dyn_cast<AssertStmt>(node)) != NULL)
as->expr = (Expr *)WalkAST(as->expr, preFunc, postFunc, data);
as->expr = (Expr *)WalkAST(as->expr, preFunc, postFunc, data, preUpdate);
else if ((dels = llvm::dyn_cast<DeleteStmt>(node)) != NULL)
dels->expr = (Expr *)WalkAST(dels->expr, preFunc, postFunc, data);
dels->expr = (Expr *)WalkAST(dels->expr, preFunc, postFunc, data, preUpdate);
else if ((ums = llvm::dyn_cast<UnmaskedStmt>(node)) != NULL)
ums->stmts = (Stmt *)WalkAST(ums->stmts, preFunc, postFunc, data);
ums->stmts = (Stmt *)WalkAST(ums->stmts, preFunc, postFunc, data, preUpdate);
else
FATAL("Unhandled statement type in WalkAST()");
}
@@ -215,57 +219,57 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
NewExpr *newe;
if ((ue = llvm::dyn_cast<UnaryExpr>(node)) != NULL)
ue->expr = (Expr *)WalkAST(ue->expr, preFunc, postFunc, data);
ue->expr = (Expr *)WalkAST(ue->expr, preFunc, postFunc, data, preUpdate);
else if ((be = llvm::dyn_cast<BinaryExpr>(node)) != NULL) {
be->arg0 = (Expr *)WalkAST(be->arg0, preFunc, postFunc, data);
be->arg1 = (Expr *)WalkAST(be->arg1, preFunc, postFunc, data);
be->arg0 = (Expr *)WalkAST(be->arg0, preFunc, postFunc, data, preUpdate);
be->arg1 = (Expr *)WalkAST(be->arg1, preFunc, postFunc, data, preUpdate);
}
else if ((ae = llvm::dyn_cast<AssignExpr>(node)) != NULL) {
ae->lvalue = (Expr *)WalkAST(ae->lvalue, preFunc, postFunc, data);
ae->rvalue = (Expr *)WalkAST(ae->rvalue, preFunc, postFunc, data);
ae->lvalue = (Expr *)WalkAST(ae->lvalue, preFunc, postFunc, data, preUpdate);
ae->rvalue = (Expr *)WalkAST(ae->rvalue, preFunc, postFunc, data, preUpdate);
}
else if ((se = llvm::dyn_cast<SelectExpr>(node)) != NULL) {
se->test = (Expr *)WalkAST(se->test, preFunc, postFunc, data);
se->expr1 = (Expr *)WalkAST(se->expr1, preFunc, postFunc, data);
se->expr2 = (Expr *)WalkAST(se->expr2, preFunc, postFunc, data);
se->test = (Expr *)WalkAST(se->test, preFunc, postFunc, data, preUpdate);
se->expr1 = (Expr *)WalkAST(se->expr1, preFunc, postFunc, data, preUpdate);
se->expr2 = (Expr *)WalkAST(se->expr2, preFunc, postFunc, data, preUpdate);
}
else if ((el = llvm::dyn_cast<ExprList>(node)) != NULL) {
for (unsigned int i = 0; i < el->exprs.size(); ++i)
el->exprs[i] = (Expr *)WalkAST(el->exprs[i], preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if ((fce = llvm::dyn_cast<FunctionCallExpr>(node)) != NULL) {
fce->func = (Expr *)WalkAST(fce->func, preFunc, postFunc, data);
fce->args = (ExprList *)WalkAST(fce->args, preFunc, postFunc, data);
fce->func = (Expr *)WalkAST(fce->func, preFunc, postFunc, data, preUpdate);
fce->args = (ExprList *)WalkAST(fce->args, preFunc, postFunc, data, preUpdate);
for (int k = 0; k < 3; k++)
fce->launchCountExpr[0] = (Expr *)WalkAST(fce->launchCountExpr[0], preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if ((ie = llvm::dyn_cast<IndexExpr>(node)) != NULL) {
ie->baseExpr = (Expr *)WalkAST(ie->baseExpr, preFunc, postFunc, data);
ie->index = (Expr *)WalkAST(ie->index, preFunc, postFunc, data);
ie->baseExpr = (Expr *)WalkAST(ie->baseExpr, preFunc, postFunc, data, preUpdate);
ie->index = (Expr *)WalkAST(ie->index, preFunc, postFunc, data, preUpdate);
}
else if ((me = llvm::dyn_cast<MemberExpr>(node)) != NULL)
me->expr = (Expr *)WalkAST(me->expr, preFunc, postFunc, data);
me->expr = (Expr *)WalkAST(me->expr, preFunc, postFunc, data, preUpdate);
else if ((tce = llvm::dyn_cast<TypeCastExpr>(node)) != NULL)
tce->expr = (Expr *)WalkAST(tce->expr, preFunc, postFunc, data);
tce->expr = (Expr *)WalkAST(tce->expr, preFunc, postFunc, data, preUpdate);
else if ((re = llvm::dyn_cast<ReferenceExpr>(node)) != NULL)
re->expr = (Expr *)WalkAST(re->expr, preFunc, postFunc, data);
re->expr = (Expr *)WalkAST(re->expr, preFunc, postFunc, data, preUpdate);
else if ((ptrderef = llvm::dyn_cast<PtrDerefExpr>(node)) != NULL)
ptrderef->expr = (Expr *)WalkAST(ptrderef->expr, preFunc, postFunc,
data);
data, preUpdate);
else if ((refderef = llvm::dyn_cast<RefDerefExpr>(node)) != NULL)
refderef->expr = (Expr *)WalkAST(refderef->expr, preFunc, postFunc,
data);
data, preUpdate);
else if ((soe = llvm::dyn_cast<SizeOfExpr>(node)) != NULL)
soe->expr = (Expr *)WalkAST(soe->expr, preFunc, postFunc, data);
soe->expr = (Expr *)WalkAST(soe->expr, preFunc, postFunc, data, preUpdate);
else if ((aoe = llvm::dyn_cast<AddressOfExpr>(node)) != NULL)
aoe->expr = (Expr *)WalkAST(aoe->expr, preFunc, postFunc, data);
aoe->expr = (Expr *)WalkAST(aoe->expr, preFunc, postFunc, data, preUpdate);
else if ((newe = llvm::dyn_cast<NewExpr>(node)) != NULL) {
newe->countExpr = (Expr *)WalkAST(newe->countExpr, preFunc,
postFunc, data);
postFunc, data, preUpdate);
newe->initExpr = (Expr *)WalkAST(newe->initExpr, preFunc,
postFunc, data);
postFunc, data, preUpdate);
}
else if (llvm::dyn_cast<SymbolExpr>(node) != NULL ||
llvm::dyn_cast<ConstExpr>(node) != NULL ||
@@ -536,11 +540,21 @@ lTranslatePolyNode(ASTNode *node, void *d) {
return node->ReplacePolyType(data->polyType, data->replacement);
}
static ASTNode *
lCopyNode(ASTNode *node, void *) {
return node->Copy();
}
ASTNode *
TranslatePoly(ASTNode *root, const PolyType *polyType, const Type *replacement) {
struct PolyData data;
data.polyType = polyType;
data.replacement = replacement;
return WalkAST(root, NULL, lTranslatePolyNode, &data);
return WalkAST(root, NULL, lTranslatePolyNode, &data, lCopyNode);
}
ASTNode *
CopyAST(ASTNode *root) {
return WalkAST(root, NULL, NULL, NULL, lCopyNode);
}

7
ast.h
View File

@@ -68,6 +68,8 @@ public:
pointer in place of the original ASTNode *. */
virtual ASTNode *TypeCheck() = 0;
virtual ASTNode *Copy() = 0;
virtual ASTNode *ReplacePolyType(const PolyType *, const Type *) = 0;
/** Estimate the execution cost of the node (not including the cost of
@@ -177,7 +179,8 @@ typedef ASTNode * (* ASTPostCallBackFunc)(ASTNode *node, void *data);
doing so, calls postFunc, at the node. The return value from the
postFunc call is ignored. */
extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc,
ASTPostCallBackFunc postFunc, void *data);
ASTPostCallBackFunc postFunc, void *data,
ASTPostCallBackFunc preUpdate = NULL);
/** Perform simple optimizations on the AST or portion thereof passed to
this function, returning the resulting AST. */
@@ -209,6 +212,8 @@ extern int EstimateCost(ASTNode *root);
extern ASTNode * TranslatePoly(ASTNode *root, const PolyType *polyType, const Type *replacement);
extern ASTNode * CopyAST(ASTNode *root);
/** Returns true if it would be safe to run the given code with an "all
off" mask. */
extern bool SafeToRunWithMaskAllOff(ASTNode *root);

View File

@@ -1927,6 +1927,11 @@ FunctionEmitContext::BinaryOperator(llvm::Instruction::BinaryOps inst,
return NULL;
}
if (v0->getType() != v1->getType()) {
v0->dump();
printf("\n\n");
v1->dump();
}
AssertPos(currentPos, v0->getType() == v1->getType());
llvm::Type *type = v0->getType();
int arraySize = lArrayVectorWidth(type);

170
expr.cpp
View File

@@ -113,7 +113,81 @@ Expr::GetBaseSymbol() const {
}
Expr *
Expr::ReplacePolyType(const PolyType *polyType, const Type *replacement) {
Expr::Copy() {
Expr *copy;
switch (getValueID()) {
case AddressOfExprID:
copy = (Expr*)new AddressOfExpr(*(AddressOfExpr*)this);
break;
case AssignExprID:
copy = (Expr*)new AssignExpr(*(AssignExpr*)this);
break;
case BinaryExprID:
copy = (Expr*)new BinaryExpr(*(BinaryExpr*)this);
break;
case ConstExprID:
copy = (Expr*)new ConstExpr(*(ConstExpr*)this);
break;
case PtrDerefExprID:
copy = (Expr*)new PtrDerefExpr(*(PtrDerefExpr*)this);
break;
case RefDerefExprID:
copy = (Expr*)new RefDerefExpr(*(RefDerefExpr*)this);
break;
case ExprListID:
copy = (Expr*)new ExprList(*(ExprList*)this);
break;
case FunctionCallExprID:
copy = (Expr*)new FunctionCallExpr(*(FunctionCallExpr*)this);
break;
case FunctionSymbolExprID:
copy = (Expr*)new FunctionSymbolExpr(*(FunctionSymbolExpr*)this);
break;
case IndexExprID:
copy = (Expr*)new IndexExpr(*(IndexExpr*)this);
break;
case StructMemberExprID:
copy = (Expr*)new StructMemberExpr(*(StructMemberExpr*)this);
break;
case VectorMemberExprID:
copy = (Expr*)new VectorMemberExpr(*(VectorMemberExpr*)this);
break;
case NewExprID:
copy = (Expr*)new NewExpr(*(NewExpr*)this);
break;
case NullPointerExprID:
copy = (Expr*)new NullPointerExpr(*(NullPointerExpr*)this);
break;
case ReferenceExprID:
copy = (Expr*)new ReferenceExpr(*(ReferenceExpr*)this);
break;
case SelectExprID:
copy = (Expr*)new SelectExpr(*(SelectExpr*)this);
break;
case SizeOfExprID:
copy = (Expr*)new SizeOfExpr(*(SizeOfExpr*)this);
break;
case SymbolExprID:
copy = (Expr*)new SymbolExpr(*(SymbolExpr*)this);
break;
case SyncExprID:
copy = (Expr*)new SyncExpr(*(SyncExpr*)this);
break;
case TypeCastExprID:
copy = (Expr*)new TypeCastExpr(*(TypeCastExpr*)this);
break;
case UnaryExprID:
copy = (Expr*)new UnaryExpr(*(UnaryExpr*)this);
break;
default:
FATAL("Unmatched case in Expr::Copy");
copy = this; // just to silence the compiler
}
return copy;
}
Expr *
Expr::ReplacePolyType(const PolyType *, const Type *) {
return this;
}
@@ -561,6 +635,7 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
"\"%s\" for %s", fromType->GetString().c_str(),
toPolyType->GetString().c_str(), errorMsgBase);
}
return false;
}
}
@@ -4679,11 +4754,11 @@ IndexExpr::ReplacePolyType(const PolyType *from, const Type *to) {
if (index == NULL || baseExpr == NULL)
return NULL;
if (Type::EqualForReplacement(this->GetType()->GetBaseType(), from)) {
if (Type::EqualForReplacement(GetType()->GetBaseType(), from)) {
type = PolyType::ReplaceType(type, to);
}
if (Type::EqualForReplacement(this->GetLValueType()->GetBaseType(), from)) {
if (Type::EqualForReplacement(GetLValueType()->GetBaseType(), from)) {
lvalueType = new PointerType(to, lvalueType->GetVariability(),
lvalueType->IsConstType());
}
@@ -4756,27 +4831,6 @@ lIdentifierToVectorElement(char id) {
//////////////////////////////////////////////////
// StructMemberExpr
class StructMemberExpr : public MemberExpr
{
public:
StructMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue);
static inline bool classof(StructMemberExpr const*) { return true; }
static inline bool classof(ASTNode const* N) {
return N->getValueID() == StructMemberExprID;
}
const Type *GetType() const;
const Type *GetLValueType() const;
int getElementNumber() const;
const Type *getElementType() const;
private:
const StructType *getStructType() const;
};
StructMemberExpr::StructMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue)
: MemberExpr(e, id, p, idpos, derefLValue, StructMemberExprID) {
@@ -4928,31 +4982,6 @@ StructMemberExpr::getStructType() const {
//////////////////////////////////////////////////
// VectorMemberExpr
class VectorMemberExpr : public MemberExpr
{
public:
VectorMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue);
static inline bool classof(VectorMemberExpr const*) { return true; }
static inline bool classof(ASTNode const* N) {
return N->getValueID() == VectorMemberExprID;
}
llvm::Value *GetValue(FunctionEmitContext* ctx) const;
llvm::Value *GetLValue(FunctionEmitContext* ctx) const;
const Type *GetType() const;
const Type *GetLValueType() const;
int getElementNumber() const;
const Type *getElementType() const;
private:
const VectorType *exprVectorType;
const VectorType *memberType;
};
VectorMemberExpr::VectorMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue)
: MemberExpr(e, id, p, idpos, derefLValue, VectorMemberExprID) {
@@ -5338,14 +5367,10 @@ MemberExpr::ReplacePolyType(const PolyType *from, const Type *to) {
if (expr == NULL)
return NULL;
if (Type::EqualForReplacement(this->GetType()->GetBaseType(), from)) {
if (Type::EqualForReplacement(GetType()->GetBaseType(), from)) {
type = PolyType::ReplaceType(type, to);
}
if (Type::EqualForReplacement(this->GetLValueType()->GetBaseType(), from)) {
lvalueType = PolyType::ReplaceType(lvalueType, lvalueType);
}
return this;
}
@@ -7148,8 +7173,11 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
return NULL;
return ctx->IntToPtrInst(exprVal, llvmToType, "int_to_ptr");
}
else {
} else if (CastType<PolyType>(toType)) {
Error(pos, "Unexpected polymorphic type cast to \"%s\"",
toType->GetString().c_str());
return NULL;
} else {
const AtomicType *toAtomic = CastType<AtomicType>(toType);
// typechecking should ensure this is the case
if (!toAtomic) {
@@ -8071,6 +8099,12 @@ SymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
if (!symbol)
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)) {
symbol->type = PolyType::ReplaceType(symbol->type, to);
}
@@ -8147,6 +8181,14 @@ FunctionSymbolExpr::Optimize() {
return this;
}
Expr *
FunctionSymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
// force re-evaluation of overloaded type
this->triedToResolve = false;
return this;
}
int
FunctionSymbolExpr::EstimateCost() const {
@@ -8393,6 +8435,16 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype,
cost[i] += 8 * costScale;
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()) {
// Here we deal with brodcasting uniform to varying.
// callType - varying and fargType - uniform is forbidden.
@@ -8519,6 +8571,12 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos,
return true;
}
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
std::string candidateMessage =
lGetOverloadCandidateMessage(matches, argTypes, argCouldBeNULL);

47
expr.h
View File

@@ -96,6 +96,7 @@ public:
encountered, NULL should be returned. */
virtual Expr *TypeCheck() = 0;
Expr *Copy();
/** This method replaces a polymorphic type with a specific atomic type */
Expr *ReplacePolyType(const PolyType *polyType, const Type *replacement);
@@ -385,6 +386,51 @@ protected:
mutable const Type *type, *lvalueType;
};
class StructMemberExpr : public MemberExpr
{
public:
StructMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue);
static inline bool classof(StructMemberExpr const*) { return true; }
static inline bool classof(ASTNode const* N) {
return N->getValueID() == StructMemberExprID;
}
const Type *GetType() const;
const Type *GetLValueType() const;
int getElementNumber() const;
const Type *getElementType() const;
private:
const StructType *getStructType() const;
};
class VectorMemberExpr : public MemberExpr
{
public:
VectorMemberExpr(Expr *e, const char *id, SourcePos p,
SourcePos idpos, bool derefLValue);
static inline bool classof(VectorMemberExpr const*) { return true; }
static inline bool classof(ASTNode const* N) {
return N->getValueID() == VectorMemberExprID;
}
llvm::Value *GetValue(FunctionEmitContext* ctx) const;
llvm::Value *GetLValue(FunctionEmitContext* ctx) const;
const Type *GetType() const;
const Type *GetLValueType() const;
int getElementNumber() const;
const Type *getElementType() const;
private:
const VectorType *exprVectorType;
const VectorType *memberType;
};
/** @brief Expression representing a compile-time constant value.
@@ -715,6 +761,7 @@ public:
Symbol *GetBaseSymbol() const;
Expr *TypeCheck();
Expr *Optimize();
Expr *ReplacePolyType(const PolyType *from, const Type *to);
void Print() const;
int EstimateCost() const;
llvm::Constant *GetConstant(const Type *type) const;

View File

@@ -90,7 +90,7 @@
#endif
#include <llvm/Support/ToolOutputFile.h>
Function::Function(Symbol *s, Stmt *c) {
Function::Function(Symbol *s, Stmt *c, bool typecheck) {
sym = s;
code = c;
@@ -98,13 +98,15 @@ Function::Function(Symbol *s, Stmt *c) {
Assert(maskSymbol != NULL);
if (code != NULL) {
code = TypeCheck(code);
if (typecheck) {
code = TypeCheck(code);
if (code != NULL && g->debugPrint) {
printf("After typechecking function \"%s\":\n",
sym->name.c_str());
code->Print(0);
printf("---------------------\n");
if (code != NULL && g->debugPrint) {
printf("After typechecking function \"%s\":\n",
sym->name.c_str());
code->Print(0);
printf("---------------------\n");
}
}
if (code != NULL) {
@@ -135,6 +137,7 @@ Function::Function(Symbol *s, Stmt *c) {
args.push_back(sym);
const Type *t = type->GetParameterType(i);
if (sym != NULL && CastType<ReferenceType>(t) == NULL)
sym->parentFunction = this;
}
@@ -632,7 +635,7 @@ Function::GenerateIR() {
const bool
Function::IsPolyFunction() const {
for (size_t i = 0; i < args.size(); i++) {
if (args[i]->type->IsPolymorphicType()) {
if (args[i] && args[i]->type->IsPolymorphicType()) {
return true;
}
}
@@ -640,7 +643,6 @@ Function::IsPolyFunction() const {
return false;
}
std::vector<Function *> *
Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
Assert(symbolTable != NULL);
@@ -651,33 +653,64 @@ Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
const FunctionType *func = CastType<FunctionType>(sym->type);
printf("%s before replacing anything:\n", sym->name.c_str());
code->Print(0);
for (size_t i=0; i<versions.size(); i++) {
if (g->debugPrint) {
printf("%s before replacing anything:\n", sym->name.c_str());
code->Print(0);
}
const FunctionType *ft = CastType<FunctionType>(versions[i]->type);
Stmt *ncode = code;
symbolTable->PushScope();
Symbol *s = symbolTable->LookupFunction(versions[i]->name.c_str(), ft);
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++) {
if (func->GetParameterType(j)->IsPolymorphicType()) {
const PolyType *from = CastType<PolyType>(
func->GetParameterType(j)->GetBaseType());
ncode = (Stmt*)TranslatePoly(ncode, from,
f->code = (Stmt*)TranslatePoly(f->code, from,
ft->GetParameterType(j)->GetBaseType());
printf("%s after replacing %s with %s:\n\n",
sym->name.c_str(), from->GetString().c_str(),
ft->GetParameterType(j)->GetBaseType()->GetString().c_str());
if (g->debugPrint) {
printf("%s after replacing %s with %s:\n\n",
sym->name.c_str(), from->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;

2
func.h
View File

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

View File

@@ -1032,8 +1032,7 @@ Module::AddFunctionDeclaration(const std::string &name,
}
std::vector<const FunctionType *> nextExpanded;
std::set<const Type*>::iterator iter;
for (iter = toExpand.begin(); iter != toExpand.end(); iter++) {
for (auto iter = toExpand.begin(); iter != toExpand.end(); iter++) {
for (size_t j=0; j<expanded.size(); j++) {
const FunctionType *eft = expanded[j];
@@ -1060,7 +1059,12 @@ Module::AddFunctionDeclaration(const std::string &name,
nargsp.push_back(eft->GetParameterSourcePos(k));
}
nextExpanded.push_back(new FunctionType(eft->GetReturnType(),
const Type *ret = eft->GetReturnType();
if (Type::EqualForReplacement(ret, pt)) {
ret = PolyType::ReplaceType(ret, *te);
}
nextExpanded.push_back(new FunctionType(ret,
nargs,
nargsn,
nargsd,
@@ -1078,6 +1082,11 @@ Module::AddFunctionDeclaration(const std::string &name,
if (expanded.size() > 1) {
for (size_t i=0; i<expanded.size(); i++) {
if (expanded[i]->GetReturnType()->IsPolymorphicType()) {
Error(pos, "Unexpected polymorphic return type \"%s\"",
expanded[i]->GetReturnType()->GetString().c_str());
return;
}
std::string nname = name;
if (functionType->isExported || functionType->isExternC) {
for (int j=0; j<expanded[i]->GetNumParameters(); j++) {
@@ -1987,11 +1996,13 @@ lPrintPolyFunctionWrappers(FILE *file, const std::vector<std::string> &funcs) {
for (size_t j=0; j<poly.size(); j++) {
const FunctionType *ftype = CastType<FunctionType>(poly[j]->type);
Assert(ftype);
std::string decl = ftype->GetCDeclaration(funcs[i]);
fprintf(file, " %s {\n", decl.c_str());
if (ftype->isExported || ftype->isExternC) {
std::string decl = ftype->GetCDeclaration(funcs[i]);
fprintf(file, " %s {\n", decl.c_str());
std::string call = ftype->GetCCall(poly[j]->name);
fprintf(file, " return %s;\n }\n", call.c_str());
std::string call = ftype->GetCCall(poly[j]->name);
fprintf(file, " return %s;\n }\n", call.c_str());
}
}
}

View File

@@ -37,7 +37,7 @@
/* one for 'if', one for 'cif' */
%expect 2
%error-verbose
%define parse.error verbose
%code requires {

116
stmt.cpp
View File

@@ -35,6 +35,7 @@
@brief File with definitions classes related to statements in the language
*/
#include "ast.h"
#include "stmt.h"
#include "ctx.h"
#include "util.h"
@@ -78,7 +79,81 @@ Stmt::Optimize() {
}
Stmt *
Stmt::ReplacePolyType(const PolyType *polyType, const Type *replacement) {
Stmt::Copy() {
Stmt *copy;
switch (getValueID()) {
case AssertStmtID:
copy = (Stmt*)new AssertStmt(*(AssertStmt*)this);
break;
case BreakStmtID:
copy = (Stmt*)new BreakStmt(*(BreakStmt*)this);
break;
case CaseStmtID:
copy = (Stmt*)new CaseStmt(*(CaseStmt*)this);
break;
case ContinueStmtID:
copy = (Stmt*)new ContinueStmt(*(ContinueStmt*)this);
break;
case DeclStmtID:
copy = (Stmt*)new DeclStmt(*(DeclStmt*)this);
break;
case DefaultStmtID:
copy = (Stmt*)new DefaultStmt(*(DefaultStmt*)this);
break;
case DeleteStmtID:
copy = (Stmt*)new DeleteStmt(*(DeleteStmt*)this);
break;
case DoStmtID:
copy = (Stmt*)new DoStmt(*(DoStmt*)this);
break;
case ExprStmtID:
copy = (Stmt*)new ExprStmt(*(ExprStmt*)this);
break;
case ForeachActiveStmtID:
copy = (Stmt*)new ForeachActiveStmt(*(ForeachActiveStmt*)this);
break;
case ForeachStmtID:
copy = (Stmt*)new ForeachStmt(*(ForeachStmt*)this);
break;
case ForeachUniqueStmtID:
copy = (Stmt*)new ForeachUniqueStmt(*(ForeachUniqueStmt*)this);
break;
case ForStmtID:
copy = (Stmt*)new ForStmt(*(ForStmt*)this);
break;
case GotoStmtID:
copy = (Stmt*)new GotoStmt(*(GotoStmt*)this);
break;
case IfStmtID:
copy = (Stmt*)new IfStmt(*(IfStmt*)this);
break;
case LabeledStmtID:
copy = (Stmt*)new LabeledStmt(*(LabeledStmt*)this);
break;
case PrintStmtID:
copy = (Stmt*)new PrintStmt(*(PrintStmt*)this);
break;
case ReturnStmtID:
copy = (Stmt*)new ReturnStmt(*(ReturnStmt*)this);
break;
case StmtListID:
copy = (Stmt*)new StmtList(*(StmtList*)this);
break;
case SwitchStmtID:
copy = (Stmt*)new SwitchStmt(*(SwitchStmt*)this);
break;
case UnmaskedStmtID:
copy = (Stmt*)new UnmaskedStmt(*(UnmaskedStmt*)this);
break;
default:
FATAL("Unmatched case in Stmt::Copy");
copy = this; // just to silence the compiler
}
return copy;
}
Stmt *
Stmt::ReplacePolyType(const PolyType *, const Type *) {
return this;
}
@@ -484,7 +559,8 @@ DeclStmt::TypeCheck() {
// an int as the constValue later...
const Type *type = vars[i].sym->type;
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
// an error. Need to leave vars[i].init as is in that case so
// it is in fact caught later, though.
@@ -502,9 +578,15 @@ DeclStmt::TypeCheck() {
Stmt *
DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) {
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;
if (Type::EqualForReplacement(s->type->GetBaseType(), from)) {
s->type = PolyType::ReplaceType(s->type, to);
// this typecast *should* be valid after typechecking
vars[i].init = TypeConvertExpr(vars[i].init, s->type,
"initializer");
}
}
@@ -1487,6 +1569,17 @@ ForeachStmt::ForeachStmt(const std::vector<Symbol *> &lvs,
stmts(s) {
}
/*
ForeachStmt::ForeachStmt(ForeachStmt *base)
: Stmt(base->pos, ForeachStmtID) {
dimVariables = base->dimVariables;
startExprs = base->startExprs;
endExprs = base->endExprs;
isTiled = base->isTiled;
stmts = base->stmts;
}
*/
/* Given a uniform counter value in the memory location pointed to by
uniformCounterPtr, compute the corresponding set of varying counter
@@ -1730,8 +1823,10 @@ ForeachStmt::EmitCode(FunctionEmitContext *ctx) const {
// Start and end value for this loop dimension
llvm::Value *sv = startExprs[i]->GetValue(ctx);
llvm::Value *ev = endExprs[i]->GetValue(ctx);
if (sv == NULL || ev == NULL)
if (sv == NULL || ev == NULL) {
fprintf(stderr, "ev is NULL again :(\n");
return;
}
startVals.push_back(sv);
endVals.push_back(ev);
@@ -2191,21 +2286,6 @@ ForeachStmt::TypeCheck() {
return anyErrors ? NULL : this;
}
Stmt *
ForeachStmt::ReplacePolyType(const PolyType *from, const Type *to) {
if (!stmts)
return NULL;
for (size_t i=0; i<dimVariables.size(); i++) {
const Type *t = dimVariables[i]->type;
if (Type::EqualForReplacement(t->GetBaseType(), from)) {
t = PolyType::ReplaceType(t, to);
}
}
return this;
}
int
ForeachStmt::EstimateCost() const {

2
stmt.h
View File

@@ -70,6 +70,7 @@ public:
// Stmts don't have anything to do here.
virtual Stmt *Optimize();
virtual Stmt *TypeCheck() = 0;
Stmt *Copy();
Stmt *ReplacePolyType(const PolyType *polyType, const Type *replacement);
};
@@ -283,7 +284,6 @@ public:
void Print(int indent) const;
Stmt *TypeCheck();
Stmt *ReplacePolyType(const PolyType *from, const Type *to);
int EstimateCost() const;
std::vector<Symbol *> dimVariables;

19
sym.cpp
View File

@@ -95,14 +95,14 @@ SymbolTable::PopScope() {
bool
SymbolTable::AddVariable(Symbol *symbol) {
SymbolTable::AddVariable(Symbol *symbol, bool issueScopeWarning) {
Assert(symbol != NULL);
// Check to see if a symbol of the same name has already been declared.
for (int i = (int)variables.size() - 1; i >= 0; --i) {
SymbolMapType &sm = *(variables[i]);
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
// same scope, it's an error.
Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".",
@@ -112,9 +112,11 @@ SymbolTable::AddVariable(Symbol *symbol) {
else {
// Otherwise it's just shadowing something else, which
// is legal but dangerous..
Warning(symbol->pos,
"Symbol \"%s\" shadows symbol declared in outer scope.",
symbol->name.c_str());
if (issueScopeWarning) {
Warning(symbol->pos,
"Symbol \"%s\" shadows symbol declared in outer scope.",
symbol->name.c_str());
}
(*variables.back())[symbol->name] = symbol;
return true;
}
@@ -147,7 +149,7 @@ bool
SymbolTable::AddFunction(Symbol *symbol) {
const FunctionType *ft = CastType<FunctionType>(symbol->type);
Assert(ft != NULL);
if (LookupFunction(symbol->name.c_str(), ft) != NULL)
if (LookupFunction(symbol->name.c_str(), ft, true) != NULL)
// A function of the same name and type has already been added to
// the symbol table
return false;
@@ -183,7 +185,8 @@ SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
Symbol *
SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
SymbolTable::LookupFunction(const char *name, const FunctionType *type,
bool ignorePoly) {
FunctionMapType::iterator iter = functions.find(name);
if (iter != functions.end()) {
std::vector<Symbol *> funcs = iter->second;
@@ -193,7 +196,7 @@ SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
}
}
// Try looking for a polymorphic function
if (polyFunctions[name].size() > 0) {
if (!ignorePoly && polyFunctions[name].size() > 0) {
std::string n = name;
return new Symbol(name, polyFunctions[name][0]->pos, type);
}

5
sym.h
View File

@@ -141,7 +141,7 @@ public:
with a symbol defined at the same scope. (Symbols may shaodow
symbols in outer scopes; a warning is issued in this case, but this
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
method searches outward from the innermost scope to the outermost,
@@ -181,7 +181,8 @@ public:
in the symbol table.
@return pointer to matching Symbol; NULL if none is found. */
Symbol *LookupFunction(const char *name, const FunctionType *type);
Symbol *LookupFunction(const char *name, const FunctionType *type,
bool ignorePoly = false);
std::vector<Symbol *>& LookupPolyFunction(const char *name);

177
tests_ispcpp/CycleTimer.h Normal file
View File

@@ -0,0 +1,177 @@
#ifndef _SYRAH_CYCLE_TIMER_H_
#define _SYRAH_CYCLE_TIMER_H_
#if defined(__APPLE__)
#if defined(__x86_64__)
#include <sys/sysctl.h>
#else
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif // __x86_64__ or not
#include <stdio.h> // fprintf
#include <stdlib.h> // exit
#elif _WIN32
# include <windows.h>
# include <time.h>
#else
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/time.h>
#endif
// This uses the cycle counter of the processor. Different
// processors in the system will have different values for this. If
// you process moves across processors, then the delta time you
// measure will likely be incorrect. This is mostly for fine
// grained measurements where the process is likely to be on the
// same processor. For more global things you should use the
// Time interface.
// Also note that if you processors' speeds change (i.e. processors
// scaling) or if you are in a heterogenous environment, you will
// likely get spurious results.
class CycleTimer {
public:
typedef unsigned long long SysClock;
//////////
// Return the current CPU time, in terms of clock ticks.
// Time zero is at some arbitrary point in the past.
static SysClock currentTicks() {
#if defined(__APPLE__) && !defined(__x86_64__)
return mach_absolute_time();
#elif defined(_WIN32)
LARGE_INTEGER qwTime;
QueryPerformanceCounter(&qwTime);
return qwTime.QuadPart;
#elif defined(__x86_64__)
unsigned int a, d;
asm volatile("rdtsc" : "=a" (a), "=d" (d));
return static_cast<unsigned long long>(a) |
(static_cast<unsigned long long>(d) << 32);
#elif defined(__ARM_NEON__) && 0 // mrc requires superuser.
unsigned int val;
asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(val));
return val;
#else
timespec spec;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &spec);
return CycleTimer::SysClock(static_cast<float>(spec.tv_sec) * 1e9 + static_cast<float>(spec.tv_nsec));
#endif
}
//////////
// Return the current CPU time, in terms of seconds.
// This is slower than currentTicks(). Time zero is at
// some arbitrary point in the past.
static double currentSeconds() {
return currentTicks() * secondsPerTick();
}
//////////
// Return the conversion from seconds to ticks.
static double ticksPerSecond() {
return 1.0/secondsPerTick();
}
static const char* tickUnits() {
#if defined(__APPLE__) && !defined(__x86_64__)
return "ns";
#elif defined(__WIN32__) || defined(__x86_64__)
return "cycles";
#else
return "ns"; // clock_gettime
#endif
}
//////////
// Return the conversion from ticks to seconds.
static double secondsPerTick() {
static bool initialized = false;
static double secondsPerTick_val;
if (initialized) return secondsPerTick_val;
#if defined(__APPLE__)
#ifdef __x86_64__
int args[] = {CTL_HW, HW_CPU_FREQ};
unsigned int Hz;
size_t len = sizeof(Hz);
if (sysctl(args, 2, &Hz, &len, NULL, 0) != 0) {
fprintf(stderr, "Failed to initialize secondsPerTick_val!\n");
exit(-1);
}
secondsPerTick_val = 1.0 / (double) Hz;
#else
mach_timebase_info_data_t time_info;
mach_timebase_info(&time_info);
// Scales to nanoseconds without 1e-9f
secondsPerTick_val = (1e-9*static_cast<double>(time_info.numer))/
static_cast<double>(time_info.denom);
#endif // x86_64 or not
#elif defined(_WIN32)
LARGE_INTEGER qwTicksPerSec;
QueryPerformanceFrequency(&qwTicksPerSec);
secondsPerTick_val = 1.0/static_cast<double>(qwTicksPerSec.QuadPart);
#else
FILE *fp = fopen("/proc/cpuinfo","r");
char input[1024];
if (!fp) {
fprintf(stderr, "CycleTimer::resetScale failed: couldn't find /proc/cpuinfo.");
exit(-1);
}
// In case we don't find it, e.g. on the N900
secondsPerTick_val = 1e-9;
while (!feof(fp) && fgets(input, 1024, fp)) {
// NOTE(boulos): Because reading cpuinfo depends on dynamic
// frequency scaling it's better to read the @ sign first
float GHz, MHz;
if (strstr(input, "model name")) {
char* at_sign = strstr(input, "@");
if (at_sign) {
char* after_at = at_sign + 1;
char* GHz_str = strstr(after_at, "GHz");
char* MHz_str = strstr(after_at, "MHz");
if (GHz_str) {
*GHz_str = '\0';
if (1 == sscanf(after_at, "%f", &GHz)) {
//printf("GHz = %f\n", GHz);
secondsPerTick_val = 1e-9f / GHz;
break;
}
} else if (MHz_str) {
*MHz_str = '\0';
if (1 == sscanf(after_at, "%f", &MHz)) {
//printf("MHz = %f\n", MHz);
secondsPerTick_val = 1e-6f / GHz;
break;
}
}
}
} else if (1 == sscanf(input, "cpu MHz : %f", &MHz)) {
//printf("MHz = %f\n", MHz);
secondsPerTick_val = 1e-6f / MHz;
break;
}
}
fclose(fp);
#endif
initialized = true;
return secondsPerTick_val;
}
//////////
// Return the conversion from ticks to milliseconds.
static double msPerTick() {
return secondsPerTick() * 1000.0;
}
private:
CycleTimer();
};
#endif // #ifndef _SYRAH_CYCLE_TIMER_H_

View File

@@ -1,12 +1,15 @@
CXX=g++
CXXFLAGS=-std=c++11
CXXFLAGS=-std=c++11 -O3 -lm -lpthread
ISPC=../ispc
ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64
ISPCFLAGS=--target=avx2 -O3 --arch=x86-64
%.out : %.cpp %.o
%.out : %.cpp %.o tasksys.o
$(CXX) $(CXXFLAGS) -o $@ $^
tasksys.o : ../examples/tasksys.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $^
$ : $.o
%.o : %.ispc

13
tests_ispcpp/array.ispc Normal file
View File

@@ -0,0 +1,13 @@
export void array(uniform int N, uniform integer * uniform X) {
integer *A = new integer[N/2];
foreach (i = 0 ... N/2) {
A[i] = X[i] + X[N/2 + i];
}
foreach (i = 0 ... N) {
X[i] = A[i/2];
}
delete[] A;
}

17
tests_ispcpp/error_5.ispc Normal file
View File

@@ -0,0 +1,17 @@
//@error
floating$0 mult(floating$0 x, floating$1 y) {
return x * y;
}
export void saxpy(uniform int N,
uniform floating$0 scale,
uniform floating$1 X[],
uniform floating$1 Y[],
uniform floating$2 result[])
{
foreach (i = 0 ... N) {
floating$ tmp = mult(scale, X[i]) + Y[i];
result[i] = tmp;
}
}

14
tests_ispcpp/error_6.ispc Normal file
View File

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

13
tests_ispcpp/error_7.ispc Normal file
View File

@@ -0,0 +1,13 @@
floating foo(floating a, floating b) {
floating d = a / b;
if (d < 0.)
return 0.;
return d;
}
export void bar(uniform integer * uniform X, uniform int N) {
foreach (i = 0 ... N-1) {
X[i] = foo(X[i], X[i+1]);
}
}

View File

@@ -1,15 +1,15 @@
floating saxpy_helper(floating scale,
floating<0> x,
floating<0> y) {
floating$3 x,
floating$3 y) {
return scale * x + y;
}
export void saxpy(uniform int N,
uniform floating<0> scale,
uniform floating<1> X[],
uniform floating<1> Y[],
uniform floating<2> result[])
uniform floating$0 scale,
uniform floating$1 X[],
uniform floating$1 Y[],
uniform floating$2 result[])
{
foreach (i = 0 ... N) {
result[i] = saxpy_helper(scale, X[i], Y[i]);

View File

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

20
tests_ispcpp/simple.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include <stdlib.h>
#include <stdio.h>
#include "simple.h"
int main() {
double A[256];
for (int i=0; i<256; i++) {
A[i] = i / 11.;
}
ispc::foo(256, (double*)&A);
for (int i=0; i<256; i++) {
printf("%f\n", A[i]);
}
return 0;
}

212
tests_ispcpp/sqrt.cpp Normal file
View File

@@ -0,0 +1,212 @@
#include <stdio.h>
#include <algorithm>
#include <pthread.h>
#include <math.h>
#include <cmath>
#include "CycleTimer.h"
#include "sqrt.h"
using namespace ispc;
void sqrtSerial(int N,
float initialGuess,
float values[],
float output[])
{
static const float kThreshold = 0.00001f;
for (int i=0; i<N; i++) {
float x = values[i];
float guess = initialGuess;
float error = fabs(guess * guess * x - 1.f);
while (error > kThreshold) {
guess = (3.f * guess - x * guess * guess * guess) * 0.5f;
error = fabs(guess * guess * x - 1.f);
}
output[i] = x * guess;
}
}
void sqrtSerial(int N,
double initialGuess,
double values[],
double output[])
{
static const double kThreshold = 0.00001f;
for (int i=0; i<N; i++) {
double x = values[i];
double guess = initialGuess;
double error = std::abs(guess * guess * x - 1.);
while (error > kThreshold) {
guess = (3. * guess - x * guess * guess * guess) * 0.5;
error = std::abs(guess * guess * x - 1.);
}
output[i] = x * guess;
}
}
static void verifyResult(int N, float* result, float* gold) {
for (int i=0; i<N; i++) {
if (fabs(result[i] - gold[i]) > 1e-4) {
printf("Error: [%d] Got %f expected %f\n", i, result[i], gold[i]);
}
}
}
static void verifyResult(int N, double* result, double* gold) {
for (int i=0; i<N; i++) {
if (std::abs(result[i] - gold[i]) > 1e-4) {
printf("Error: [%d] Got %f expected %f\n", i, result[i], gold[i]);
}
}
}
int main() {
const unsigned int N = 20 * 1000 * 1000;
const float initialGuess = 1.0f;
const double dinitialGuess = 1.0;
float* values = new float[N];
float* output = new float[N];
float* gold = new float[N];
double* dvalues = new double[N];
double* doutput = new double[N];
double* dgold = new double[N];
for (unsigned int i=0; i<N; i++)
{
// random input values
values[i] = .001f + 2.998f * static_cast<float>(rand()) / RAND_MAX;
dvalues[i] = .001 + 2.998 * static_cast<double>(rand()) / RAND_MAX;
output[i] = 0.f;
doutput[i] = 0.;
}
// generate a gold version to check results
for (unsigned int i=0; i<N; i++) {
gold[i] = sqrt(values[i]);
dgold[i] = sqrt(dvalues[i]);
}
//
// And run the serial implementation 3 times, again reporting the
// minimum time.
//
double minSerial = 1e30;
for (int i = 0; i < 5; ++i) {
double startTime = CycleTimer::currentSeconds();
sqrtSerial(N, initialGuess, values, output);
double endTime = CycleTimer::currentSeconds();
minSerial = std::min(minSerial, endTime - startTime);
}
printf("[sqrt float serial]:\t\t[%.3f] ms\n", minSerial * 1000);
verifyResult(N, output, gold);
double minDSerial = 1e30;
for (int i = 0; i < 5; ++i) {
double startTime = CycleTimer::currentSeconds();
sqrtSerial(N, dinitialGuess, dvalues, doutput);
double endTime = CycleTimer::currentSeconds();
minDSerial = std::min(minDSerial, endTime - startTime);
}
printf("[sqrt double serial]:\t\t[%.3f] ms\n", minDSerial * 1000);
verifyResult(N, doutput, dgold);
// Clear out the buffer
for (unsigned int i = 0; i < N; ++i) {
output[i] = 0;
doutput[i] = 0;
}
//
// Compute the image using the ispc implementation; report the minimum
// time of three runs.
//
double minISPC = 1e30;
for (int i = 0; i < 5; ++i) {
double startTime = CycleTimer::currentSeconds();
ispc::sqrt_ispc(N, initialGuess, values, output);
double endTime = CycleTimer::currentSeconds();
minISPC = std::min(minISPC, endTime - startTime);
}
printf("[sqrt float ispc]:\t\t[%.3f] ms\n", minISPC * 1000);
verifyResult(N, output, gold);
double minDISPC = 1e30;
for (int i = 0; i < 5; ++i) {
double startTime = CycleTimer::currentSeconds();
ispc::sqrt_ispc(N, dinitialGuess, dvalues, doutput);
double endTime = CycleTimer::currentSeconds();
minDISPC = std::min(minDISPC, endTime - startTime);
}
printf("[sqrt double ispc]:\t\t[%.3f] ms\n", minDISPC * 1000);
verifyResult(N, doutput, dgold);
// Clear out the buffer
for (unsigned int i = 0; i < N; ++i) {
output[i] = 0;
doutput[i] = 0;
}
//
// Tasking version of the ISPC code
//
double minTaskISPC = 1e30;
for (int i = 0; i < 3; ++i) {
double startTime = CycleTimer::currentSeconds();
ispc::sqrt_ispc_withtasks(N, initialGuess, values, output);
double endTime = CycleTimer::currentSeconds();
minTaskISPC = std::min(minTaskISPC, endTime - startTime);
}
printf("[sqrt float task ispc]:\t\t[%.3f] ms\n", minTaskISPC * 1000);
verifyResult(N, output, gold);
double minDTaskISPC = 1e30;
for (int i = 0; i < 3; ++i) {
double startTime = CycleTimer::currentSeconds();
ispc::sqrt_ispc_withtasks(N, dinitialGuess, dvalues, doutput);
double endTime = CycleTimer::currentSeconds();
minDTaskISPC = std::min(minDTaskISPC, endTime - startTime);
}
printf("[sqrt double task ispc]:\t[%.3f] ms\n", minDTaskISPC * 1000);
verifyResult(N, output, gold);
printf("\t\t\t\t(%.2fx speedup from ISPC float)\n", minSerial/minISPC);
printf("\t\t\t\t(%.2fx speedup from ISPC double)\n", minDSerial/minDISPC);
printf("\t\t\t\t(%.2fx speedup from task ISPC float)\n", minSerial/minTaskISPC);
printf("\t\t\t\t(%.2fx speedup from task ISPC double)\n", minDSerial/minDTaskISPC);
delete[] values;
delete[] output;
delete[] gold;
delete[] dvalues;
delete[] doutput;
delete[] dgold;
return 0;
}

62
tests_ispcpp/sqrt.ispc Normal file
View File

@@ -0,0 +1,62 @@
static const float kThreshold = 0.00001f;
export void sqrt_ispc(uniform int N,
uniform floating initialGuess,
uniform floating values[],
uniform floating output[])
{
foreach (i = 0 ... N) {
floating x = values[i];
floating guess = initialGuess;
floating pred = abs(guess * guess * x - 1.f);
while (pred > kThreshold) {
guess = (3.f * guess - x * guess * guess * guess) * 0.5f;
pred = abs(guess * guess * x - 1.f);
}
output[i] = x * guess;
}
}
task void sqrt_ispc_task(uniform int N,
uniform int span,
uniform floating initialGuess,
uniform floating values[],
uniform floating output[])
{
uniform int indexStart = taskIndex * span;
uniform int indexEnd = min(N, indexStart + span);
foreach (i = indexStart ... indexEnd) {
floating x = values[i];
floating guess = initialGuess;
floating pred = abs(guess * guess * x - 1.f);
while (pred > kThreshold) {
guess = (3.f * guess - x * guess * guess * guess) * 0.5f;
pred = abs(guess * guess * x - 1.f);
}
output[i] = x * guess;
}
}
export void sqrt_ispc_withtasks(uniform int N,
uniform floating initialGuess,
uniform floating values[],
uniform floating output[])
{
uniform int span = N / 64; // 64 tasks
launch[N/span] sqrt_ispc_task(N, span, initialGuess, values, output);
}

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];
float 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, (float*)&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 @@
number pow(number b, int a) {
number out = b;
for (int i = 1; i<a; i++) {
out *= b;
}
return out;
}
export void square(uniform int N, uniform number b[], uniform number out[]) {
foreach (i = 0 ... N) {
out[i] = pow(b[i], 2);
}
}

View File

@@ -721,9 +721,11 @@ PolyType::ReplaceType(const Type *from, const Type *to) {
if (from->IsVaryingType())
t = t->GetAsVaryingType();
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
from->GetString().c_str(),
t->GetString().c_str());
if (g->debugPrint) {
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
from->GetString().c_str(),
t->GetString().c_str());
}
return t;
}
@@ -4078,7 +4080,8 @@ bool
Type::IsBasicType(const Type *type) {
return (CastType<AtomicType>(type) != NULL ||
CastType<EnumType>(type) != NULL ||
CastType<PointerType>(type) != NULL);
CastType<PointerType>(type) != NULL ||
CastType<PolyType>(type) != NULL);
}