summaryrefslogtreecommitdiff
path: root/compiler/optimizing/codegen_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/codegen_test.cc')
-rw-r--r--compiler/optimizing/codegen_test.cc67
1 files changed, 67 insertions, 0 deletions
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 7365f0fb7f..14a419fcd8 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -73,6 +73,7 @@ class CodegenTest : public CommonCompilerTest, public OptimizingUnitTestHelper {
int64_t j,
DataType::Type type,
const CodegenTargetConfig target_config);
+ void TestPackedSwitch(const CodegenTargetConfig target_config);
};
void CodegenTest::TestCode(const std::vector<uint16_t>& data, bool has_result, int32_t expected) {
@@ -682,6 +683,72 @@ TEST_F(CodegenTest, ComparisonsLong) {
}
}
+// Tests a PackedSwitch in a very large HGraph; validates that the switch jump table is in
+// range for the PC-relative load in the codegen visitor.
+void CodegenTest::TestPackedSwitch(const CodegenTargetConfig target_config) {
+ HBasicBlock* return_block = InitEntryMainExitGraph();
+ constexpr DataType::Type data_type = DataType::Type::kInt32;
+
+ // A number of entries - we are interested to test jump table implementation.
+ constexpr size_t kNumSwitchEntries = 10;
+
+ // Number of jump targets (including a 'default' case).
+ constexpr size_t kNumBB = kNumSwitchEntries + 1;
+ // Some arbitrary value to be used as input.
+ constexpr int kInputValue = kNumBB - 4;
+
+ HInstruction* input = graph_->GetIntConstant(kInputValue);
+ HIntConstant* constant_1 = graph_->GetIntConstant(1);
+
+ HBasicBlock* switch_block = AddNewBlock();
+ entry_block_->ReplaceSuccessor(return_block, switch_block);
+
+ HPackedSwitch* hswitch = new (GetAllocator()) HPackedSwitch(0, kNumSwitchEntries, input);
+ switch_block->AddInstruction(hswitch);
+
+ std::vector<HInstruction*> phi_inputs {};
+
+ // Add switch jump target blocks.
+ for (int i = 0; i < kNumBB; i++) {
+ HBasicBlock* case_block = AddNewBlock();
+ case_block->AddPredecessor(switch_block);
+ case_block->AddSuccessor(return_block);
+
+ HIntConstant* case_value = graph_->GetIntConstant(i);
+ HAdd* add = MakeBinOp<HAdd>(case_block, data_type, input, case_value);
+ phi_inputs.emplace_back(add);
+
+ MakeGoto(case_block);
+ }
+
+ HPhi* phi = MakePhi(return_block, phi_inputs);
+ HInstruction* return_val = phi;
+
+ // Emit a huge number of HAdds - to simulate a very large HGraph.
+ constexpr int kNumOfAdds = 2 * 1024 * 1024;
+ for (int i = 0; i < kNumOfAdds; i++) {
+ return_val = MakeBinOp<HAdd>(return_block, data_type, return_val, constant_1);
+ }
+
+ MakeReturn(return_block, return_val);
+
+ graph_->BuildDominatorTree();
+ EXPECT_TRUE(CheckGraph());
+
+ std::unique_ptr<CompilerOptions> compiler_options =
+ CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
+ RunCode(target_config,
+ *compiler_options,
+ graph_,
+ [](HGraph*) {}, true, kNumOfAdds + 2 * kInputValue);
+}
+
+TEST_F(CodegenTest, PackedSwitchInHugeMethod) {
+ for (CodegenTargetConfig target_config : GetTargetConfigs()) {
+ TestPackedSwitch(target_config);
+ }
+}
+
#ifdef ART_ENABLE_CODEGEN_arm
TEST_F(CodegenTest, ARMVIXLParallelMoveResolver) {
std::unique_ptr<CompilerOptions> compiler_options =