Skip to content

Commit 0e4e513

Browse files
author
likun
committed
GH-50371: [C++][Gandiva] Address cache and test feedback
1 parent 473a9e5 commit 0e4e513

4 files changed

Lines changed: 85 additions & 46 deletions

File tree

cpp/src/gandiva/projector.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,12 @@ Status Projector::ValidateArrayDataCapacity(const arrow::ArrayData& array_data,
288288

289289
const std::string& Projector::DumpIR() { return llvm_generator_->ir(); }
290290

291-
const std::string& Projector::DumpUnoptimizedIR() {
291+
Result<std::string> Projector::DumpUnoptimizedIR() {
292+
ARROW_RETURN_IF(!configuration_->dump_ir(),
293+
Status::Invalid("IR dumping is not enabled for this projector"));
294+
ARROW_RETURN_IF(
295+
built_from_cache_,
296+
Status::Invalid("Unoptimized IR is unavailable for projectors built from cache"));
292297
return llvm_generator_->unoptimized_ir();
293298
}
294299

cpp/src/gandiva/projector.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ class GANDIVA_EXPORT Projector {
120120

121121
const std::string& DumpIR();
122122

123-
const std::string& DumpUnoptimizedIR();
123+
/// Return the generated IR before the optimizer pipeline runs.
124+
/// Unavailable when IR dumping is disabled or the projector is built from cache.
125+
Result<std::string> DumpUnoptimizedIR();
124126

125127
void SetBuiltFromCache(bool flag);
126128

cpp/src/gandiva/tests/filter_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,49 @@ TEST_F(TestFilter, TestFilterCache) {
8787
EXPECT_FALSE(should_be_new_filter->GetBuiltFromCache());
8888
}
8989

90+
TEST_F(TestFilter, TestCommonSubexpressionFoldAndCache) {
91+
auto field0 = field("filter_cse_f0", int32());
92+
auto field1 = field("filter_cse_f1", int32());
93+
auto schema = arrow::schema({field0, field1});
94+
95+
auto make_less_than = [&]() {
96+
auto sum = TreeExprBuilder::MakeFunction(
97+
"add", {TreeExprBuilder::MakeField(field0), TreeExprBuilder::MakeField(field1)},
98+
arrow::int32());
99+
return TreeExprBuilder::MakeFunction(
100+
"less_than", {sum, TreeExprBuilder::MakeLiteral(static_cast<int32_t>(10))},
101+
arrow::boolean());
102+
};
103+
auto repeated_condition = TreeExprBuilder::MakeCondition(
104+
TreeExprBuilder::MakeAnd({make_less_than(), make_less_than(), make_less_than()}));
105+
auto configuration = TestConfiguration();
106+
107+
std::shared_ptr<Filter> filter;
108+
ASSERT_OK(Filter::Make(schema, repeated_condition, configuration, &filter));
109+
ASSERT_FALSE(filter->GetBuiltFromCache());
110+
111+
auto input0 = MakeArrowArrayInt32({1, 2, 3, 4, 6}, {true, true, true, false, true});
112+
auto input1 = MakeArrowArrayInt32({5, 9, 6, 17, 3}, {true, true, false, true, true});
113+
auto batch = arrow::RecordBatch::Make(schema, 5, {input0, input1});
114+
auto expected = MakeArrowArrayUint16({0, 4});
115+
116+
std::shared_ptr<SelectionVector> selection_vector;
117+
ASSERT_OK(SelectionVector::MakeInt16(batch->num_rows(), pool_, &selection_vector));
118+
ASSERT_OK(filter->Evaluate(*batch, selection_vector));
119+
EXPECT_ARROW_ARRAY_EQUALS(expected, selection_vector->ToArray());
120+
121+
auto equivalent_condition = TreeExprBuilder::MakeCondition(make_less_than());
122+
std::shared_ptr<Filter> cached_filter;
123+
ASSERT_OK(Filter::Make(schema, equivalent_condition, configuration, &cached_filter));
124+
ASSERT_TRUE(cached_filter->GetBuiltFromCache());
125+
126+
std::shared_ptr<SelectionVector> cached_selection_vector;
127+
ASSERT_OK(
128+
SelectionVector::MakeInt16(batch->num_rows(), pool_, &cached_selection_vector));
129+
ASSERT_OK(cached_filter->Evaluate(*batch, cached_selection_vector));
130+
EXPECT_ARROW_ARRAY_EQUALS(expected, cached_selection_vector->ToArray());
131+
}
132+
90133
TEST_F(TestFilter, TestFilterCacheNullTreatment) {
91134
// schema for input fields
92135
auto field0 = field("f0", utf8());

cpp/src/gandiva/tests/projector_test.cc

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ int CountOccurrences(const std::string& text, const std::string& needle) {
5252
return count;
5353
}
5454

55-
int CountInt32AddInstructions(const std::string& ir) {
56-
return CountOccurrences(ir, " add i32 ") + CountOccurrences(ir, " add nsw i32 ") +
57-
CountOccurrences(ir, " add nuw i32 ") +
58-
CountOccurrences(ir, " add nuw nsw i32 ");
59-
}
60-
6155
std::string ExtractFunctionIR(const std::string& ir, const std::string& function_name) {
6256
const auto name_pos = ir.find("@" + function_name + "(");
6357
if (name_pos == std::string::npos) {
@@ -455,24 +449,42 @@ TEST_F(TestProjector, TestCommonSubexpressionEliminationIR) {
455449
std::shared_ptr<Projector> projector;
456450
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
457451

458-
const auto unoptimized_expr_ir =
459-
ExtractFunctionIR(projector->DumpUnoptimizedIR(), "expr_0_0");
460-
const auto optimized_expr_ir = ExtractFunctionIR(projector->DumpIR(), "expr_0_0");
452+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
453+
const auto unoptimized_expr_ir = ExtractFunctionIR(unoptimized_ir, "expr_0_0");
461454
ASSERT_FALSE(unoptimized_expr_ir.empty());
462-
ASSERT_FALSE(optimized_expr_ir.empty());
463455

464456
EXPECT_EQ(2, CountOccurrences(unoptimized_expr_ir, "call i32 @add_int32_int32"));
465457
EXPECT_EQ(1, CountOccurrences(unoptimized_expr_ir, "call i32 @multiply_int32_int32"));
466-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "call i32 @add_int32_int32"));
467-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "call i32 @multiply_int32_int32"));
468-
EXPECT_EQ(1, CountInt32AddInstructions(optimized_expr_ir));
469458

470459
auto input0 = MakeArrowArrayInt32({1, 2, 3, 4}, {true, true, false, true});
471460
auto input1 = MakeArrowArrayInt32({10, -2, 3, 5}, {true, true, true, false});
472461
auto expected = MakeArrowArrayInt32({121, 0, 0, 0}, {true, true, false, false});
473462
ExpectProjectorOutput(projector, schema, {input0, input1}, expected, pool_);
474463
}
475464

465+
TEST_F(TestProjector, TestUnoptimizedIRUnavailableForCachedProjector) {
466+
auto field0 = arrow::field("cached_ir_f0", arrow::int32());
467+
auto field1 = arrow::field("cached_ir_f1", arrow::int32());
468+
auto schema = arrow::schema({field0, field1});
469+
auto expr = TreeExprBuilder::MakeExpression(
470+
"add", {field0, field1}, arrow::field("cached_ir_out", arrow::int32()));
471+
auto configuration = std::make_shared<Configuration>(
472+
true, gandiva::default_function_registry(), /*dump_ir=*/true);
473+
474+
std::shared_ptr<Projector> projector;
475+
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
476+
ASSERT_FALSE(projector->GetBuiltFromCache());
477+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
478+
ASSERT_FALSE(unoptimized_ir.empty());
479+
480+
std::shared_ptr<Projector> cached_projector;
481+
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &cached_projector));
482+
ASSERT_TRUE(cached_projector->GetBuiltFromCache());
483+
ASSERT_RAISES_WITH_MESSAGE(
484+
Invalid, "Invalid: Unoptimized IR is unavailable for projectors built from cache",
485+
cached_projector->DumpUnoptimizedIR());
486+
}
487+
476488
TEST_F(TestProjector, TestNestedCommonSubexpressionEliminationIR) {
477489
auto field0 = arrow::field("nested_cse_f0", arrow::int32());
478490
auto field1 = arrow::field("nested_cse_f1", arrow::int32());
@@ -497,16 +509,12 @@ TEST_F(TestProjector, TestNestedCommonSubexpressionEliminationIR) {
497509
std::shared_ptr<Projector> projector;
498510
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
499511

500-
const auto unoptimized_expr_ir =
501-
ExtractFunctionIR(projector->DumpUnoptimizedIR(), "expr_0_0");
502-
const auto optimized_expr_ir = ExtractFunctionIR(projector->DumpIR(), "expr_0_0");
512+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
513+
const auto unoptimized_expr_ir = ExtractFunctionIR(unoptimized_ir, "expr_0_0");
503514
ASSERT_FALSE(unoptimized_expr_ir.empty());
504-
ASSERT_FALSE(optimized_expr_ir.empty());
505515

506516
EXPECT_EQ(5, CountOccurrences(unoptimized_expr_ir, "call i32 @add_int32_int32"));
507517
EXPECT_EQ(2, CountOccurrences(unoptimized_expr_ir, "call i32 @multiply_int32_int32"));
508-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "call i32 @add_int32_int32"));
509-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "call i32 @multiply_int32_int32"));
510518

