diff --git a/be/src/exprs/agg_fn.cc b/be/src/exprs/agg_fn.cc index 0c561fe133..d6fff8c4be 100644 --- a/be/src/exprs/agg_fn.cc +++ b/be/src/exprs/agg_fn.cc @@ -17,7 +17,6 @@ #include "exprs/agg_fn.h" -#include "codegen/llvm_codegen.h" #include "exprs/anyval_util.h" #include "runtime/descriptors.h" #include "runtime/user_function_cache.h" @@ -26,7 +25,6 @@ #include "common/names.h" using namespace doris_udf; -using namespace llvm; namespace doris { @@ -167,31 +165,6 @@ FunctionContext::TypeDesc AggFn::GetOutputTypeDesc() const { return AnyValUtil::column_type_to_type_desc(output_slot_desc_.type()); } -//Status AggFn::CodegenUpdateOrMergeFunction(LlvmCodeGen* codegen, Function** uda_fn) { -// const string& symbol = -// is_merge_ ? fn_.aggregate_fn.merge_fn_symbol : _fn.aggregate_fn.update_fn_symbol; -// std::vector fn_arg_types; -// for (Expr* input_expr : children()) { -// fn_arg_types.push_back(input_expr->type()); -// } -// // The intermediate value is passed as the last argument. -// fn_arg_types.push_back(intermediate_type()); -// RETURN_IF_ERROR(codegen->LoadFunction(_fn, symbol, nullptr, fn_arg_types, -// fn_arg_types.size(), false, uda_fn, &_cache_entry)); -// -// // Inline constants into the function body (if there is an IR body). -// if (!(*uda_fn)->isDeclaration()) { -// // TODO: IMPALA-4785: we should also replace references to GetIntermediateType() -// // with constants. -// codegen->InlineConstFnAttrs(GetOutputTypeDesc(), arg_type_descs_, *uda_fn); -// *uda_fn = codegen->FinalizeFunction(*uda_fn); -// if (*uda_fn == nullptr) { -// return Status::InternalError(TErrorCode::UDF_VERIFY_FAILED, symbol, fn_.hdfs_location); -// } -// } -// return Status::OK(); -//} - void AggFn::Close() { // This also closes all the input expressions. Expr::close(); diff --git a/be/src/exprs/agg_fn.h b/be/src/exprs/agg_fn.h index bed805d5b4..e3a7107acf 100644 --- a/be/src/exprs/agg_fn.h +++ b/be/src/exprs/agg_fn.h @@ -26,7 +26,6 @@ namespace doris { using doris_udf::FunctionContext; -class LlvmCodeGen; class MemPool; class MemTracker; class ObjectPool; @@ -128,17 +127,6 @@ class AggFn : public Expr { return arg_type_descs_; } - /// Generates an IR wrapper function to call update_fn_/merge_fn_ which may either be - /// cross-compiled or loaded from an external library. The generated IR function is - /// returned in 'uda_fn'. Returns error status on failure. - /// TODO: implement codegen path for init, finalize, serialize functions etc. - Status CodegenUpdateOrMergeFunction(LlvmCodeGen* codegen, llvm::Function** uda_fn) - WARN_UNUSED_RESULT; - - Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return Status::OK(); - } - /// Releases all cache entries to libCache for all nodes in the expr tree. virtual void Close(); static void Close(const std::vector& exprs); diff --git a/be/src/exprs/agg_fn_evaluator.cpp b/be/src/exprs/agg_fn_evaluator.cpp index e0ef163931..6c0f211bc9 100755 --- a/be/src/exprs/agg_fn_evaluator.cpp +++ b/be/src/exprs/agg_fn_evaluator.cpp @@ -19,7 +19,6 @@ #include -#include "codegen/llvm_codegen.h" #include "common/logging.h" #include "exec/aggregation_node.h" #include "exprs/aggregate_functions.h" diff --git a/be/src/exprs/anyval_util.h b/be/src/exprs/anyval_util.h index 61f8778a50..2a710177e9 100755 --- a/be/src/exprs/anyval_util.h +++ b/be/src/exprs/anyval_util.h @@ -18,12 +18,12 @@ #ifndef DORIS_BE_SRC_QUERY_EXPRS_ANYVAL_UTIL_H #define DORIS_BE_SRC_QUERY_EXPRS_ANYVAL_UTIL_H -#include "codegen/llvm_codegen.h" #include "runtime/primitive_type.h" #include "udf/udf.h" #include "util/hash_util.hpp" #include "util/types.h" #include "common/status.h" +#include "exprs/expr.h" namespace doris { diff --git a/be/src/exprs/arithmetic_expr.cpp b/be/src/exprs/arithmetic_expr.cpp index 4562dc2380..adf7239334 100644 --- a/be/src/exprs/arithmetic_expr.cpp +++ b/be/src/exprs/arithmetic_expr.cpp @@ -17,19 +17,9 @@ #include "exprs/arithmetic_expr.h" -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "runtime/runtime_state.h" -using llvm::BasicBlock; -using llvm::Constant; -using llvm::ConstantFP; -using llvm::ConstantInt; -using llvm::Function; -using llvm::LLVMContext; -using llvm::PHINode; -using llvm::Value; - namespace doris { Expr* ArithmeticExpr::from_thrift(const TExprNode& node) { @@ -170,428 +160,5 @@ BINARY_BIT_FNS(BitXorExpr, ^) BITNOT_OP_FN(LargeIntVal, get_large_int_val) \ BITNOT_FNS() - -// IR codegen for compound add predicates. Compound predicate has non trivial -// null handling as well as many branches so this is pretty complicated. The IR -// for x && y is: -// -// define i16 @Add(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// entry: -// %lhs_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %0 = extractvalue { i8, i64 } %lhs_val, 0 -// %lhs_is_null = trunc i8 %0 to i1 -// br i1 %lhs_is_null, label %null, label %lhs_not_null -// -// lhs_not_null: ; preds = %entry -// %rhs_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %1 = extractvalue { i8, i64 } %lhs_val, 0 -// %rhs_is_null = trunc i8 %1 to i1 -// br i1 %rhs_is_null, label %null, label %rhs_not_null -// -// rhs_not_null: ; preds = %entry -// %2 = extractvalue { i8, i64 } %lhs_val, 1 -// %3 = extractvalue { i8, i64 } %rhs_val, 1 -// %val = add i64 %2, %3 -// br label %ret -// -// ret: ; preds = %not_null_block, %null_block -// %ret3 = phi i1 [ false, %null_block ], [ %4, %not_null_block ] -// %5 = zext i1 %ret3 to i16 -// %6 = shl i16 %5, 8 -// %7 = or i16 0, %6 -// ret i16 %7 -// } -Status ArithmeticExpr::codegen_binary_op( - RuntimeState* state, llvm::Function** fn, BinaryOpType op_type) { - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Function* lhs_fn = NULL; - RETURN_IF_ERROR(_children[0]->get_codegend_compute_fn(state, &lhs_fn)); - Function* rhs_fn = NULL; - RETURN_IF_ERROR(_children[1]->get_codegend_compute_fn(state, &rhs_fn)); - - // Function protocol - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "add", &args); - LLVMContext& cg_ctx = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(cg_ctx); - - // Constant - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - - // Block - BasicBlock* entry_block = BasicBlock::Create(cg_ctx, "entry", *fn); - BasicBlock* lhs_not_null_block = BasicBlock::Create(cg_ctx, "lhs_not_null", *fn); - BasicBlock* rhs_not_null_block = NULL; - if ((op_type == BinaryOpType::DIV || op_type == BinaryOpType::MOD)) { - // && _type.type != TYPE_DOUBLE && _type.type != TYPE_FLOAT) { - rhs_not_null_block = BasicBlock::Create(cg_ctx, "rhs_not_null", *fn); - } - BasicBlock* compute_block = BasicBlock::Create(cg_ctx, "compute", *fn); - BasicBlock* null_block = BasicBlock::Create(cg_ctx, "null", *fn); - BasicBlock* ret_block = BasicBlock::Create(cg_ctx, "ret", *fn); - - // entry block - builder.SetInsertPoint(entry_block); - CodegenAnyVal lhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[0]->type(), lhs_fn, args, "lhs_val"); - // if (v1.is_null) return null; - Value* lhs_is_null = lhs_val.get_is_null(); - builder.CreateCondBr(lhs_is_null, null_block, lhs_not_null_block); - - // lhs_not_null_block - builder.SetInsertPoint(lhs_not_null_block); - CodegenAnyVal rhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[1]->type(), rhs_fn, args, "lhs_val"); - Value* rhs_is_null = rhs_val.get_is_null(); - // if (v2.is_null) return null; - Value* rhs_llvm_val = NULL; - if ((op_type == BinaryOpType::DIV || op_type == BinaryOpType::MOD)) { - // && _type.type != TYPE_DOUBLE && _type.type != TYPE_FLOAT) { - builder.CreateCondBr(rhs_is_null, null_block, rhs_not_null_block); - // if (v2.val == 0) - builder.SetInsertPoint(rhs_not_null_block); - rhs_llvm_val = rhs_val.get_val(); - Value* rhs_zero = NULL; - Value* rhs_is_zero = NULL; - if (_type.type == TYPE_DOUBLE || _type.type == TYPE_FLOAT) { - rhs_zero = ConstantFP::get(rhs_llvm_val->getType(), 0.0); - rhs_is_zero = builder.CreateFCmpOEQ(rhs_llvm_val, rhs_zero, "rhs_is_zero"); - } else { - rhs_zero = ConstantInt::get(rhs_llvm_val->getType(), 0); - rhs_is_zero = builder.CreateICmpEQ(rhs_llvm_val, rhs_zero, "rhs_is_zero"); - } - builder.CreateCondBr(rhs_is_zero, null_block, compute_block); - } else { - builder.CreateCondBr(rhs_is_null, null_block, compute_block); - } - - // compute_block - builder.SetInsertPoint(compute_block); - Value* val = NULL; - switch (op_type) { - case ADD: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateAdd(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - val = builder.CreateFAdd(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case SUB: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateSub(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - val = builder.CreateFSub(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case MUL: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateMul(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - val = builder.CreateFMul(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case DIV: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateSDiv(lhs_val.get_val(), rhs_llvm_val, "val"); - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - val = builder.CreateFDiv(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case MOD: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateSRem(lhs_val.get_val(), rhs_llvm_val, "val"); - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - val = builder.CreateFRem(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case BIT_AND: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateAnd(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case BIT_OR: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateOr(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - case BIT_XOR: { - switch (_type.type) { - case TYPE_TINYINT: - case TYPE_SMALLINT: - case TYPE_INT: - case TYPE_BIGINT: - case TYPE_LARGEINT: - val = builder.CreateXor(lhs_val.get_val(), rhs_val.get_val(), "val"); - break; - default: - return Status::InternalError("Unk"); - } - break; - } - default: - return Status::InternalError("Unknow operato"); - } - builder.CreateBr(ret_block); - - // null block - builder.SetInsertPoint(null_block); - builder.CreateBr(ret_block); - - // ret block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi"); - is_null_phi->addIncoming(one, null_block); - is_null_phi->addIncoming(zero, compute_block); - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - val_phi->addIncoming(null, null_block); - val_phi->addIncoming(val, compute_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - - *fn = codegen->finalize_function(*fn); - return Status::OK(); -} - -Status AddExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::ADD)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status SubExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::SUB)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status MulExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::MUL)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status DivExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::DIV)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status ModExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::MOD)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status BitAndExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::BIT_AND)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status BitOrExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::BIT_OR)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status BitXorExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - RETURN_IF_ERROR(codegen_binary_op(state, fn , BinaryOpType::BIT_XOR)); - _ir_compute_fn = *fn; - return Status::OK(); -} - -// IR codegen for compound add predicates. Compound predicate has non trivial -// null handling as well as many branches so this is pretty complicated. The IR -// for x && y is: -// -// define i16 @Add(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// entry: -// %lhs_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %0 = extractvalue { i8, i64 } %lhs_val, 0 -// %lhs_is_null = trunc i8 %0 to i1 -// br i1 %lhs_is_null, label %null, label %lhs_not_null -// -// ret: ; preds = %not_null_block, %null_block -// %ret3 = phi i1 [ false, %null_block ], [ %4, %not_null_block ] -// %5 = zext i1 %ret3 to i16 -// %6 = shl i16 %5, 8 -// %7 = or i16 0, %6 -// ret i16 %7 -// } -Status BitNotExpr::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Function* child_fn = NULL; - RETURN_IF_ERROR(_children[0]->get_codegend_compute_fn(state, &child_fn)); - - // Function protocol - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "add", &args); - LLVMContext& cg_ctx = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(cg_ctx); - - // Constant - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - - // Block - BasicBlock* entry_block = BasicBlock::Create(cg_ctx, "entry", *fn); - BasicBlock* compute_block = BasicBlock::Create(cg_ctx, "compute", *fn); - BasicBlock* ret_block = BasicBlock::Create(cg_ctx, "ret", *fn); - - // entry block - builder.SetInsertPoint(entry_block); - CodegenAnyVal child_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[0]->type(), child_fn, args, "child_val"); - // if (v1.is_null) return null; - Value* child_is_null = child_val.get_is_null(); - builder.CreateCondBr(child_is_null, ret_block, compute_block); - - // compute_block - builder.SetInsertPoint(compute_block); - Value* val = builder.CreateNot(child_val.get_val(), "val"); - builder.CreateBr(ret_block); - - // ret block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi"); - is_null_phi->addIncoming(one, entry_block); - is_null_phi->addIncoming(zero, compute_block); - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - val_phi->addIncoming(null, entry_block); - val_phi->addIncoming(val, compute_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val(codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - - *fn = codegen->finalize_function(*fn); - _ir_compute_fn = *fn; - return Status::OK(); -} - } diff --git a/be/src/exprs/arithmetic_expr.h b/be/src/exprs/arithmetic_expr.h index b83f89c319..9af571b451 100644 --- a/be/src/exprs/arithmetic_expr.h +++ b/be/src/exprs/arithmetic_expr.h @@ -41,9 +41,6 @@ protected: ArithmeticExpr(const TExprNode& node) : Expr(node) { } virtual ~ArithmeticExpr() { } - - Status codegen_binary_op( - RuntimeState* state, llvm::Function** fn, BinaryOpType op_type); }; class AddExpr : public ArithmeticExpr { @@ -53,7 +50,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new AddExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -70,7 +66,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new SubExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -87,7 +82,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new MulExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -104,7 +98,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new DivExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -121,7 +114,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new ModExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -138,7 +130,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new BitAndExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -153,7 +144,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new BitOrExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -168,7 +158,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new BitXorExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); @@ -183,7 +172,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new BitNotExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); virtual IntVal get_int_val(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/binary_predicate.cpp b/be/src/exprs/binary_predicate.cpp index c5ef475ffa..ea79e3649d 100644 --- a/be/src/exprs/binary_predicate.cpp +++ b/be/src/exprs/binary_predicate.cpp @@ -19,7 +19,6 @@ #include -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "util/debug_util.h" #include "gen_cpp/Exprs_types.h" @@ -29,15 +28,6 @@ #include "runtime/decimal_value.h" #include "runtime/decimalv2_value.h" -using llvm::BasicBlock; -using llvm::CmpInst; -using llvm::Constant; -using llvm::ConstantInt; -using llvm::Function; -using llvm::LLVMContext; -using llvm::PHINode; -using llvm::Value; - namespace doris { Expr* BinaryPredicate::from_thrift(const TExprNode& node) { @@ -278,114 +268,6 @@ std::string BinaryPredicate::debug_string() const { return out.str(); } -// IR codegen for compound add predicates. Compound predicate has non trivial -// null handling as well as many branches so this is pretty complicated. The IR -// for x && y is: -// -// define i16 @Add(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// entry: -// %lhs_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %0 = extractvalue { i8, i64 } %lhs_val, 0 -// %lhs_is_null = trunc i8 %0 to i1 -// br i1 %lhs_is_null, label %null, label %lhs_not_null -// -// lhs_not_null: ; preds = %entry -// %rhs_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %1 = extractvalue { i8, i64 } %lhs_val, 0 -// %rhs_is_null = trunc i8 %1 to i1 -// br i1 %rhs_is_null, label %null, label %rhs_not_null -// -// rhs_not_null: ; preds = %entry -// %2 = extractvalue { i8, i64 } %lhs_val, 1 -// %3 = extractvalue { i8, i64 } %rhs_val, 1 -// %val = add i64 %2, %3 -// br label %ret -// -// ret: ; preds = %not_null_block, %null_block -// %ret3 = phi i1 [ false, %null_block ], [ %4, %not_null_block ] -// %5 = zext i1 %ret3 to i16 -// %6 = shl i16 %5, 8 -// %7 = or i16 0, %6 -// ret i16 %7 -// } -Status BinaryPredicate::codegen_compare_fn( - RuntimeState* state, llvm::Function** fn, CmpInst::Predicate pred) { - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Function* lhs_fn = NULL; - RETURN_IF_ERROR(_children[0]->get_codegend_compute_fn(state, &lhs_fn)); - Function* rhs_fn = NULL; - RETURN_IF_ERROR(_children[1]->get_codegend_compute_fn(state, &rhs_fn)); - - // Function protocol - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "compare", &args); - LLVMContext& cg_ctx = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(cg_ctx); - - // Constant - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - - // Block - BasicBlock* entry_block = BasicBlock::Create(cg_ctx, "entry", *fn); - BasicBlock* lhs_not_null_block = BasicBlock::Create(cg_ctx, "lhs_not_null", *fn); - BasicBlock* compute_block = BasicBlock::Create(cg_ctx, "compute", *fn); - BasicBlock* null_block = BasicBlock::Create(cg_ctx, "null", *fn); - BasicBlock* ret_block = BasicBlock::Create(cg_ctx, "ret", *fn); - - // entry block - builder.SetInsertPoint(entry_block); - CodegenAnyVal lhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[0]->type(), lhs_fn, args, "lhs_val"); - // if (v1.is_null) return null; - Value* lhs_is_null = lhs_val.get_is_null(); - builder.CreateCondBr(lhs_is_null, null_block, lhs_not_null_block); - - // lhs_not_null_block - builder.SetInsertPoint(lhs_not_null_block); - CodegenAnyVal rhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[1]->type(), rhs_fn, args, "rhs_val"); - Value* rhs_is_null = rhs_val.get_is_null(); - builder.CreateCondBr(rhs_is_null, null_block, compute_block); - - // compute_block - builder.SetInsertPoint(compute_block); - Value* val = NULL; - if (_children[0]->type().type == TYPE_DOUBLE || _children[0]->type().type == TYPE_FLOAT) { - val = builder.CreateFCmp(pred, lhs_val.get_val(), rhs_val.get_val(), "val"); - } else { - val = builder.CreateICmp(pred, lhs_val.get_val(), rhs_val.get_val(), "val"); - } - builder.CreateBr(ret_block); - - // null block - builder.SetInsertPoint(null_block); - builder.CreateBr(ret_block); - - // ret block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi"); - is_null_phi->addIncoming(one, null_block); - is_null_phi->addIncoming(zero, compute_block); - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - val_phi->addIncoming(null, null_block); - val_phi->addIncoming(val, compute_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - - *fn = codegen->finalize_function(*fn); - return Status::OK(); -} - #define BINARY_PRED_FN(CLASS, TYPE, FN, OP, LLVM_PRED) \ BooleanVal CLASS::get_boolean_val(ExprContext* ctx, TupleRow* row) { \ TYPE v1 = _children[0]->FN(ctx, row); \ @@ -397,15 +279,6 @@ Status BinaryPredicate::codegen_compare_fn( return BooleanVal::null(); \ } \ return BooleanVal(v1.val OP v2.val); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - if (_ir_compute_fn != NULL) { \ - *fn = _ir_compute_fn; \ - return Status::OK(); \ - } \ - RETURN_IF_ERROR(codegen_compare_fn(state, fn, LLVM_PRED)); \ - _ir_compute_fn = *fn; \ - return Status::OK(); \ } // add '/**/' to pass codestyle check of cooder @@ -448,9 +321,6 @@ BINARY_PRED_FLOAT_FNS(DoubleVal, get_double_val); DORIS_TYPE pv1 = DORIS_TYPE::FROM_FUNC(v1); \ DORIS_TYPE pv2 = DORIS_TYPE::FROM_FUNC(v2); \ return BooleanVal(pv1 OP pv2); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - return get_codegend_compute_fn_wrapper(state, fn); \ } @@ -476,15 +346,6 @@ COMPLICATE_BINARY_PRED_FNS(DecimalV2Val, get_decimalv2_val, DecimalV2Value, from return BooleanVal::null(); \ } \ return BooleanVal(v1.packed_time OP v2.packed_time); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - if (_ir_compute_fn != NULL) { \ - *fn = _ir_compute_fn; \ - return Status::OK(); \ - } \ - RETURN_IF_ERROR(codegen_compare_fn(state, fn , LLVM_PRED)); \ - _ir_compute_fn = *fn; \ - return Status::OK(); \ } #define DATETIME_BINARY_PRED_FNS() \ @@ -510,9 +371,6 @@ DATETIME_BINARY_PRED_FNS() StringValue pv1 = StringValue::from_string_val(v1); \ StringValue pv2 = StringValue::from_string_val(v2); \ return BooleanVal(pv1 OP pv2); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - return get_codegend_compute_fn_wrapper(state, fn); \ } #define STRING_BINARY_PRED_FNS() \ @@ -539,10 +397,6 @@ BooleanVal EqStringValPred::get_boolean_val(ExprContext* ctx, TupleRow* row) { return BooleanVal(string_compare((char*)v1.ptr, v1.len, (char*)v2.ptr, v2.len, v1.len) == 0); } -Status EqStringValPred::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return get_codegend_compute_fn_wrapper(state, fn); -} - #define BINARY_PRED_FOR_NULL_FN(CLASS, TYPE, FN, OP, LLVM_PRED) \ BooleanVal CLASS::get_boolean_val(ExprContext* ctx, TupleRow* row) { \ TYPE v1 = _children[0]->FN(ctx, row); \ @@ -553,15 +407,6 @@ Status EqStringValPred::get_codegend_compute_fn(RuntimeState* state, llvm::Funct return BooleanVal(false); \ } \ return BooleanVal(v1.val OP v2.val); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - if (_ir_compute_fn != NULL) { \ - *fn = _ir_compute_fn; \ - return Status::OK(); \ - } \ - RETURN_IF_ERROR(codegen_compare_fn(state, fn, LLVM_PRED)); \ - _ir_compute_fn = *fn; \ - return Status::OK(); \ } // add '/**/' to pass codestyle check of cooder @@ -594,12 +439,8 @@ BINARY_PRED_FOR_NULL_FLOAT_FNS(DoubleVal, get_double_val); DORIS_TYPE pv1 = DORIS_TYPE::FROM_FUNC(v1); \ DORIS_TYPE pv2 = DORIS_TYPE::FROM_FUNC(v2); \ return BooleanVal(pv1 OP pv2); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - return get_codegend_compute_fn_wrapper(state, fn); \ } - #define COMPLICATE_BINARY_FOR_NULL_PRED_FNS(TYPE, FN, DORIS_TYPE, FROM_FUNC) \ COMPLICATE_BINARY_FOR_NULL_PRED_FN(EqForNull##TYPE##Pred, TYPE, FN, DORIS_TYPE, FROM_FUNC, ==) @@ -616,15 +457,6 @@ COMPLICATE_BINARY_FOR_NULL_PRED_FNS(DecimalV2Val, get_decimalv2_val, DecimalV2Va return BooleanVal(false); \ } \ return BooleanVal(v1.packed_time OP v2.packed_time); \ - } \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - if (_ir_compute_fn != NULL) { \ - *fn = _ir_compute_fn; \ - return Status::OK(); \ - } \ - RETURN_IF_ERROR(codegen_compare_fn(state, fn , LLVM_PRED)); \ - _ir_compute_fn = *fn; \ - return Status::OK(); \ } #define DATETIME_BINARY_FOR_NULL_PRED_FNS() \ @@ -647,102 +479,4 @@ BooleanVal EqForNullStringValPred::get_boolean_val(ExprContext* ctx, TupleRow* r return BooleanVal(string_compare((char*)v1.ptr, v1.len, (char*)v2.ptr, v2.len, v1.len) == 0); } -Status EqForNullStringValPred::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return get_codegend_compute_fn_wrapper(state, fn); -} - -#if 0 -Status EqStringValPred::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Function* lhs_fn = NULL; - RETURN_IF_ERROR(_children[0]->get_codegend_compute_fn(state, &lhs_fn)); - Function* rhs_fn = NULL; - RETURN_IF_ERROR(_children[1]->get_codegend_compute_fn(state, &rhs_fn)); - - // Function protocol - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "compare", &args); - LLVMContext& cg_ctx = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(cg_ctx); - - // Constant - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - Value* false_val = ConstantInt::get(llvm::Type::getInt1Ty(cg_ctx), 0); - // Value* true_val = ConstantInt::get(llvm::Type::getInt1Ty(cg_ctx), 1); - - // Block - BasicBlock* entry_block = BasicBlock::Create(cg_ctx, "entry", *fn); - BasicBlock* lhs_not_null_block = BasicBlock::Create(cg_ctx, "lhs_not_null", *fn); - BasicBlock* rhs_not_null_block = BasicBlock::Create(cg_ctx, "rhs_not_null", *fn); - BasicBlock* length_equal_block = BasicBlock::Create(cg_ctx, "length_equal", *fn); - BasicBlock* null_block = BasicBlock::Create(cg_ctx, "null", *fn); - BasicBlock* false_block = BasicBlock::Create(cg_ctx, "false", *fn); - BasicBlock* ret_block = BasicBlock::Create(cg_ctx, "ret", *fn); - - // entry block - builder.SetInsertPoint(entry_block); - CodegenAnyVal lhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[0]->type(), lhs_fn, args, "lhs_val"); - // if (v1.is_null) return null; - Value* lhs_is_null = lhs_val.get_is_null(); - builder.CreateCondBr(lhs_is_null, null_block, lhs_not_null_block); - - // lhs_not_null_block - builder.SetInsertPoint(lhs_not_null_block); - CodegenAnyVal rhs_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[1]->type(), rhs_fn, args, "rhs_val"); - Value* rhs_is_null = rhs_val.get_is_null(); - builder.CreateCondBr(rhs_is_null, null_block, rhs_not_null_block); - - // rhs_not_null_block - builder.SetInsertPoint(rhs_not_null_block); - Value* lhs_len = lhs_val.get_len(); - Value* rhs_len = rhs_val.get_len(); - // if (v1.len != v2.len) - Value* len_eq = builder.CreateICmpEQ(lhs_len, rhs_len, "len_eq"); - builder.CreateCondBr(len_eq, length_equal_block, false_block); - - // length_equal_block - builder.SetInsertPoint(length_equal_block); - Function* compare_fn = codegen->get_function(IRFunction::IR_STRING_COMPARE); - Value* compare_args[4] = {lhs_val.get_ptr(), lhs_len, lhs_val.get_ptr(), lhs_len}; - Value* compare_res = builder.CreateCall(compare_fn, compare_args, "compare_res"); - Value* int_zero = ConstantInt::get(codegen->get_type(TYPE_INT), 0); - Value* val = builder.CreateICmpEQ(compare_res, int_zero, "val"); - builder.CreateBr(ret_block); - - // null block - builder.SetInsertPoint(null_block); - builder.CreateBr(ret_block); - - // false block - builder.SetInsertPoint(false_block); - builder.CreateBr(ret_block); - - // ret block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 3, "is_null_phi"); - is_null_phi->addIncoming(one, null_block); - is_null_phi->addIncoming(zero, false_block); - is_null_phi->addIncoming(zero, length_equal_block); - PHINode* val_phi = builder.CreatePHI(val->getType(), 3, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - val_phi->addIncoming(null, null_block); - val_phi->addIncoming(false_val, false_block); - val_phi->addIncoming(val, length_equal_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - - *fn = codegen->finalize_function(*fn); - return Status::OK(); -} - -#endif - } diff --git a/be/src/exprs/binary_predicate.h b/be/src/exprs/binary_predicate.h index 236832660c..893f446f93 100644 --- a/be/src/exprs/binary_predicate.h +++ b/be/src/exprs/binary_predicate.h @@ -21,8 +21,6 @@ #include #include -#include - #include "common/object_pool.h" #include "exprs/predicate.h" #include "gen_cpp/Exprs_types.h" @@ -41,10 +39,6 @@ protected: // virtual Status prepare(RuntimeState* state, const RowDescriptor& desc); virtual std::string debug_string() const; - - - Status codegen_compare_fn( - RuntimeState* state, llvm::Function** fn, llvm::CmpInst::Predicate pred); }; #define BIN_PRED_CLASS_DEFINE(CLASS) \ @@ -55,7 +49,6 @@ protected: virtual Expr* clone(ObjectPool* pool) const override { \ return pool->add(new CLASS(*this)); } \ \ - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); \ virtual BooleanVal get_boolean_val(ExprContext* context, TupleRow* row); \ }; @@ -89,7 +82,6 @@ BIN_PRED_CLASSES_DEFINE(DecimalV2Val) virtual Expr* clone(ObjectPool* pool) const override { \ return pool->add(new CLASS(*this)); } \ \ - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); \ virtual BooleanVal get_boolean_val(ExprContext* context, TupleRow* row); \ }; diff --git a/be/src/exprs/case_expr.cpp b/be/src/exprs/case_expr.cpp index 178df68499..6ca84e8070 100644 --- a/be/src/exprs/case_expr.cpp +++ b/be/src/exprs/case_expr.cpp @@ -17,21 +17,11 @@ #include "exprs/case_expr.h" -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "exprs/anyval_util.h" #include "runtime/runtime_state.h" #include "gen_cpp/Exprs_types.h" -using llvm::BasicBlock; -using llvm::Constant; -using llvm::ConstantInt; -using llvm::Function; -using llvm::LLVMContext; -using llvm::PHINode; -using llvm::PointerType; -using llvm::Value; - namespace doris { struct CaseExprState { @@ -95,208 +85,6 @@ std::string CaseExpr::debug_string() const { return out.str(); } -// Sample IR output when there is a case expression and else expression -// define i16 @CaseExpr(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// eval_case_expr: -// %case_val = call i64 @GetSlotRef(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %is_null = trunc i64 %case_val to i1 -// br i1 %is_null, label %return_else_expr, label %eval_first_when_expr -// -// eval_first_when_expr: ; preds = %eval_case_expr -// %when_val = call i64 @Literal(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %is_null1 = trunc i64 %when_val to i1 -// br i1 %is_null1, label %return_else_expr, label %check_when_expr_block -// -// check_when_expr_block: ; preds = %eval_first_when_expr -// %0 = ashr i64 %when_val, 32 -// %1 = trunc i64 %0 to i32 -// %2 = ashr i64 %case_val, 32 -// %3 = trunc i64 %2 to i32 -// %eq = icmp eq i32 %3, %1 -// br i1 %eq, label %return_then_expr, label %return_else_expr -// -// return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal12(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// ret i16 %then_val -// -// return_else_expr: ; preds = %check_when_expr_block, %eval_first_when_expr, %eval_case_expr -// %else_val = call i16 @Literal13(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// ret i16 %else_val -// } -// -// Sample IR output when there is case expression and no else expression -// define i16 @CaseExpr(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// eval_case_expr: -// %case_val = call i64 @GetSlotRef(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %is_null = trunc i64 %case_val to i1 -// br i1 %is_null, label %return_null, label %eval_first_when_expr -// -// eval_first_when_expr: ; preds = %eval_case_expr -// %when_val = call i64 @Literal(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %is_null1 = trunc i64 %when_val to i1 -// br i1 %is_null1, label %return_null, label %check_when_expr_block -// -// check_when_expr_block: ; preds = %eval_first_when_expr -// %0 = ashr i64 %when_val, 32 -// %1 = trunc i64 %0 to i32 -// %2 = ashr i64 %case_val, 32 -// %3 = trunc i64 %2 to i32 -// %eq = icmp eq i32 %3, %1 -// br i1 %eq, label %return_then_expr, label %return_null -// -// return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal12(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// ret i16 %then_val -// -// return_null: ; preds = %check_when_expr_block, %eval_first_when_expr, %eval_case_expr -// ret i16 1 -// } -// -// Sample IR output when there is no case expr and else expression -// define i16 @CaseExpr(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// eval_first_when_expr: -// %when_val = call i16 @Eq_IntVal_IntValWrapper1( -// %"class.doris::ExprContext"* %context, %"class.doris::TupleRow"* %row) -// %is_null = trunc i16 %when_val to i1 -// br i1 %is_null, label %return_else_expr, label %check_when_expr_block -// -// check_when_expr_block: ; preds = %eval_first_when_expr -// %0 = ashr i16 %when_val, 8 -// %1 = trunc i16 %0 to i8 -// %val = trunc i8 %1 to i1 -// br i1 %val, label %return_then_expr, label %return_else_expr -// -// return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal14(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// ret i16 %then_val -// -// return_else_expr: ; preds = %check_when_expr_block, %eval_first_when_expr -// %else_val = call i16 @Literal15(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// ret i16 %else_val -// } -Status CaseExpr::get_codegend_compute_fn(RuntimeState* state, Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - const int num_children = get_num_children(); - Function* child_fns[num_children]; - for (int i = 0; i < num_children; ++i) { - RETURN_IF_ERROR(children()[i]->get_codegend_compute_fn(state, &child_fns[i])); - } - - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - LLVMContext& context = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(context); - - Value* args[2]; - Function* function = create_ir_function_prototype(codegen, "CaseExpr", &args); - BasicBlock* eval_case_expr_block = NULL; - - // This is the block immediately after the when/then exprs. It will either point to a - // block which returns the else expr, or returns NULL if no else expr is specified. - BasicBlock* default_value_block = BasicBlock::Create( - context, has_else_expr() ? "return_else_expr" : "return_null", function); - - // If there is a case expression, create a block to evaluate it. - CodegenAnyVal case_val; - BasicBlock* eval_first_when_expr_block = BasicBlock::Create( - context, "eval_first_when_expr", function, default_value_block); - BasicBlock* current_when_expr_block = eval_first_when_expr_block; - if (has_case_expr()) { - // Need at least case, when and then expr, and optionally an else expr - DCHECK_GE(num_children, (has_else_expr()) ? 4 : 3); - // If there is a case expr, create block eval_case_expr to evaluate the - // case expr. Place this block before eval_first_when_expr_block - eval_case_expr_block = BasicBlock::Create(context, "eval_case_expr", - function, eval_first_when_expr_block); - builder.SetInsertPoint(eval_case_expr_block); - case_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, children()[0]->type(), child_fns[0], args, "case_val"); - builder.CreateCondBr( - case_val.get_is_null(), default_value_block, eval_first_when_expr_block); - } else { - DCHECK_GE(num_children, (has_else_expr()) ? 3 : 2); - } - - const int loop_end = (has_else_expr()) ? num_children - 1 : num_children; - const int last_loop_iter = loop_end - 2; - // The loop increments by two each time, because each iteration handles one when/then - // pair. Both when and then subexpressions are single children. If there is a case expr - // start loop at index 1. (case expr is children()[0] and has already be evaluated. - for (int i = (has_case_expr()) ? 1 : 0; i < loop_end; i += 2) { - BasicBlock* check_when_expr_block = BasicBlock::Create( - context, "check_when_expr_block", function, default_value_block); - BasicBlock* return_then_expr_block = - BasicBlock::Create(context, "return_then_expr", function, default_value_block); - - // continue_or_exit_block either points to the next eval_next_when_expr block, - // or points to the defaut_value_block if there are no more when/then expressions. - BasicBlock* continue_or_exit_block = NULL; - if (i == last_loop_iter) { - continue_or_exit_block = default_value_block; - } else { - continue_or_exit_block = BasicBlock::Create( - context, "eval_next_when_expr", function, default_value_block); - } - - // Get the child value of the when statement. If NULL simply continue to next when - // statement - builder.SetInsertPoint(current_when_expr_block); - CodegenAnyVal when_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, children()[i]->type(), child_fns[i], args, "when_val"); - builder.CreateCondBr( - when_val.get_is_null(), continue_or_exit_block, check_when_expr_block); - - builder.SetInsertPoint(check_when_expr_block); - if (has_case_expr()) { - // Compare for equality - Value* is_equal = case_val.eq(&when_val); - builder.CreateCondBr(is_equal, return_then_expr_block, continue_or_exit_block); - } else { - builder.CreateCondBr( - when_val.get_val(), return_then_expr_block, continue_or_exit_block); - } - - builder.SetInsertPoint(return_then_expr_block); - - // Eval and return then value - Value* then_val = CodegenAnyVal::create_call( - codegen, &builder, child_fns[i+1], args, "then_val"); - builder.CreateRet(then_val); - - current_when_expr_block = continue_or_exit_block; - } - - builder.SetInsertPoint(default_value_block); - if (has_else_expr()) { - Value* else_val = CodegenAnyVal::create_call( - codegen, &builder, child_fns[num_children - 1], args, "else_val"); - builder.CreateRet(else_val); - } else { - builder.CreateRet(CodegenAnyVal::get_null_val(codegen, type())); - } - - *fn = codegen->finalize_function(function); - DCHECK(*fn != NULL); - _ir_compute_fn = *fn; - return Status::OK(); -} - void CaseExpr::get_child_val(int child_idx, ExprContext* ctx, TupleRow* row, AnyVal* dst) { switch (_children[child_idx]->type().type) { case TYPE_BOOLEAN: diff --git a/be/src/exprs/case_expr.h b/be/src/exprs/case_expr.h index 470bb44290..f78aa2813c 100644 --- a/be/src/exprs/case_expr.h +++ b/be/src/exprs/case_expr.h @@ -22,10 +22,6 @@ #include "expr.h" #include "common/object_pool.h" -namespace llvm { -class Function; -} - namespace doris { class TExprNode; @@ -36,7 +32,6 @@ public: virtual Expr* clone(ObjectPool* pool) const override { return pool->add(new CaseExpr(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override; virtual BooleanVal get_boolean_val(ExprContext* ctx, TupleRow* row); virtual TinyIntVal get_tiny_int_val(ExprContext* ctx, TupleRow* row); virtual SmallIntVal get_small_int_val(ExprContext* ctx, TupleRow* row); diff --git a/be/src/exprs/cast_expr.cpp b/be/src/exprs/cast_expr.cpp index 834ffea9dc..5e5bc82d15 100644 --- a/be/src/exprs/cast_expr.cpp +++ b/be/src/exprs/cast_expr.cpp @@ -17,19 +17,9 @@ #include "exprs/cast_expr.h" -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "runtime/runtime_state.h" -using llvm::BasicBlock; -using llvm::Constant; -using llvm::ConstantInt; -using llvm::Function; -using llvm::Instruction; -using llvm::LLVMContext; -using llvm::PHINode; -using llvm::Value; - namespace doris { Expr* CastExpr::from_thrift(const TExprNode& node) { @@ -165,105 +155,4 @@ CAST_FROM_DOUBLE(IntVal, get_int_val) CAST_FROM_DOUBLE(BigIntVal, get_big_int_val) CAST_FROM_DOUBLE(LargeIntVal, get_large_int_val) CAST_FROM_DOUBLE(FloatVal, get_float_val) - -// IR codegen for cast expression -// -// define i16 @cast(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) #20 { -// entry: -// %child_val = call { i8, i64 } @get_slot_ref(%"class.doris::ExprContext"* %context, -// %"class.doris::TupleRow"* %row) -// %0 = extractvalue { i8, i64 } %child_val, 0 -// %child_is_null = trunc i8 %0 to i1 -// br i1 %child_is_null, label %ret, label %child_not_null -// -// child_not_null: ; preds = %entry -// %val = add i64 %2, %3 -// br label %ret -// -// ret: ; preds = %not_null_block, %null_block -// %ret3 = phi i1 [ false, %null_block ], [ %4, %not_null_block ] -// %5 = zext i1 %ret3 to i16 -// %6 = shl i16 %5, 8 -// %7 = or i16 0, %6 -// ret i16 %7 -// } -Status CastExpr::codegen_cast_fn(RuntimeState* state, llvm::Function** fn) { - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Function* child_fn = NULL; - RETURN_IF_ERROR(_children[0]->get_codegend_compute_fn(state, &child_fn)); - - // Function protocol - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "cast", &args); - LLVMContext& cg_ctx = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(cg_ctx); - - // Constant - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - - // Block - BasicBlock* entry_block = BasicBlock::Create(cg_ctx, "entry", *fn); - BasicBlock* child_not_null_block = BasicBlock::Create(cg_ctx, "child_not_null", *fn); - BasicBlock* ret_block = BasicBlock::Create(cg_ctx, "ret", *fn); - - // entry block - builder.SetInsertPoint(entry_block); - CodegenAnyVal child_val = CodegenAnyVal::create_call_wrapped( - codegen, &builder, _children[0]->type(), child_fn, args, "child_val"); - // if (v1.is_null) return null; - Value* child_is_null = child_val.get_is_null(); - builder.CreateCondBr(child_is_null, ret_block, child_not_null_block); - - // child_not_null_block - builder.SetInsertPoint(child_not_null_block); - Value* val = NULL; - Instruction::CastOps cast_op = codegen->get_cast_op(_children[0]->type(), _type); - if (cast_op == Instruction::CastOps::CastOpsEnd) { - return Status::InternalError("Unknow type"); - } - val = builder.CreateCast(cast_op, child_val.get_val(), codegen->get_type(_type), "val"); - builder.CreateBr(ret_block); - - // ret_block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi"); - is_null_phi->addIncoming(one, entry_block); - is_null_phi->addIncoming(zero, child_not_null_block); - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - val_phi->addIncoming(null, entry_block); - val_phi->addIncoming(val, child_not_null_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - - *fn = codegen->finalize_function(*fn); - return Status::OK(); -} - -#define CODEGEN_DEFINE(CLASS) \ - Status CLASS::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - if (_ir_compute_fn != NULL) { \ - *fn = _ir_compute_fn; \ - return Status::OK(); \ - } \ - RETURN_IF_ERROR(codegen_cast_fn(state, fn)); \ - _ir_compute_fn = *fn; \ - return Status::OK(); \ - } - -CODEGEN_DEFINE(CastBooleanExpr); -CODEGEN_DEFINE(CastTinyIntExpr); -CODEGEN_DEFINE(CastSmallIntExpr); -CODEGEN_DEFINE(CastIntExpr); -CODEGEN_DEFINE(CastBigIntExpr); -CODEGEN_DEFINE(CastLargeIntExpr); -CODEGEN_DEFINE(CastFloatExpr); -CODEGEN_DEFINE(CastDoubleExpr); } diff --git a/be/src/exprs/cast_expr.h b/be/src/exprs/cast_expr.h index e7e516afe8..e4b16a3579 100644 --- a/be/src/exprs/cast_expr.h +++ b/be/src/exprs/cast_expr.h @@ -28,8 +28,6 @@ public: CastExpr(const TExprNode& node) : Expr(node) { } virtual ~CastExpr() { } static Expr* from_thrift(const TExprNode& node); -protected: - Status codegen_cast_fn(RuntimeState* state, llvm::Function** fn); }; #define CAST_EXPR_DEFINE(CLASS) \ @@ -40,7 +38,6 @@ protected: virtual Expr* clone(ObjectPool* pool) const override { \ return pool->add(new CLASS(*this)); \ } \ - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); \ virtual BooleanVal get_boolean_val(ExprContext* context, TupleRow*); \ virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); \ virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); \ diff --git a/be/src/exprs/compound_predicate.cpp b/be/src/exprs/compound_predicate.cpp index 24783b809f..3dd52cecab 100644 --- a/be/src/exprs/compound_predicate.cpp +++ b/be/src/exprs/compound_predicate.cpp @@ -19,17 +19,10 @@ #include -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "util/debug_util.h" #include "runtime/runtime_state.h" -using llvm::BasicBlock; -using llvm::Function; -using llvm::PHINode; -using llvm::Value; -using llvm::LLVMContext; - namespace doris { CompoundPredicate::CompoundPredicate(const TExprNode& node) : @@ -98,182 +91,4 @@ std::string CompoundPredicate::debug_string() const { return out.str(); } -// IR codegen for compound and/or predicates. Compound predicate has non trivial -// null handling as well as many branches so this is pretty complicated. The IR -// for x && y is: -// -// define i16 @CompoundPredicate(%"class.impala::ExprContext"* %context, -// %"class.impala::TupleRow"* %row) #20 { -// entry: -// %lhs_call = call i16 @GetSlotRef1(%"class.impala::ExprContext"* %context, -// %"class.impala::TupleRow"* %row) -// %rhs_call = call i16 @Eq_IntVal_IntValWrapper(%"class.impala::ExprContext"* %context, -// %"class.impala::TupleRow"* %row) -// %is_null = trunc i16 %lhs_call to i1 -// %is_null1 = trunc i16 %rhs_call to i1 -// %0 = ashr i16 %lhs_call, 8 -// %1 = trunc i16 %0 to i8 -// %val = trunc i8 %1 to i1 -// %2 = ashr i16 %rhs_call, 8 -// %3 = trunc i16 %2 to i8 -// %val2 = trunc i8 %3 to i1 -// %tmp_and = and i1 %val, %val2 -// br i1 %is_null, label %lhs_null, label %lhs_not_null -// -// lhs_null: ; preds = %entry -// br i1 %is_null1, label %null_block, label %lhs_null_rhs_not_null -// -// lhs_not_null: ; preds = %entry -// br i1 %is_null1, label %lhs_not_null_rhs_null, label %not_null_block -// -// lhs_null_rhs_not_null: ; preds = %lhs_null -// br i1 %val2, label %null_block, label %not_null_block -// -// lhs_not_null_rhs_null: ; preds = %lhs_not_null -// br i1 %val, label %null_block, label %not_null_block -// -// null_block: ; preds = %lhs_null_rhs_not_null, -// %lhs_not_null_rhs_null, %lhs_null -// br label %ret -// -// not_null_block: ; preds = %lhs_null_rhs_not_null, -// %lhs_not_null_rhs_null, %lhs_not_null -// %4 = phi i1 [ false, %lhs_null_rhs_not_null ], -// [ false, %lhs_not_null_rhs_null ], -// [ %tmp_and, %lhs_not_null ] -// br label %ret -// -// ret: ; preds = %not_null_block, %null_block -// %ret3 = phi i1 [ false, %null_block ], [ %4, %not_null_block ] -// %5 = zext i1 %ret3 to i16 -// %6 = shl i16 %5, 8 -// %7 = or i16 0, %6 -// ret i16 %7 -// } -Status CompoundPredicate::codegen_compute_fn( - bool and_fn, RuntimeState* state, Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - DCHECK_EQ(get_num_children(), 2); - - Function* lhs_function = NULL; - RETURN_IF_ERROR(children()[0]->get_codegend_compute_fn(state, &lhs_function)); - Function* rhs_function = NULL; - RETURN_IF_ERROR(children()[1]->get_codegend_compute_fn(state, &rhs_function)); - - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - LLVMContext& context = codegen->context(); - LlvmCodeGen::LlvmBuilder builder(context); - Value* args[2]; - Function* function = create_ir_function_prototype(codegen, "CompoundPredicate", &args); - - BasicBlock* entry_block = BasicBlock::Create(context, "entry", function); - builder.SetInsertPoint(entry_block); - - // Control blocks for aggregating results - BasicBlock* lhs_null_block = BasicBlock::Create(context, "lhs_null", function); - BasicBlock* lhs_not_null_block = - BasicBlock::Create(context, "lhs_not_null", function); - BasicBlock* lhs_null_rhs_not_null_block = - BasicBlock::Create(context, "lhs_null_rhs_not_null", function); - BasicBlock* lhs_not_null_rhs_null_block = - BasicBlock::Create(context, "lhs_not_null_rhs_null", function); - BasicBlock* null_block = BasicBlock::Create(context, "null_block", function); - BasicBlock* not_null_block = BasicBlock::Create(context, "not_null_block", function); - BasicBlock* ret_block = BasicBlock::Create(context, "ret", function); - - // Call lhs - CodegenAnyVal lhs_result = CodegenAnyVal::create_call_wrapped( - codegen, &builder, TypeDescriptor(TYPE_BOOLEAN), lhs_function, args, "lhs_call"); - // Call rhs - CodegenAnyVal rhs_result = CodegenAnyVal::create_call_wrapped( - codegen, &builder, TypeDescriptor(TYPE_BOOLEAN), rhs_function, args, "rhs_call"); - - Value* lhs_is_null = lhs_result.get_is_null(); - Value* rhs_is_null = rhs_result.get_is_null(); - Value* lhs_value = lhs_result.get_val(); - Value* rhs_value = rhs_result.get_val(); - - // Apply predicate - Value* compare = NULL; - if (and_fn) { - compare = builder.CreateAnd(lhs_value, rhs_value, "tmp_and"); - } else { - compare = builder.CreateOr(lhs_value, rhs_value, "tmp_or"); - } - - // Branch if lhs is null - builder.CreateCondBr(lhs_is_null, lhs_null_block, lhs_not_null_block); - - // lhs_is_null block - builder.SetInsertPoint(lhs_null_block); - builder.CreateCondBr(rhs_is_null, null_block, lhs_null_rhs_not_null_block); - - // lhs_is_not_null block - builder.SetInsertPoint(lhs_not_null_block); - builder.CreateCondBr(rhs_is_null, lhs_not_null_rhs_null_block, not_null_block); - - // lhs_not_null rhs_null block - builder.SetInsertPoint(lhs_not_null_rhs_null_block); - if (and_fn) { - // false && null -> false; true && null -> null - builder.CreateCondBr(lhs_value, null_block, not_null_block); - } else { - // true || null -> true; false || null -> null - builder.CreateCondBr(lhs_value, not_null_block, null_block); - } - - // lhs_null rhs_not_null block - builder.SetInsertPoint(lhs_null_rhs_not_null_block); - if (and_fn) { - // null && false -> false; null && true -> null - builder.CreateCondBr(rhs_value, null_block, not_null_block); - } else { - // null || true -> true; null || false -> null - builder.CreateCondBr(rhs_value, not_null_block, null_block); - } - - // NULL block - builder.SetInsertPoint(null_block); - builder.CreateBr(ret_block); - - // not-NULL block - builder.SetInsertPoint(not_null_block); - PHINode* not_null_phi = builder.CreatePHI(codegen->get_type(TYPE_BOOLEAN), 3); - if (and_fn) { - not_null_phi->addIncoming(codegen->false_value(), lhs_null_rhs_not_null_block); - not_null_phi->addIncoming(codegen->false_value(), lhs_not_null_rhs_null_block); - not_null_phi->addIncoming(compare, lhs_not_null_block); - } else { - not_null_phi->addIncoming(codegen->true_value(), lhs_null_rhs_not_null_block); - not_null_phi->addIncoming(codegen->true_value(), lhs_not_null_rhs_null_block); - not_null_phi->addIncoming(compare, lhs_not_null_block); - } - builder.CreateBr(ret_block); - - // Ret/merge block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->boolean_type(), 2, "is_null"); - is_null_phi->addIncoming(codegen->true_value(), null_block); - is_null_phi->addIncoming(codegen->false_value(), not_null_block); - - PHINode* val_phi = builder.CreatePHI(codegen->boolean_type(), 2, "val"); - val_phi->addIncoming(codegen->false_value(), null_block); - val_phi->addIncoming(not_null_phi, not_null_block); - - CodegenAnyVal ret(codegen, &builder, TypeDescriptor(TYPE_BOOLEAN), NULL, "ret"); - ret.set_is_null(is_null_phi); - ret.set_val(val_phi); - builder.CreateRet(ret.value()); - - *fn = codegen->finalize_function(function); - DCHECK(*fn != NULL); - _ir_compute_fn = *fn; - return Status::OK(); -} - } diff --git a/be/src/exprs/compound_predicate.h b/be/src/exprs/compound_predicate.h index fbecd28777..dc384db203 100644 --- a/be/src/exprs/compound_predicate.h +++ b/be/src/exprs/compound_predicate.h @@ -24,10 +24,6 @@ #include "exprs/predicate.h" #include "gen_cpp/Exprs_types.h" -namespace llvm { -class Function; -} - namespace doris { class CompoundPredicate: public Predicate { @@ -40,7 +36,6 @@ protected: CompoundPredicate(const TExprNode& node); - Status codegen_compute_fn(bool and_fn, RuntimeState* state, llvm::Function** fn); // virtual Status prepare(RuntimeState* state, const RowDescriptor& desc); virtual std::string debug_string() const; @@ -60,10 +55,6 @@ public: } virtual doris_udf::BooleanVal get_boolean_val(ExprContext* context, TupleRow*); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return CompoundPredicate::codegen_compute_fn(true, state, fn); - } - protected: friend class Expr; AndPredicate(const TExprNode& node) : CompoundPredicate(node) { } @@ -86,10 +77,6 @@ public: } virtual doris_udf::BooleanVal get_boolean_val(ExprContext* context, TupleRow*); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return CompoundPredicate::codegen_compute_fn(false, state, fn); - } - protected: friend class Expr; OrPredicate(const TExprNode& node) : CompoundPredicate(node) { } @@ -112,10 +99,6 @@ public: } virtual doris_udf::BooleanVal get_boolean_val(ExprContext* context, TupleRow*); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - return get_codegend_compute_fn_wrapper(state, fn); - } - protected: friend class Expr; NotPredicate(const TExprNode& node) : CompoundPredicate(node) { } diff --git a/be/src/exprs/conditional_functions.cpp b/be/src/exprs/conditional_functions.cpp index c81ce2f47f..5d40bb3d31 100644 --- a/be/src/exprs/conditional_functions.cpp +++ b/be/src/exprs/conditional_functions.cpp @@ -23,20 +23,8 @@ #include "runtime/tuple_row.h" #include "udf/udf.h" -using llvm::Function; - namespace doris { -#define CONDITIONAL_CODEGEN_FN(expr_class) \ - Status expr_class::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { \ - return get_codegend_compute_fn_wrapper(state, fn); \ - } - -CONDITIONAL_CODEGEN_FN(IfNullExpr); -CONDITIONAL_CODEGEN_FN(NullIfExpr); -CONDITIONAL_CODEGEN_FN(IfExpr); -CONDITIONAL_CODEGEN_FN(CoalesceExpr); - #define CTOR_DCTOR_FUN(expr_class) \ expr_class::expr_class(const TExprNode& node) : Expr(node) { \ };\ diff --git a/be/src/exprs/conditional_functions.h b/be/src/exprs/conditional_functions.h index 3d279001fb..28aaf42b57 100644 --- a/be/src/exprs/conditional_functions.h +++ b/be/src/exprs/conditional_functions.h @@ -23,10 +23,6 @@ #include "exprs/expr.h" #include "udf/udf.h" -namespace llvm { -class Function; -} - namespace doris { class TupleRow; @@ -57,8 +53,6 @@ public: virtual DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow* row); virtual LargeIntVal get_large_int_val(ExprContext* context, TupleRow* row); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); - virtual std::string debug_string() const { return Expr::debug_string("IfNullExpr"); } @@ -86,7 +80,6 @@ public: // virtual DecimalVal get_decimal_val(ExprContext* context, TupleRow* row); virtual LargeIntVal get_large_int_val(ExprContext* context, TupleRow* row); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual std::string debug_string() const { return Expr::debug_string("NullIfExpr"); } @@ -115,7 +108,6 @@ public: virtual DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow* row); virtual LargeIntVal get_large_int_val(ExprContext* context, TupleRow* row); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual std::string debug_string() const { return Expr::debug_string("IfExpr"); } @@ -145,7 +137,6 @@ public: virtual DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow* row); virtual LargeIntVal get_large_int_val(ExprContext* context, TupleRow* row); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual std::string debug_string() const { return Expr::debug_string("CoalesceExpr"); } protected: diff --git a/be/src/exprs/expr.cpp b/be/src/exprs/expr.cpp index 663a095a80..5b114d34d4 100644 --- a/be/src/exprs/expr.cpp +++ b/be/src/exprs/expr.cpp @@ -20,10 +20,8 @@ #include #include #include -#include #include "codegen/codegen_anyval.h" -#include "codegen/llvm_codegen.h" #include "common/object_pool.h" #include "common/status.h" #include "exprs/anyval_util.h" @@ -54,15 +52,9 @@ #include "gen_cpp/Exprs_types.h" #include "gen_cpp/PaloService_types.h" -using llvm::Function; -using llvm::Instruction; -using llvm::CallInst; -using llvm::ConstantInt; -using llvm::Value; using std::vector; namespace doris { -const char* Expr::_s_llvm_class_name = "class.doris::Expr"; const char* Expr::_s_get_constant_symbol_prefix = "_ZN4doris4Expr12get_constant"; template @@ -101,7 +93,6 @@ Expr::Expr(const Expr& expr) _output_column(expr._output_column), _fn(expr._fn), _fn_context_index(expr._fn_context_index), - _ir_compute_fn(expr._ir_compute_fn), _constant_val(expr._constant_val), _vector_compute_fn(expr._vector_compute_fn) { } @@ -113,8 +104,7 @@ Expr::Expr(const TypeDescriptor& type) : _type(type), _output_scale(-1), _output_column(-1), - _fn_context_index(-1), - _ir_compute_fn(NULL) { + _fn_context_index(-1) { switch (_type.type) { case TYPE_BOOLEAN: _node_type = (TExprNodeType::BOOL_LITERAL); @@ -170,8 +160,7 @@ Expr::Expr(const TypeDescriptor& type, bool is_slotref) : _type(type), _output_scale(-1), _output_column(-1), - _fn_context_index(-1), - _ir_compute_fn(NULL) { + _fn_context_index(-1) { if (is_slotref) { _node_type = (TExprNodeType::SLOT_REF); } else { @@ -232,8 +221,7 @@ Expr::Expr(const TExprNode& node) : _type(TypeDescriptor::from_thrift(node.type)), _output_scale(node.output_scale), _output_column(node.__isset.output_column ? node.output_column : -1), - _fn_context_index(-1), - _ir_compute_fn(NULL) { + _fn_context_index(-1) { if (node.__isset.fn) { _fn = node.fn; } @@ -248,8 +236,7 @@ Expr::Expr(const TExprNode& node, bool is_slotref) : _type(TypeDescriptor::from_thrift(node.type)), _output_scale(node.output_scale), _output_column(node.__isset.output_column ? node.output_column : -1), - _fn_context_index(-1), - _ir_compute_fn(NULL) { + _fn_context_index(-1) { if (node.__isset.fn) { _fn = node.fn; } @@ -641,7 +628,7 @@ std::string Expr::debug_string() const { out << " opcode=" << _opcode; } - out << " codegen=" << (_ir_compute_fn == NULL ? "false" : "true"); + out << " codegen=" << "false"; if (!_children.empty()) { out << " children=" << debug_string(_children); @@ -863,131 +850,6 @@ Status Expr::get_fn_context_error(ExprContext* ctx) { return Status::OK(); } -llvm::Function* Expr::create_ir_function_prototype( - LlvmCodeGen* codegen, const std::string& name, llvm::Value* (*args)[2]) { - llvm::Type* return_type = CodegenAnyVal::get_lowered_type(codegen, type()); - LlvmCodeGen::FnPrototype prototype(codegen, name, return_type); - prototype.add_argument( - LlvmCodeGen::NamedVariable( - "context", codegen->get_ptr_type(ExprContext::_s_llvm_class_name))); - prototype.add_argument( - LlvmCodeGen::NamedVariable("row", codegen->get_ptr_type(TupleRow::_s_llvm_class_name))); - llvm::Function* function = prototype.generate_prototype(NULL, args[0]); - DCHECK(function != NULL); - return function; -} - -llvm::Function* Expr::get_static_get_val_wrapper( - const TypeDescriptor& type, LlvmCodeGen* codegen) { - switch (type.type) { - case TYPE_BOOLEAN: - return codegen->get_function(IRFunction::EXPR_GET_BOOLEAN_VAL); - case TYPE_TINYINT: - return codegen->get_function(IRFunction::EXPR_GET_TINYINT_VAL); - case TYPE_SMALLINT: - return codegen->get_function(IRFunction::EXPR_GET_SMALLINT_VAL); - case TYPE_INT: - return codegen->get_function(IRFunction::EXPR_GET_INT_VAL); - case TYPE_BIGINT: - return codegen->get_function(IRFunction::EXPR_GET_BIGINT_VAL); - case TYPE_LARGEINT: - return codegen->get_function(IRFunction::EXPR_GET_LARGEINT_VAL); - case TYPE_FLOAT: - return codegen->get_function(IRFunction::EXPR_GET_FLOAT_VAL); - case TYPE_DOUBLE: - return codegen->get_function(IRFunction::EXPR_GET_DOUBLE_VAL); - case TYPE_CHAR: - case TYPE_VARCHAR: - return codegen->get_function(IRFunction::EXPR_GET_STRING_VAL); - case TYPE_DATE: - case TYPE_DATETIME: - return codegen->get_function(IRFunction::EXPR_GET_DATETIME_VAL); - case TYPE_DECIMAL: - return codegen->get_function(IRFunction::EXPR_GET_DECIMAL_VAL); - default: - DCHECK(false) << "Invalid type: " << type.debug_string(); - return NULL; - } -} - -Value* Expr::get_ir_constant(LlvmCodeGen* codegen, ExprConstant c, int i) { - switch (c) { - case RETURN_TYPE_SIZE: - DCHECK_EQ(i, -1); - return ConstantInt::get(codegen->get_type(TYPE_INT), _type.get_byte_size()); - case ARG_TYPE_SIZE: - DCHECK_GE(i, 0); - DCHECK_LT(i, _children.size()); - return ConstantInt::get( - codegen->get_type(TYPE_INT), _children[i]->_type.get_byte_size()); - default: - CHECK(false) << "NYI"; - return NULL; - } -} - -int Expr::inline_constants(LlvmCodeGen* codegen, Function* fn) { - int replaced = 0; - for (llvm::inst_iterator iter = llvm::inst_begin(fn), end = llvm::inst_end(fn); - iter != end;) { - // Increment iter now so we don't mess it up modifying the instrunction below - Instruction* instr = &*(iter++); - - // Look for call instructions - if (!llvm::isa(instr)) { - continue; - } - CallInst* call_instr = llvm::cast(instr); - Function* called_fn = call_instr->getCalledFunction(); - - // Look for call to Expr::GetConstant() - if (called_fn == NULL || - called_fn->getName().find(_s_get_constant_symbol_prefix) == std::string::npos) { - continue; - } - - // 'c' and 'i' arguments must be constant - ConstantInt* c_arg = llvm::dyn_cast(call_instr->getArgOperand(1)); - ConstantInt* i_arg = llvm::dyn_cast(call_instr->getArgOperand(2)); - DCHECK(c_arg != NULL) << "Non-constant 'c' argument to Expr::GetConstant()"; - DCHECK(i_arg != NULL) << "Non-constant 'i' argument to Expr::GetConstant()"; - - // Replace the called function with the appropriate constant - ExprConstant c_val = static_cast(c_arg->getSExtValue()); - int i_val = static_cast(i_arg->getSExtValue()); - call_instr->replaceAllUsesWith(get_ir_constant(codegen, c_val, i_val)); - call_instr->eraseFromParent(); - ++replaced; - } - return replaced; -} - -Status Expr::get_codegend_compute_fn_wrapper(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - llvm::Function* static_getval_fn = get_static_get_val_wrapper(type(), codegen); - - // Call it passing this as the additional first argument. - llvm::Value* args[2]; - _ir_compute_fn = create_ir_function_prototype(codegen, "codegen_compute_fn_wrapper", &args); - llvm::BasicBlock* entry_block = - llvm::BasicBlock::Create(codegen->context(), "entry", _ir_compute_fn); - LlvmCodeGen::LlvmBuilder builder(entry_block); - llvm::Value* this_ptr = - codegen->cast_ptr_to_llvm_ptr(codegen->get_ptr_type(Expr::_s_llvm_class_name), this); - llvm::Value* compute_fn_args[] = { this_ptr, args[0], args[1] }; - llvm::Value* ret = CodegenAnyVal::create_call( - codegen, &builder, static_getval_fn, compute_fn_args, "ret", NULL); - builder.CreateRet(ret); - _ir_compute_fn = codegen->finalize_function(_ir_compute_fn); - *fn = _ir_compute_fn; - return Status::OK(); -} - Expr* Expr::copy(ObjectPool* pool, Expr* old_expr) { auto new_expr = old_expr->clone(pool); for (auto child : old_expr->_children) { diff --git a/be/src/exprs/expr.h b/be/src/exprs/expr.h index a32bfd3bbd..fa72194ad3 100644 --- a/be/src/exprs/expr.h +++ b/be/src/exprs/expr.h @@ -43,17 +43,9 @@ USING_DORIS_UDF; -namespace llvm { -class BasicBlock; -class Function; -class Type; -class Value; -}; - namespace doris { class Expr; -class LlvmCodeGen; class ObjectPool; class RowDescriptor; class RuntimeState; @@ -265,24 +257,12 @@ public: static int compute_results_layout(const std::vector& ctxs, std::vector* offsets, int* var_result_begin); - /// Returns an llvm::Function* with signature: - /// ComputeFn(ExprContext* context, TupleRow* row) - // - /// The function should evaluate this expr over 'row' and return the result as the - /// appropriate type of AnyVal. - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) = 0; - /// If this expr is constant, evaluates the expr with no input row argument and returns /// the output. Returns NULL if the argument is not constant. The returned AnyVal* is /// owned by this expr. This should only be called after Open() has been called on this /// expr. virtual AnyVal* get_const_val(ExprContext* context); - /// Finds all calls to Expr::GetConstant() in 'fn' and replaces them with the requested - /// runtime constant. Returns the number of calls replaced. This should be used in - /// GetCodegendComputeFn(). - int inline_constants(LlvmCodeGen* codegen, llvm::Function* fn); - /// Assigns indices into the FunctionContext vector 'fn_ctxs_' in an evaluator to /// nodes which need FunctionContext in the tree. 'next_fn_ctx_idx' is the index /// of the next available entry in the vector. It's updated as this function is @@ -293,8 +273,6 @@ public: static std::string debug_string(const std::vector& exprs); static std::string debug_string(const std::vector& ctxs); - static const char* _s_llvm_class_name; - // Prefix of Expr::GetConstant() symbols, regardless of template specialization static const char* _s_get_constant_symbol_prefix; @@ -430,9 +408,6 @@ protected: /// doesn't call RegisterFunctionContext(). int _fn_context_index; - /// Cached codegened compute function. Exprs should set this in get_codegend_compute_fn(). - llvm::Function* _ir_compute_fn; - // If this expr is constant, this will store and cache the value generated by // get_const_val(). std::shared_ptr _constant_val; @@ -440,30 +415,6 @@ protected: // function to evaluate vectorize expr; typically set in prepare() VectorComputeFn _vector_compute_fn; - // vector function opcode - // TExprOpcode::type _vector_opcode; - - /// Helper function to create an empty Function* with the appropriate signature to be - /// returned by GetCodegendComputeFn(). 'name' is the name of the returned Function*. - /// The arguments to the function are returned in 'args'. - llvm::Function* create_ir_function_prototype( - LlvmCodeGen* codegen, const std::string& name, llvm::Value* (*args)[2]); - - /// Generates an IR compute function that calls the appropriate interpreted Get*Val() - /// compute function. - // - /// This is useful for builtins that can't be implemented with the UDF interface - /// (e.g. functions that need short-circuiting) and that don't have custom codegen - /// functions that use the IRBuilder. It doesn't provide any performance benefit over - /// the interpreted path. - /// TODO: this should be replaced with fancier xcompiling infrastructure - Status get_codegend_compute_fn_wrapper(RuntimeState* state, llvm::Function** fn); - - /// Returns the IR version of the static Get*Val() wrapper function corresponding to - /// 'type'. This is used for calling interpreted Get*Val() functions from codegen'd - /// functions (e.g. in ScalarFnCall() when codegen is disabled). - llvm::Function* get_static_get_val_wrapper(const TypeDescriptor& type, LlvmCodeGen* codegen); - /// Simple debug string that provides no expr subclass-specific information std::string debug_string(const std::string& expr_name) const { std::stringstream out; @@ -520,10 +471,6 @@ private: static DecimalVal get_decimal_val(Expr* expr, ExprContext* context, TupleRow* row); static DecimalV2Val get_decimalv2_val(Expr* expr, ExprContext* context, TupleRow* row); - // Helper function for InlineConstants(). Returns the IR version of what GetConstant() - // would return. - llvm::Value* get_ir_constant(LlvmCodeGen* codegen, ExprConstant c, int i); - /// Creates an expression tree rooted at 'root' via depth-first traversal. /// Called recursively to create children expr trees for sub-expressions. /// diff --git a/be/src/exprs/expr_context.cpp b/be/src/exprs/expr_context.cpp index 6c21b89025..99506f2df7 100644 --- a/be/src/exprs/expr_context.cpp +++ b/be/src/exprs/expr_context.cpp @@ -33,8 +33,6 @@ namespace doris { -const char* ExprContext::_s_llvm_class_name = "class.doris::ExprContext"; - ExprContext::ExprContext(Expr* root) : _fn_contexts_ptr(NULL), _root(root), diff --git a/be/src/exprs/expr_context.h b/be/src/exprs/expr_context.h index 36c300c899..ebc0822e10 100644 --- a/be/src/exprs/expr_context.h +++ b/be/src/exprs/expr_context.h @@ -150,8 +150,6 @@ public: static void free_local_allocations(const std::vector& ctxs); static void free_local_allocations(const std::vector& ctxs); - static const char* _s_llvm_class_name; - bool opened() { return _opened; } diff --git a/be/src/exprs/in_predicate.cpp b/be/src/exprs/in_predicate.cpp index f9ac0223bf..862f01006f 100644 --- a/be/src/exprs/in_predicate.cpp +++ b/be/src/exprs/in_predicate.cpp @@ -21,7 +21,6 @@ #include "exprs/anyval_util.h" #include "exprs/anyval_util.h" -#include "codegen/llvm_codegen.h" #include "runtime/raw_value.h" #include "runtime/string_value.hpp" #include "runtime/runtime_state.h" diff --git a/be/src/exprs/in_predicate.h b/be/src/exprs/in_predicate.h index 4b3c6fa572..742e35a61e 100644 --- a/be/src/exprs/in_predicate.h +++ b/be/src/exprs/in_predicate.h @@ -47,10 +47,6 @@ public: virtual BooleanVal get_boolean_val(ExprContext* context, TupleRow* row); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override { - return get_codegend_compute_fn_wrapper(state, fn); - } - // this function add one item in hashset, not add to children. // if add to children, when List is long, copy is a expensive op. void insert(void* value); diff --git a/be/src/exprs/info_func.h b/be/src/exprs/info_func.h index f0c05bb80d..9a145b62e2 100644 --- a/be/src/exprs/info_func.h +++ b/be/src/exprs/info_func.h @@ -39,10 +39,6 @@ protected: InfoFunc(const TExprNode& node); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override { - return get_codegend_compute_fn_wrapper(state, fn); - } - virtual StringVal get_string_val(ExprContext* context, TupleRow*); virtual BigIntVal get_big_int_val(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/literal.cpp b/be/src/exprs/literal.cpp index cb66f61449..061f3c5952 100644 --- a/be/src/exprs/literal.cpp +++ b/be/src/exprs/literal.cpp @@ -19,17 +19,11 @@ #include -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "gen_cpp/Exprs_types.h" #include "util/string_parser.hpp" #include "runtime/runtime_state.h" -using llvm::BasicBlock; -using llvm::Function; -using llvm::Type; -using llvm::Value; - namespace doris { Literal::Literal(const TExprNode& node) : @@ -182,81 +176,4 @@ StringVal Literal::get_string_val(ExprContext* context, TupleRow* row) { return str_val; } -// IR produced for bigint literal 10: -// -// define { i8, i64 } @Literal(i8* %context, %"class.doris::TupleRow"* %row) { -// entry: -// ret { i8, i64 } { i8 0, i64 10 } -// } -Status Literal::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - DCHECK_EQ(get_num_children(), 0); - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "literal", &args); - BasicBlock* entry_block = BasicBlock::Create(codegen->context(), "entry", *fn); - LlvmCodeGen::LlvmBuilder builder(entry_block); - - CodegenAnyVal v = CodegenAnyVal::get_non_null_val(codegen, &builder, _type); - switch (_type.type) { - case TYPE_BOOLEAN: - v.set_val(_value.bool_val); - break; - case TYPE_TINYINT: - v.set_val(_value.tinyint_val); - break; - case TYPE_SMALLINT: - v.set_val(_value.smallint_val); - break; - case TYPE_INT: - v.set_val(_value.int_val); - break; - case TYPE_BIGINT: - v.set_val(_value.bigint_val); - break; - case TYPE_LARGEINT: - v.set_val(_value.large_int_val); - break; - case TYPE_FLOAT: - v.set_val(_value.float_val); - break; - case TYPE_DOUBLE: - v.set_val(_value.double_val); - break; - case TYPE_CHAR: - case TYPE_VARCHAR: - v.set_len(builder.getInt32(_value.string_val.len)); - v.set_ptr(codegen->cast_ptr_to_llvm_ptr(codegen->ptr_type(), _value.string_val.ptr)); - break; - case TYPE_DECIMAL: { - Type* raw_ptr_type = codegen->decimal_val_type()->getPointerTo(); - Value* raw_ptr = codegen->cast_ptr_to_llvm_ptr(raw_ptr_type, &_value.decimal_val); - v.set_from_raw_ptr(raw_ptr); - break; - } - case TYPE_DATE: - case TYPE_DATETIME: { - Type* raw_ptr_type = codegen->decimal_val_type()->getPointerTo(); - Value* raw_ptr = codegen->cast_ptr_to_llvm_ptr(raw_ptr_type, &_value.datetime_val); - v.set_from_raw_ptr(raw_ptr); - break; - } - default: - std::stringstream ss; - ss << "Invalid type: " << _type; - DCHECK(false) << ss.str(); - return Status::InternalError(ss.str()); - } - - builder.CreateRet(v.value()); - *fn = codegen->finalize_function(*fn); - _ir_compute_fn = *fn; - return Status::OK(); -} - } diff --git a/be/src/exprs/literal.h b/be/src/exprs/literal.h index cf48f26689..dc12f908e6 100644 --- a/be/src/exprs/literal.h +++ b/be/src/exprs/literal.h @@ -33,8 +33,6 @@ public: return pool->add(new Literal(*this)); } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); - virtual BooleanVal get_boolean_val(ExprContext* context, TupleRow*); virtual TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); virtual SmallIntVal get_small_int_val(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/new_agg_fn_evaluator.cc b/be/src/exprs/new_agg_fn_evaluator.cc index f51ef33bb8..56409d79ab 100644 --- a/be/src/exprs/new_agg_fn_evaluator.cc +++ b/be/src/exprs/new_agg_fn_evaluator.cc @@ -19,7 +19,6 @@ #include -#include "codegen/llvm_codegen.h" #include "common/logging.h" #include "exprs/aggregate_functions.h" #include "exprs/agg_fn.h" @@ -41,7 +40,6 @@ using namespace doris; using namespace doris_udf; -using namespace llvm; using std::move; // typedef for builtin aggregate functions. Unfortunately, these type defs don't @@ -89,7 +87,6 @@ typedef StringVal (*SerializeFn)(FunctionContext*, const StringVal&); typedef AnyVal (*GetValueFn)(FunctionContext*, const AnyVal&); typedef AnyVal (*FinalizeFn)(FunctionContext*, const AnyVal&); -const char* NewAggFnEvaluator::LLVM_CLASS_NAME = "class.impala::NewAggFnEvaluator"; const int DEFAULT_MULTI_DISTINCT_COUNT_STRING_BUFFER_SIZE = 1024; NewAggFnEvaluator::NewAggFnEvaluator(const AggFn& agg_fn, MemPool* mem_pool, MemTracker* tracker, bool is_clone) diff --git a/be/src/exprs/new_agg_fn_evaluator.h b/be/src/exprs/new_agg_fn_evaluator.h index 529bd240ec..5d482e92cd 100644 --- a/be/src/exprs/new_agg_fn_evaluator.h +++ b/be/src/exprs/new_agg_fn_evaluator.h @@ -200,8 +200,6 @@ class NewAggFnEvaluator { std::string DebugString() const; static std::string DebugString(const std::vector& evals); - static const char* LLVM_CLASS_NAME; - private: uint64_t _total_mem_consumption; diff --git a/be/src/exprs/null_literal.cpp b/be/src/exprs/null_literal.cpp index 691a01e472..baade57d6c 100644 --- a/be/src/exprs/null_literal.cpp +++ b/be/src/exprs/null_literal.cpp @@ -17,15 +17,10 @@ #include "null_literal.h" -#include "codegen/llvm_codegen.h" #include "codegen/codegen_anyval.h" #include "gen_cpp/Exprs_types.h" #include "runtime/runtime_state.h" -using llvm::BasicBlock; -using llvm::Function; -using llvm::Value; - namespace doris { NullLiteral::NullLiteral(const TExprNode& node) : @@ -78,31 +73,5 @@ DecimalVal NullLiteral::get_decimal_val(ExprContext*, TupleRow*) { DecimalV2Val NullLiteral::get_decimalv2_val(ExprContext*, TupleRow*) { return DecimalV2Val::null(); } -// Generated IR for a bigint NULL literal: -// -// define { i8, i64 } @NullLiteral(i8* %context, %"class.impala::TupleRow"* %row) { -// entry: -// ret { i8, i64 } { i8 1, i64 0 } -// } -Status NullLiteral::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - DCHECK_EQ(get_num_children(), 0); - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "NullLiteral", &args); - BasicBlock* entry_block = BasicBlock::Create(codegen->context(), "entry", *fn); - LlvmCodeGen::LlvmBuilder builder(entry_block); - - Value* v = CodegenAnyVal::get_null_val(codegen, type()); - builder.CreateRet(v); - *fn = codegen->finalize_function(*fn); - _ir_compute_fn = *fn; - return Status::OK(); -} } diff --git a/be/src/exprs/null_literal.h b/be/src/exprs/null_literal.h index c53aee7ed9..6eeb105aca 100644 --- a/be/src/exprs/null_literal.h +++ b/be/src/exprs/null_literal.h @@ -21,10 +21,6 @@ #include "common/object_pool.h" #include "exprs/expr.h" -namespace llvm { -class Function; -} - namespace doris { class TExprNode; @@ -36,7 +32,6 @@ public: return pool->add(new NullLiteral(*this)); } // NullLiteral(PrimitiveType type); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn); virtual doris_udf::BooleanVal get_boolean_val(ExprContext*, TupleRow*); virtual doris_udf::TinyIntVal get_tiny_int_val(ExprContext*, TupleRow*); virtual doris_udf::SmallIntVal get_small_int_val(ExprContext*, TupleRow*); diff --git a/be/src/exprs/scalar_fn_call.cpp b/be/src/exprs/scalar_fn_call.cpp index 7b75ea68fa..b6a3dc67b5 100644 --- a/be/src/exprs/scalar_fn_call.cpp +++ b/be/src/exprs/scalar_fn_call.cpp @@ -18,11 +18,8 @@ #include "exprs/scalar_fn_call.h" #include -//#include -#include #include "codegen/codegen_anyval.h" -#include "codegen/llvm_codegen.h" #include "exprs/anyval_util.h" #include "exprs/expr_context.h" #include "runtime/user_function_cache.h" @@ -31,11 +28,6 @@ #include "util/debug_util.h" #include "util/symbols_util.h" -using llvm::Value; -using llvm::Function; -using llvm::FunctionType; -using llvm::BasicBlock; -using llvm::Type; namespace doris { ScalarFnCall::ScalarFnCall(const TExprNode& node) : @@ -244,300 +236,6 @@ bool ScalarFnCall::is_constant() const { return Expr::is_constant(); } -// Dynamically loads the pre-compiled UDF and codegens a function that calls each child's -// codegen'd function, then passes those values to the UDF and returns the result. -// Example generated IR for a UDF with signature -// create function Udf(double, int...) returns double -// select Udf(1.0, 2, 3, 4, 5) -// define { i8, double } @UdfWrapper(i8* %context, %"class.impala::TupleRow"* %row) { -// entry: -// %arg_val = call { i8, double } -// @ExprWrapper(i8* %context, %"class.impala::TupleRow"* %row) -// %arg_ptr = alloca { i8, double } -// store { i8, double } %arg_val, { i8, double }* %arg_ptr -// %arg_val1 = call i64 @ExprWrapper1(i8* %context, %"class.impala::TupleRow"* %row) -// store i64 %arg_val1, i64* inttoptr (i64 89111072 to i64*) -// %arg_val2 = call i64 @ExprWrapper2(i8* %context, %"class.impala::TupleRow"* %row) -// store i64 %arg_val2, i64* inttoptr (i64 89111080 to i64*) -// %arg_val3 = call i64 @ExprWrapper3(i8* %context, %"class.impala::TupleRow"* %row) -// store i64 %arg_val3, i64* inttoptr (i64 89111088 to i64*) -// %arg_val4 = call i64 @ExprWrapper4(i8* %context, %"class.impala::TupleRow"* %row) -// store i64 %arg_val4, i64* inttoptr (i64 89111096 to i64*) -// %result = call { i8, double } -// @_Z14VarSumMultiplyPN10impala_udf15FunctionContextERKNS_9DoubleValEiPKNS_6IntValE( -// %"class.doris_udf::FunctionContext"* inttoptr -// (i64 37522464 to %"class.doris_udf::FunctionContext"*), -// {i8, double }* %arg_ptr, -// i32 4, -// i64* inttoptr (i64 89111072 to i64*)) -// ret { i8, double } %result -Status ScalarFnCall::get_codegend_compute_fn(RuntimeState* state, Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - for (int i = 0; i < get_num_children(); ++i) { - if (_children[i]->type().type == TYPE_CHAR) { - *fn = NULL; - return Status::InternalError("ScalarFnCall Codegen not supported for CHAR"); - } - } - - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - - Function* udf = NULL; - RETURN_IF_ERROR(get_udf(state, &udf)); - - // Create wrapper that computes args and calls UDF - std::stringstream fn_name; - fn_name << udf->getName().str() << "_wrapper"; - - Value* args[2]; - *fn = create_ir_function_prototype(codegen, fn_name.str(), &args); - Value* expr_ctx = args[0]; - Value* row = args[1]; - BasicBlock* block = BasicBlock::Create(codegen->context(), "entry", *fn); - LlvmCodeGen::LlvmBuilder builder(block); - - // Populate UDF arguments - std::vector udf_args; - - // First argument is always FunctionContext*. - // Index into our registered offset in the ExprContext. - Value* expr_ctx_gep = builder.CreateStructGEP(expr_ctx, 1, "expr_ctx_gep"); - Value* fn_ctxs_base = builder.CreateLoad(expr_ctx_gep, "fn_ctxs_base"); - // Use GEP to add our index to the base pointer - Value* fn_ctx_ptr = - builder.CreateConstGEP1_32(fn_ctxs_base, _fn_context_index, "fn_ctx_ptr"); - Value* fn_ctx = builder.CreateLoad(fn_ctx_ptr, "fn_ctx"); - udf_args.push_back(fn_ctx); - - // Get IR i8* pointer to varargs buffer from FunctionContext* argument - // (if there are varargs) - Value* varargs_buffer = NULL; - if (_vararg_start_idx != -1) { - // FunctionContextImpl is first field of FunctionContext - // fn_ctx_impl_ptr has type FunctionContextImpl** - Value* fn_ctx_impl_ptr = builder.CreateStructGEP(fn_ctx, 0, "fn_ctx_impl_ptr"); - Value* fn_ctx_impl = builder.CreateLoad(fn_ctx_impl_ptr, "fn_ctx_impl"); - // varargs_buffer is first field of FunctionContextImpl - // varargs_buffer_ptr has type i8** - Value* varargs_buffer_ptr = - builder.CreateStructGEP(fn_ctx_impl, 0, "varargs_buffer"); - varargs_buffer = builder.CreateLoad(varargs_buffer_ptr); - } - // Tracks where to write the next vararg to - int varargs_buffer_offset = 0; - - // Call children to populate remaining arguments - for (int i = 0; i < get_num_children(); ++i) { - Function* child_fn = NULL; - std::vector child_fn_args; - if (state->codegen_level() > 0) { - // Set 'child_fn' to the codegen'd function, sets child_fn = NULL if codegen fails - _children[i]->get_codegend_compute_fn(state, &child_fn); - } - if (child_fn == NULL) { - // Set 'child_fn' to the interpreted function - child_fn = get_static_get_val_wrapper(_children[i]->type(), codegen); - // First argument to interpreted function is _children[i] - Type* expr_ptr_type = codegen->get_ptr_type(Expr::_s_llvm_class_name); - child_fn_args.push_back(codegen->cast_ptr_to_llvm_ptr(expr_ptr_type, _children[i])); - } - child_fn_args.push_back(expr_ctx); - child_fn_args.push_back(row); - - // Call 'child_fn', adding the result to either 'udf_args' or 'varargs_buffer' - DCHECK(child_fn != NULL); - Type* arg_type = CodegenAnyVal::get_unlowered_type(codegen, _children[i]->type()); - Value* arg_val_ptr = NULL; - if (_vararg_start_idx == -1 || i < _vararg_start_idx) { - // Either no varargs or arguments before varargs begin. Allocate space to store - // 'child_fn's result so we can pass the pointer to the UDF. - arg_val_ptr = codegen->create_entry_block_alloca(builder, arg_type, "arg_val_ptr"); - - if (_children[i]->type().type == TYPE_DECIMAL) { - // UDFs may manipulate DecimalVal arguments via SIMD instructions such as 'movaps' - // that require 16-byte memory alignment. LLVM uses 8-byte alignment by default, - // so explicitly set the alignment for DecimalVals. - llvm::cast(arg_val_ptr)->setAlignment(16); - } - udf_args.push_back(arg_val_ptr); - } else { - // Store the result of 'child_fn' in varargs_buffer + varargs_buffer_offset - arg_val_ptr = - builder.CreateConstGEP1_32(varargs_buffer, varargs_buffer_offset, "arg_val_ptr"); - varargs_buffer_offset += AnyValUtil::any_val_size(_children[i]->type()); - // Cast arg_val_ptr from i8* to AnyVal pointer type - arg_val_ptr = - builder.CreateBitCast(arg_val_ptr, arg_type->getPointerTo(), "arg_val_ptr"); - } - DCHECK_EQ(arg_val_ptr->getType(), arg_type->getPointerTo()); - // The result of the call must be stored in a lowered AnyVal - Value* lowered_arg_val_ptr = builder.CreateBitCast( - arg_val_ptr, CodegenAnyVal::get_lowered_ptr_type(codegen, _children[i]->type()), - "lowered_arg_val_ptr"); - CodegenAnyVal::create_call( - codegen, &builder, child_fn, child_fn_args, "arg_val", lowered_arg_val_ptr); - } - - if (_vararg_start_idx != -1) { - // We've added the FunctionContext argument plus any non-variadic arguments - DCHECK_EQ(udf_args.size(), _vararg_start_idx + 1); - DCHECK_GE(get_num_children(), 1); - // Add the number of varargs - udf_args.push_back(codegen->get_int_constant( - TYPE_INT, get_num_children() - _vararg_start_idx)); - // Add all the accumulated vararg inputs as one input argument. - llvm::PointerType* vararg_type = codegen->get_ptr_type( - CodegenAnyVal::get_unlowered_type(codegen, _children.back()->type())); - udf_args.push_back(builder.CreateBitCast(varargs_buffer, vararg_type, "varargs")); - } - - // Call UDF - Value* result_val = - CodegenAnyVal::create_call(codegen, &builder, udf, udf_args, "result", NULL); - builder.CreateRet(result_val); - - *fn = codegen->finalize_function(*fn); - DCHECK(*fn != NULL); - _ir_compute_fn = *fn; - return Status::OK(); -} - -Status ScalarFnCall::get_udf(RuntimeState* state, Function** udf) { - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - - // from_utc_timestamp and to_utc_timestamp have inline ASM that cannot be JIT'd. - // DatetimeFunctions::AddSub() contains a try/catch which doesn't work in JIT'd - // code. Always use the statically compiled versions of these functions so the - // xcompiled versions are not included in the final module to be JIT'd. - // TODO: fix this - bool broken_builtin = _fn.name.function_name == "from_utc_timestamp" || - _fn.name.function_name == "to_utc_timestamp" || - _fn.scalar_fn.symbol.find("add_sub") != std::string::npos; - if (_fn.binary_type == TFunctionBinaryType::NATIVE - || (_fn.binary_type == TFunctionBinaryType::BUILTIN - && (!(state->codegen_level() > 0) || broken_builtin))) { - // In this path, we are code that has been statically compiled to assembly. - // This can either be a UDF implemented in a .so or a builtin using the UDF - // interface with the code in impalad. - void* fn_ptr = NULL; - Status status = UserFunctionCache::instance()->get_function_ptr( - _fn.id, _fn.scalar_fn.symbol, _fn.hdfs_location, _fn.checksum, &fn_ptr, &_cache_entry); - if (!status.ok() && _fn.binary_type == TFunctionBinaryType::BUILTIN) { - // Builtins symbols should exist unless there is a version mismatch. - // TODO(zc ) - // status.add_detail(ErrorMsg(TErrorCode::MISSING_BUILTIN, - // _fn.name.function_name, _fn.scalar_fn.symbol).msg()); - } - RETURN_IF_ERROR(status); - DCHECK(fn_ptr != NULL); - - // Convert UDF function pointer to Function* - // First generate the FunctionType* corresponding to the UDF. - Type* return_type = CodegenAnyVal::get_lowered_type(codegen, type()); - std::vector arg_types; - - if (type().type == TYPE_DECIMAL || type().type == TYPE_DECIMALV2) { - // Per the x64 ABI, DecimalVals are returned via a DecmialVal* output argument - return_type = codegen->void_type(); - arg_types.push_back( - codegen->get_ptr_type(CodegenAnyVal::get_unlowered_type(codegen, type()))); - } - - arg_types.push_back(codegen->get_ptr_type("class.doris_udf::FunctionContext")); - for (int i = 0; i < num_fixed_args(); ++i) { - Type* arg_type = codegen->get_ptr_type( - CodegenAnyVal::get_unlowered_type(codegen, _children[i]->type())); - arg_types.push_back(arg_type); - } - - if (_vararg_start_idx >= 0) { - Type* vararg_type = CodegenAnyVal::get_unlowered_ptr_type( - codegen, _children[_vararg_start_idx]->type()); - arg_types.push_back(codegen->get_type(TYPE_INT)); - arg_types.push_back(vararg_type); - } - FunctionType* udf_type = FunctionType::get(return_type, arg_types, false); - - // Create a Function* with the generated type. This is only a function - // declaration, not a definition, since we do not create any basic blocks or - // instructions in it. - *udf = Function::Create( - udf_type, llvm::GlobalValue::ExternalLinkage, - _fn.scalar_fn.symbol, codegen->module()); - - // Associate the dynamically loaded function pointer with the Function* we - // defined. This tells LLVM where the compiled function definition is located in - // memory. - codegen->execution_engine()->addGlobalMapping(*udf, fn_ptr); - } else if (_fn.binary_type == TFunctionBinaryType::BUILTIN) { - // In this path, we're running a builtin with the UDF interface. The IR is - // in the llvm module. - DCHECK(state->codegen_level() > 0); - // TODO(zc) - std::string symbol = _fn.scalar_fn.symbol; -#if 0 - *udf = codegen->module()->getFunction(_fn.scalar_fn.symbol); - if (*udf == NULL) { - // Builtins symbols should exist unless there is a version mismatch. - std::stringstream ss; - ss << "Builtin '" << _fn.name.function_name << "' with symbol '" - << _fn.scalar_fn.symbol << "' does not exist. " - << "Verify that all your impalads are the same version."; - return Status::InternalError(ss.str()); - } -#else - if (!SymbolsUtil::is_mangled(symbol)) { - std::vector arg_types; - for (auto& t_type : _fn.arg_types) { - arg_types.push_back(TypeDescriptor::from_thrift(t_type)); - } - // ColumnType ret_type(INVALID_TYPE); - // ret_type = ColumnType(thrift_to_type(_fn.ret_type)); - symbol = SymbolsUtil::mangle_user_function(symbol, arg_types, _fn.has_var_args, NULL); - } -#endif - *udf = codegen->module()->getFunction(symbol); - if (*udf == NULL) { - // Builtins symbols should exist unless there is a version mismatch. - std::stringstream ss; - ss << "Builtin '" << _fn.name.function_name << "' with symbol '" - << symbol << "' does not exist. " - << "Verify that all your impalads are the same version."; - return Status::InternalError(ss.str()); - } - // Builtin functions may use Expr::GetConstant(). Clone the function in case we need - // to use it again, and rename it to something more manageable than the mangled name. - std::string demangled_name = SymbolsUtil::demangle_no_args((*udf)->getName().str()); - *udf = codegen->clone_function(*udf); - (*udf)->setName(demangled_name); - inline_constants(codegen, *udf); - *udf = codegen->finalize_function(*udf); - DCHECK(*udf != NULL); - } else { - // We're running an IR UDF. - DCHECK_EQ(_fn.binary_type, TFunctionBinaryType::IR); - *udf = codegen->module()->getFunction(_fn.scalar_fn.symbol); - if (*udf == NULL) { - std::stringstream ss; - ss << "Unable to locate function " << _fn.scalar_fn.symbol - << " from LLVM module " << _fn.hdfs_location; - return Status::InternalError(ss.str()); - } - *udf = codegen->finalize_function(*udf); - if (*udf == NULL) { - return Status::InternalError("udf verify failed"); - // TODO(zc) - // TErrorCode::UDF_VERIFY_FAILED, _fn.scalar_fn.symbol, _fn.hdfs_location); - } - } - return Status::OK(); -} - Status ScalarFnCall::get_function(RuntimeState* state, const std::string& symbol, void** fn) { if (_fn.binary_type == TFunctionBinaryType::NATIVE || _fn.binary_type == TFunctionBinaryType::BUILTIN diff --git a/be/src/exprs/scalar_fn_call.h b/be/src/exprs/scalar_fn_call.h index 4bf337723d..58c296a2a5 100644 --- a/be/src/exprs/scalar_fn_call.h +++ b/be/src/exprs/scalar_fn_call.h @@ -64,7 +64,6 @@ protected: RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope); virtual void close( RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override; virtual bool is_constant() const; @@ -111,9 +110,6 @@ private: return _vararg_start_idx >= 0 ? _vararg_start_idx : _children.size(); } - /// Loads the native or IR function from HDFS and puts the result in *udf. - Status get_udf(RuntimeState* state, llvm::Function** udf); - /// Loads the native or IR function 'symbol' from HDFS and puts the result in *fn. /// If the function is loaded from an IR module, it cannot be called until the module /// has been JIT'd (i.e. after Prepare() has completed). diff --git a/be/src/exprs/slot_ref.cpp b/be/src/exprs/slot_ref.cpp index c14a42db65..439c2dee46 100644 --- a/be/src/exprs/slot_ref.cpp +++ b/be/src/exprs/slot_ref.cpp @@ -20,20 +20,10 @@ #include #include "codegen/codegen_anyval.h" -#include "codegen/llvm_codegen.h" #include "gen_cpp/Exprs_types.h" #include "runtime/runtime_state.h" #include "util/types.h" -using llvm::BasicBlock; -using llvm::Constant; -using llvm::ConstantInt; -using llvm::Function; -using llvm::LLVMContext; -using llvm::PHINode; -using llvm::PointerType; -using llvm::Value; - namespace doris { SlotRef::SlotRef(const TExprNode& node) : @@ -145,292 +135,6 @@ std::string SlotRef::debug_string() const { return out.str(); } -// There are four possible cases we may generate: -// 1. Tuple is non-nullable and slot is non-nullable -// 2. Tuple is non-nullable and slot is nullable -// 3. Tuple is nullable and slot is non-nullable (when the aggregate output is the -// "nullable" side of an outer join). -// 4. Tuple is nullable and slot is nullable -// -// Resulting IR for a bigint slotref: -// (Note: some of the GEPs that look like no-ops are because certain offsets are 0 -// in this slot descriptor.) -// -// define { i8, i64 } @get_slot_ref(i8** %context, %"class.doris::TupleRow"* %row) { -// entry: -// %cast_row_ptr = bitcast %"class.doris::TupleRow"* %row to i8** -// %tuple_addr = getelementptr i8** %cast_row_ptr, i32 0 -// %tuple_ptr = load i8** %tuple_addr -// br label %check_slot_null -// -// check_slot_null: ; preds = %entry -// %null_ptr = getelementptr i8* %tuple_ptr, i32 0 -// %null_byte = load i8* %null_ptr -// %null_byte_set = and i8 %null_byte, 2 -// %slot_is_null = icmp ne i8 %null_byte_set, 0 -// br i1 %slot_is_null, label %ret, label %get_slot -// -// get_slot: ; preds = %check_slot_null -// %slot_addr = getelementptr i8* %tuple_ptr, i32 8 -// %val_ptr = bitcast i8* %slot_addr to i64* -// %val = load i64* %val_ptr -// br label %ret -// -// ret: ; preds = %get_slot, %check_slot_null -// %is_null_phi = phi i8 [ 1, %check_slot_null ], [ 0, %get_slot ] -// %val_phi = phi i64 [ 0, %check_slot_null ], [ %val, %get_slot ] -// %result = insertvalue { i8, i64 } zeroinitializer, i8 %is_null_phi, 0 -// %result1 = insertvalue { i8, i64 } %result, i64 %val_phi, 1 -// ret { i8, i64 } %result1 -// } -// -// TODO: We could generate a typed struct (and not a char*) for Tuple for llvm. We know -// the types from the TupleDesc. It will likey make this code simpler to reason about. -Status SlotRef::get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) { - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - DCHECK_EQ(get_num_children(), 0); - LlvmCodeGen* codegen = NULL; - RETURN_IF_ERROR(state->get_codegen(&codegen)); - - // SlotRefs are based on the slot_id and tuple_idx. Combine them to make a - // query-wide unique id. We also need to combine whether the tuple is nullable. For - // example, in an outer join the scan node could have the same tuple id and slot id - // as the join node. When the slot is being used in the scan-node, the tuple is - // non-nullable. Used in the join node (and above in the plan tree), it is nullable. - // TODO: can we do something better. - const int64_t TUPLE_NULLABLE_MASK = 1L << 63; - int64_t unique_slot_id = _slot_id | ((int64_t)_tuple_idx) << 32; - DCHECK_EQ(unique_slot_id & TUPLE_NULLABLE_MASK, 0); - if (_tuple_is_nullable) { - unique_slot_id |= TUPLE_NULLABLE_MASK; - } - Function* _ir_compute_fn = codegen->get_registered_expr_fn(unique_slot_id); - if (_ir_compute_fn != NULL) { - *fn = _ir_compute_fn; - return Status::OK(); - } - - LLVMContext& context = codegen->context(); - Value* args[2]; - *fn = create_ir_function_prototype(codegen, "get_slot_ref", &args); - Value* row_ptr = args[1]; - - Value* tuple_offset = ConstantInt::get(codegen->int_type(), _tuple_idx); - Value* null_byte_offset = ConstantInt::get( - codegen->int_type(), _null_indicator_offset.byte_offset); - Value* slot_offset = ConstantInt::get(codegen->int_type(), _slot_offset); - Value* null_mask = ConstantInt::get( - codegen->tinyint_type(), _null_indicator_offset.bit_mask); - Value* zero = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 0); - Value* one = ConstantInt::get(codegen->get_type(TYPE_TINYINT), 1); - - BasicBlock* entry_block = BasicBlock::Create(context, "entry", *fn); - BasicBlock* check_slot_null_indicator_block = NULL; - if (_null_indicator_offset.bit_mask != 0) { - check_slot_null_indicator_block = BasicBlock::Create( - context, "check_slot_null", *fn); - } - BasicBlock* get_slot_block = BasicBlock::Create(context, "get_slot", *fn); - BasicBlock* ret_block = BasicBlock::Create(context, "ret", *fn); - - LlvmCodeGen::LlvmBuilder builder(entry_block); - // Get the tuple offset addr from the row - Value* cast_row_ptr = builder.CreateBitCast( - row_ptr, PointerType::get(codegen->ptr_type(), 0), "cast_row_ptr"); - Value* tuple_addr = builder.CreateGEP(cast_row_ptr, tuple_offset, "tuple_addr"); - // Load the tuple* - Value* tuple_ptr = builder.CreateLoad(tuple_addr, "tuple_ptr"); - - // Check if tuple* is null only if the tuple is nullable - if (_tuple_is_nullable) { - Value* tuple_is_null = builder.CreateIsNull(tuple_ptr, "tuple_is_null"); - // Check slot is null only if the null indicator bit is set - if (_null_indicator_offset.bit_mask == 0) { - builder.CreateCondBr(tuple_is_null, ret_block, get_slot_block); - } else { - builder.CreateCondBr(tuple_is_null, ret_block, check_slot_null_indicator_block); - } - } else { - if (_null_indicator_offset.bit_mask == 0) { - builder.CreateBr(get_slot_block); - } else { - builder.CreateBr(check_slot_null_indicator_block); - } - } - - // Branch for tuple* != NULL. Need to check if null-indicator is set - if (check_slot_null_indicator_block != NULL) { - builder.SetInsertPoint(check_slot_null_indicator_block); - Value* null_addr = builder.CreateGEP(tuple_ptr, null_byte_offset, "null_ptr"); - Value* null_val = builder.CreateLoad(null_addr, "null_byte"); - Value* slot_null_mask = builder.CreateAnd(null_val, null_mask, "null_byte_set"); - Value* is_slot_null = builder.CreateICmpNE(slot_null_mask, zero, "slot_is_null"); - builder.CreateCondBr(is_slot_null, ret_block, get_slot_block); - } - - // Branch for slot != NULL - builder.SetInsertPoint(get_slot_block); - Value* slot_ptr = builder.CreateGEP(tuple_ptr, slot_offset, "slot_addr"); - Value* val_ptr = builder.CreateBitCast(slot_ptr, codegen->get_ptr_type(_type), "val_ptr"); - // Depending on the type, load the values we need - Value* val = NULL; - Value* ptr = NULL; - Value* len = NULL; - if (_type.is_string_type()) { - Value* ptr_ptr = builder.CreateStructGEP(val_ptr, 0, "ptr_ptr"); - ptr = builder.CreateLoad(ptr_ptr, "ptr"); - Value* len_ptr = builder.CreateStructGEP(val_ptr, 1, "len_ptr"); - len = builder.CreateLoad(len_ptr, "len"); - } else if (_type.is_date_type()) { - // TODO(zc) -#if 0 - Value* time_of_day_ptr = builder.CreateStructGEP(val_ptr, 0, "time_of_day_ptr"); - // Cast boost::posix_time::time_duration to i64 - Value* time_of_day_cast = - builder.CreateBitCast(time_of_day_ptr, codegen->get_ptr_type(TYPE_BIGINT)); - time_of_day = builder.CreateLoad(time_of_day_cast, "time_of_day"); - Value* date_ptr = builder.CreateStructGEP(val_ptr, 1, "date_ptr"); - // Cast boost::gregorian::date to i32 - Value* date_cast = builder.CreateBitCast(date_ptr, codegen->get_ptr_type(TYPE_INT)); - date = builder.CreateLoad(date_cast, "date"); -#endif - Function* func = codegen->get_function(IRFunction::TO_DATETIME_VAL); - Value* val_val_ptr = codegen->create_entry_block_alloca( - builder, CodegenAnyVal::get_lowered_type(codegen, _type), "val_val_ptr"); - builder.CreateCall2(func, val_ptr, val_val_ptr); - val = builder.CreateLoad(val_val_ptr, "val"); - } else if (_type.is_decimal_type()) { - // TODO(zc): to think about it - Function* func = codegen->get_function(IRFunction::TO_DECIMAL_VAL); - Value* val_val_ptr = codegen->create_entry_block_alloca( - builder, CodegenAnyVal::get_lowered_type(codegen, _type), "val_val_ptr"); - builder.CreateCall2(func, val_ptr, val_val_ptr); - val = builder.CreateLoad(val_val_ptr, "val"); - } else { - // val_ptr is a native type - val = builder.CreateLoad(val_ptr, "val"); - } - builder.CreateBr(ret_block); - - // Return block - builder.SetInsertPoint(ret_block); - PHINode* is_null_phi = builder.CreatePHI(codegen->tinyint_type(), 2, "is_null_phi"); - if (_tuple_is_nullable) { - is_null_phi->addIncoming(one, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - is_null_phi->addIncoming(one, check_slot_null_indicator_block); - } - is_null_phi->addIncoming(zero, get_slot_block); - - // Depending on the type, create phi nodes for each value needed to populate the return - // *Val. The optimizer does a better job when there is a phi node for each value, rather - // than having get_slot_block generate an AnyVal and having a single phi node over that. - // TODO: revisit this code, can possibly be simplified - if (type().is_string_type()) { - DCHECK(ptr != NULL); - DCHECK(len != NULL); - PHINode* ptr_phi = builder.CreatePHI(ptr->getType(), 2, "ptr_phi"); - Value* null = Constant::getNullValue(ptr->getType()); - if (_tuple_is_nullable) { - ptr_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - ptr_phi->addIncoming(null, check_slot_null_indicator_block); - } - ptr_phi->addIncoming(ptr, get_slot_block); - - PHINode* len_phi = builder.CreatePHI(len->getType(), 2, "len_phi"); - null = ConstantInt::get(len->getType(), 0); - if (_tuple_is_nullable) { - len_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - len_phi->addIncoming(null, check_slot_null_indicator_block); - } - len_phi->addIncoming(len, get_slot_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_ptr(ptr_phi); - result.set_len(len_phi); - builder.CreateRet(result.value()); -#if 0 - } else if (type().is_date_type()) { - DCHECK(time_of_day != NULL); - DCHECK(date != NULL); - PHINode* time_of_day_phi = - builder.CreatePHI(time_of_day->getType(), 2, "time_of_day_phi"); - Value* null = ConstantInt::get(time_of_day->getType(), 0); - if (_tuple_is_nullable) { - time_of_day_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - time_of_day_phi->addIncoming(null, check_slot_null_indicator_block); - } - time_of_day_phi->addIncoming(time_of_day, get_slot_block); - - PHINode* date_phi = builder.CreatePHI(date->getType(), 2, "date_phi"); - null = ConstantInt::get(date->getType(), 0); - if (_tuple_is_nullable) { - date_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - date_phi->addIncoming(null, check_slot_null_indicator_block); - } - date_phi->addIncoming(date, get_slot_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_time_of_day(time_of_day_phi); - result.set_date(date_phi); - builder.CreateRet(result.value()); -#endif - } else if (type().is_decimal_type() || type().is_date_type()) { - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - if (_tuple_is_nullable) { - val_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - val_phi->addIncoming(null, check_slot_null_indicator_block); - } - val_phi->addIncoming(val, get_slot_block); - - CodegenAnyVal result(codegen, &builder, _type, val_phi, "result"); - result.set_is_null(is_null_phi); - builder.CreateRet(result.value()); - } else { - DCHECK(val != NULL); - PHINode* val_phi = builder.CreatePHI(val->getType(), 2, "val_phi"); - Value* null = Constant::getNullValue(val->getType()); - if (_tuple_is_nullable) { - val_phi->addIncoming(null, entry_block); - } - if (check_slot_null_indicator_block != NULL) { - val_phi->addIncoming(null, check_slot_null_indicator_block); - } - val_phi->addIncoming(val, get_slot_block); - - CodegenAnyVal result = CodegenAnyVal::get_non_null_val( - codegen, &builder, type(), "result"); - result.set_is_null(is_null_phi); - result.set_val(val_phi); - builder.CreateRet(result.value()); - } - - *fn = codegen->finalize_function(*fn); - codegen->register_expr_fn(unique_slot_id, *fn); - _ir_compute_fn = *fn; - return Status::OK(); -} - BooleanVal SlotRef::get_boolean_val(ExprContext* context, TupleRow* row) { DCHECK_EQ(_type.type, TYPE_BOOLEAN); Tuple* t = row->get_tuple(_tuple_idx); diff --git a/be/src/exprs/slot_ref.h b/be/src/exprs/slot_ref.h index 91c708c1d7..e2c4c052d3 100644 --- a/be/src/exprs/slot_ref.h +++ b/be/src/exprs/slot_ref.h @@ -68,7 +68,6 @@ public: inline NullIndicatorOffset null_indicator_offset() const { return _null_indicator_offset; } - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override; virtual doris_udf::BooleanVal get_boolean_val(ExprContext* context, TupleRow*); virtual doris_udf::TinyIntVal get_tiny_int_val(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/tuple_is_null_predicate.cpp b/be/src/exprs/tuple_is_null_predicate.cpp index a8b7ab03a8..a0dfce4125 100644 --- a/be/src/exprs/tuple_is_null_predicate.cpp +++ b/be/src/exprs/tuple_is_null_predicate.cpp @@ -21,8 +21,6 @@ #include "gen_cpp/Exprs_types.h" -using llvm::Function; - namespace doris { TupleIsNullPredicate::TupleIsNullPredicate(const TExprNode& node) : @@ -55,11 +53,6 @@ BooleanVal TupleIsNullPredicate::get_boolean_val(ExprContext* ctx, TupleRow* row return BooleanVal(!_tuple_idxs.empty() && count == _tuple_idxs.size()); } -Status TupleIsNullPredicate::get_codegend_compute_fn( - RuntimeState* state, llvm::Function** fn) { - return get_codegend_compute_fn_wrapper(state, fn); -} - std::string TupleIsNullPredicate::debug_string() const { std::stringstream out; out << "TupleIsNullPredicate(tupleids=["; diff --git a/be/src/exprs/tuple_is_null_predicate.h b/be/src/exprs/tuple_is_null_predicate.h index f55b0e0271..f891c6225b 100644 --- a/be/src/exprs/tuple_is_null_predicate.h +++ b/be/src/exprs/tuple_is_null_predicate.h @@ -39,7 +39,6 @@ protected: virtual Status prepare( RuntimeState* state, const RowDescriptor& row_desc, ExprContext* ctx); - virtual Status get_codegend_compute_fn(RuntimeState* state, llvm::Function** fn) override; virtual BooleanVal get_boolean_val(ExprContext* ctx, TupleRow* row); virtual std::string debug_string() const; diff --git a/be/test/util/arrow/arrow_work_flow_test.cpp b/be/test/util/arrow/arrow_work_flow_test.cpp index 0f9f32f545..0b77655ad5 100644 --- a/be/test/util/arrow/arrow_work_flow_test.cpp +++ b/be/test/util/arrow/arrow_work_flow_test.cpp @@ -88,7 +88,7 @@ void ArrowWorkFlowTest::init() { void ArrowWorkFlowTest::init_runtime_state() { ResultQueueMgr* result_queue_mgr = new ResultQueueMgr(); - ThreadResourceMgr* thrbg56gead_mgr = new ThreadResourceMgr(); + ThreadResourceMgr* thread_mgr = new ThreadResourceMgr(); _exec_env->_result_queue_mgr = result_queue_mgr; _exec_env->_thread_mgr = thread_mgr; _exec_env->_buffer_reservation = new ReservationTracker();