#pragma once #include #include #include #include #include #include #include #if USE_EMBEDDED_COMPILER # include # include #endif namespace DB { struct Settings; template struct AggregateFunctionGroupBitOrData { T value = 0; static const char * name() { return "groupBitOr"; } void update(T x) { value |= x; } #if USE_EMBEDDED_COMPILER static void compileCreate(llvm::IRBuilderBase & builder, llvm::Value * value_ptr) { auto type = toNativeType(builder); builder.CreateStore(llvm::Constant::getNullValue(type), value_ptr); } static llvm::Value* compileUpdate(llvm::IRBuilderBase & builder, llvm::Value * lhs, llvm::Value * rhs) { return builder.CreateOr(lhs, rhs); } #endif }; template struct AggregateFunctionGroupBitAndData { T value = -1; /// Two's complement arithmetic, sign extension. static const char * name() { return "groupBitAnd"; } void update(T x) { value &= x; } #if USE_EMBEDDED_COMPILER static void compileCreate(llvm::IRBuilderBase & builder, llvm::Value * value_ptr) { auto type = toNativeType(builder); builder.CreateStore(llvm::ConstantInt::get(type, -1), value_ptr); } static llvm::Value* compileUpdate(llvm::IRBuilderBase & builder, llvm::Value * lhs, llvm::Value * rhs) { return builder.CreateAnd(lhs, rhs); } #endif }; template struct AggregateFunctionGroupBitXorData { T value = 0; static const char * name() { return "groupBitXor"; } void update(T x) { value ^= x; } #if USE_EMBEDDED_COMPILER static void compileCreate(llvm::IRBuilderBase & builder, llvm::Value * value_ptr) { auto type = toNativeType(builder); builder.CreateStore(llvm::Constant::getNullValue(type), value_ptr); } static llvm::Value* compileUpdate(llvm::IRBuilderBase & builder, llvm::Value * lhs, llvm::Value * rhs) { return builder.CreateXor(lhs, rhs); } #endif }; /// Counts bitwise operation on numbers. template class AggregateFunctionBitwise final : public IAggregateFunctionDataHelper> { public: explicit AggregateFunctionBitwise(const DataTypePtr & type) : IAggregateFunctionDataHelper>({type}, {}) {} String getName() const override { return Data::name(); } DataTypePtr getReturnType() const override { return std::make_shared>(); } bool allocatesMemoryInArena() const override { return false; } void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override { this->data(place).update(assert_cast &>(*columns[0]).getData()[row_num]); } void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override { this->data(place).update(this->data(rhs).value); } void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf) const override { writeBinary(this->data(place).value, buf); } void deserialize(AggregateDataPtr __restrict place, ReadBuffer & buf, Arena *) const override { readBinary(this->data(place).value, buf); } void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override { assert_cast &>(to).getData().push_back(this->data(place).value); } #if USE_EMBEDDED_COMPILER bool isCompilable() const override { auto return_type = getReturnType(); return canBeNativeType(*return_type); } void compileCreate(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) const override { llvm::IRBuilder<> & b = static_cast &>(builder); auto * return_type = toNativeType(b, getReturnType()); auto * value_ptr = b.CreatePointerCast(aggregate_data_ptr, return_type->getPointerTo()); Data::compileCreate(builder, value_ptr); } void compileAdd(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, const DataTypes &, const std::vector & argument_values) const override { llvm::IRBuilder<> & b = static_cast &>(builder); auto * return_type = toNativeType(b, getReturnType()); auto * value_ptr = b.CreatePointerCast(aggregate_data_ptr, return_type->getPointerTo()); auto * value = b.CreateLoad(return_type, value_ptr); const auto & argument_value = argument_values[0]; auto * result_value = Data::compileUpdate(builder, value, argument_value); b.CreateStore(result_value, value_ptr); } void compileMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) const override { llvm::IRBuilder<> & b = static_cast &>(builder); auto * return_type = toNativeType(b, getReturnType()); auto * value_dst_ptr = b.CreatePointerCast(aggregate_data_dst_ptr, return_type->getPointerTo()); auto * value_dst = b.CreateLoad(return_type, value_dst_ptr); auto * value_src_ptr = b.CreatePointerCast(aggregate_data_src_ptr, return_type->getPointerTo()); auto * value_src = b.CreateLoad(return_type, value_src_ptr); auto * result_value = Data::compileUpdate(builder, value_dst, value_src); b.CreateStore(result_value, value_dst_ptr); } llvm::Value * compileGetResult(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) const override { llvm::IRBuilder<> & b = static_cast &>(builder); auto * return_type = toNativeType(b, getReturnType()); auto * value_ptr = b.CreatePointerCast(aggregate_data_ptr, return_type->getPointerTo()); return b.CreateLoad(return_type, value_ptr); } #endif }; }