void CseSpotter::analyseExpr(IHqlExpression * expr) { CseSpotterInfo * extra = queryBodyExtra(expr); if (!extra->annotatedExpr && expr->isAnnotation()) extra->annotatedExpr = expr; if (isAssociated) extra->numAssociatedRefs++; node_operator op = expr->getOperator(); #ifdef OPTIMIZE_INVERSE if (getInverseOp(op) != no_none) { OwnedHqlExpr inverse = getInverse(expr); CseSpotterInfo * inverseExtra = queryBodyExtra(inverse); extra->inverse = inverseExtra; inverseExtra->inverse = extra; } #endif if (op == no_alias) { queryBodyExtra(expr->queryChild(0))->alreadyAliased = true; extra->alreadyAliased = true; } switch (op) { case no_assign: case no_transform: case no_newtransform: case no_range: case no_rangefrom: if (expr->isConstant()) return; break; case no_constant: return; } if (extra->numRefs++ != 0) { if (op == no_alias) return; if (!spottedCandidate && extra->worthAliasing()) spottedCandidate = true; if (canCreateTemporary(expr)) return; //Ugly! This is here as a temporary hack to stop branches of maps being commoned up and always //evaluated. The alias spotting and generation really needs to take conditionality into account.... if (op == no_mapto) return; } if (!containsPotentialCSE(expr)) return; if (canAlias && !expr->isDataset()) extra->canAlias = true; bool savedCanAlias = canAlias; if (expr->isDataset() && (op != no_select) && (!spotCseInIfDatasetConditions || (op != no_if))) { //There is little point looking for CSEs within dataset expressions, because only a very small //minority which would correctly cse, and it can cause lots of problems - e.g., join conditions. unsigned first = getFirstActivityArgument(expr); unsigned num = getNumActivityArguments(expr); HqlExprArray children; bool defaultCanAlias = canAlias; ForEachChild(i, expr) { IHqlExpression * cur = expr->queryChild(i); if (i >= first && i < first+num) canAlias = defaultCanAlias; else canAlias = false; analyseExpr(cur); }
inline void noteCandidate(IHqlExpression * expr) { noteCandidate(queryBodyExtra(expr)); }