OmniSciDB  04ee39c94c
ResultSetReductionJIT.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, 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 "CgenState.h"
20 #include "CodeCache.h"
21 
23 #include "Shared/TargetInfo.h"
24 
25 #include <llvm/ExecutionEngine/ExecutionEngine.h>
26 #include <llvm/IR/Module.h>
27 #include <llvm/IR/Value.h>
28 
29 struct ReductionCode {
30  ReductionCode(ReductionCode&&) = default;
31 
33  // We only need to worry about races for the interpreter, which owns the execution
34  // engine and has a null native function pointer.
35  if (own_execution_engine.get() && !func_ptr) {
36  std::lock_guard<std::mutex> reduction_guard(ReductionCode::s_reduction_mutex);
37  cgen_state = nullptr;
38  module = nullptr;
40  }
41  }
42 
43  // Function which reduces 'that_buff' into 'this_buff', for rows between
44  // [start_entry_index, end_entry_index).
45  using FuncPtr = int32_t (*)(int8_t* this_buff,
46  const int8_t* that_buff,
47  const int32_t start_entry_index,
48  const int32_t end_entry_index,
49  const int32_t that_entry_count,
50  const void* this_qmd,
51  const void* that_qmd,
52  const void* serialized_varlen_buffer);
53 
54  std::unique_ptr<CgenState> cgen_state;
55  llvm::ExecutionEngine* execution_engine;
57  std::unique_ptr<llvm::Module> module;
58  llvm::Function* ir_is_empty;
59  llvm::Function* ir_reduce_one_entry;
60  llvm::Function* ir_reduce_one_entry_idx;
61  llvm::Function* ir_reduce_loop;
63 
64  static std::mutex s_reduction_mutex;
65 };
66 
68  public:
69  ResultSetReductionJIT(const QueryMemoryDescriptor& query_mem_desc,
70  const std::vector<TargetInfo>& targets,
71  const std::vector<int64_t>& target_init_vals);
72 
73  // Generate the code for the result set reduction loop.
74  ReductionCode codegen() const;
75 
76  static void clearCache();
77 
78  private:
79  // Generate a function which checks whether a row is empty.
80  void isEmpty(const ReductionCode& reduction_code) const;
81 
82  // Generate a function which reduces two rows given by their start pointer, for the
83  // perfect hash layout.
84  void reduceOneEntryNoCollisions(const ReductionCode& reduction_code) const;
85 
86  // Used to implement 'reduceOneEntryNoCollisions'.
87  void reduceOneEntryTargetsNoCollisions(const ReductionCode& reduction_code,
88  llvm::Value* this_targets_start_ptr,
89  llvm::Value* that_targets_start_ptr) const;
90 
91  // Same as above, for the baseline layout.
92  void reduceOneEntryBaseline(const ReductionCode& reduction_code) const;
93 
94  // Generate a function which reduces two rows given by the start pointer of the result
95  // buffers they are part of and the indices inside those buffers.
96  void reduceOneEntryNoCollisionsIdx(const ReductionCode& reduction_code) const;
97 
98  // Same as above, for the baseline layout.
99  void reduceOneEntryBaselineIdx(const ReductionCode& reduction_code) const;
100 
101  // Generate a function for the reduction of an entire result set chunk.
102  void reduceLoop(const ReductionCode& reduction_code) const;
103 
104  // Generate reduction code for a single slot.
105  void reduceOneSlot(llvm::Value* this_ptr1,
106  llvm::Value* this_ptr2,
107  llvm::Value* that_ptr1,
108  llvm::Value* that_ptr2,
109  const TargetInfo& target_info,
110  const size_t target_logical_idx,
111  const size_t target_slot_idx,
112  const size_t init_agg_val_idx,
113  const size_t first_slot_idx_for_target,
114  const ReductionCode& reduction_code) const;
115 
116  // Generate reduction code for a single aggregate (with the exception of sample) slot.
117  void reduceOneAggregateSlot(llvm::Value* this_ptr1,
118  llvm::Value* this_ptr2,
119  llvm::Value* that_ptr1,
120  llvm::Value* that_ptr2,
121  const TargetInfo& target_info,
122  const size_t target_logical_idx,
123  const size_t target_slot_idx,
124  const int64_t init_val,
125  const int8_t chosen_bytes,
126  const ReductionCode& reduction_code) const;
127 
128  // Generate reduction code for a count distinct slot.
129  void reduceOneCountDistinctSlot(llvm::Value* this_ptr1,
130  llvm::Value* that_ptr1,
131  const size_t target_logical_idx,
132  const ReductionCode& reduction_code) const;
133 
134  ReductionCode finalizeReductionCode(ReductionCode reduction_code) const;
135 
136  // Returns true iff we will (should and is possible to) use the LLVM interpreter.
137  bool useInterpreter(const CgenState* cgen_state) const;
138 
140  const std::vector<TargetInfo> targets_;
141  const std::vector<int64_t> target_init_vals_;
143 };
std::unique_ptr< CgenState > cgen_state
llvm::Function * ir_reduce_one_entry
llvm::Function * ir_is_empty
llvm::ExecutionEngine * get()
Definition: CodeCache.h:45
ReductionCode(ReductionCode &&)=default
const std::vector< int64_t > target_init_vals_
int32_t(*)(int8_t *this_buff, const int8_t *that_buff, const int32_t start_entry_index, const int32_t end_entry_index, const int32_t that_entry_count, const void *this_qmd, const void *that_qmd, const void *serialized_varlen_buffer) FuncPtr
const QueryMemoryDescriptor query_mem_desc_
static std::mutex s_reduction_mutex
llvm::Function * ir_reduce_one_entry_idx
ExecutionEngineWrapper own_execution_engine
Descriptor for the result set buffer layout.
std::unique_ptr< llvm::Module > module
llvm::Function * ir_reduce_loop
llvm::ExecutionEngine * execution_engine
const std::vector< TargetInfo > targets_