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::ScalarExprEvaluator"* %eval, %"class.impala::TupleRow"* %row) #20 { entry: %lhs_call = call i16 @GetSlotRef1(%"class.impala::ScalarExprEvaluator"* %eval, %"class.impala::TupleRow"*
| 121 | // ret i16 %7 |
| 122 | // } |
| 123 | Status CompoundPredicate::CodegenComputeFn( |
| 124 | bool and_fn, LlvmCodeGen* codegen, llvm::Function** fn) { |
| 125 | DCHECK_EQ(GetNumChildren(), 2); |
| 126 | llvm::Function* lhs_function; |
| 127 | RETURN_IF_ERROR(children()[0]->GetCodegendComputeFn(codegen, false, &lhs_function)); |
| 128 | llvm::Function* rhs_function; |
| 129 | RETURN_IF_ERROR(children()[1]->GetCodegendComputeFn(codegen, false, &rhs_function)); |
| 130 | |
| 131 | llvm::LLVMContext& context = codegen->context(); |
| 132 | LlvmBuilder builder(context); |
| 133 | llvm::Value* args[2]; |
| 134 | llvm::Function* function = |
| 135 | CreateIrFunctionPrototype("CompoundPredicate", codegen, &args); |
| 136 | |
| 137 | llvm::BasicBlock* entry_block = llvm::BasicBlock::Create(context, "entry", function); |
| 138 | builder.SetInsertPoint(entry_block); |
| 139 | |
| 140 | // Control blocks for aggregating results |
| 141 | llvm::BasicBlock* lhs_null_block = |
| 142 | llvm::BasicBlock::Create(context, "lhs_null", function); |
| 143 | llvm::BasicBlock* lhs_not_null_block = |
| 144 | llvm::BasicBlock::Create(context, "lhs_not_null", function); |
| 145 | llvm::BasicBlock* lhs_null_rhs_not_null_block = |
| 146 | llvm::BasicBlock::Create(context, "lhs_null_rhs_not_null", function); |
| 147 | llvm::BasicBlock* lhs_not_null_rhs_null_block = |
| 148 | llvm::BasicBlock::Create(context, "lhs_not_null_rhs_null", function); |
| 149 | llvm::BasicBlock* null_block = |
| 150 | llvm::BasicBlock::Create(context, "null_block", function); |
| 151 | llvm::BasicBlock* not_null_block = |
| 152 | llvm::BasicBlock::Create(context, "not_null_block", function); |
| 153 | llvm::BasicBlock* ret_block = llvm::BasicBlock::Create(context, "ret", function); |
| 154 | |
| 155 | // Call lhs |
| 156 | CodegenAnyVal lhs_result = CodegenAnyVal::CreateCallWrapped( |
| 157 | codegen, &builder, ColumnType(TYPE_BOOLEAN), lhs_function, args, "lhs_call"); |
| 158 | // Call rhs |
| 159 | CodegenAnyVal rhs_result = CodegenAnyVal::CreateCallWrapped( |
| 160 | codegen, &builder, ColumnType(TYPE_BOOLEAN), rhs_function, args, "rhs_call"); |
| 161 | |
| 162 | llvm::Value* lhs_is_null = lhs_result.GetIsNull(); |
| 163 | llvm::Value* rhs_is_null = rhs_result.GetIsNull(); |
| 164 | llvm::Value* lhs_value = lhs_result.GetVal(); |
| 165 | llvm::Value* rhs_value = rhs_result.GetVal(); |
| 166 | |
| 167 | // Apply predicate |
| 168 | llvm::Value* compare = NULL; |
| 169 | if (and_fn) { |
| 170 | compare = builder.CreateAnd(lhs_value, rhs_value, "tmp_and"); |
| 171 | } else { |
| 172 | compare = builder.CreateOr(lhs_value, rhs_value, "tmp_or"); |
| 173 | } |
| 174 | |
| 175 | // Branch if lhs is null |
| 176 | builder.CreateCondBr(lhs_is_null, lhs_null_block, lhs_not_null_block); |
| 177 | |
| 178 | // lhs_is_null block |
| 179 | builder.SetInsertPoint(lhs_null_block); |
| 180 | builder.CreateCondBr(rhs_is_null, null_block, lhs_null_rhs_not_null_block); |
nothing calls this directly
no test coverage detected