OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JoinLoop.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <llvm/IR/BasicBlock.h>
20 #include <llvm/IR/IRBuilder.h>
21 #include <llvm/IR/Value.h>
22 #include "Logger/Logger.h"
23 
24 #include "../../Shared/sqldefs.h"
25 #include "../CgenState.h"
26 #include "../IRCodegenUtils.h"
27 
28 #include <functional>
29 #include <vector>
30 
31 enum class JoinLoopKind {
32  UpperBound, // loop join
33  Set, // one to many hash join
34  Singleton, // one to one hash join
35  MultiSet // many to many hash join
36 };
37 
38 // The domain of iteration for a join:
39 // 1. For loop join, from 0 to `upper_bound`.
40 // 2. For one-to-one joins, at most one value: `slot_lookup_result` if valid (greater than
41 // or equal to zero).
42 // 3. For one-to-many joins, the `element_count` values in `values_buffer`.
44  union {
45  llvm::Value* upper_bound; // for UpperBound
46  llvm::Value* element_count; // for Set
47  llvm::Value* slot_lookup_result; // for Singleton
48  };
49  llvm::Value* values_buffer; // used for Set
50  llvm::Value* error_code;
51 };
52 
53 // Any join is logically a loop. Hash joins just limit the domain of iteration,
54 // which can be as little as one element for one to one hash join, in which case
55 // we'll not generate IR for an actual loop.
56 class JoinLoop {
57  public:
58  using HoistedFiltersCallback = std::function<llvm::BasicBlock*(llvm::BasicBlock*,
59  llvm::BasicBlock*,
60  const std::string&,
61  llvm::Function*,
63 
64  JoinLoop(const JoinLoopKind,
65  const JoinType,
66  const std::function<JoinLoopDomain(const std::vector<llvm::Value*>&)>&
67  iteration_domain_codegen,
68  const std::function<llvm::Value*(const std::vector<llvm::Value*>&)>&
69  outer_condition_match,
70  const std::function<void(llvm::Value*)>& found_outer_matches,
71  const HoistedFiltersCallback& hoisted_filters,
72  const std::function<llvm::Value*(const std::vector<llvm::Value*>& prev_iters,
73  llvm::Value*)>& is_deleted,
74  const bool nested_loop_join = false,
75  const std::string& name = "");
76 
77  static llvm::BasicBlock* codegen(
78  const std::vector<JoinLoop>& join_loops,
79  const std::function<llvm::BasicBlock*(const std::vector<llvm::Value*>&)>&
80  body_codegen,
81  llvm::Value* outer_iter,
82  llvm::BasicBlock* exit_bb,
83  CgenState* cgen_state);
84 
85  JoinLoopKind kind() const { return kind_; }
86 
87  bool isNestedLoopJoin() const { return nested_loop_join_; }
88 
89  private:
90  static std::pair<llvm::BasicBlock*, llvm::Value*> evaluateOuterJoinCondition(
91  const JoinLoop& join_loop,
92  const JoinLoopDomain& iteration_domain,
93  const std::vector<llvm::Value*>& iterators,
94  llvm::Value* iteration_counter,
95  llvm::Value* have_more_inner_rows,
96  llvm::Value* found_an_outer_match_ptr,
97  llvm::Value* current_condition_match_ptr,
98  CgenState* cgen_state);
99 
101  // SQL type of the join.
103  // Callback provided from the executor which generates the code for the given join
104  // domain of iteration.
105  const std::function<JoinLoopDomain(const std::vector<llvm::Value*>&)>
107  // Callback provided from the executor which generates true iff the outer condition
108  // evaluates to true.
109  const std::function<llvm::Value*(const std::vector<llvm::Value*>&)>
111  // Callback provided from the executor which receives the IR boolean value which tracks
112  // whether there are matches for the current iteration.
113  const std::function<void(llvm::Value*)> found_outer_matches_;
114  // Callback to hoist left hand side filters through the join, evaluating the filters
115  // prior to evaluating the join (but within the same kernel)
117  // Callback provided from the executor which returns if the current row (given by
118  // position) is deleted. The second argument is true iff the iteration isn't done yet.
119  // Useful for UpperBound and Set, which need to avoid fetching the deleted column from a
120  // past-the-end position. It's null for Singleton.
121  const std::function<llvm::Value*(const std::vector<llvm::Value*>& prev_iters,
122  llvm::Value*)>
124  // true if the join loop is for nested loop join
125  const bool nested_loop_join_;
126  const std::string name_;
127 };
JoinType
Definition: sqldefs.h:238
llvm::Value * element_count
Definition: JoinLoop.h:46
llvm::Value * values_buffer
Definition: JoinLoop.h:49
std::function< llvm::BasicBlock *(llvm::BasicBlock *, llvm::BasicBlock *, const std::string &, llvm::Function *, CgenState *)> HoistedFiltersCallback
Definition: JoinLoop.h:62
const std::function< llvm::Value *(const std::vector< llvm::Value * > &)> outer_condition_match_
Definition: JoinLoop.h:110
const JoinType type_
Definition: JoinLoop.h:102
const JoinLoopKind kind_
Definition: JoinLoop.h:100
llvm::Value * error_code
Definition: JoinLoop.h:50
const std::function< JoinLoopDomain(const std::vector< llvm::Value * > &)> iteration_domain_codegen_
Definition: JoinLoop.h:106
const std::function< void(llvm::Value *)> found_outer_matches_
Definition: JoinLoop.h:113
const std::string name_
Definition: JoinLoop.h:126
static llvm::BasicBlock * codegen(const std::vector< JoinLoop > &join_loops, const std::function< llvm::BasicBlock *(const std::vector< llvm::Value * > &)> &body_codegen, llvm::Value *outer_iter, llvm::BasicBlock *exit_bb, CgenState *cgen_state)
Definition: JoinLoop.cpp:50
JoinLoopKind kind() const
Definition: JoinLoop.h:85
llvm::Value * slot_lookup_result
Definition: JoinLoop.h:47
llvm::Value * upper_bound
Definition: JoinLoop.h:45
JoinLoop(const JoinLoopKind, const JoinType, const std::function< JoinLoopDomain(const std::vector< llvm::Value * > &)> &iteration_domain_codegen, const std::function< llvm::Value *(const std::vector< llvm::Value * > &)> &outer_condition_match, const std::function< void(llvm::Value *)> &found_outer_matches, const HoistedFiltersCallback &hoisted_filters, const std::function< llvm::Value *(const std::vector< llvm::Value * > &prev_iters, llvm::Value *)> &is_deleted, const bool nested_loop_join=false, const std::string &name="")
Definition: JoinLoop.cpp:25
const std::function< llvm::Value *(const std::vector< llvm::Value * > &prev_iters, llvm::Value *)> is_deleted_
Definition: JoinLoop.h:123
JoinLoopKind
Definition: JoinLoop.h:31
const bool nested_loop_join_
Definition: JoinLoop.h:125
bool isNestedLoopJoin() const
Definition: JoinLoop.h:87
string name
Definition: setup.in.py:72
const HoistedFiltersCallback hoisted_filters_
Definition: JoinLoop.h:116
static std::pair< llvm::BasicBlock *, llvm::Value * > evaluateOuterJoinCondition(const JoinLoop &join_loop, const JoinLoopDomain &iteration_domain, const std::vector< llvm::Value * > &iterators, llvm::Value *iteration_counter, llvm::Value *have_more_inner_rows, llvm::Value *found_an_outer_match_ptr, llvm::Value *current_condition_match_ptr, CgenState *cgen_state)
Definition: JoinLoop.cpp:313