diff options
author | 2024-06-03 16:25:38 +0100 | |
---|---|---|
committer | 2024-11-06 10:48:31 +0000 | |
commit | 740ae3479b54495d2dda92a000107325b08faf35 (patch) | |
tree | 66db8e0034b1d901988d2b4c67371f238bad88b7 /compiler/optimizing/codegen_test.cc | |
parent | 8cec104ae64bd45e1377d799ac4653fbce7fb631 (diff) |
Support all conditions in predicated vectorization
Support all condition types inside the condition when performing
diamond loop auto-vectorization. This allows diamond loop
auto-vectorization to be performed on a greater variety of loops.
To support this change, new vector condition nodes are added to
mirror the scalar condition nodes.
Also add a new gtest class to test whether predicated vectorization
can be performed on different combinations of condition types and
data types.
Authors: Chris Jones <christopher.jones@arm.com>,
Konstantin Baladurin <konstantin.baladurin@arm.com>
Test: export ART_FORCE_TRY_PREDICATED_SIMD=true && \
art/test.py --target --optimizing
Test: art/test.py --target --host --optimizing
Test: 661-checker-simd-cf-loops
Test: art/test.py --gtest art_compiler_tests
Change-Id: Ic9c925f1a58ada13d9031de3b445dcd4f77764b7
Diffstat (limited to 'compiler/optimizing/codegen_test.cc')
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 143 |
1 files changed, 108 insertions, 35 deletions
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 4f8551ab87..98b0550c4d 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -74,6 +74,11 @@ class CodegenTest : public CommonCompilerTest, public OptimizingUnitTestHelper { DataType::Type type, const CodegenTargetConfig target_config); void TestPackedSwitch(const CodegenTargetConfig target_config); + void TestVectorComparison(IfCondition condition, + int64_t lhs_value, + int64_t rhs_value, + DataType::Type type, + CodeGenerator* codegen); }; void CodegenTest::TestCode(const std::vector<uint16_t>& data, bool has_result, int32_t expected) { @@ -594,6 +599,35 @@ TEST_F(CodegenTest, ReturnDivInt2Addr) { TestCode(data, true, 2); } +static bool GetExpectedResultFromComparison(IfCondition condition, int64_t lhs, int64_t rhs) { + const uint64_t unsigned_lhs = lhs; + const uint64_t unsigned_rhs = rhs; + switch (condition) { + case kCondEQ: + return lhs == rhs; + case kCondNE: + return lhs != rhs; + case kCondLT: + return lhs < rhs; + case kCondLE: + return lhs <= rhs; + case kCondGT: + return lhs > rhs; + case kCondGE: + return lhs >= rhs; + case kCondB: + return unsigned_lhs < unsigned_rhs; + case kCondBE: + return unsigned_lhs <= unsigned_rhs; + case kCondA: + return unsigned_lhs > unsigned_rhs; + case kCondAE: + return unsigned_lhs >= unsigned_rhs; + } + LOG(FATAL) << "Condition '" << enum_cast<uint32_t>(condition) << "' not supported: "; + UNREACHABLE(); +} + // Helper method. void CodegenTest::TestComparison(IfCondition condition, int64_t i, @@ -613,47 +647,13 @@ void CodegenTest::TestComparison(IfCondition condition, op2 = graph_->GetLongConstant(j); } - bool expected_result = false; - const uint64_t x = i; - const uint64_t y = j; - switch (condition) { - case kCondEQ: - expected_result = (i == j); - break; - case kCondNE: - expected_result = (i != j); - break; - case kCondLT: - expected_result = (i < j); - break; - case kCondLE: - expected_result = (i <= j); - break; - case kCondGT: - expected_result = (i > j); - break; - case kCondGE: - expected_result = (i >= j); - break; - case kCondB: - expected_result = (x < y); - break; - case kCondBE: - expected_result = (x <= y); - break; - case kCondA: - expected_result = (x > y); - break; - case kCondAE: - expected_result = (x >= y); - break; - } HInstruction* comparison = MakeCondition(block, condition, op1, op2); MakeReturn(block, comparison); graph_->BuildDominatorTree(); std::unique_ptr<CompilerOptions> compiler_options = CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default"); + bool expected_result = GetExpectedResultFromComparison(condition, i, j); RunCode(target_config, *compiler_options, graph_, [](HGraph*) {}, true, expected_result); } @@ -976,6 +976,79 @@ TEST_F(CodegenTest, ARM64SvePredicateToBoolean) { } } +void CodegenTest::TestVectorComparison(IfCondition condition, + int64_t lhs_value, + int64_t rhs_value, + DataType::Type type, + CodeGenerator* codegen) { + HBasicBlock* block = entry_block_->GetSingleSuccessor(); + + size_t vector_size_in_bytes = codegen->GetSIMDRegisterWidth(); + + HVecPredSetAll* predicate = MakeVecPredSetAll(block, + graph_->GetIntConstant(1), + type, + vector_size_in_bytes); + HVecReplicateScalar* op1 = MakeVecReplicateScalar(block, + graph_->GetConstant(type, lhs_value), + type, + vector_size_in_bytes, + predicate); + HVecReplicateScalar* op2 = MakeVecReplicateScalar(block, + graph_->GetConstant(type, rhs_value), + type, + vector_size_in_bytes, + predicate); + HVecCondition* comparison = MakeVecCondition(block, + condition, + op1, + op2, + type, + vector_size_in_bytes, + predicate); + HInstruction* boolean_return = MakeVecPredToBoolean(block, + comparison, + HVecPredToBoolean::PCondKind::kFirst, + type, + vector_size_in_bytes); + MakeReturn(block, boolean_return); + + graph_->SetHasPredicatedSIMD(true); + graph_->BuildDominatorTree(); + + if (CanExecute(*codegen)) { + bool expected_result = GetExpectedResultFromComparison(condition, lhs_value, rhs_value); + RunCode(codegen, graph_, [](HGraph*) {}, true, expected_result); + } +} + +// Define tests ensuring that all types of conditions can be generated correctly and return the +// expected result. +#define DEFINE_CONDITION_TESTS(CondType) \ +TEST_F(CodegenTest, ComparisonsVector##CondType) { \ + std::unique_ptr<CompilerOptions> compiler_options = \ + CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default", "sve"); \ + for (int64_t i = -1; i <= 1; i++) { \ + for (int64_t j = -1; j <= 1; j++) { \ + for (int cond = kCondFirst; cond <= kCondLast; cond++) { \ + InitEntryMainExitGraph(); \ + TestCodeGeneratorARM64 codegen(graph_, *compiler_options); \ + if (!codegen.SupportsPredicatedSIMD()) { \ + GTEST_SKIP() << "Predicated SIMD is not supported."; \ + } \ + TestVectorComparison( \ + static_cast<IfCondition>(cond), i, j, DataType::Type::k##CondType, &codegen); \ + } \ + } \ + } \ +} +DEFINE_CONDITION_TESTS(Uint8) +DEFINE_CONDITION_TESTS(Int8) +DEFINE_CONDITION_TESTS(Uint16) +DEFINE_CONDITION_TESTS(Int16) +DEFINE_CONDITION_TESTS(Int32) +#undef DEFINE_CONDITION_TESTS + #endif } // namespace art |