Add a very simple cost model to estimate runtime cost of running code.

This is currently only used to decide whether it's worth doing an
"are all lanes running" check at the start of functions--for small
functions, it's not worth the overhead.

The cost is estimated relatively early in compilation (e.g. before
we know if an array access is a scatter/gather or not, before
constant folding, etc.), so there are many known shortcomings.
This commit is contained in:
Matt Pharr
2011-09-16 15:09:17 -07:00
parent 38fc13d1ab
commit ca87579f23
6 changed files with 263 additions and 9 deletions

117
expr.cpp
View File

@@ -741,6 +741,12 @@ UnaryExpr::TypeCheck() {
}
int
UnaryExpr::EstimateCost() const {
return (expr ? expr->EstimateCost() : 0) + COST_SIMPLE_ARITH_LOGIC_OP;
}
void
UnaryExpr::Print() const {
if (!expr || !GetType())
@@ -1445,6 +1451,15 @@ BinaryExpr::TypeCheck() {
}
int
BinaryExpr::EstimateCost() const {
return ((arg0 ? arg0->EstimateCost() : 0) +
(arg1 ? arg1->EstimateCost() : 0) +
(op == Div || op == Mod) ? COST_COMPLEX_ARITH_OP :
COST_SIMPLE_ARITH_LOGIC_OP);
}
void
BinaryExpr::Print() const {
if (!arg0 || !arg1 || !GetType())
@@ -1696,6 +1711,19 @@ AssignExpr::TypeCheck() {
}
int
AssignExpr::EstimateCost() const {
int cost = ((lvalue ? lvalue->EstimateCost() : 0) +
(rvalue ? rvalue->EstimateCost() : 0));
if (op == Assign)
return cost;
if (op == DivAssign || op == ModAssign)
return cost + COST_COMPLEX_ARITH_OP;
else
return cost + COST_SIMPLE_ARITH_LOGIC_OP;
}
void
AssignExpr::Print() const {
if (!lvalue || !rvalue || !GetType())
@@ -1944,6 +1972,12 @@ SelectExpr::TypeCheck() {
}
int
SelectExpr::EstimateCost() const {
return COST_SELECT;
}
void
SelectExpr::Print() const {
if (!test || !expr1 || !expr2 || !GetType())
@@ -2440,6 +2474,13 @@ FunctionCallExpr::TypeCheck() {
}
int
FunctionCallExpr::EstimateCost() const {
return ((args ? args->EstimateCost() : 0) +
(isLaunch ? COST_TASK_LAUNCH : COST_FUNCALL));
}
void
FunctionCallExpr::Print() const {
if (!func || !args || !GetType())
@@ -2551,6 +2592,17 @@ ExprList::GetConstant(const Type *type) const {
}
int
ExprList::EstimateCost() const {
int cost = 0;
for (unsigned int i = 0; i < exprs.size(); ++i) {
if (exprs[i] != NULL)
cost += exprs[i]->EstimateCost();
}
return cost;
}
void
ExprList::Print() const {
printf("expr list (");
@@ -2749,6 +2801,16 @@ IndexExpr::TypeCheck() {
}
int
IndexExpr::EstimateCost() const {
// be pessimistic
if (index && index->GetType()->IsVaryingType())
return COST_GATHER;
else
return COST_LOAD;
}
void
IndexExpr::Print() const {
if (!arrayOrVector || !index || !GetType())
@@ -3048,6 +3110,7 @@ MemberExpr::create(Expr *e, const char *id, SourcePos p, SourcePos idpos) {
return new MemberExpr(e, id, p, idpos);
}
MemberExpr::MemberExpr(Expr *e, const char *id, SourcePos p, SourcePos idpos)
: Expr(p), identifierPos(idpos) {
expr = e;
@@ -3144,6 +3207,14 @@ MemberExpr::Optimize() {
}
int
MemberExpr::EstimateCost() const {
// FIXME: return gather cost when we can tell a gather is going to be
// needed
return COST_SIMPLE_ARITH_LOGIC_OP;
}
void
MemberExpr::Print() const {
if (!expr || !GetType())
@@ -3939,6 +4010,12 @@ ConstExpr::TypeCheck() {
}
int
ConstExpr::EstimateCost() const {
return 0;
}
void
ConstExpr::Print() const {
printf("[%s] (", GetType()->GetString().c_str());
@@ -4859,6 +4936,13 @@ TypeCastExpr::Optimize() {
}
int
TypeCastExpr::EstimateCost() const {
// FIXME: return COST_TYPECAST_COMPLEX when appropriate
return COST_TYPECAST_SIMPLE;
}
void
TypeCastExpr::Print() const {
printf("[%s] type cast (", GetType()->GetString().c_str());
@@ -4924,6 +5008,12 @@ ReferenceExpr::TypeCheck() {
}
int
ReferenceExpr::EstimateCost() const {
return 0;
}
void
ReferenceExpr::Print() const {
if (expr == NULL || GetType() == NULL)
@@ -5002,6 +5092,12 @@ DereferenceExpr::Optimize() {
}
int
DereferenceExpr::EstimateCost() const {
return COST_DEREF;
}
void
DereferenceExpr::Print() const {
if (expr == NULL || GetType() == NULL)
@@ -5073,6 +5169,15 @@ SymbolExpr::Optimize() {
}
int
SymbolExpr::EstimateCost() const {
if (symbol->constValue != NULL)
return 0;
else
return COST_LOAD;
}
void
SymbolExpr::Print() const {
if (symbol == NULL || GetType() == NULL)
@@ -5126,6 +5231,12 @@ FunctionSymbolExpr::Optimize() {
}
int
FunctionSymbolExpr::EstimateCost() const {
return 0;
}
void
FunctionSymbolExpr::Print() const {
if (!matchingFunc || !GetType())
@@ -5160,6 +5271,12 @@ SyncExpr::GetValue(FunctionEmitContext *ctx) const {
}
int
SyncExpr::EstimateCost() const {
return COST_SYNC;
}
void
SyncExpr::Print() const {
printf("sync");