int UnrolledLoopStatement::inlineCost(InlineCostState *ics) { int cost = 0; for (size_t i = 0; i < statements->dim; i++) { Statement *s = (*statements)[i]; if (s) { cost += s->inlineCost(ics); if (tooCostly(cost)) break; } } return cost; }
int CompoundStatement::inlineCost(InlineCostState *ics) { int cost = 0; for (size_t i = 0; i < statements->dim; i++) { Statement *s = (*statements)[i]; if (s) { cost += s->inlineCost(ics); if (tooCostly(cost)) break; } } //printf("CompoundStatement::inlineCost = %d\n", cost); return cost; }
void visit(CompoundStatement *s) { InlineCostVisitor icv(this); for (size_t i = 0; i < s->statements->dim; i++) { Statement *s2 = (*s->statements)[i]; if (s2) { s2->accept(&icv); if (tooCostly(icv.cost)) break; } } cost += icv.cost; }
int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) { InlineCostState ics; int cost; #define CANINLINE_LOG 0 #if CANINLINE_LOG printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toPrettyChars()); #endif if (needThis() && !hasthis) return 0; if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan)) { #if CANINLINE_LOG printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); #endif return 0; } #if 1 switch (statementsToo ? inlineStatusStmt : inlineStatusExp) { case ILSyes: #if CANINLINE_LOG printf("\t1: yes %s\n", toChars()); #endif return 1; case ILSno: #if CANINLINE_LOG printf("\t1: no %s\n", toChars()); #endif return 0; case ILSuninitialized: break; default: assert(0); } #endif if (type) { assert(type->ty == Tfunction); TypeFunction *tf = (TypeFunction *)type; if (tf->varargs == 1) // no variadic parameter lists goto Lno; /* Don't inline a function that returns non-void, but has * no return expression. * No statement inlining for non-voids. */ if (tf->next && tf->next->ty != Tvoid && (!(hasReturnExp & 1) || statementsToo) && !hdrscan) goto Lno; } // cannot inline constructor calls because we need to convert: // return; // to: // return this; if ( !fbody || ident == Id::ensure || // ensure() has magic properties the inliner loses (ident == Id::require && // require() has magic properties too toParent()->isFuncDeclaration() && // see bug 7699 toParent()->isFuncDeclaration()->needThis()) || !hdrscan && ( isSynchronized() || isImportedSymbol() || hasNestedFrameRefs() || // no nested references to this frame (isVirtual() && !isFinalFunc()) )) { goto Lno; } #if 0 /* If any parameters are Tsarray's (which are passed by reference) * or out parameters (also passed by reference), don't do inlining. */ if (parameters) { for (size_t i = 0; i < parameters->dim; i++) { VarDeclaration *v = (*parameters)[i]; if (v->type->toBasetype()->ty == Tsarray) goto Lno; } } #endif memset(&ics, 0, sizeof(ics)); ics.hasthis = hasthis; ics.fd = this; ics.hdrscan = hdrscan; cost = fbody->inlineCost(&ics); #if CANINLINE_LOG printf("cost = %d for %s\n", cost, toChars()); #endif if (tooCostly(cost)) goto Lno; if (!statementsToo && cost > COST_MAX) goto Lno; if (!hdrscan) { // Don't modify inlineStatus for header content scan if (statementsToo) inlineStatusStmt = ILSyes; else inlineStatusExp = ILSyes; inlineScan(); // Don't scan recursively for header content scan if (inlineStatusExp == ILSuninitialized) { // Need to redo cost computation, as some statements or expressions have been inlined memset(&ics, 0, sizeof(ics)); ics.hasthis = hasthis; ics.fd = this; ics.hdrscan = hdrscan; cost = fbody->inlineCost(&ics); #if CANINLINE_LOG printf("recomputed cost = %d for %s\n", cost, toChars()); #endif if (tooCostly(cost)) goto Lno; if (!statementsToo && cost > COST_MAX) goto Lno; if (statementsToo) inlineStatusStmt = ILSyes; else inlineStatusExp = ILSyes; } } #if CANINLINE_LOG printf("\t2: yes %s\n", toChars()); #endif return 1; Lno: if (!hdrscan) // Don't modify inlineStatus for header content scan { if (statementsToo) inlineStatusStmt = ILSno; else inlineStatusExp = ILSno; } #if CANINLINE_LOG printf("\t2: no %s\n", toChars()); #endif return 0; }