511519
auto input0 = MakeArrowArrayInt32({1, 2, 3, 4}, {true, true, false, true});
512520
auto input1 = MakeArrowArrayInt32({10, -2, 3, 5}, {true, true, true, false});
@@ -531,22 +539,16 @@ TEST_F(TestProjector, TestGeneratedIfCommonSubexpressionEliminationIR) {
531539
std::shared_ptr<Projector> projector;
532540
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
533541

534-
const auto unoptimized_expr_ir =
535-
ExtractFunctionIR(projector->DumpUnoptimizedIR(), "expr_0_0");
536-
const auto optimized_expr_ir = ExtractFunctionIR(projector->DumpIR(), "expr_0_0");
542+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
543+
const auto unoptimized_expr_ir = ExtractFunctionIR(unoptimized_ir, "expr_0_0");
537544
ASSERT_FALSE(unoptimized_expr_ir.empty());
538-
ASSERT_FALSE(optimized_expr_ir.empty());
539545

540546
EXPECT_NE(std::string::npos, unoptimized_expr_ir.find("generated_if_value"));
541547
EXPECT_EQ(std::string::npos, unoptimized_expr_ir.find("generated_if_cond"));
542548
EXPECT_EQ(std::string::npos, unoptimized_expr_ir.find("then:"));
543549
EXPECT_EQ(std::string::npos, unoptimized_expr_ir.find("else:"));
544550
EXPECT_EQ(std::string::npos, unoptimized_expr_ir.find("validAndMatch"));
545551
EXPECT_EQ(std::string::npos, unoptimized_expr_ir.find("res_value = phi"));
546-
EXPECT_NE(std::string::npos, optimized_expr_ir.find("generated_if_value"));
547-
EXPECT_EQ(std::string::npos, optimized_expr_ir.find("generated_if_cond"));
548-
EXPECT_EQ(std::string::npos, optimized_expr_ir.find("validAndMatch"));
549-
EXPECT_EQ(std::string::npos, optimized_expr_ir.find("res_value = phi"));
550552

551553
auto conditions =
552554
MakeArrowArrayBool({true, false, false, true}, {true, true, false, true});
@@ -573,23 +575,16 @@ TEST_F(TestProjector, TestGeneratedBooleanCommonSubexpressionEliminationIR) {
573575
std::shared_ptr<Projector> projector;
574576
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
575577

576-
const auto unoptimized_expr_ir =
577-
ExtractFunctionIR(projector->DumpUnoptimizedIR(), "expr_0_0");
578-
const auto optimized_expr_ir = ExtractFunctionIR(projector->DumpIR(), "expr_0_0");
578+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
579+
const auto unoptimized_expr_ir = ExtractFunctionIR(unoptimized_ir, "expr_0_0");
579580
ASSERT_FALSE(unoptimized_expr_ir.empty());
580-
ASSERT_FALSE(optimized_expr_ir.empty());
581581

582582
EXPECT_GT(CountOccurrences(unoptimized_expr_ir, "short_circuit"), 0);
583583
EXPECT_GT(CountOccurrences(unoptimized_expr_ir, "non_short_circuit"), 0);
584584
EXPECT_GT(CountOccurrences(unoptimized_expr_ir, "res_value = phi"), 0);
585585
EXPECT_GT(CountOccurrences(unoptimized_expr_ir, "\"0_lbmap\""), 0);
586586
EXPECT_EQ(0, CountOccurrences(unoptimized_expr_ir, "\"1_lbmap\""));
587587
EXPECT_EQ(0, CountOccurrences(unoptimized_expr_ir, "\"2_lbmap\""));
588-
EXPECT_GT(CountOccurrences(optimized_expr_ir, "generated_bool_f0"), 0);
589-
EXPECT_GT(CountOccurrences(optimized_expr_ir, "generated_bool_f1"), 0);
590-
EXPECT_GT(CountOccurrences(optimized_expr_ir, "\"0_lbmap\""), 0);
591-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "\"1_lbmap\""));
592-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir, "\"2_lbmap\""));
593588

