Remove no longer needed lSafeToRunWithAllLanesOff utility functions.

This commit is contained in:
Matt Pharr
2011-12-15 16:56:30 -08:00
parent f9463af75b
commit 45767ad197

212
stmt.cpp
View File

@@ -655,7 +655,8 @@ IfStmt::emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask,
} }
/** Given an AST node, check to see if it's safe if we happen to run the
code for that node with the execution mask all off. */
static void static void
lCheckAllOffSafety(ASTNode *node, void *data) { lCheckAllOffSafety(ASTNode *node, void *data) {
bool *okPtr = (bool *)data; bool *okPtr = (bool *)data;
@@ -721,213 +722,6 @@ lCheckAllOffSafety(ASTNode *node, void *data) {
} }
/** Similar to the Stmt variant of this function, this conservatively
checks to see if it's safe to run the code for the given Expr even if
the mask is 'all off'.
*/
static bool
lSafeToRunWithAllLanesOff(Expr *expr) {
if (expr == NULL)
return true;
UnaryExpr *ue;
if ((ue = dynamic_cast<UnaryExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(ue->expr);
BinaryExpr *be;
if ((be = dynamic_cast<BinaryExpr *>(expr)) != NULL)
return (lSafeToRunWithAllLanesOff(be->arg0) &&
lSafeToRunWithAllLanesOff(be->arg1));
AssignExpr *ae;
if ((ae = dynamic_cast<AssignExpr *>(expr)) != NULL)
return (lSafeToRunWithAllLanesOff(ae->lvalue) &&
lSafeToRunWithAllLanesOff(ae->rvalue));
SelectExpr *se;
if ((se = dynamic_cast<SelectExpr *>(expr)) != NULL)
return (lSafeToRunWithAllLanesOff(se->test) &&
lSafeToRunWithAllLanesOff(se->expr1) &&
lSafeToRunWithAllLanesOff(se->expr2));
ExprList *el;
if ((el = dynamic_cast<ExprList *>(expr)) != NULL) {
for (unsigned int i = 0; i < el->exprs.size(); ++i)
if (!lSafeToRunWithAllLanesOff(el->exprs[i]))
return false;
return true;
}
FunctionCallExpr *fce;
if ((fce = dynamic_cast<FunctionCallExpr *>(expr)) != NULL)
// FIXME: If we could somehow determine that the function being
// called was safe (and all of the args Exprs were safe, then it'd
// be nice to be able to return true here. (Consider a call to
// e.g. floatbits() in the stdlib.) Unfortunately for now we just
// have to be conservative.
return false;
IndexExpr *ie;
if ((ie = dynamic_cast<IndexExpr *>(expr)) != NULL) {
// If we can determine at compile time the size of the array/vector
// and if the indices are compile-time constants, then we may be
// able to safely run this under a predicated if statement..
if (ie->baseExpr == NULL)
return false;
const Type *type = ie->baseExpr->GetType();
ConstExpr *ce = dynamic_cast<ConstExpr *>(ie->index);
if (type == NULL || ce == NULL)
return false;
if (dynamic_cast<const ReferenceType *>(type) != NULL)
type = type->GetReferenceTarget();
const PointerType *pointerType =
dynamic_cast<const PointerType *>(type);
if (pointerType != NULL)
// pointer[offset] -> can't be sure
return false;
const SequentialType *seqType =
dynamic_cast<const SequentialType *>(type);
Assert(seqType != NULL);
int nElements = seqType->GetElementCount();
if (nElements == 0)
// Unsized array, so we can't be sure
return false;
int32_t indices[ISPC_MAX_NVEC];
int count = ce->AsInt32(indices);
for (int i = 0; i < count; ++i)
if (indices[i] < 0 || indices[i] >= nElements)
return false;
// All indices are in-bounds
return true;
}
MemberExpr *me;
if ((me = dynamic_cast<MemberExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(me->expr);
if (dynamic_cast<ConstExpr *>(expr) != NULL)
return true;
TypeCastExpr *tce;
if ((tce = dynamic_cast<TypeCastExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(tce->expr);
ReferenceExpr *re;
if ((re = dynamic_cast<ReferenceExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(re->expr);
DereferenceExpr *dre;
if ((dre = dynamic_cast<DereferenceExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(dre->expr);
SizeOfExpr *soe;
if ((soe = dynamic_cast<SizeOfExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(soe->expr);
AddressOfExpr *aoe;
if ((aoe = dynamic_cast<AddressOfExpr *>(expr)) != NULL)
return lSafeToRunWithAllLanesOff(aoe->expr);
if (dynamic_cast<SymbolExpr *>(expr) != NULL ||
dynamic_cast<FunctionSymbolExpr *>(expr) != NULL ||
dynamic_cast<SyncExpr *>(expr) != NULL ||
dynamic_cast<NullPointerExpr *>(expr) != NULL)
return true;
FATAL("Unknown Expr type in lSafeToRunWithAllLanesOff()");
return false;
}
/** Given an arbitrary statement, this function conservatively tests to see
if it's safe to run the code for the statement even if the mask is all
off. Here we just need to determine which kind of statement we have
and recursively traverse it and/or the expressions inside of it.
*/
static bool
lSafeToRunWithAllLanesOff(Stmt *stmt) {
if (stmt == NULL)
return true;
ExprStmt *es;
if ((es = dynamic_cast<ExprStmt *>(stmt)) != NULL)
return lSafeToRunWithAllLanesOff(es->expr);
DeclStmt *ds;
if ((ds = dynamic_cast<DeclStmt *>(stmt)) != NULL) {
for (unsigned int i = 0; i < ds->vars.size(); ++i)
if (!lSafeToRunWithAllLanesOff(ds->vars[i].init))
return false;
return true;
}
IfStmt *is;
if ((is = dynamic_cast<IfStmt *>(stmt)) != NULL)
return (lSafeToRunWithAllLanesOff(is->test) &&
lSafeToRunWithAllLanesOff(is->trueStmts) &&
lSafeToRunWithAllLanesOff(is->falseStmts));
DoStmt *dos;
if ((dos = dynamic_cast<DoStmt *>(stmt)) != NULL)
return (lSafeToRunWithAllLanesOff(dos->testExpr) &&
lSafeToRunWithAllLanesOff(dos->bodyStmts));
ForStmt *fs;
if ((fs = dynamic_cast<ForStmt *>(stmt)) != NULL)
return (lSafeToRunWithAllLanesOff(fs->init) &&
lSafeToRunWithAllLanesOff(fs->test) &&
lSafeToRunWithAllLanesOff(fs->step) &&
lSafeToRunWithAllLanesOff(fs->stmts));
ForeachStmt *fes;
if ((fes = dynamic_cast<ForeachStmt *>(stmt)) != NULL) {
for (unsigned int i = 0; i < fes->startExprs.size(); ++i)
if (!lSafeToRunWithAllLanesOff(fes->startExprs[i]))
return false;
for (unsigned int i = 0; i < fes->endExprs.size(); ++i)
if (!lSafeToRunWithAllLanesOff(fes->endExprs[i]))
return false;
return lSafeToRunWithAllLanesOff(fes->stmts);
}
if (dynamic_cast<BreakStmt *>(stmt) != NULL ||
dynamic_cast<ContinueStmt *>(stmt) != NULL)
return true;
ReturnStmt *rs;
if ((rs = dynamic_cast<ReturnStmt *>(stmt)) != NULL)
return lSafeToRunWithAllLanesOff(rs->val);
StmtList *sl;
if ((sl = dynamic_cast<StmtList *>(stmt)) != NULL) {
const std::vector<Stmt *> &sls = sl->GetStatements();
for (unsigned int i = 0; i < sls.size(); ++i)
if (!lSafeToRunWithAllLanesOff(sls[i]))
return false;
return true;
}
PrintStmt *ps;
if ((ps = dynamic_cast<PrintStmt *>(stmt)) != NULL)
return lSafeToRunWithAllLanesOff(ps->values);
AssertStmt *as;
if ((as = dynamic_cast<AssertStmt *>(stmt)) != NULL)
// While this is fine for varying tests, it's not going to be
// desirable to check an assert on a uniform variable if all of the
// lanes are off.
return false;
FATAL("Unexpected stmt type in lSafeToRunWithAllLanesOff()");
return false;
}
/** Emit code for an if test that checks the mask and the test values and /** Emit code for an if test that checks the mask and the test values and
tries to be smart about jumping over code that doesn't need to be run. tries to be smart about jumping over code that doesn't need to be run.
*/ */
@@ -995,8 +789,6 @@ IfStmt::emitVaryingIf(FunctionEmitContext *ctx, llvm::Value *ltest) const {
bool safeToRunWithAllLanesOff = true; bool safeToRunWithAllLanesOff = true;
WalkAST(trueStmts, lCheckAllOffSafety, NULL, &safeToRunWithAllLanesOff); WalkAST(trueStmts, lCheckAllOffSafety, NULL, &safeToRunWithAllLanesOff);
WalkAST(falseStmts, lCheckAllOffSafety, NULL, &safeToRunWithAllLanesOff); WalkAST(falseStmts, lCheckAllOffSafety, NULL, &safeToRunWithAllLanesOff);
assert(safe == (lSafeToRunWithAllLanesOff(trueStmts) &
lSafeToRunWithAllLanesOff(falseStmts)));
if (safeToRunWithAllLanesOff && if (safeToRunWithAllLanesOff &&
(costIsAcceptable || g->opt.disableCoherentControlFlow)) { (costIsAcceptable || g->opt.disableCoherentControlFlow)) {