mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-30 05:30:51 +00:00
Updated interfaces
This commit is contained in:
parent
d2eecfe593
commit
24798ef07c
@ -1323,7 +1323,7 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
assert(2 == types.size() && 2 == values.size());
|
||||
|
||||
@ -1340,8 +1340,8 @@ public:
|
||||
{
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
auto type = std::make_shared<ResultDataType>();
|
||||
auto * lval = nativeCast(b, types[0], values[0](), type);
|
||||
auto * rval = nativeCast(b, types[1], values[1](), type);
|
||||
auto * lval = nativeCast(b, types[0], values[0], type);
|
||||
auto * rval = nativeCast(b, types[1], values[1], type);
|
||||
result = OpSpec::compile(b, lval, rval, std::is_signed_v<typename ResultDataType::FieldType>);
|
||||
return true;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
auto type = getReturnTypeImpl(types);
|
||||
@ -54,7 +54,7 @@ public:
|
||||
{
|
||||
auto * then = llvm::BasicBlock::Create(head->getContext(), "", head->getParent());
|
||||
auto * next = llvm::BasicBlock::Create(head->getContext(), "", head->getParent());
|
||||
auto * cond = values[i]();
|
||||
auto * cond = values[i];
|
||||
if (!null_is_false && types[i]->isNullable())
|
||||
{
|
||||
auto * nonnull = llvm::BasicBlock::Create(head->getContext(), "", head->getParent());
|
||||
@ -68,12 +68,12 @@ public:
|
||||
b.CreateCondBr(nativeBoolCast(b, types[i], cond), then, next);
|
||||
}
|
||||
b.SetInsertPoint(then);
|
||||
auto * value = nativeCast(b, types[i + 1], values[i + 1](), type);
|
||||
auto * value = nativeCast(b, types[i + 1], values[i + 1], type);
|
||||
returns.emplace_back(b.GetInsertBlock(), value);
|
||||
b.CreateBr(join);
|
||||
b.SetInsertPoint(next);
|
||||
}
|
||||
auto * value = nativeCast(b, types.back(), values.back()(), type);
|
||||
auto * value = nativeCast(b, types.back(), values.back(), type);
|
||||
returns.emplace_back(b.GetInsertBlock(), value);
|
||||
b.CreateBr(join);
|
||||
b.SetInsertPoint(join);
|
||||
|
@ -243,7 +243,7 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
assert(1 == types.size() && 1 == values.size());
|
||||
|
||||
@ -260,7 +260,7 @@ public:
|
||||
if constexpr (!std::is_same_v<T1, InvalidType> && !IsDataTypeDecimal<DataType> && Op<T0>::compilable)
|
||||
{
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
auto * v = nativeCast(b, types[0], values[0](), std::make_shared<DataTypeNumber<T1>>());
|
||||
auto * v = nativeCast(b, types[0], values[0], std::make_shared<DataTypeNumber<T1>>());
|
||||
result = Op<T0>::compile(b, v, is_signed_v<T1>);
|
||||
return true;
|
||||
}
|
||||
|
@ -1254,13 +1254,13 @@ public:
|
||||
return isCompilableType(types[0]) && isCompilableType(types[1]);
|
||||
}
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
assert(2 == types.size() && 2 == values.size());
|
||||
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
auto * x = values[0]();
|
||||
auto * y = values[1]();
|
||||
auto * x = values[0];
|
||||
auto * y = values[1];
|
||||
if (!types[0]->equals(*types[1]))
|
||||
{
|
||||
llvm::Type * common;
|
||||
|
@ -160,16 +160,16 @@ public:
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
bool isCompilableImpl(const DataTypes &) const override { return useDefaultImplementationForNulls(); }
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
assert(!types.empty() && !values.empty());
|
||||
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
if constexpr (!Impl::isSaturable())
|
||||
{
|
||||
auto * result = nativeBoolCast(b, types[0], values[0]());
|
||||
auto * result = nativeBoolCast(b, types[0], values[0]);
|
||||
for (size_t i = 1; i < types.size(); i++)
|
||||
result = Impl::apply(b, result, nativeBoolCast(b, types[i], values[i]()));
|
||||
result = Impl::apply(b, result, nativeBoolCast(b, types[i], values[i]));
|
||||
return b.CreateSelect(result, b.getInt8(1), b.getInt8(0));
|
||||
}
|
||||
constexpr bool breakOnTrue = Impl::isSaturatedValue(true);
|
||||
@ -180,7 +180,7 @@ public:
|
||||
for (size_t i = 0; i < types.size(); i++)
|
||||
{
|
||||
b.SetInsertPoint(next);
|
||||
auto * value = values[i]();
|
||||
auto * value = values[i];
|
||||
auto * truth = nativeBoolCast(b, types[i], value);
|
||||
if (!types[i]->equals(DataTypeUInt8{}))
|
||||
value = b.CreateSelect(truth, b.getInt8(1), b.getInt8(0));
|
||||
@ -223,10 +223,10 @@ public:
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
bool isCompilableImpl(const DataTypes &) const override { return true; }
|
||||
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, ValuePlaceholders values) const override
|
||||
llvm::Value * compileImpl(llvm::IRBuilderBase & builder, const DataTypes & types, Values values) const override
|
||||
{
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
return b.CreateSelect(Impl<UInt8>::apply(b, nativeBoolCast(b, types[0], values[0]())), b.getInt8(1), b.getInt8(0));
|
||||
return b.CreateSelect(Impl<UInt8>::apply(b, nativeBoolCast(b, types[0], values[0])), b.getInt8(1), b.getInt8(0));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
@ -516,58 +516,47 @@ bool IFunction::isCompilable(const DataTypes & arguments) const
|
||||
return isCompilableImpl(arguments);
|
||||
}
|
||||
|
||||
llvm::Value * IFunction::compile(llvm::IRBuilderBase & builder, const DataTypes & arguments, ValuePlaceholders values) const
|
||||
llvm::Value * IFunction::compile(llvm::IRBuilderBase & builder, const DataTypes & arguments, Values values) const
|
||||
{
|
||||
auto denulled_arguments = removeNullables(arguments);
|
||||
if (useDefaultImplementationForNulls() && denulled_arguments)
|
||||
{
|
||||
auto & b = static_cast<llvm::IRBuilder<> &>(builder);
|
||||
|
||||
std::vector<llvm::Value*> non_lazy_values;
|
||||
std::vector<llvm::Value*> unwrapped_values;
|
||||
std::vector<llvm::Value*> is_null_values;
|
||||
|
||||
non_lazy_values.reserve(arguments.size());
|
||||
unwrapped_values.reserve(arguments.size());
|
||||
is_null_values.reserve(arguments.size());
|
||||
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
auto * value = values[i]();
|
||||
auto * value = values[i];
|
||||
|
||||
WhichDataType data_type(arguments[i]);
|
||||
if (data_type.isNullable())
|
||||
{
|
||||
non_lazy_values.emplace_back(b.CreateExtractValue(value, {0}));
|
||||
unwrapped_values.emplace_back(b.CreateExtractValue(value, {0}));
|
||||
is_null_values.emplace_back(b.CreateExtractValue(value, {1}));
|
||||
}
|
||||
else
|
||||
{
|
||||
non_lazy_values.emplace_back(value);
|
||||
unwrapped_values.emplace_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
ValuePlaceholders place_holders;
|
||||
place_holders.reserve(non_lazy_values.size());
|
||||
auto * result = compileImpl(builder, *denulled_arguments, unwrapped_values);
|
||||
|
||||
for (size_t i = 0; i < non_lazy_values.size(); ++i)
|
||||
place_holders.emplace_back([lazy_value = non_lazy_values[i]](){ return lazy_value; });
|
||||
auto * nullable_structure_type = toNativeType(b, makeNullable(getReturnTypeImpl(*denulled_arguments)));
|
||||
auto * nullable_structure_value = llvm::Constant::getNullValue(nullable_structure_type);
|
||||
|
||||
auto * result = compileImpl(builder, *denulled_arguments, place_holders);
|
||||
auto * nullable_structure_with_result_value = b.CreateInsertValue(nullable_structure_value, result, {0});
|
||||
auto * nullable_structure_result_null = b.CreateExtractValue(nullable_structure_with_result_value, {1});
|
||||
|
||||
if (!is_null_values.empty())
|
||||
{
|
||||
auto * nullable_structure_type = toNativeType(b, makeNullable(getReturnTypeImpl(*denulled_arguments)));
|
||||
auto * nullable_structure_value = llvm::Constant::getNullValue(nullable_structure_type);
|
||||
for (auto * is_null_value : is_null_values)
|
||||
nullable_structure_result_null = b.CreateOr(nullable_structure_result_null, is_null_value);
|
||||
|
||||
auto * nullable_structure_with_result_value = b.CreateInsertValue(nullable_structure_value, result, {0});
|
||||
auto * nullable_structure_result_null = b.CreateExtractValue(nullable_structure_with_result_value, {1});
|
||||
|
||||
for (auto * is_null_value : is_null_values)
|
||||
nullable_structure_result_null = b.CreateOr(nullable_structure_result_null, is_null_value);
|
||||
|
||||
return b.CreateInsertValue(nullable_structure_with_result_value, nullable_structure_result_null, {1});
|
||||
}
|
||||
|
||||
return result;
|
||||
return b.CreateInsertValue(nullable_structure_with_result_value, nullable_structure_result_null, {1});
|
||||
// DataTypes non_null_arguments;
|
||||
// non_null_arguments.reserve(arguments.size());
|
||||
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
using ExecutableFunctionPtr = std::shared_ptr<IExecutableFunction>;
|
||||
|
||||
|
||||
using ValuePlaceholders = std::vector<std::function<llvm::Value * ()>>;
|
||||
using Values = std::vector<llvm::Value *>;
|
||||
|
||||
/// Function with known arguments and return type (when the specific overload was chosen).
|
||||
/// It is also the point where all function-specific properties are known.
|
||||
@ -90,7 +90,7 @@ public:
|
||||
* templates with default arguments is impossible and including LLVM in such a generic header
|
||||
* as this one is a major pain.
|
||||
*/
|
||||
virtual llvm::Value * compile(llvm::IRBuilderBase & /*builder*/, ValuePlaceholders /*values*/) const
|
||||
virtual llvm::Value * compile(llvm::IRBuilderBase & /*builder*/, Values /*values*/) const
|
||||
{
|
||||
throw Exception(getName() + " is not JIT-compilable", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
|
||||
bool isCompilable() const final { return impl->isCompilable(); }
|
||||
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, Values values) const override
|
||||
{
|
||||
return impl->compile(builder, std::move(values));
|
||||
}
|
||||
@ -183,7 +183,10 @@ public:
|
||||
|
||||
bool isCompilable() const override { return function->isCompilable(getArgumentTypes()); }
|
||||
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override { return function->compile(builder, getArgumentTypes(), std::move(values)); }
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, Values values) const override
|
||||
{
|
||||
return function->compile(builder, getArgumentTypes(), std::move(values));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
|
||||
virtual bool isCompilable() const { return false; }
|
||||
|
||||
virtual llvm::Value * compile(llvm::IRBuilderBase & /*builder*/, ValuePlaceholders /*values*/) const
|
||||
virtual llvm::Value * compile(llvm::IRBuilderBase & /*builder*/, Values /*values*/) const
|
||||
{
|
||||
throw Exception(getName() + " is not JIT-compilable", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
@ -284,7 +284,7 @@ public:
|
||||
|
||||
bool isCompilable(const DataTypes & arguments) const;
|
||||
|
||||
llvm::Value * compile(llvm::IRBuilderBase &, const DataTypes & arguments, ValuePlaceholders values) const;
|
||||
llvm::Value * compile(llvm::IRBuilderBase &, const DataTypes & arguments, Values values) const;
|
||||
|
||||
#endif
|
||||
|
||||
@ -294,7 +294,7 @@ protected:
|
||||
|
||||
virtual bool isCompilableImpl(const DataTypes &) const { return false; }
|
||||
|
||||
virtual llvm::Value * compileImpl(llvm::IRBuilderBase &, const DataTypes &, ValuePlaceholders) const
|
||||
virtual llvm::Value * compileImpl(llvm::IRBuilderBase &, const DataTypes &, Values) const
|
||||
{
|
||||
throw Exception(getName() + " is not JIT-compilable", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
@ -46,14 +46,12 @@ namespace
|
||||
{
|
||||
const char * data = nullptr;
|
||||
const char * null = nullptr;
|
||||
size_t stride = 0;
|
||||
};
|
||||
|
||||
struct ColumnDataPlaceholder
|
||||
{
|
||||
llvm::Value * data_init; /// first row
|
||||
llvm::Value * null_init;
|
||||
llvm::Value * stride;
|
||||
llvm::PHINode * data; /// current row
|
||||
llvm::PHINode * null;
|
||||
};
|
||||
@ -63,16 +61,18 @@ static ColumnData getColumnData(const IColumn * column)
|
||||
{
|
||||
ColumnData result;
|
||||
const bool is_const = isColumnConst(*column);
|
||||
/// TODO: There should be no const columns
|
||||
|
||||
if (is_const)
|
||||
column = &reinterpret_cast<const ColumnConst *>(column)->getDataColumn();
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Input columns should not be constant");
|
||||
|
||||
if (const auto * nullable = typeid_cast<const ColumnNullable *>(column))
|
||||
{
|
||||
result.null = nullable->getNullMapColumn().getRawData().data;
|
||||
column = &nullable->getNestedColumn();
|
||||
}
|
||||
|
||||
result.data = column->getRawData().data;
|
||||
result.stride = is_const ? 0 : column->sizeOfValueIfFixed();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -123,6 +123,7 @@ public:
|
||||
const auto * column = arguments[i].column.get();
|
||||
if (!column)
|
||||
throw Exception("Column " + arguments[i].name + " is missing", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
columns[i] = getColumnData(column);
|
||||
}
|
||||
|
||||
@ -182,7 +183,6 @@ static void compileFunction(llvm::Module & module, const IFunctionBaseImpl & f)
|
||||
auto * data = b.CreateLoad(b.CreateConstInBoundsGEP1_32(data_type, columns_arg, i));
|
||||
columns[i].data_init = b.CreatePointerCast(b.CreateExtractValue(data, {0}), toNativeType(b, removeNullable(type))->getPointerTo());
|
||||
columns[i].null_init = type->isNullable() ? b.CreateExtractValue(data, {1}) : nullptr;
|
||||
columns[i].stride = b.CreateExtractValue(data, {2});
|
||||
}
|
||||
|
||||
/// assume nonzero initial value in `counter_arg`
|
||||
@ -202,20 +202,25 @@ static void compileFunction(llvm::Module & module, const IFunctionBaseImpl & f)
|
||||
}
|
||||
}
|
||||
|
||||
ValuePlaceholders arguments(arg_types.size());
|
||||
for (size_t i = 0; i < arguments.size(); ++i) // NOLINT
|
||||
Values arguments;
|
||||
arguments.reserve(arg_types.size());
|
||||
|
||||
for (size_t i = 0; i < arg_types.size(); ++i) // NOLINT
|
||||
{
|
||||
arguments[i] = [&b, &col = columns[i], &type = arg_types[i]]() -> llvm::Value *
|
||||
auto & column = columns[i];
|
||||
auto type = arg_types[i];
|
||||
|
||||
auto * value = b.CreateLoad(column.data);
|
||||
if (!column.null)
|
||||
{
|
||||
auto * value = b.CreateLoad(col.data);
|
||||
if (!col.null)
|
||||
return value;
|
||||
arguments.emplace_back(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto * is_null = b.CreateICmpNE(b.CreateLoad(col.null), b.getInt8(0));
|
||||
auto * nullable = llvm::Constant::getNullValue(toNativeType(b, type));
|
||||
|
||||
return b.CreateInsertValue(b.CreateInsertValue(nullable, value, {0}), is_null, {1});
|
||||
};
|
||||
auto * is_null = b.CreateICmpNE(b.CreateLoad(column.null), b.getInt8(0));
|
||||
auto * nullable_unitilized = llvm::Constant::getNullValue(toNativeType(b, type));
|
||||
auto * nullable_value = b.CreateInsertValue(b.CreateInsertValue(nullable_unitilized, value, {0}), is_null, {1});
|
||||
arguments.emplace_back(nullable_value);
|
||||
}
|
||||
|
||||
auto * result = f.compile(b, std::move(arguments));
|
||||
@ -269,35 +274,32 @@ static llvm::Constant * getNativeValue(llvm::Type * type, const IColumn & column
|
||||
}
|
||||
|
||||
/// Same as IFunctionBase::compile, but also for constants and input columns.
|
||||
using CompilableExpression = std::function<llvm::Value * (llvm::IRBuilderBase &, const ValuePlaceholders &)>;
|
||||
|
||||
static CompilableExpression subexpression(ColumnPtr c, DataTypePtr type)
|
||||
{
|
||||
return [=](llvm::IRBuilderBase & b, const ValuePlaceholders &)
|
||||
return [=](llvm::IRBuilderBase & b, const Values &)
|
||||
{
|
||||
auto * native_value = getNativeValue(toNativeType(b, type), *c, 0);
|
||||
llvm::errs() << "Constant subexpression " << *native_value->getType() << "\n";
|
||||
return native_value;
|
||||
};
|
||||
}
|
||||
|
||||
static CompilableExpression subexpression(size_t i)
|
||||
{
|
||||
return [=](llvm::IRBuilderBase &, const ValuePlaceholders & inputs)
|
||||
return [=](llvm::IRBuilderBase &, const Values & inputs)
|
||||
{
|
||||
auto * column = inputs[i]();
|
||||
llvm::errs() << "Column subexpression " << *column->getType() << "\n";
|
||||
auto * column = inputs[i];
|
||||
return column;
|
||||
};
|
||||
}
|
||||
|
||||
static CompilableExpression subexpression(const IFunctionBase & f, std::vector<CompilableExpression> args)
|
||||
{
|
||||
return [&, args = std::move(args)](llvm::IRBuilderBase & builder, const ValuePlaceholders & inputs)
|
||||
return [&, args = std::move(args)](llvm::IRBuilderBase & builder, const Values & inputs)
|
||||
{
|
||||
ValuePlaceholders input;
|
||||
Values input;
|
||||
for (const auto & arg : args)
|
||||
input.push_back([&]() { return arg(builder, inputs); });
|
||||
input.push_back(arg(builder, inputs));
|
||||
|
||||
auto * result = f.compile(builder, input);
|
||||
if (result->getType() != toNativeType(builder, f.getResultType()))
|
||||
@ -369,11 +371,11 @@ LLVMFunction::LLVMFunction(const CompileDAG & dag)
|
||||
// std::cerr << "Func name " << std::string(func.getName()) << std::endl;
|
||||
// }
|
||||
|
||||
module.print(llvm::errs(), nullptr);
|
||||
// module.print(llvm::errs(), nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
llvm::Value * LLVMFunction::compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const
|
||||
llvm::Value * LLVMFunction::compile(llvm::IRBuilderBase & builder, Values values) const
|
||||
{
|
||||
return expression(builder, values);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using CompilableExpression = std::function<llvm::Value * (llvm::IRBuilderBase &, const ValuePlaceholders &)>;
|
||||
using CompilableExpression = std::function<llvm::Value * (llvm::IRBuilderBase &, const Values &)>;
|
||||
|
||||
class LLVMFunction : public IFunctionBaseImpl
|
||||
{
|
||||
@ -61,7 +61,7 @@ public:
|
||||
|
||||
bool isCompilable() const override { return true; }
|
||||
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, ValuePlaceholders values) const override;
|
||||
llvm::Value * compile(llvm::IRBuilderBase & builder, Values values) const override;
|
||||
|
||||
String getName() const override { return name; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user