594589
auto input0 = MakeArrowArrayBool({true, true, false, false, false},
595590
{true, true, true, false, false});
@@ -628,11 +623,9 @@ TEST_F(TestProjector, TestNestedBetweenCommonSubexpressionFoldIR) {
628623
std::shared_ptr<Projector> projector;
629624
ASSERT_OK(Projector::Make(schema, {expr}, configuration, &projector));
630625

631-
const auto unoptimized_expr_ir =
632-
ExtractFunctionIR(projector->DumpUnoptimizedIR(), "expr_0_0");
633-
const auto optimized_expr_ir = ExtractFunctionIR(projector->DumpIR(), "expr_0_0");
626+
ASSERT_OK_AND_ASSIGN(auto unoptimized_ir, projector->DumpUnoptimizedIR());
627+
const auto unoptimized_expr_ir = ExtractFunctionIR(unoptimized_ir, "expr_0_0");
634628
ASSERT_FALSE(unoptimized_expr_ir.empty());
635-
ASSERT_FALSE(optimized_expr_ir.empty());
636629

637630
EXPECT_EQ(1, CountOccurrences(unoptimized_expr_ir,
638631
"call i1 @greater_than_or_equal_to_int32_int32"));
@@ -641,10 +634,6 @@ TEST_F(TestProjector, TestNestedBetweenCommonSubexpressionFoldIR) {
641634
EXPECT_GT(CountOccurrences(unoptimized_expr_ir, "\"0_lbmap\""), 0);
642635
EXPECT_EQ(0, CountOccurrences(unoptimized_expr_ir, "\"1_lbmap\""));
643636
EXPECT_EQ(0, CountOccurrences(unoptimized_expr_ir, "\"2_lbmap\""));
644-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir,
645-
"call i1 @greater_than_or_equal_to_int32_int32"));
646-
EXPECT_EQ(0, CountOccurrences(optimized_expr_ir,
647-
"call i1 @less_than_or_equal_to_int32_int32"));
648637

649638
auto values = MakeArrowArrayInt32({5, 1, 10, 7, 4}, {true, true, true, true, false});
650639
auto lowers = MakeArrowArrayInt32({1, 2, 10, 6, 0}, {true, true, true, false, true});

0 commit comments

Comments
 (0)