blob: fe6c0a305e16ced0c3b2ac3ec748ef43d24fd633 [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Nicolas Geoffray360231a2014-10-08 21:07:48 +010017#include <functional>
18
Ian Rogersd582fa42014-11-05 23:46:43 -080019#include "arch/instruction_set.h"
Calin Juravle34166012014-12-19 17:22:29 +000020#include "arch/arm/instruction_set_features_arm.h"
Nicolas Geoffray5da21802015-04-20 09:29:18 +010021#include "arch/arm/registers_arm.h"
Serban Constantinescu579885a2015-02-22 20:51:33 +000022#include "arch/arm64/instruction_set_features_arm64.h"
Goran Jakovljevicf652cec2015-08-25 16:11:42 +020023#include "arch/mips/instruction_set_features_mips.h"
24#include "arch/mips/registers_mips.h"
Alexey Frunze4dda3372015-06-01 18:31:49 -070025#include "arch/mips64/instruction_set_features_mips64.h"
26#include "arch/mips64/registers_mips64.h"
Mark Mendellfb8d2792015-03-31 22:16:59 -040027#include "arch/x86/instruction_set_features_x86.h"
Nicolas Geoffray5da21802015-04-20 09:29:18 +010028#include "arch/x86/registers_x86.h"
Mark Mendellfb8d2792015-03-31 22:16:59 -040029#include "arch/x86_64/instruction_set_features_x86_64.h"
Alexandre Rames92730742014-10-01 12:55:56 +010030#include "base/macros.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000031#include "builder.h"
Phil Wang751beff2015-08-28 15:17:15 +080032#include "code_simulator_container.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033#include "common_compiler_test.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000034#include "dex_file.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000035#include "dex_instruction.h"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000036#include "driver/compiler_options.h"
David Brazdil58282f42016-01-14 12:45:10 +000037#include "graph_checker.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000038#include "nodes.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000039#include "optimizing_unit_test.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010040#include "prepare_for_register_allocation.h"
Matthew Gharritye9288852016-07-14 14:08:16 -070041#include "register_allocator_linear_scan.h"
Nicolas Geoffray360231a2014-10-08 21:07:48 +010042#include "ssa_liveness_analysis.h"
Roland Levillain55dcfb52014-10-24 18:09:09 +010043#include "utils.h"
Nicolas Geoffray5da21802015-04-20 09:29:18 +010044#include "utils/arm/managed_register_arm.h"
Goran Jakovljevicf652cec2015-08-25 16:11:42 +020045#include "utils/mips/managed_register_mips.h"
Alexey Frunze4dda3372015-06-01 18:31:49 -070046#include "utils/mips64/managed_register_mips64.h"
Nicolas Geoffray5da21802015-04-20 09:29:18 +010047#include "utils/x86/managed_register_x86.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000048
Colin Crossa75b01a2016-08-18 13:45:24 -070049#ifdef ART_ENABLE_CODEGEN_arm
50#include "code_generator_arm.h"
51#endif
52
53#ifdef ART_ENABLE_CODEGEN_arm64
54#include "code_generator_arm64.h"
55#endif
56
57#ifdef ART_ENABLE_CODEGEN_x86
58#include "code_generator_x86.h"
59#endif
60
61#ifdef ART_ENABLE_CODEGEN_x86_64
62#include "code_generator_x86_64.h"
63#endif
64
65#ifdef ART_ENABLE_CODEGEN_mips
66#include "code_generator_mips.h"
67#endif
68
69#ifdef ART_ENABLE_CODEGEN_mips64
70#include "code_generator_mips64.h"
71#endif
72
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000073#include "gtest/gtest.h"
Nicolas Geoffraye6362282015-01-26 13:57:30 +000074
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000075namespace art {
76
Colin Crossa75b01a2016-08-18 13:45:24 -070077#ifdef ART_ENABLE_CODEGEN_arm
Nicolas Geoffraya0bb2bd2015-01-26 12:49:35 +000078// Provide our own codegen, that ensures the C calling conventions
79// are preserved. Currently, ART and C do not match as R4 is caller-save
80// in ART, and callee-save in C. Alternatively, we could use or write
81// the stub that saves and restores all registers, but it is easier
82// to just overwrite the code generator.
83class TestCodeGeneratorARM : public arm::CodeGeneratorARM {
84 public:
85 TestCodeGeneratorARM(HGraph* graph,
86 const ArmInstructionSetFeatures& isa_features,
87 const CompilerOptions& compiler_options)
88 : arm::CodeGeneratorARM(graph, isa_features, compiler_options) {
Nicolas Geoffray5da21802015-04-20 09:29:18 +010089 AddAllocatedRegister(Location::RegisterLocation(arm::R6));
90 AddAllocatedRegister(Location::RegisterLocation(arm::R7));
Nicolas Geoffraya0bb2bd2015-01-26 12:49:35 +000091 }
92
David Brazdil58282f42016-01-14 12:45:10 +000093 void SetupBlockedRegisters() const OVERRIDE {
94 arm::CodeGeneratorARM::SetupBlockedRegisters();
Nicolas Geoffray5da21802015-04-20 09:29:18 +010095 blocked_core_registers_[arm::R4] = true;
96 blocked_core_registers_[arm::R6] = false;
97 blocked_core_registers_[arm::R7] = false;
Nicolas Geoffraye6362282015-01-26 13:57:30 +000098 // Makes pair R6-R7 available.
Nicolas Geoffray5da21802015-04-20 09:29:18 +010099 blocked_register_pairs_[arm::R6_R7] = false;
100 }
101};
Colin Crossa75b01a2016-08-18 13:45:24 -0700102#endif
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100103
Colin Crossa75b01a2016-08-18 13:45:24 -0700104#ifdef ART_ENABLE_CODEGEN_x86
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100105class TestCodeGeneratorX86 : public x86::CodeGeneratorX86 {
106 public:
107 TestCodeGeneratorX86(HGraph* graph,
108 const X86InstructionSetFeatures& isa_features,
109 const CompilerOptions& compiler_options)
110 : x86::CodeGeneratorX86(graph, isa_features, compiler_options) {
111 // Save edi, we need it for getting enough registers for long multiplication.
112 AddAllocatedRegister(Location::RegisterLocation(x86::EDI));
113 }
114
David Brazdil58282f42016-01-14 12:45:10 +0000115 void SetupBlockedRegisters() const OVERRIDE {
116 x86::CodeGeneratorX86::SetupBlockedRegisters();
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100117 // ebx is a callee-save register in C, but caller-save for ART.
118 blocked_core_registers_[x86::EBX] = true;
119 blocked_register_pairs_[x86::EAX_EBX] = true;
120 blocked_register_pairs_[x86::EDX_EBX] = true;
121 blocked_register_pairs_[x86::ECX_EBX] = true;
122 blocked_register_pairs_[x86::EBX_EDI] = true;
123
124 // Make edi available.
125 blocked_core_registers_[x86::EDI] = false;
126 blocked_register_pairs_[x86::ECX_EDI] = false;
Nicolas Geoffraya0bb2bd2015-01-26 12:49:35 +0000127 }
128};
Colin Crossa75b01a2016-08-18 13:45:24 -0700129#endif
Nicolas Geoffraya0bb2bd2015-01-26 12:49:35 +0000130
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000131class InternalCodeAllocator : public CodeAllocator {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000132 public:
Ian Rogersd582fa42014-11-05 23:46:43 -0800133 InternalCodeAllocator() : size_(0) { }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000134
135 virtual uint8_t* Allocate(size_t size) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000136 size_ = size;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000137 memory_.reset(new uint8_t[size]);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000138 return memory_.get();
139 }
140
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000141 size_t GetSize() const { return size_; }
142 uint8_t* GetMemory() const { return memory_.get(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000143
144 private:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000145 size_t size_;
Ian Rogers700a4022014-05-19 16:49:03 -0700146 std::unique_ptr<uint8_t[]> memory_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000147
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000148 DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000149};
150
Phil Wang751beff2015-08-28 15:17:15 +0800151static bool CanExecuteOnHardware(InstructionSet target_isa) {
152 return (target_isa == kRuntimeISA)
153 // Handle the special case of ARM, with two instructions sets (ARM32 and Thumb-2).
154 || (kRuntimeISA == kArm && target_isa == kThumb2);
155}
156
157static bool CanExecute(InstructionSet target_isa) {
158 CodeSimulatorContainer simulator(target_isa);
159 return CanExecuteOnHardware(target_isa) || simulator.CanSimulate();
160}
161
162template <typename Expected>
163static Expected SimulatorExecute(CodeSimulator* simulator, Expected (*f)());
164
165template <>
166bool SimulatorExecute<bool>(CodeSimulator* simulator, bool (*f)()) {
167 simulator->RunFrom(reinterpret_cast<intptr_t>(f));
168 return simulator->GetCReturnBool();
169}
170
171template <>
172int32_t SimulatorExecute<int32_t>(CodeSimulator* simulator, int32_t (*f)()) {
173 simulator->RunFrom(reinterpret_cast<intptr_t>(f));
174 return simulator->GetCReturnInt32();
175}
176
177template <>
178int64_t SimulatorExecute<int64_t>(CodeSimulator* simulator, int64_t (*f)()) {
179 simulator->RunFrom(reinterpret_cast<intptr_t>(f));
180 return simulator->GetCReturnInt64();
181}
182
183template <typename Expected>
184static void VerifyGeneratedCode(InstructionSet target_isa,
185 Expected (*f)(),
186 bool has_result,
187 Expected expected) {
188 ASSERT_TRUE(CanExecute(target_isa)) << "Target isa is not executable.";
189
190 // Verify on simulator.
191 CodeSimulatorContainer simulator(target_isa);
192 if (simulator.CanSimulate()) {
193 Expected result = SimulatorExecute<Expected>(simulator.Get(), f);
194 if (has_result) {
195 ASSERT_EQ(expected, result);
196 }
197 }
198
199 // Verify on hardware.
200 if (CanExecuteOnHardware(target_isa)) {
201 Expected result = f();
202 if (has_result) {
203 ASSERT_EQ(expected, result);
204 }
205 }
206}
207
Roland Levillain55dcfb52014-10-24 18:09:09 +0100208template <typename Expected>
Nicolas Geoffray8d486732014-07-16 16:23:40 +0100209static void Run(const InternalCodeAllocator& allocator,
210 const CodeGenerator& codegen,
211 bool has_result,
Roland Levillain55dcfb52014-10-24 18:09:09 +0100212 Expected expected) {
Phil Wang751beff2015-08-28 15:17:15 +0800213 InstructionSet target_isa = codegen.GetInstructionSet();
214
Roland Levillain55dcfb52014-10-24 18:09:09 +0100215 typedef Expected (*fptr)();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100216 CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize());
Dave Allison20dfc792014-06-16 20:44:29 -0700217 fptr f = reinterpret_cast<fptr>(allocator.GetMemory());
Phil Wang751beff2015-08-28 15:17:15 +0800218 if (target_isa == kThumb2) {
Nicolas Geoffray8d486732014-07-16 16:23:40 +0100219 // For thumb we need the bottom bit set.
220 f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
221 }
Phil Wang751beff2015-08-28 15:17:15 +0800222 VerifyGeneratedCode(target_isa, f, has_result, expected);
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100223}
224
Roland Levillain55dcfb52014-10-24 18:09:09 +0100225template <typename Expected>
David Brazdil58282f42016-01-14 12:45:10 +0000226static void RunCode(CodeGenerator* codegen,
227 HGraph* graph,
228 std::function<void(HGraph*)> hook_before_codegen,
229 bool has_result,
230 Expected expected) {
David Brazdilbadd8262016-02-02 16:28:56 +0000231 GraphChecker graph_checker(graph);
David Brazdil58282f42016-01-14 12:45:10 +0000232 graph_checker.Run();
David Brazdilbadd8262016-02-02 16:28:56 +0000233 if (!graph_checker.IsValid()) {
234 for (auto error : graph_checker.GetErrors()) {
235 std::cout << error << std::endl;
236 }
237 }
David Brazdil58282f42016-01-14 12:45:10 +0000238 ASSERT_TRUE(graph_checker.IsValid());
Nicolas Geoffray9cf35522014-06-09 18:40:10 +0100239
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100240 SsaLivenessAnalysis liveness(graph, codegen);
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100241
David Brazdil58282f42016-01-14 12:45:10 +0000242 PrepareForRegisterAllocation(graph).Run();
243 liveness.Analyze();
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700244 RegisterAllocator::Create(graph->GetArena(), codegen, liveness)->AllocateRegisters();
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100245 hook_before_codegen(graph);
246
247 InternalCodeAllocator allocator;
David Brazdil58282f42016-01-14 12:45:10 +0000248 codegen->Compile(&allocator);
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100249 Run(allocator, *codegen, has_result, expected);
250}
251
Roland Levillain55dcfb52014-10-24 18:09:09 +0100252template <typename Expected>
David Brazdil58282f42016-01-14 12:45:10 +0000253static void RunCode(InstructionSet target_isa,
254 HGraph* graph,
255 std::function<void(HGraph*)> hook_before_codegen,
256 bool has_result,
257 Expected expected) {
Calin Juravlecd6dffe2015-01-08 17:35:35 +0000258 CompilerOptions compiler_options;
Colin Crossa75b01a2016-08-18 13:45:24 -0700259#ifdef ART_ENABLE_CODEGEN_arm
Phil Wang751beff2015-08-28 15:17:15 +0800260 if (target_isa == kArm || target_isa == kThumb2) {
261 std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
262 ArmInstructionSetFeatures::FromCppDefines());
263 TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000264 RunCode(&codegenARM, graph, hook_before_codegen, has_result, expected);
Colin Crossa75b01a2016-08-18 13:45:24 -0700265 }
266#endif
267#ifdef ART_ENABLE_CODEGEN_arm64
268 if (target_isa == kArm64) {
Phil Wang751beff2015-08-28 15:17:15 +0800269 std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
270 Arm64InstructionSetFeatures::FromCppDefines());
271 arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000272 RunCode(&codegenARM64, graph, hook_before_codegen, has_result, expected);
Colin Crossa75b01a2016-08-18 13:45:24 -0700273 }
274#endif
275#ifdef ART_ENABLE_CODEGEN_x86
276 if (target_isa == kX86) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400277 std::unique_ptr<const X86InstructionSetFeatures> features_x86(
278 X86InstructionSetFeatures::FromCppDefines());
Matthew Gharrity1aa559d2016-08-11 17:20:05 -0700279 TestCodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000280 RunCode(&codegenX86, graph, hook_before_codegen, has_result, expected);
Colin Crossa75b01a2016-08-18 13:45:24 -0700281 }
282#endif
283#ifdef ART_ENABLE_CODEGEN_x86_64
284 if (target_isa == kX86_64) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400285 std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
286 X86_64InstructionSetFeatures::FromCppDefines());
287 x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000288 RunCode(&codegenX86_64, graph, hook_before_codegen, has_result, expected);
Colin Crossa75b01a2016-08-18 13:45:24 -0700289 }
290#endif
291#ifdef ART_ENABLE_CODEGEN_mips
292 if (target_isa == kMips) {
Goran Jakovljevicf652cec2015-08-25 16:11:42 +0200293 std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
294 MipsInstructionSetFeatures::FromCppDefines());
295 mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000296 RunCode(&codegenMIPS, graph, hook_before_codegen, has_result, expected);
Colin Crossa75b01a2016-08-18 13:45:24 -0700297 }
298#endif
299#ifdef ART_ENABLE_CODEGEN_mips64
300 if (target_isa == kMips64) {
Alexey Frunze4dda3372015-06-01 18:31:49 -0700301 std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
302 Mips64InstructionSetFeatures::FromCppDefines());
303 mips64::CodeGeneratorMIPS64 codegenMIPS64(graph, *features_mips64.get(), compiler_options);
David Brazdil58282f42016-01-14 12:45:10 +0000304 RunCode(&codegenMIPS64, graph, hook_before_codegen, has_result, expected);
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100305 }
Colin Crossa75b01a2016-08-18 13:45:24 -0700306#endif
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100307}
308
David Brazdil58282f42016-01-14 12:45:10 +0000309static ::std::vector<InstructionSet> GetTargetISAs() {
310 ::std::vector<InstructionSet> v;
311 // Add all ISAs that are executable on hardware or on simulator.
312 const ::std::vector<InstructionSet> executable_isa_candidates = {
313 kArm,
314 kArm64,
315 kThumb2,
316 kX86,
317 kX86_64,
318 kMips,
319 kMips64
320 };
321
322 for (auto target_isa : executable_isa_candidates) {
323 if (CanExecute(target_isa)) {
324 v.push_back(target_isa);
325 }
326 }
327
328 return v;
329}
330
331static void TestCode(const uint16_t* data,
Phil Wang751beff2015-08-28 15:17:15 +0800332 bool has_result = false,
333 int32_t expected = 0) {
David Brazdil58282f42016-01-14 12:45:10 +0000334 for (InstructionSet target_isa : GetTargetISAs()) {
335 ArenaPool pool;
336 ArenaAllocator arena(&pool);
David Brazdilbadd8262016-02-02 16:28:56 +0000337 HGraph* graph = CreateCFG(&arena, data);
David Brazdil58282f42016-01-14 12:45:10 +0000338 // Remove suspend checks, they cannot be executed in this context.
339 RemoveSuspendChecks(graph);
David Brazdil58282f42016-01-14 12:45:10 +0000340 RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
341 }
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100342}
343
David Brazdil58282f42016-01-14 12:45:10 +0000344static void TestCodeLong(const uint16_t* data,
Phil Wang751beff2015-08-28 15:17:15 +0800345 bool has_result,
346 int64_t expected) {
David Brazdil58282f42016-01-14 12:45:10 +0000347 for (InstructionSet target_isa : GetTargetISAs()) {
348 ArenaPool pool;
349 ArenaAllocator arena(&pool);
David Brazdilbadd8262016-02-02 16:28:56 +0000350 HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong);
David Brazdil58282f42016-01-14 12:45:10 +0000351 // Remove suspend checks, they cannot be executed in this context.
352 RemoveSuspendChecks(graph);
David Brazdil58282f42016-01-14 12:45:10 +0000353 RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
354 }
Roland Levillain55dcfb52014-10-24 18:09:09 +0100355}
356
David Brazdil58282f42016-01-14 12:45:10 +0000357class CodegenTest : public CommonCompilerTest {};
Phil Wang751beff2015-08-28 15:17:15 +0800358
David Brazdil58282f42016-01-14 12:45:10 +0000359TEST_F(CodegenTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000360 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
David Brazdil58282f42016-01-14 12:45:10 +0000361 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000362}
363
David Brazdil58282f42016-01-14 12:45:10 +0000364TEST_F(CodegenTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000365 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000366 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000367 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000368
David Brazdil58282f42016-01-14 12:45:10 +0000369 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000370}
371
David Brazdil58282f42016-01-14 12:45:10 +0000372TEST_F(CodegenTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000373 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000374 Instruction::GOTO | 0x100,
375 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000376 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000377
David Brazdil58282f42016-01-14 12:45:10 +0000378 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000379}
380
David Brazdil58282f42016-01-14 12:45:10 +0000381TEST_F(CodegenTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000382 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000383 Instruction::GOTO | 0x200,
384 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000385 Instruction::GOTO | 0xFF00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000386
David Brazdil58282f42016-01-14 12:45:10 +0000387 TestCode(data1);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000388
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000389 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000390 Instruction::GOTO_16, 3,
391 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000392 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000393
David Brazdil58282f42016-01-14 12:45:10 +0000394 TestCode(data2);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000395
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000396 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000397 Instruction::GOTO_32, 4, 0,
398 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000399 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000400
David Brazdil58282f42016-01-14 12:45:10 +0000401 TestCode(data3);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000402}
403
David Brazdil58282f42016-01-14 12:45:10 +0000404TEST_F(CodegenTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000405 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000406 Instruction::RETURN_VOID,
407 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000408 Instruction::GOTO | 0xFE00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000409
David Brazdil58282f42016-01-14 12:45:10 +0000410 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000411}
412
David Brazdil58282f42016-01-14 12:45:10 +0000413TEST_F(CodegenTest, CFG5) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000414 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
415 Instruction::CONST_4 | 0 | 0,
416 Instruction::IF_EQ, 3,
417 Instruction::GOTO | 0x100,
418 Instruction::RETURN_VOID);
419
David Brazdil58282f42016-01-14 12:45:10 +0000420 TestCode(data);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000421}
422
David Brazdil58282f42016-01-14 12:45:10 +0000423TEST_F(CodegenTest, IntConstant) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000424 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
425 Instruction::CONST_4 | 0 | 0,
426 Instruction::RETURN_VOID);
427
David Brazdil58282f42016-01-14 12:45:10 +0000428 TestCode(data);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000429}
430
David Brazdil58282f42016-01-14 12:45:10 +0000431TEST_F(CodegenTest, Return1) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000432 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
433 Instruction::CONST_4 | 0 | 0,
434 Instruction::RETURN | 0);
435
David Brazdil58282f42016-01-14 12:45:10 +0000436 TestCode(data, true, 0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000437}
438
David Brazdil58282f42016-01-14 12:45:10 +0000439TEST_F(CodegenTest, Return2) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000440 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
441 Instruction::CONST_4 | 0 | 0,
442 Instruction::CONST_4 | 0 | 1 << 8,
443 Instruction::RETURN | 1 << 8);
444
David Brazdil58282f42016-01-14 12:45:10 +0000445 TestCode(data, true, 0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000446}
447
David Brazdil58282f42016-01-14 12:45:10 +0000448TEST_F(CodegenTest, Return3) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000449 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
450 Instruction::CONST_4 | 0 | 0,
451 Instruction::CONST_4 | 1 << 8 | 1 << 12,
452 Instruction::RETURN | 1 << 8);
453
David Brazdil58282f42016-01-14 12:45:10 +0000454 TestCode(data, true, 1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000455}
456
David Brazdil58282f42016-01-14 12:45:10 +0000457TEST_F(CodegenTest, ReturnIf1) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000458 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
459 Instruction::CONST_4 | 0 | 0,
460 Instruction::CONST_4 | 1 << 8 | 1 << 12,
461 Instruction::IF_EQ, 3,
462 Instruction::RETURN | 0 << 8,
463 Instruction::RETURN | 1 << 8);
464
David Brazdil58282f42016-01-14 12:45:10 +0000465 TestCode(data, true, 1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000466}
467
David Brazdil58282f42016-01-14 12:45:10 +0000468TEST_F(CodegenTest, ReturnIf2) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000469 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
470 Instruction::CONST_4 | 0 | 0,
471 Instruction::CONST_4 | 1 << 8 | 1 << 12,
472 Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
473 Instruction::RETURN | 0 << 8,
474 Instruction::RETURN | 1 << 8);
475
David Brazdil58282f42016-01-14 12:45:10 +0000476 TestCode(data, true, 0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000477}
478
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100479// Exercise bit-wise (one's complement) not-int instruction.
480#define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
David Brazdil58282f42016-01-14 12:45:10 +0000481TEST_F(CodegenTest, TEST_NAME) { \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100482 const int32_t input = INPUT; \
Roland Levillain55dcfb52014-10-24 18:09:09 +0100483 const uint16_t input_lo = Low16Bits(input); \
484 const uint16_t input_hi = High16Bits(input); \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100485 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( \
486 Instruction::CONST | 0 << 8, input_lo, input_hi, \
487 Instruction::NOT_INT | 1 << 8 | 0 << 12 , \
488 Instruction::RETURN | 1 << 8); \
489 \
David Brazdil58282f42016-01-14 12:45:10 +0000490 TestCode(data, true, EXPECTED_OUTPUT); \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100491}
492
493NOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
494NOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
495NOT_INT_TEST(ReturnNotInt0, 0, -1)
496NOT_INT_TEST(ReturnNotInt1, 1, -2)
Roland Levillain55dcfb52014-10-24 18:09:09 +0100497NOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647) // (2^31) - 1
498NOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646) // (2^31) - 2
499NOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1
500NOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648) // -(2^31)
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100501
502#undef NOT_INT_TEST
503
Roland Levillain55dcfb52014-10-24 18:09:09 +0100504// Exercise bit-wise (one's complement) not-long instruction.
505#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
David Brazdil58282f42016-01-14 12:45:10 +0000506TEST_F(CodegenTest, TEST_NAME) { \
Roland Levillain55dcfb52014-10-24 18:09:09 +0100507 const int64_t input = INPUT; \
508 const uint16_t word0 = Low16Bits(Low32Bits(input)); /* LSW. */ \
509 const uint16_t word1 = High16Bits(Low32Bits(input)); \
510 const uint16_t word2 = Low16Bits(High32Bits(input)); \
511 const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */ \
512 const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM( \
513 Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, \
514 Instruction::NOT_LONG | 2 << 8 | 0 << 12, \
515 Instruction::RETURN_WIDE | 2 << 8); \
516 \
David Brazdil58282f42016-01-14 12:45:10 +0000517 TestCodeLong(data, true, EXPECTED_OUTPUT); \
Roland Levillain55dcfb52014-10-24 18:09:09 +0100518}
519
520NOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1))
521NOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0))
522NOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1))
523NOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2))
524
525NOT_LONG_TEST(ReturnNotLongINT32_MIN,
526 INT64_C(-2147483648),
527 INT64_C(2147483647)) // (2^31) - 1
528NOT_LONG_TEST(ReturnNotLongINT32_MINPlus1,
529 INT64_C(-2147483647),
530 INT64_C(2147483646)) // (2^31) - 2
531NOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1,
532 INT64_C(2147483646),
533 INT64_C(-2147483647)) // -(2^31) - 1
534NOT_LONG_TEST(ReturnNotLongINT32_MAX,
535 INT64_C(2147483647),
536 INT64_C(-2147483648)) // -(2^31)
537
538// Note that the C++ compiler won't accept
539// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid
540// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead.
541NOT_LONG_TEST(ReturnNotINT64_MIN,
542 INT64_C(-9223372036854775807)-1,
543 INT64_C(9223372036854775807)); // (2^63) - 1
544NOT_LONG_TEST(ReturnNotINT64_MINPlus1,
545 INT64_C(-9223372036854775807),
546 INT64_C(9223372036854775806)); // (2^63) - 2
547NOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1,
548 INT64_C(9223372036854775806),
549 INT64_C(-9223372036854775807)); // -(2^63) - 1
550NOT_LONG_TEST(ReturnNotLongINT64_MAX,
551 INT64_C(9223372036854775807),
552 INT64_C(-9223372036854775807)-1); // -(2^63)
553
554#undef NOT_LONG_TEST
555
David Brazdil58282f42016-01-14 12:45:10 +0000556TEST_F(CodegenTest, IntToLongOfLongToInt) {
Roland Levillain946e1432014-11-11 17:35:19 +0000557 const int64_t input = INT64_C(4294967296); // 2^32
558 const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW.
559 const uint16_t word1 = High16Bits(Low32Bits(input));
560 const uint16_t word2 = Low16Bits(High32Bits(input));
561 const uint16_t word3 = High16Bits(High32Bits(input)); // MSW.
562 const uint16_t data[] = FIVE_REGISTERS_CODE_ITEM(
563 Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
564 Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0,
565 Instruction::ADD_LONG | 0, 0 << 8 | 2, // v0 <- 2^32 + 1
566 Instruction::LONG_TO_INT | 4 << 8 | 0 << 12,
567 Instruction::INT_TO_LONG | 2 << 8 | 4 << 12,
568 Instruction::RETURN_WIDE | 2 << 8);
569
David Brazdil58282f42016-01-14 12:45:10 +0000570 TestCodeLong(data, true, 1);
Roland Levillain946e1432014-11-11 17:35:19 +0000571}
572
David Brazdil58282f42016-01-14 12:45:10 +0000573TEST_F(CodegenTest, ReturnAdd1) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000574 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
575 Instruction::CONST_4 | 3 << 12 | 0,
576 Instruction::CONST_4 | 4 << 12 | 1 << 8,
577 Instruction::ADD_INT, 1 << 8 | 0,
578 Instruction::RETURN);
579
David Brazdil58282f42016-01-14 12:45:10 +0000580 TestCode(data, true, 7);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000581}
582
David Brazdil58282f42016-01-14 12:45:10 +0000583TEST_F(CodegenTest, ReturnAdd2) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000584 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
585 Instruction::CONST_4 | 3 << 12 | 0,
586 Instruction::CONST_4 | 4 << 12 | 1 << 8,
587 Instruction::ADD_INT_2ADDR | 1 << 12,
588 Instruction::RETURN);
589
David Brazdil58282f42016-01-14 12:45:10 +0000590 TestCode(data, true, 7);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000591}
592
David Brazdil58282f42016-01-14 12:45:10 +0000593TEST_F(CodegenTest, ReturnAdd3) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000594 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
595 Instruction::CONST_4 | 4 << 12 | 0 << 8,
596 Instruction::ADD_INT_LIT8, 3 << 8 | 0,
597 Instruction::RETURN);
598
David Brazdil58282f42016-01-14 12:45:10 +0000599 TestCode(data, true, 7);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000600}
601
David Brazdil58282f42016-01-14 12:45:10 +0000602TEST_F(CodegenTest, ReturnAdd4) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000603 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
604 Instruction::CONST_4 | 4 << 12 | 0 << 8,
605 Instruction::ADD_INT_LIT16, 3,
606 Instruction::RETURN);
607
David Brazdil58282f42016-01-14 12:45:10 +0000608 TestCode(data, true, 7);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000609}
610
David Brazdil58282f42016-01-14 12:45:10 +0000611TEST_F(CodegenTest, ReturnMulInt) {
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100612 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
613 Instruction::CONST_4 | 3 << 12 | 0,
614 Instruction::CONST_4 | 4 << 12 | 1 << 8,
615 Instruction::MUL_INT, 1 << 8 | 0,
616 Instruction::RETURN);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100617
David Brazdil58282f42016-01-14 12:45:10 +0000618 TestCode(data, true, 12);
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100619}
620
David Brazdil58282f42016-01-14 12:45:10 +0000621TEST_F(CodegenTest, ReturnMulInt2addr) {
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100622 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
623 Instruction::CONST_4 | 3 << 12 | 0,
624 Instruction::CONST_4 | 4 << 12 | 1 << 8,
625 Instruction::MUL_INT_2ADDR | 1 << 12,
626 Instruction::RETURN);
627
David Brazdil58282f42016-01-14 12:45:10 +0000628 TestCode(data, true, 12);
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100629}
630
David Brazdil58282f42016-01-14 12:45:10 +0000631TEST_F(CodegenTest, ReturnMulLong) {
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100632 const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
David Brazdil58282f42016-01-14 12:45:10 +0000633 Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
634 Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100635 Instruction::MUL_LONG, 2 << 8 | 0,
636 Instruction::RETURN_WIDE);
637
David Brazdil58282f42016-01-14 12:45:10 +0000638 TestCodeLong(data, true, 12);
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100639}
640
David Brazdil58282f42016-01-14 12:45:10 +0000641TEST_F(CodegenTest, ReturnMulLong2addr) {
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100642 const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
David Brazdil58282f42016-01-14 12:45:10 +0000643 Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
644 Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100645 Instruction::MUL_LONG_2ADDR | 2 << 12,
646 Instruction::RETURN_WIDE);
647
David Brazdil58282f42016-01-14 12:45:10 +0000648 TestCodeLong(data, true, 12);
Nicolas Geoffray5da21802015-04-20 09:29:18 +0100649}
Calin Juravle34bacdf2014-10-07 20:23:36 +0100650
David Brazdil58282f42016-01-14 12:45:10 +0000651TEST_F(CodegenTest, ReturnMulIntLit8) {
Calin Juravle34bacdf2014-10-07 20:23:36 +0100652 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
653 Instruction::CONST_4 | 4 << 12 | 0 << 8,
654 Instruction::MUL_INT_LIT8, 3 << 8 | 0,
655 Instruction::RETURN);
656
David Brazdil58282f42016-01-14 12:45:10 +0000657 TestCode(data, true, 12);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100658}
659
David Brazdil58282f42016-01-14 12:45:10 +0000660TEST_F(CodegenTest, ReturnMulIntLit16) {
Calin Juravle34bacdf2014-10-07 20:23:36 +0100661 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
662 Instruction::CONST_4 | 4 << 12 | 0 << 8,
663 Instruction::MUL_INT_LIT16, 3,
664 Instruction::RETURN);
665
David Brazdil58282f42016-01-14 12:45:10 +0000666 TestCode(data, true, 12);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100667}
668
David Brazdil58282f42016-01-14 12:45:10 +0000669TEST_F(CodegenTest, NonMaterializedCondition) {
670 for (InstructionSet target_isa : GetTargetISAs()) {
Alexandre Rames92730742014-10-01 12:55:56 +0100671 ArenaPool pool;
672 ArenaAllocator allocator(&pool);
David Brazdil58282f42016-01-14 12:45:10 +0000673
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100674 HGraph* graph = CreateGraph(&allocator);
David Brazdilbadd8262016-02-02 16:28:56 +0000675
David Brazdil58282f42016-01-14 12:45:10 +0000676 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
677 graph->AddBlock(entry);
678 graph->SetEntryBlock(entry);
679 entry->AddInstruction(new (&allocator) HGoto());
Alexandre Rames92730742014-10-01 12:55:56 +0100680
David Brazdil58282f42016-01-14 12:45:10 +0000681 HBasicBlock* first_block = new (&allocator) HBasicBlock(graph);
682 graph->AddBlock(first_block);
683 entry->AddSuccessor(first_block);
684 HIntConstant* constant0 = graph->GetIntConstant(0);
685 HIntConstant* constant1 = graph->GetIntConstant(1);
686 HEqual* equal = new (&allocator) HEqual(constant0, constant0);
687 first_block->AddInstruction(equal);
688 first_block->AddInstruction(new (&allocator) HIf(equal));
689
690 HBasicBlock* then_block = new (&allocator) HBasicBlock(graph);
691 HBasicBlock* else_block = new (&allocator) HBasicBlock(graph);
Alexandre Rames92730742014-10-01 12:55:56 +0100692 HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
Alexandre Rames92730742014-10-01 12:55:56 +0100693 graph->SetExitBlock(exit_block);
694
David Brazdil58282f42016-01-14 12:45:10 +0000695 graph->AddBlock(then_block);
696 graph->AddBlock(else_block);
697 graph->AddBlock(exit_block);
698 first_block->AddSuccessor(then_block);
699 first_block->AddSuccessor(else_block);
700 then_block->AddSuccessor(exit_block);
701 else_block->AddSuccessor(exit_block);
702
703 exit_block->AddInstruction(new (&allocator) HExit());
704 then_block->AddInstruction(new (&allocator) HReturn(constant0));
705 else_block->AddInstruction(new (&allocator) HReturn(constant1));
706
David Brazdilb11b0722016-01-28 16:22:40 +0000707 ASSERT_FALSE(equal->IsEmittedAtUseSite());
David Brazdilbadd8262016-02-02 16:28:56 +0000708 graph->BuildDominatorTree();
David Brazdil58282f42016-01-14 12:45:10 +0000709 PrepareForRegisterAllocation(graph).Run();
David Brazdilb11b0722016-01-28 16:22:40 +0000710 ASSERT_TRUE(equal->IsEmittedAtUseSite());
Alexandre Rames92730742014-10-01 12:55:56 +0100711
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800712 auto hook_before_codegen = [](HGraph* graph_in) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100713 HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800714 HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
Alexandre Rames92730742014-10-01 12:55:56 +0100715 block->InsertInstructionBefore(move, block->GetLastInstruction());
716 };
717
David Brazdil58282f42016-01-14 12:45:10 +0000718 RunCode(target_isa, graph, hook_before_codegen, true, 0);
Alexandre Rames92730742014-10-01 12:55:56 +0100719 }
720}
721
David Brazdil58282f42016-01-14 12:45:10 +0000722TEST_F(CodegenTest, MaterializedCondition1) {
723 for (InstructionSet target_isa : GetTargetISAs()) {
724 // Check that condition are materialized correctly. A materialized condition
725 // should yield `1` if it evaluated to true, and `0` otherwise.
726 // We force the materialization of comparisons for different combinations of
Alexandre Rames92730742014-10-01 12:55:56 +0100727
David Brazdil58282f42016-01-14 12:45:10 +0000728 // inputs and check the results.
Alexandre Rames92730742014-10-01 12:55:56 +0100729
David Brazdil58282f42016-01-14 12:45:10 +0000730 int lhs[] = {1, 2, -1, 2, 0xabc};
731 int rhs[] = {2, 1, 2, -1, 0xabc};
Alexandre Rames92730742014-10-01 12:55:56 +0100732
David Brazdil58282f42016-01-14 12:45:10 +0000733 for (size_t i = 0; i < arraysize(lhs); i++) {
734 ArenaPool pool;
735 ArenaAllocator allocator(&pool);
736 HGraph* graph = CreateGraph(&allocator);
Alexandre Rames92730742014-10-01 12:55:56 +0100737
David Brazdil58282f42016-01-14 12:45:10 +0000738 HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
739 graph->AddBlock(entry_block);
740 graph->SetEntryBlock(entry_block);
741 entry_block->AddInstruction(new (&allocator) HGoto());
742 HBasicBlock* code_block = new (&allocator) HBasicBlock(graph);
743 graph->AddBlock(code_block);
744 HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
745 graph->AddBlock(exit_block);
746 exit_block->AddInstruction(new (&allocator) HExit());
Alexandre Rames92730742014-10-01 12:55:56 +0100747
David Brazdil58282f42016-01-14 12:45:10 +0000748 entry_block->AddSuccessor(code_block);
749 code_block->AddSuccessor(exit_block);
750 graph->SetExitBlock(exit_block);
Alexandre Rames92730742014-10-01 12:55:56 +0100751
David Brazdil58282f42016-01-14 12:45:10 +0000752 HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
753 HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
754 HLessThan cmp_lt(cst_lhs, cst_rhs);
755 code_block->AddInstruction(&cmp_lt);
756 HReturn ret(&cmp_lt);
757 code_block->AddInstruction(&ret);
Alexandre Rames92730742014-10-01 12:55:56 +0100758
David Brazdilbadd8262016-02-02 16:28:56 +0000759 graph->BuildDominatorTree();
David Brazdil58282f42016-01-14 12:45:10 +0000760 auto hook_before_codegen = [](HGraph* graph_in) {
761 HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
762 HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
763 block->InsertInstructionBefore(move, block->GetLastInstruction());
764 };
765 RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
766 }
Alexandre Rames92730742014-10-01 12:55:56 +0100767 }
768}
Calin Juravle34bacdf2014-10-07 20:23:36 +0100769
David Brazdil58282f42016-01-14 12:45:10 +0000770TEST_F(CodegenTest, MaterializedCondition2) {
771 for (InstructionSet target_isa : GetTargetISAs()) {
772 // Check that HIf correctly interprets a materialized condition.
773 // We force the materialization of comparisons for different combinations of
774 // inputs. An HIf takes the materialized combination as input and returns a
775 // value that we verify.
776
777 int lhs[] = {1, 2, -1, 2, 0xabc};
778 int rhs[] = {2, 1, 2, -1, 0xabc};
779
780
781 for (size_t i = 0; i < arraysize(lhs); i++) {
782 ArenaPool pool;
783 ArenaAllocator allocator(&pool);
784 HGraph* graph = CreateGraph(&allocator);
785
786 HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
787 graph->AddBlock(entry_block);
788 graph->SetEntryBlock(entry_block);
789 entry_block->AddInstruction(new (&allocator) HGoto());
790
791 HBasicBlock* if_block = new (&allocator) HBasicBlock(graph);
792 graph->AddBlock(if_block);
793 HBasicBlock* if_true_block = new (&allocator) HBasicBlock(graph);
794 graph->AddBlock(if_true_block);
795 HBasicBlock* if_false_block = new (&allocator) HBasicBlock(graph);
796 graph->AddBlock(if_false_block);
797 HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
798 graph->AddBlock(exit_block);
799 exit_block->AddInstruction(new (&allocator) HExit());
800
801 graph->SetEntryBlock(entry_block);
802 entry_block->AddSuccessor(if_block);
803 if_block->AddSuccessor(if_true_block);
804 if_block->AddSuccessor(if_false_block);
805 if_true_block->AddSuccessor(exit_block);
806 if_false_block->AddSuccessor(exit_block);
807 graph->SetExitBlock(exit_block);
808
809 HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
810 HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
811 HLessThan cmp_lt(cst_lhs, cst_rhs);
812 if_block->AddInstruction(&cmp_lt);
David Brazdil6e332522016-02-02 16:15:27 +0000813 // We insert a dummy instruction to separate the HIf from the HLessThan
814 // and force the materialization of the condition.
815 HMemoryBarrier force_materialization(MemBarrierKind::kAnyAny, 0);
David Brazdil58282f42016-01-14 12:45:10 +0000816 if_block->AddInstruction(&force_materialization);
817 HIf if_lt(&cmp_lt);
818 if_block->AddInstruction(&if_lt);
819
820 HIntConstant* cst_lt = graph->GetIntConstant(1);
821 HReturn ret_lt(cst_lt);
822 if_true_block->AddInstruction(&ret_lt);
823 HIntConstant* cst_ge = graph->GetIntConstant(0);
824 HReturn ret_ge(cst_ge);
825 if_false_block->AddInstruction(&ret_ge);
826
David Brazdilbadd8262016-02-02 16:28:56 +0000827 graph->BuildDominatorTree();
David Brazdil58282f42016-01-14 12:45:10 +0000828 auto hook_before_codegen = [](HGraph* graph_in) {
829 HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
830 HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
831 block->InsertInstructionBefore(move, block->GetLastInstruction());
832 };
833 RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
834 }
835 }
836}
837
838TEST_F(CodegenTest, ReturnDivIntLit8) {
Calin Juravled0d48522014-11-04 16:40:20 +0000839 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
840 Instruction::CONST_4 | 4 << 12 | 0 << 8,
841 Instruction::DIV_INT_LIT8, 3 << 8 | 0,
842 Instruction::RETURN);
843
David Brazdil58282f42016-01-14 12:45:10 +0000844 TestCode(data, true, 1);
Calin Juravled0d48522014-11-04 16:40:20 +0000845}
846
David Brazdil58282f42016-01-14 12:45:10 +0000847TEST_F(CodegenTest, ReturnDivInt2Addr) {
Calin Juravle865fc882014-11-06 17:09:03 +0000848 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
849 Instruction::CONST_4 | 4 << 12 | 0,
850 Instruction::CONST_4 | 2 << 12 | 1 << 8,
851 Instruction::DIV_INT_2ADDR | 1 << 12,
852 Instruction::RETURN);
853
David Brazdil58282f42016-01-14 12:45:10 +0000854 TestCode(data, true, 2);
Calin Juravle865fc882014-11-06 17:09:03 +0000855}
856
Aart Bike9f37602015-10-09 11:15:55 -0700857// Helper method.
Phil Wang751beff2015-08-28 15:17:15 +0800858static void TestComparison(IfCondition condition,
859 int64_t i,
860 int64_t j,
861 Primitive::Type type,
862 const InstructionSet target_isa) {
Aart Bike9f37602015-10-09 11:15:55 -0700863 ArenaPool pool;
864 ArenaAllocator allocator(&pool);
865 HGraph* graph = CreateGraph(&allocator);
866
867 HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph);
868 graph->AddBlock(entry_block);
869 graph->SetEntryBlock(entry_block);
870 entry_block->AddInstruction(new (&allocator) HGoto());
871
872 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
873 graph->AddBlock(block);
874
875 HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph);
876 graph->AddBlock(exit_block);
877 graph->SetExitBlock(exit_block);
878 exit_block->AddInstruction(new (&allocator) HExit());
879
880 entry_block->AddSuccessor(block);
881 block->AddSuccessor(exit_block);
882
883 HInstruction* op1;
884 HInstruction* op2;
885 if (type == Primitive::kPrimInt) {
886 op1 = graph->GetIntConstant(i);
887 op2 = graph->GetIntConstant(j);
888 } else {
889 DCHECK_EQ(type, Primitive::kPrimLong);
890 op1 = graph->GetLongConstant(i);
891 op2 = graph->GetLongConstant(j);
892 }
893
894 HInstruction* comparison = nullptr;
895 bool expected_result = false;
896 const uint64_t x = i;
897 const uint64_t y = j;
898 switch (condition) {
899 case kCondEQ:
900 comparison = new (&allocator) HEqual(op1, op2);
901 expected_result = (i == j);
902 break;
903 case kCondNE:
904 comparison = new (&allocator) HNotEqual(op1, op2);
905 expected_result = (i != j);
906 break;
907 case kCondLT:
908 comparison = new (&allocator) HLessThan(op1, op2);
909 expected_result = (i < j);
910 break;
911 case kCondLE:
912 comparison = new (&allocator) HLessThanOrEqual(op1, op2);
913 expected_result = (i <= j);
914 break;
915 case kCondGT:
916 comparison = new (&allocator) HGreaterThan(op1, op2);
917 expected_result = (i > j);
918 break;
919 case kCondGE:
920 comparison = new (&allocator) HGreaterThanOrEqual(op1, op2);
921 expected_result = (i >= j);
922 break;
923 case kCondB:
924 comparison = new (&allocator) HBelow(op1, op2);
925 expected_result = (x < y);
926 break;
927 case kCondBE:
928 comparison = new (&allocator) HBelowOrEqual(op1, op2);
929 expected_result = (x <= y);
930 break;
931 case kCondA:
932 comparison = new (&allocator) HAbove(op1, op2);
933 expected_result = (x > y);
934 break;
935 case kCondAE:
936 comparison = new (&allocator) HAboveOrEqual(op1, op2);
937 expected_result = (x >= y);
938 break;
939 }
940 block->AddInstruction(comparison);
941 block->AddInstruction(new (&allocator) HReturn(comparison));
942
David Brazdilbadd8262016-02-02 16:28:56 +0000943 graph->BuildDominatorTree();
David Brazdil58282f42016-01-14 12:45:10 +0000944 RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result);
Aart Bike9f37602015-10-09 11:15:55 -0700945}
946
David Brazdil58282f42016-01-14 12:45:10 +0000947TEST_F(CodegenTest, ComparisonsInt) {
948 for (InstructionSet target_isa : GetTargetISAs()) {
949 for (int64_t i = -1; i <= 1; i++) {
950 for (int64_t j = -1; j <= 1; j++) {
951 TestComparison(kCondEQ, i, j, Primitive::kPrimInt, target_isa);
952 TestComparison(kCondNE, i, j, Primitive::kPrimInt, target_isa);
953 TestComparison(kCondLT, i, j, Primitive::kPrimInt, target_isa);
954 TestComparison(kCondLE, i, j, Primitive::kPrimInt, target_isa);
955 TestComparison(kCondGT, i, j, Primitive::kPrimInt, target_isa);
956 TestComparison(kCondGE, i, j, Primitive::kPrimInt, target_isa);
957 TestComparison(kCondB, i, j, Primitive::kPrimInt, target_isa);
958 TestComparison(kCondBE, i, j, Primitive::kPrimInt, target_isa);
959 TestComparison(kCondA, i, j, Primitive::kPrimInt, target_isa);
960 TestComparison(kCondAE, i, j, Primitive::kPrimInt, target_isa);
961 }
Aart Bike9f37602015-10-09 11:15:55 -0700962 }
963 }
964}
965
David Brazdil58282f42016-01-14 12:45:10 +0000966TEST_F(CodegenTest, ComparisonsLong) {
Aart Bike9f37602015-10-09 11:15:55 -0700967 // TODO: make MIPS work for long
968 if (kRuntimeISA == kMips || kRuntimeISA == kMips64) {
969 return;
970 }
971
David Brazdil58282f42016-01-14 12:45:10 +0000972 for (InstructionSet target_isa : GetTargetISAs()) {
973 if (target_isa == kMips || target_isa == kMips64) {
974 continue;
975 }
Phil Wang751beff2015-08-28 15:17:15 +0800976
David Brazdil58282f42016-01-14 12:45:10 +0000977 for (int64_t i = -1; i <= 1; i++) {
978 for (int64_t j = -1; j <= 1; j++) {
979 TestComparison(kCondEQ, i, j, Primitive::kPrimLong, target_isa);
980 TestComparison(kCondNE, i, j, Primitive::kPrimLong, target_isa);
981 TestComparison(kCondLT, i, j, Primitive::kPrimLong, target_isa);
982 TestComparison(kCondLE, i, j, Primitive::kPrimLong, target_isa);
983 TestComparison(kCondGT, i, j, Primitive::kPrimLong, target_isa);
984 TestComparison(kCondGE, i, j, Primitive::kPrimLong, target_isa);
985 TestComparison(kCondB, i, j, Primitive::kPrimLong, target_isa);
986 TestComparison(kCondBE, i, j, Primitive::kPrimLong, target_isa);
987 TestComparison(kCondA, i, j, Primitive::kPrimLong, target_isa);
988 TestComparison(kCondAE, i, j, Primitive::kPrimLong, target_isa);
989 }
Aart Bike9f37602015-10-09 11:15:55 -0700990 }
991 }
992}
993
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000994} // namespace art