1#pragma once
2
3#include "config_core.h"
4#if USE_EMBEDDED_COMPILER
5
6#include <Functions/IFunctionImpl.h>
7#include <Interpreters/Context.h>
8#include <Interpreters/ExpressionActions.h>
9#include <Common/LRUCache.h>
10#include <set>
11
12
13namespace DB
14{
15
16using CompilableExpression = std::function<llvm::Value * (llvm::IRBuilderBase &, const ValuePlaceholders &)>;
17
18struct LLVMModuleState;
19
20class LLVMFunction : public IFunctionBaseImpl
21{
22 std::string name;
23 Names arg_names;
24 DataTypes arg_types;
25
26 std::vector<FunctionBasePtr> originals;
27 std::unordered_map<StringRef, CompilableExpression> subexpressions;
28
29 std::unique_ptr<LLVMModuleState> module_state;
30
31public:
32 LLVMFunction(const ExpressionActions::Actions & actions, const Block & sample_block);
33
34 bool isCompilable() const override { return true; }
35
36 llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override;
37
38 String getName() const override { return name; }
39
40 const Names & getArgumentNames() const { return arg_names; }
41
42 const DataTypes & getArgumentTypes() const override { return arg_types; }
43
44 const DataTypePtr & getReturnType() const override { return originals.back()->getReturnType(); }
45
46 ExecutableFunctionImplPtr prepare(const Block &, const ColumnNumbers &, size_t) const override;
47
48 bool isDeterministic() const override;
49
50 bool isDeterministicInScopeOfQuery() const override;
51
52 bool isSuitableForConstantFolding() const override;
53
54 bool isInjective(const Block & sample_block) override;
55
56 bool hasInformationAboutMonotonicity() const override;
57
58 Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const override;
59
60 const LLVMModuleState * getLLVMModuleState() const { return module_state.get(); }
61};
62
63/** This child of LRUCache breaks one of it's invariants: total weight may be changed after insertion.
64 * We have to do so, because we don't known real memory consumption of generated LLVM code for every function.
65 */
66class CompiledExpressionCache : public LRUCache<UInt128, IFunctionBase, UInt128Hash>
67{
68public:
69 using Base = LRUCache<UInt128, IFunctionBase, UInt128Hash>;
70 using Base::Base;
71};
72
73/// For each APPLY_FUNCTION action, try to compile the function to native code; if the only uses of a compilable
74/// function's result are as arguments to other compilable functions, inline it and leave the now-redundant action as-is.
75void compileFunctions(ExpressionActions::Actions & actions, const Names & output_columns, const Block & sample_block, std::shared_ptr<CompiledExpressionCache> compilation_cache, size_t min_count_to_compile_expression);
76
77}
78
79#endif
80