Esempio n. 1
0
void SubExpressionTap::Optimize(Block *block){
	blocks.push(block);
	SubExpressionBlock *exprList = block->GetExprBlock();
	const int size = block->body.size();
	for(int i = 0; i < size; i++){
		Node *expr = block->body[i + temp_counter];
		if(expr->isCycle())
			continue;
		if(Block* b = dynamic_cast<Block*>(expr)){
			Optimize(b);
			continue;
		}
		if(FuncCallNode *cNode = dynamic_cast<FuncCallNode*>(expr)){
			for(Node *arg : cNode->args)
				GetArgs(*exprList, arg);
			continue;			
		}
		if(IfStatement *$if = dynamic_cast<IfStatement*>(expr)){
			Optimize(dynamic_cast<Block*>($if->if_branch));
			if($if->else_branch)
				Optimize(dynamic_cast<Block*>($if->else_branch));
			continue;
		}
		if(ReturnStatement *retNode = dynamic_cast<ReturnStatement*>(expr))
			expr = retNode->value;
		if(!expr->isExpression())
			continue;
		Node *t = OptimizeExpression(expr);
		if(t != expr){
			block->body[i + temp_counter] = t;		
		}
	}
	ReplaceFirstOccur();
	blocks.pop();
}
Esempio n. 2
0
Node* SubExpressionTap::OptimizeExpression(Node *node){
	Block *block = blocks.top();
	SubExpressionBlock *expBlock = block->exprBlock;
	vector<Node*> *opList = expBlock->expressions[node->value()];
	if(opList)
		for(Node *expr : *opList){
			if(expr == node){
				if(expr->commonNode){
					if(*expr->commonNode == expr){
						CreateNewIdent(expr->commonNode);
						return expr->commonNode->replaced;
					}
					return expr;
				}
			}
		}
	if(BinaryOpNode *bNode = dynamic_cast<BinaryOpNode*>(node)){
		Node *l_opt = OptimizeExpression(bNode->left),
			 *r_opt = OptimizeExpression(bNode->right);
		if(bNode->left != l_opt)
			bNode->left = l_opt;
		
		if(bNode->right != r_opt)
			bNode->right = r_opt;
	} else
		if(UnaryOpNode *uNode = dynamic_cast<UnaryOpNode*>(node)){
			bool opt = false;
			for(Node *expr : *opList){
				if(uNode->operand == expr){
					opt = true;
					if(uNode->operand->commonNode)
						CreateNewIdent(uNode->operand->commonNode);
					Node *optNode = OptimizeExpression(uNode->operand);
					if(optNode != uNode->operand){
						delete uNode->operand;
						uNode->operand = optNode;
					}
					break;
				}
			}
			if(!opt)
				OptimizeExpression(uNode->operand);
		}
	return node;
}
Esempio n. 3
0
void Optimizer::OptimizeGroup(GroupID id, PropertySet requirements) {
  LOG_TRACE("Optimizing group %d", id);
  Group *group = memo.GetGroupByID(id);
  const std::vector<std::shared_ptr<GroupExpression>> exprs =
      group->GetExpressions();
  for (size_t i = 0; i < exprs.size(); ++i) {
    OptimizeExpression(exprs[i], requirements);
  }
}
Esempio n. 4
0
void Optimizer::OptimizeExpression(std::shared_ptr<GroupExpression> gexpr,
                                   PropertySet requirements)
{
  LOG_TRACE("Optimizing expression of group %d with op %s",
            gexpr->GetGroupID(), gexpr->Op().name().c_str());

  // Helper function for costing follow up expressions
  auto CostCandidate =
    [this](std::shared_ptr<GroupExpression> candidate,
           PropertySet requirements)
    {
      // Cost the expression
      this->CostExpression(candidate);

      // Only include cost if it meets the property requirements
      if (requirements.IsSubset(candidate->Op().ProvidedOutputProperties())) {
        // Add to group as potential best cost
        Group *group = this->memo.GetGroupByID(candidate->GetGroupID());
        LOG_TRACE("Adding expression cost on group %d with op %s",
                  candidate->GetGroupID(), candidate->Op().name().c_str());
        group->SetExpressionCost(candidate,
                                 candidate->GetCost(),
                                 requirements);
      }
    };

  // Cost the root expression
  if (gexpr->Op().IsPhysical()) {
    CostCandidate(gexpr, requirements);
    // Transformation rules shouldn't match on physical operators so don't apply
    // rules
  } else {
    // Apply transformations and cost those which match the requirements
    for (const std::unique_ptr<Rule> &rule : rules) {
      // Apply all rules to operator which match. We apply all rules to one
      // operator before moving on to the next operator in the group because
      // then we avoid missing the application of a rule e.g. an application
      // of some rule creates a match for a previously applied rule, but it is
      // missed because the prev rule was already checked
      std::vector<std::shared_ptr<GroupExpression>> candidates =
        TransformExpression(gexpr, *(rule.get()));

      for (std::shared_ptr<GroupExpression> candidate : candidates) {
        // If logical...
        if (candidate->Op().IsLogical()) {
          // Optimize the expression
          OptimizeExpression(candidate, requirements);
        }
        if (candidate->Op().IsPhysical()) {
          CostCandidate(candidate, requirements);
        }
      }
    }
  }
}
Esempio n. 5
0
std::shared_ptr<planner::AbstractPlan> Optimizer::GeneratePlan(
    std::shared_ptr<Select> select_tree) {
  // Generate initial operator tree from query tree
  std::shared_ptr<GroupExpression> gexpr = InsertQueryTree(select_tree);
  GroupID root_id = gexpr->GetGroupID();

  // Get the physical properties the final plan must output
  PropertySet properties = GetQueryTreeRequiredProperties(select_tree);

  // Find least cost plan for root group
  OptimizeExpression(gexpr, properties);

  std::shared_ptr<OpExpression> best_plan = ChooseBestPlan(root_id, properties);

  if (best_plan == nullptr) return nullptr;

  planner::AbstractPlan *top_plan = OptimizerPlanToPlannerPlan(best_plan);

  std::shared_ptr<planner::AbstractPlan> final_plan(top_plan);

  return final_plan;
}