From 099e0f74bd148c5cfedec534b5aa0ce05486eb62 Mon Sep 17 00:00:00 2001 From: trueeyu Date: Mon, 24 Feb 2020 18:23:08 +0800 Subject: [PATCH] Remove unused LLVM related codes of directory:be/src/exprs (#2910) (#2972) Remove unused LLVM related codes of directory (step 3):be/src/exprs (#2910) there are many LLVM related codes in code base, but these codes are not really used. The higher version of GCC is not compatible with the LLVM 3.4.2 version currently used by Doris. The PR delete all LLVM related code of directory: be/src/exprs --- be/src/exprs/agg_fn.cc | 27 -- be/src/exprs/agg_fn.h | 12 - be/src/exprs/agg_fn_evaluator.cpp | 1 - be/src/exprs/anyval_util.h | 2 +- be/src/exprs/arithmetic_expr.cpp | 433 -------------------- be/src/exprs/arithmetic_expr.h | 12 - be/src/exprs/binary_predicate.cpp | 266 ------------ be/src/exprs/binary_predicate.h | 8 - be/src/exprs/case_expr.cpp | 212 ---------- be/src/exprs/case_expr.h | 5 - be/src/exprs/cast_expr.cpp | 111 ----- be/src/exprs/cast_expr.h | 3 - be/src/exprs/compound_predicate.cpp | 185 --------- be/src/exprs/compound_predicate.h | 17 - be/src/exprs/conditional_functions.cpp | 12 - be/src/exprs/conditional_functions.h | 9 - be/src/exprs/expr.cpp | 148 +------ be/src/exprs/expr.h | 53 --- be/src/exprs/expr_context.cpp | 2 - be/src/exprs/expr_context.h | 2 - be/src/exprs/in_predicate.cpp | 1 - be/src/exprs/in_predicate.h | 4 - be/src/exprs/info_func.h | 4 - be/src/exprs/literal.cpp | 83 ---- be/src/exprs/literal.h | 2 - be/src/exprs/new_agg_fn_evaluator.cc | 3 - be/src/exprs/new_agg_fn_evaluator.h | 2 - be/src/exprs/null_literal.cpp | 31 -- be/src/exprs/null_literal.h | 5 - be/src/exprs/scalar_fn_call.cpp | 302 -------------- be/src/exprs/scalar_fn_call.h | 4 - be/src/exprs/slot_ref.cpp | 296 ------------- be/src/exprs/slot_ref.h | 1 - be/src/exprs/tuple_is_null_predicate.cpp | 7 - be/src/exprs/tuple_is_null_predicate.h | 1 - be/test/util/arrow/arrow_work_flow_test.cpp | 2 +- 36 files changed, 7 insertions(+), 2261 deletions(-) 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();