zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #03220
[Merge] lp:~zorba-coders/zorba/gen-flwor-opt into lp:zorba
Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/gen-flwor-opt into lp:zorba.
Requested reviews:
Markos Zaharioudakis (markos-za)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/gen-flwor-opt/+merge/87444
general flwor compile-time optimizations
--
https://code.launchpad.net/~zorba-coders/zorba/gen-flwor-opt/+merge/87444
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/compiler/expression/fo_expr.cpp'
--- src/compiler/expression/fo_expr.cpp 2011-11-23 15:16:51 +0000
+++ src/compiler/expression/fo_expr.cpp 2012-01-04 09:24:32 +0000
@@ -38,7 +38,7 @@
{
if (v.begin_visit(*this))
{
- accept_children(v);
+ accept_children(v);
}
v.end_visit(*this);
@@ -147,6 +147,17 @@
return theFunction->getName();
}
+void fo_expr::add_arg(expr_t e)
+{
+ theArgs.push_back(e);
+ compute_scripting_kind();
+}
+
+void fo_expr::add_args(const std::vector<expr_t> &args)
+{
+ theArgs.insert(theArgs.end(), args.begin(), args.end());
+ compute_scripting_kind();
+}
void fo_expr::compute_scripting_kind()
{
@@ -179,7 +190,7 @@
ERROR_PARAMS(ZED(XUST0001_CONCAT)),
ERROR_LOC(theArgs[i]->get_loc()));
}
-
+
if (i > 0 && !is_updating() && !is_vacuous() && (argKind & UPDATING_EXPR))
{
throw XQUERY_EXCEPTION(err::XUST0001,
@@ -248,7 +259,7 @@
expr_t fo_expr::clone(substitution_t& subst) const
{
- if (get_func()->getKind() ==
+ if (get_func()->getKind() ==
FunctionConsts::ZORBA_STORE_COLLECTIONS_STATIC_DML_COLLECTION_1)
{
expr::subst_iter_t i = subst.find(this);
=== modified file 'src/compiler/expression/fo_expr.h'
--- src/compiler/expression/fo_expr.h 2012-01-03 12:10:06 +0000
+++ src/compiler/expression/fo_expr.h 2012-01-04 09:24:32 +0000
@@ -79,11 +79,25 @@
const store::Item* get_fname() const;
+<<<<<<< TREE
csize num_args() const { return theArgs.size(); }
expr* get_arg(csize i) const { return theArgs[i].getp(); }
void set_arg(csize i, expr* e) { theArgs[i] = e; }
+=======
+ ulong num_args() const { return (ulong)theArgs.size(); }
+
+ expr* get_arg(ulong i) const { return theArgs[i].getp(); }
+
+ const std::vector<expr_t>& get_args() const {return theArgs;}
+
+ void set_arg(ulong i, expr* e) { theArgs[i] = e; }
+>>>>>>> MERGE-SOURCE
+
+ void add_arg(expr_t e);
+
+ void add_args(const std::vector<expr_t> &args);
void compute_scripting_kind();
=== modified file 'src/compiler/rewriter/rules/flwor_rules.cpp'
--- src/compiler/rewriter/rules/flwor_rules.cpp 2011-09-02 20:43:46 +0000
+++ src/compiler/rewriter/rules/flwor_rules.cpp 2012-01-04 09:24:32 +0000
@@ -173,7 +173,7 @@
expr* whereExpr;
if ((whereExpr = flwor.get_where()) != NULL && !flwor.has_sequential_clauses())
{
- const expr_tools::var_ptr_set& whereVars =
+ const expr_tools::var_ptr_set& whereVars =
expr_tools::get_varset_annotation(whereExpr);
expr_tools::var_ptr_set diff;
@@ -229,7 +229,7 @@
ulong domainCount = TypeOps::type_max_cnt(tm, *domainType);
const var_expr* pvar = fc->get_pos_var();
- if (pvar != NULL &&
+ if (pvar != NULL &&
expr_tools::count_variable_uses(&flwor, pvar, &rCtx, 1) == 0)
{
MODIFY(fc->set_pos_var(NULL));
@@ -340,7 +340,7 @@
let_clause_t save = lc;
MODIFY(flwor.remove_clause(i));
const QueryLoc& loc = var->get_loc();
- var_expr_t fvar = new var_expr(sctx, loc, var_expr::for_var, var->get_name());
+ var_expr_t fvar = new var_expr(sctx, loc, var_expr::for_var, var->get_name());
for_clause_t fc = new for_clause(sctx, loc, fvar, domainExpr);
flwor.add_clause(i, fc);
@@ -376,7 +376,7 @@
if ((whereExpr = flwor.get_where()) != NULL)
{
- rchandle<if_expr> ifExpr =
+ rchandle<if_expr> ifExpr =
new if_expr(whereExpr->get_sctx(),
LOC(whereExpr),
whereExpr,
@@ -384,7 +384,7 @@
fo_expr::create_seq(whereExpr->get_sctx(),
LOC(whereExpr)));
fix_if_annotations(ifExpr);
-
+
return ifExpr.getp();
}
@@ -406,7 +406,7 @@
FOR, LET, or WINDOW clauses of a flwor expr.
********************************************************************************/
static void collect_flw_vars(
- const flwor_expr& flwor,
+ const flwor_expr& flwor,
expr_tools::VarSetAnnVal& vars)
{
for (uint32_t i = 0; i < flwor.num_clauses(); ++i)
@@ -499,9 +499,9 @@
Check if it is OK to fold (inline) a FOR/LET var X that we know is referenced
only once withing its flwor expr.
- For a LET var, varQuant is always QUNAT_ONE.
+ For a LET var, varQuant is always QUNAT_ONE.
- For a FOR var, varQuant is the quantifier of the type of the domain expr.
+ For a FOR var, varQuant is the quantifier of the type of the domain expr.
It can be either QUANT_ONE or QUANT_QUESTION.
********************************************************************************/
static bool safe_to_fold_single_use(
@@ -597,7 +597,7 @@
if (varQuant != TypeConstants::QUANT_ONE)
{
// X is a FOR var which is referenced in the current LET clause, and
- // whose domain may be the empty sequence. We cannot inline in this
+ // whose domain may be the empty sequence. We cannot inline in this
// case.
return false;
}
@@ -612,7 +612,7 @@
}
else if (kind == flwor_clause::where_clause)
{
- if (varQuant == TypeConstants::QUANT_ONE &&
+ if (varQuant == TypeConstants::QUANT_ONE &&
expr_tools::count_variable_uses(c.get_expr(), var, NULL, 1) == 1)
{
referencingExpr = c.get_expr();
@@ -639,7 +639,7 @@
{
if (varQuant != TypeConstants::QUANT_ONE)
{
- xqtref_t type =
+ xqtref_t type =
flwor.get_return_expr()->get_return_type_with_empty_input(var);
if (TypeOps::is_equal(tm,
@@ -661,16 +661,16 @@
return !var_in_try_block_or_in_loop(var,
referencingExpr,
false,
- hasNodeConstr,
+ hasNodeConstr,
found);
}
/*******************************************************************************
- Given a variable V and an expression E that references V at most once, return
+ Given a variable V and an expression E that references V at most once, return
true if E does indeed reference V and
(a) the reference occurs inside a for-loop within E, or
- (b)
+ (b)
********************************************************************************/
static bool var_in_try_block_or_in_loop(
const var_expr* v,
@@ -758,7 +758,7 @@
TypeOps::type_max_cnt(tm, *flc.get_expr()->get_return_type()) >= 2)
{
// we assume here that the var will be referenced somewhere in the
- // remainder of the flwor expr, but this is not necessarily true
+ // remainder of the flwor expr, but this is not necessarily true
// ???? TODO
return true;
}
@@ -866,38 +866,88 @@
flwor_expr* flwor = dynamic_cast<flwor_expr *>(node);
- if (flwor == NULL || flwor->is_general())
+ if (flwor == NULL)
return NULL;
bool modified = false;
- if_expr* ifReturnExpr = NULL;
- expr* elseExpr = NULL;
- expr_t condExpr;
- expr_t thenExpr;
+ expr* whereExpr = NULL;
+ if(!flwor->is_general())
+ whereExpr = flwor->get_where();
if (flwor->get_return_expr()->get_expr_kind() == if_expr_kind)
{
- ifReturnExpr = static_cast<if_expr*>(flwor->get_return_expr());
- condExpr = ifReturnExpr->get_cond_expr();
- thenExpr = ifReturnExpr->get_then_expr();
- elseExpr = ifReturnExpr->get_else_expr();
- }
-
- expr* whereExpr = flwor->get_where();
-
- // "for $x in ... return if (ce) then te else ()" -->
- // "for $x in ... where ce return te"
- if (ifReturnExpr != NULL &&
- whereExpr == NULL &&
- !condExpr->is_sequential() &&
- (elseExpr->is_simple() || elseExpr->is_vacuous()) &&
- !elseExpr->isNonDiscardable() &&
- TypeOps::is_empty(tm, *elseExpr->get_return_type()))
- {
- flwor->set_where(condExpr);
- flwor->set_return_expr(thenExpr);
- modified = true;
+ if_expr* ifReturnExpr = static_cast<if_expr*>(flwor->get_return_expr());
+
+ expr_t condExpr = ifReturnExpr->get_cond_expr();
+ expr_t thenExpr = ifReturnExpr->get_then_expr();
+ expr* elseExpr = ifReturnExpr->get_else_expr();
+
+ expr_t newWhereExpr = condExpr;
+
+ if(!flwor->is_general())
+ {
+
+ if(whereExpr->get_expr_kind() == fo_expr_kind &&
+ static_cast<fo_expr*>(whereExpr)->get_func() ==
+ GET_BUILTIN_FUNCTION(OP_AND_N))
+ {
+ if(condExpr->get_expr_kind() == fo_expr_kind &&
+ static_cast<fo_expr*>(condExpr.getp())->get_func() ==
+ GET_BUILTIN_FUNCTION(OP_AND_N))
+ {
+ newWhereExpr = whereExpr;
+ static_cast<fo_expr*>(newWhereExpr.getp())->add_args(
+ static_cast<fo_expr*>(condExpr.getp())->get_args());
+ }
+ else
+ {
+ newWhereExpr = whereExpr;
+ static_cast<fo_expr*>(newWhereExpr.getp())->add_arg(condExpr);
+ }
+ }
+ else if(condExpr->get_expr_kind() == fo_expr_kind &&
+ static_cast<fo_expr*>(condExpr.getp())->get_func() ==
+ GET_BUILTIN_FUNCTION(OP_AND_N))
+ {
+ newWhereExpr = condExpr;
+ static_cast<fo_expr*>(newWhereExpr.getp())->add_arg(whereExpr);
+ }
+ else
+ {
+
+ newWhereExpr = new fo_expr(whereExpr->get_sctx(),
+ whereExpr->get_loc(),
+ GET_BUILTIN_FUNCTION(OP_AND_N),
+ condExpr,
+ whereExpr);
+
+ }
+
+ }
+
+
+ // "for $x in ... return if (ce) then te else ()" -->
+ // "for $x in ... where ce return te"
+ if (!condExpr->is_sequential() &&
+ (elseExpr->is_simple() || elseExpr->is_vacuous()) &&
+ !elseExpr->isNonDiscardable() &&
+ TypeOps::is_empty(tm, *elseExpr->get_return_type()))
+ {
+
+ if(flwor->is_general())
+ {
+ flwor->add_where(condExpr);
+ }
+ else
+ {
+ flwor->set_where(newWhereExpr);
+ }
+
+ flwor->set_return_expr(thenExpr);
+ modified = true;
+ }
+
}
expr_t posExpr;
@@ -909,7 +959,8 @@
// referenced more than once?
// TODO: we should be able to apply the rule if all the sequential clauses
// are before the clause that defines the pos var.
- if (whereExpr != NULL &&
+ if (!flwor->is_general() &&
+ whereExpr != NULL &&
! flwor->has_sequential_clauses() &&
is_subseq_pred(rCtx, flwor, whereExpr, posVar, posExpr) &&
expr_tools::count_variable_uses(flwor, posVar, &rCtx, 2) <= 1)
@@ -949,12 +1000,12 @@
(a) op is eq or =, and
(b1) posExpr is an integer literal with value >= 1, or
- (b2) the flwor expr has no sequential clauses and posExpr is an expression
- whose type is xs:Integer? and which does not reference the for var
- associated with posVar nor any other vars that are defined after that
+ (b2) the flwor expr has no sequential clauses and posExpr is an expression
+ whose type is xs:Integer? and which does not reference the for var
+ associated with posVar nor any other vars that are defined after that
for var.
- TODO: (b2) can be relaxed somewhat: it is ok if all the sequential clauses are
+ TODO: (b2) can be relaxed somewhat: it is ok if all the sequential clauses are
before the clause that defines the pos var.
********************************************************************************/
static bool is_subseq_pred(
@@ -1043,7 +1094,7 @@
if (posExprVarIds[i] >= forVarId)
return false;
}
-
+
return true;
}
}
@@ -1096,11 +1147,11 @@
}
ulong numClauses = returnFlwor->num_clauses();
-
+
for (ulong i = 0; i < numClauses; ++i)
{
const flwor_clause* c = (*returnFlwor)[i];
-
+
if (c->get_kind() == flwor_clause::group_clause ||
c->get_kind() == flwor_clause::order_clause)
{
@@ -1133,7 +1184,7 @@
expr* domainExpr = c->get_expr();
- if (domainExpr != NULL &&
+ if (domainExpr != NULL &&
domainExpr->get_expr_kind() == flwor_expr_kind &&
!domainExpr->is_sequential())
{
Follow ups