1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <functional>
18*795d594fSAndroid Build Coastguard Worker #include <memory>
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
22*795d594fSAndroid Build Coastguard Worker #include "builder.h"
23*795d594fSAndroid Build Coastguard Worker #include "codegen_test_utils.h"
24*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction.h"
26*795d594fSAndroid Build Coastguard Worker #include "driver/compiler_options.h"
27*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
28*795d594fSAndroid Build Coastguard Worker #include "optimizing_unit_test.h"
29*795d594fSAndroid Build Coastguard Worker #include "register_allocator_linear_scan.h"
30*795d594fSAndroid Build Coastguard Worker #include "utils/arm/assembler_arm_vixl.h"
31*795d594fSAndroid Build Coastguard Worker #include "utils/arm/managed_register_arm.h"
32*795d594fSAndroid Build Coastguard Worker #include "utils/x86/managed_register_x86.h"
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker // Return all combinations of ISA and code generator that are executable on
39*795d594fSAndroid Build Coastguard Worker // hardware, or on simulator, and that we'd like to test.
GetTargetConfigs()40*795d594fSAndroid Build Coastguard Worker static ::std::vector<CodegenTargetConfig> GetTargetConfigs() {
41*795d594fSAndroid Build Coastguard Worker ::std::vector<CodegenTargetConfig> v;
42*795d594fSAndroid Build Coastguard Worker ::std::vector<CodegenTargetConfig> test_config_candidates = {
43*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
44*795d594fSAndroid Build Coastguard Worker // TODO: Should't this be `kThumb2` instead of `kArm` here?
45*795d594fSAndroid Build Coastguard Worker CodegenTargetConfig(InstructionSet::kArm, create_codegen_arm_vixl32),
46*795d594fSAndroid Build Coastguard Worker #endif
47*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
48*795d594fSAndroid Build Coastguard Worker CodegenTargetConfig(InstructionSet::kArm64, create_codegen_arm64),
49*795d594fSAndroid Build Coastguard Worker #endif
50*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
51*795d594fSAndroid Build Coastguard Worker CodegenTargetConfig(InstructionSet::kX86, create_codegen_x86),
52*795d594fSAndroid Build Coastguard Worker #endif
53*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
54*795d594fSAndroid Build Coastguard Worker CodegenTargetConfig(InstructionSet::kX86_64, create_codegen_x86_64),
55*795d594fSAndroid Build Coastguard Worker #endif
56*795d594fSAndroid Build Coastguard Worker };
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Worker for (const CodegenTargetConfig& test_config : test_config_candidates) {
59*795d594fSAndroid Build Coastguard Worker if (CanExecuteISA(test_config.GetInstructionSet())) {
60*795d594fSAndroid Build Coastguard Worker v.push_back(test_config);
61*795d594fSAndroid Build Coastguard Worker }
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
64*795d594fSAndroid Build Coastguard Worker return v;
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker class CodegenTest : public CommonCompilerTest, public OptimizingUnitTestHelper {
68*795d594fSAndroid Build Coastguard Worker protected:
69*795d594fSAndroid Build Coastguard Worker void TestCode(const std::vector<uint16_t>& data, bool has_result = false, int32_t expected = 0);
70*795d594fSAndroid Build Coastguard Worker void TestCodeLong(const std::vector<uint16_t>& data, bool has_result, int64_t expected);
71*795d594fSAndroid Build Coastguard Worker void TestComparison(IfCondition condition,
72*795d594fSAndroid Build Coastguard Worker int64_t i,
73*795d594fSAndroid Build Coastguard Worker int64_t j,
74*795d594fSAndroid Build Coastguard Worker DataType::Type type,
75*795d594fSAndroid Build Coastguard Worker const CodegenTargetConfig target_config);
76*795d594fSAndroid Build Coastguard Worker void TestPackedSwitch(const CodegenTargetConfig target_config);
77*795d594fSAndroid Build Coastguard Worker void TestVectorComparison(IfCondition condition,
78*795d594fSAndroid Build Coastguard Worker int64_t lhs_value,
79*795d594fSAndroid Build Coastguard Worker int64_t rhs_value,
80*795d594fSAndroid Build Coastguard Worker DataType::Type type,
81*795d594fSAndroid Build Coastguard Worker CodeGenerator* codegen);
82*795d594fSAndroid Build Coastguard Worker };
83*795d594fSAndroid Build Coastguard Worker
TestCode(const std::vector<uint16_t> & data,bool has_result,int32_t expected)84*795d594fSAndroid Build Coastguard Worker void CodegenTest::TestCode(const std::vector<uint16_t>& data, bool has_result, int32_t expected) {
85*795d594fSAndroid Build Coastguard Worker for (const CodegenTargetConfig& target_config : GetTargetConfigs()) {
86*795d594fSAndroid Build Coastguard Worker ResetPoolAndAllocator();
87*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateCFG(data);
88*795d594fSAndroid Build Coastguard Worker // Remove suspend checks, they cannot be executed in this context.
89*795d594fSAndroid Build Coastguard Worker RemoveSuspendChecks(graph);
90*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
91*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
92*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, has_result, expected);
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker
TestCodeLong(const std::vector<uint16_t> & data,bool has_result,int64_t expected)96*795d594fSAndroid Build Coastguard Worker void CodegenTest::TestCodeLong(const std::vector<uint16_t>& data,
97*795d594fSAndroid Build Coastguard Worker bool has_result, int64_t expected) {
98*795d594fSAndroid Build Coastguard Worker for (const CodegenTargetConfig& target_config : GetTargetConfigs()) {
99*795d594fSAndroid Build Coastguard Worker ResetPoolAndAllocator();
100*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateCFG(data, DataType::Type::kInt64);
101*795d594fSAndroid Build Coastguard Worker // Remove suspend checks, they cannot be executed in this context.
102*795d594fSAndroid Build Coastguard Worker RemoveSuspendChecks(graph);
103*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
104*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
105*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, has_result, expected);
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnVoid)109*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnVoid) {
110*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
111*795d594fSAndroid Build Coastguard Worker TestCode(data);
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,CFG1)114*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, CFG1) {
115*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
116*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
117*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker TestCode(data);
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,CFG2)122*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, CFG2) {
123*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
124*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
125*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
126*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker TestCode(data);
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,CFG3)131*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, CFG3) {
132*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data1 = ZERO_REGISTER_CODE_ITEM(
133*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x200,
134*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID,
135*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFF00);
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker TestCode(data1);
138*795d594fSAndroid Build Coastguard Worker
139*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data2 = ZERO_REGISTER_CODE_ITEM(
140*795d594fSAndroid Build Coastguard Worker Instruction::GOTO_16, 3,
141*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID,
142*795d594fSAndroid Build Coastguard Worker Instruction::GOTO_16, 0xFFFF);
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker TestCode(data2);
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data3 = ZERO_REGISTER_CODE_ITEM(
147*795d594fSAndroid Build Coastguard Worker Instruction::GOTO_32, 4, 0,
148*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID,
149*795d594fSAndroid Build Coastguard Worker Instruction::GOTO_32, 0xFFFF, 0xFFFF);
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker TestCode(data3);
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,CFG4)154*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, CFG4) {
155*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ZERO_REGISTER_CODE_ITEM(
156*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID,
157*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
158*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFE00);
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker TestCode(data);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,CFG5)163*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, CFG5) {
164*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
165*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
166*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
167*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
168*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
169*795d594fSAndroid Build Coastguard Worker
170*795d594fSAndroid Build Coastguard Worker TestCode(data);
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,IntConstant)173*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, IntConstant) {
174*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
175*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
176*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
177*795d594fSAndroid Build Coastguard Worker
178*795d594fSAndroid Build Coastguard Worker TestCode(data);
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,Return1)181*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, Return1) {
182*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
183*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
184*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0);
185*795d594fSAndroid Build Coastguard Worker
186*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 0);
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,Return2)189*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, Return2) {
190*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
191*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
192*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 1 << 8,
193*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
194*795d594fSAndroid Build Coastguard Worker
195*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 0);
196*795d594fSAndroid Build Coastguard Worker }
197*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,Return3)198*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, Return3) {
199*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
200*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
201*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 1 << 12,
202*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
203*795d594fSAndroid Build Coastguard Worker
204*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 1);
205*795d594fSAndroid Build Coastguard Worker }
206*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnIf1)207*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnIf1) {
208*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
209*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
210*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 1 << 12,
211*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
212*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8,
213*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
214*795d594fSAndroid Build Coastguard Worker
215*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 1);
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnIf2)218*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnIf2) {
219*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
220*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
221*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 1 << 12,
222*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
223*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8,
224*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
225*795d594fSAndroid Build Coastguard Worker
226*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 0);
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker
229*795d594fSAndroid Build Coastguard Worker // Exercise bit-wise (one's complement) not-int instruction.
230*795d594fSAndroid Build Coastguard Worker #define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
231*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, TEST_NAME) { \
232*795d594fSAndroid Build Coastguard Worker const int32_t input = INPUT; \
233*795d594fSAndroid Build Coastguard Worker const uint16_t input_lo = Low16Bits(input); \
234*795d594fSAndroid Build Coastguard Worker const uint16_t input_hi = High16Bits(input); \
235*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM( \
236*795d594fSAndroid Build Coastguard Worker Instruction::CONST | 0 << 8, input_lo, input_hi, \
237*795d594fSAndroid Build Coastguard Worker Instruction::NOT_INT | 1 << 8 | 0 << 12 , \
238*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8); \
239*795d594fSAndroid Build Coastguard Worker \
240*795d594fSAndroid Build Coastguard Worker TestCode(data, true, EXPECTED_OUTPUT); \
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker
243*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntMinus2, -2, 1)
244*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntMinus1, -1, 0)
245*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotInt0, 0, -1)
246*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotInt1, 1, -2)
247*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647) // (2^31) - 1
248*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646) // (2^31) - 2
249*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1
250*795d594fSAndroid Build Coastguard Worker NOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648) // -(2^31)
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Worker #undef NOT_INT_TEST
253*795d594fSAndroid Build Coastguard Worker
254*795d594fSAndroid Build Coastguard Worker // Exercise bit-wise (one's complement) not-long instruction.
255*795d594fSAndroid Build Coastguard Worker #define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \
256*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, TEST_NAME) { \
257*795d594fSAndroid Build Coastguard Worker const int64_t input = INPUT; \
258*795d594fSAndroid Build Coastguard Worker const uint16_t word0 = Low16Bits(Low32Bits(input)); /* LSW. */ \
259*795d594fSAndroid Build Coastguard Worker const uint16_t word1 = High16Bits(Low32Bits(input)); \
260*795d594fSAndroid Build Coastguard Worker const uint16_t word2 = Low16Bits(High32Bits(input)); \
261*795d594fSAndroid Build Coastguard Worker const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */ \
262*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = FOUR_REGISTERS_CODE_ITEM( \
263*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, \
264*795d594fSAndroid Build Coastguard Worker Instruction::NOT_LONG | 2 << 8 | 0 << 12, \
265*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE | 2 << 8); \
266*795d594fSAndroid Build Coastguard Worker \
267*795d594fSAndroid Build Coastguard Worker TestCodeLong(data, true, EXPECTED_OUTPUT); \
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker
270*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1))
271*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0))
272*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1))
273*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2))
274*795d594fSAndroid Build Coastguard Worker
275*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT32_MIN,
276*795d594fSAndroid Build Coastguard Worker INT64_C(-2147483648),
277*795d594fSAndroid Build Coastguard Worker INT64_C(2147483647)) // (2^31) - 1
278*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT32_MINPlus1,
279*795d594fSAndroid Build Coastguard Worker INT64_C(-2147483647),
280*795d594fSAndroid Build Coastguard Worker INT64_C(2147483646)) // (2^31) - 2
281*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1,
282*795d594fSAndroid Build Coastguard Worker INT64_C(2147483646),
283*795d594fSAndroid Build Coastguard Worker INT64_C(-2147483647)) // -(2^31) - 1
284*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT32_MAX,
285*795d594fSAndroid Build Coastguard Worker INT64_C(2147483647),
286*795d594fSAndroid Build Coastguard Worker INT64_C(-2147483648)) // -(2^31)
287*795d594fSAndroid Build Coastguard Worker
288*795d594fSAndroid Build Coastguard Worker // Note that the C++ compiler won't accept
289*795d594fSAndroid Build Coastguard Worker // INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid
290*795d594fSAndroid Build Coastguard Worker // int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead.
291*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotINT64_MIN,
292*795d594fSAndroid Build Coastguard Worker INT64_C(-9223372036854775807)-1,
293*795d594fSAndroid Build Coastguard Worker INT64_C(9223372036854775807)); // (2^63) - 1
294*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotINT64_MINPlus1,
295*795d594fSAndroid Build Coastguard Worker INT64_C(-9223372036854775807),
296*795d594fSAndroid Build Coastguard Worker INT64_C(9223372036854775806)); // (2^63) - 2
297*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1,
298*795d594fSAndroid Build Coastguard Worker INT64_C(9223372036854775806),
299*795d594fSAndroid Build Coastguard Worker INT64_C(-9223372036854775807)); // -(2^63) - 1
300*795d594fSAndroid Build Coastguard Worker NOT_LONG_TEST(ReturnNotLongINT64_MAX,
301*795d594fSAndroid Build Coastguard Worker INT64_C(9223372036854775807),
302*795d594fSAndroid Build Coastguard Worker INT64_C(-9223372036854775807)-1); // -(2^63)
303*795d594fSAndroid Build Coastguard Worker
304*795d594fSAndroid Build Coastguard Worker #undef NOT_LONG_TEST
305*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,IntToLongOfLongToInt)306*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, IntToLongOfLongToInt) {
307*795d594fSAndroid Build Coastguard Worker const int64_t input = INT64_C(4294967296); // 2^32
308*795d594fSAndroid Build Coastguard Worker const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW.
309*795d594fSAndroid Build Coastguard Worker const uint16_t word1 = High16Bits(Low32Bits(input));
310*795d594fSAndroid Build Coastguard Worker const uint16_t word2 = Low16Bits(High32Bits(input));
311*795d594fSAndroid Build Coastguard Worker const uint16_t word3 = High16Bits(High32Bits(input)); // MSW.
312*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = FIVE_REGISTERS_CODE_ITEM(
313*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
314*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 2 << 8, 1, 0, 0, 0,
315*795d594fSAndroid Build Coastguard Worker Instruction::ADD_LONG | 0, 0 << 8 | 2, // v0 <- 2^32 + 1
316*795d594fSAndroid Build Coastguard Worker Instruction::LONG_TO_INT | 4 << 8 | 0 << 12,
317*795d594fSAndroid Build Coastguard Worker Instruction::INT_TO_LONG | 2 << 8 | 4 << 12,
318*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE | 2 << 8);
319*795d594fSAndroid Build Coastguard Worker
320*795d594fSAndroid Build Coastguard Worker TestCodeLong(data, true, 1);
321*795d594fSAndroid Build Coastguard Worker }
322*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnAdd1)323*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnAdd1) {
324*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
325*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 3 << 12 | 0,
326*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 1 << 8,
327*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT, 1 << 8 | 0,
328*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
329*795d594fSAndroid Build Coastguard Worker
330*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 7);
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnAdd2)333*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnAdd2) {
334*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
335*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 3 << 12 | 0,
336*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 1 << 8,
337*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_2ADDR | 1 << 12,
338*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
339*795d594fSAndroid Build Coastguard Worker
340*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 7);
341*795d594fSAndroid Build Coastguard Worker }
342*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnAdd3)343*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnAdd3) {
344*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
345*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0 << 8,
346*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT8, 3 << 8 | 0,
347*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
348*795d594fSAndroid Build Coastguard Worker
349*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 7);
350*795d594fSAndroid Build Coastguard Worker }
351*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnAdd4)352*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnAdd4) {
353*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
354*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0 << 8,
355*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT16, 3,
356*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
357*795d594fSAndroid Build Coastguard Worker
358*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 7);
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulInt)361*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulInt) {
362*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
363*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 3 << 12 | 0,
364*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 1 << 8,
365*795d594fSAndroid Build Coastguard Worker Instruction::MUL_INT, 1 << 8 | 0,
366*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
367*795d594fSAndroid Build Coastguard Worker
368*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 12);
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulInt2addr)371*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulInt2addr) {
372*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
373*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 3 << 12 | 0,
374*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 1 << 8,
375*795d594fSAndroid Build Coastguard Worker Instruction::MUL_INT_2ADDR | 1 << 12,
376*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
377*795d594fSAndroid Build Coastguard Worker
378*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 12);
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulLong)381*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulLong) {
382*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = FOUR_REGISTERS_CODE_ITEM(
383*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
384*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
385*795d594fSAndroid Build Coastguard Worker Instruction::MUL_LONG, 2 << 8 | 0,
386*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE);
387*795d594fSAndroid Build Coastguard Worker
388*795d594fSAndroid Build Coastguard Worker TestCodeLong(data, true, 12);
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulLong2addr)391*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulLong2addr) {
392*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = FOUR_REGISTERS_CODE_ITEM(
393*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 0 << 8, 3, 0, 0, 0,
394*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 2 << 8, 4, 0, 0, 0,
395*795d594fSAndroid Build Coastguard Worker Instruction::MUL_LONG_2ADDR | 2 << 12,
396*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE);
397*795d594fSAndroid Build Coastguard Worker
398*795d594fSAndroid Build Coastguard Worker TestCodeLong(data, true, 12);
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulIntLit8)401*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulIntLit8) {
402*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
403*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0 << 8,
404*795d594fSAndroid Build Coastguard Worker Instruction::MUL_INT_LIT8, 3 << 8 | 0,
405*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
406*795d594fSAndroid Build Coastguard Worker
407*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 12);
408*795d594fSAndroid Build Coastguard Worker }
409*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnMulIntLit16)410*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnMulIntLit16) {
411*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
412*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0 << 8,
413*795d594fSAndroid Build Coastguard Worker Instruction::MUL_INT_LIT16, 3,
414*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
415*795d594fSAndroid Build Coastguard Worker
416*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 12);
417*795d594fSAndroid Build Coastguard Worker }
418*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,NonMaterializedCondition)419*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, NonMaterializedCondition) {
420*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
421*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
422*795d594fSAndroid Build Coastguard Worker
423*795d594fSAndroid Build Coastguard Worker HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
424*795d594fSAndroid Build Coastguard Worker graph->AddBlock(entry);
425*795d594fSAndroid Build Coastguard Worker graph->SetEntryBlock(entry);
426*795d594fSAndroid Build Coastguard Worker MakeGoto(entry);
427*795d594fSAndroid Build Coastguard Worker
428*795d594fSAndroid Build Coastguard Worker HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph);
429*795d594fSAndroid Build Coastguard Worker graph->AddBlock(first_block);
430*795d594fSAndroid Build Coastguard Worker entry->AddSuccessor(first_block);
431*795d594fSAndroid Build Coastguard Worker HIntConstant* constant0 = graph->GetIntConstant(0);
432*795d594fSAndroid Build Coastguard Worker HIntConstant* constant1 = graph->GetIntConstant(1);
433*795d594fSAndroid Build Coastguard Worker HInstruction* equal = MakeCondition(first_block, kCondEQ, constant0, constant0);
434*795d594fSAndroid Build Coastguard Worker MakeIf(first_block, equal);
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker HBasicBlock* then_block = new (GetAllocator()) HBasicBlock(graph);
437*795d594fSAndroid Build Coastguard Worker HBasicBlock* else_block = new (GetAllocator()) HBasicBlock(graph);
438*795d594fSAndroid Build Coastguard Worker HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
439*795d594fSAndroid Build Coastguard Worker graph->SetExitBlock(exit_block);
440*795d594fSAndroid Build Coastguard Worker
441*795d594fSAndroid Build Coastguard Worker graph->AddBlock(then_block);
442*795d594fSAndroid Build Coastguard Worker graph->AddBlock(else_block);
443*795d594fSAndroid Build Coastguard Worker graph->AddBlock(exit_block);
444*795d594fSAndroid Build Coastguard Worker first_block->AddSuccessor(then_block);
445*795d594fSAndroid Build Coastguard Worker first_block->AddSuccessor(else_block);
446*795d594fSAndroid Build Coastguard Worker then_block->AddSuccessor(exit_block);
447*795d594fSAndroid Build Coastguard Worker else_block->AddSuccessor(exit_block);
448*795d594fSAndroid Build Coastguard Worker
449*795d594fSAndroid Build Coastguard Worker MakeExit(exit_block);
450*795d594fSAndroid Build Coastguard Worker MakeReturn(then_block, constant0);
451*795d594fSAndroid Build Coastguard Worker MakeReturn(else_block, constant1);
452*795d594fSAndroid Build Coastguard Worker
453*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(equal->IsEmittedAtUseSite());
454*795d594fSAndroid Build Coastguard Worker graph->BuildDominatorTree();
455*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
456*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
457*795d594fSAndroid Build Coastguard Worker PrepareForRegisterAllocation(graph, *compiler_options).Run();
458*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(equal->IsEmittedAtUseSite());
459*795d594fSAndroid Build Coastguard Worker
460*795d594fSAndroid Build Coastguard Worker auto hook_before_codegen = [](HGraph* graph_in) {
461*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
462*795d594fSAndroid Build Coastguard Worker HParallelMove* move = new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
463*795d594fSAndroid Build Coastguard Worker block->InsertInstructionBefore(move, block->GetLastInstruction());
464*795d594fSAndroid Build Coastguard Worker };
465*795d594fSAndroid Build Coastguard Worker
466*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, 0);
467*795d594fSAndroid Build Coastguard Worker }
468*795d594fSAndroid Build Coastguard Worker }
469*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,MaterializedCondition1)470*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, MaterializedCondition1) {
471*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
472*795d594fSAndroid Build Coastguard Worker // Check that condition are materialized correctly. A materialized condition
473*795d594fSAndroid Build Coastguard Worker // should yield `1` if it evaluated to true, and `0` otherwise.
474*795d594fSAndroid Build Coastguard Worker // We force the materialization of comparisons for different combinations of
475*795d594fSAndroid Build Coastguard Worker
476*795d594fSAndroid Build Coastguard Worker // inputs and check the results.
477*795d594fSAndroid Build Coastguard Worker
478*795d594fSAndroid Build Coastguard Worker int lhs[] = {1, 2, -1, 2, 0xabc};
479*795d594fSAndroid Build Coastguard Worker int rhs[] = {2, 1, 2, -1, 0xabc};
480*795d594fSAndroid Build Coastguard Worker
481*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(lhs); i++) {
482*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
483*795d594fSAndroid Build Coastguard Worker
484*795d594fSAndroid Build Coastguard Worker HBasicBlock* entry_block = new (GetAllocator()) HBasicBlock(graph);
485*795d594fSAndroid Build Coastguard Worker graph->AddBlock(entry_block);
486*795d594fSAndroid Build Coastguard Worker graph->SetEntryBlock(entry_block);
487*795d594fSAndroid Build Coastguard Worker MakeGoto(entry_block);
488*795d594fSAndroid Build Coastguard Worker HBasicBlock* code_block = new (GetAllocator()) HBasicBlock(graph);
489*795d594fSAndroid Build Coastguard Worker graph->AddBlock(code_block);
490*795d594fSAndroid Build Coastguard Worker HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
491*795d594fSAndroid Build Coastguard Worker graph->AddBlock(exit_block);
492*795d594fSAndroid Build Coastguard Worker MakeExit(exit_block);
493*795d594fSAndroid Build Coastguard Worker
494*795d594fSAndroid Build Coastguard Worker entry_block->AddSuccessor(code_block);
495*795d594fSAndroid Build Coastguard Worker code_block->AddSuccessor(exit_block);
496*795d594fSAndroid Build Coastguard Worker graph->SetExitBlock(exit_block);
497*795d594fSAndroid Build Coastguard Worker
498*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
499*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
500*795d594fSAndroid Build Coastguard Worker HInstruction* cmp_lt = MakeCondition(code_block, kCondLT, cst_lhs, cst_rhs);
501*795d594fSAndroid Build Coastguard Worker MakeReturn(code_block, cmp_lt);
502*795d594fSAndroid Build Coastguard Worker
503*795d594fSAndroid Build Coastguard Worker graph->BuildDominatorTree();
504*795d594fSAndroid Build Coastguard Worker auto hook_before_codegen = [](HGraph* graph_in) {
505*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
506*795d594fSAndroid Build Coastguard Worker HParallelMove* move =
507*795d594fSAndroid Build Coastguard Worker new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
508*795d594fSAndroid Build Coastguard Worker block->InsertInstructionBefore(move, block->GetLastInstruction());
509*795d594fSAndroid Build Coastguard Worker };
510*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
511*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
512*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker }
515*795d594fSAndroid Build Coastguard Worker }
516*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,MaterializedCondition2)517*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, MaterializedCondition2) {
518*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
519*795d594fSAndroid Build Coastguard Worker // Check that HIf correctly interprets a materialized condition.
520*795d594fSAndroid Build Coastguard Worker // We force the materialization of comparisons for different combinations of
521*795d594fSAndroid Build Coastguard Worker // inputs. An HIf takes the materialized combination as input and returns a
522*795d594fSAndroid Build Coastguard Worker // value that we verify.
523*795d594fSAndroid Build Coastguard Worker
524*795d594fSAndroid Build Coastguard Worker int lhs[] = {1, 2, -1, 2, 0xabc};
525*795d594fSAndroid Build Coastguard Worker int rhs[] = {2, 1, 2, -1, 0xabc};
526*795d594fSAndroid Build Coastguard Worker
527*795d594fSAndroid Build Coastguard Worker
528*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(lhs); i++) {
529*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
530*795d594fSAndroid Build Coastguard Worker
531*795d594fSAndroid Build Coastguard Worker HBasicBlock* entry_block = new (GetAllocator()) HBasicBlock(graph);
532*795d594fSAndroid Build Coastguard Worker graph->AddBlock(entry_block);
533*795d594fSAndroid Build Coastguard Worker graph->SetEntryBlock(entry_block);
534*795d594fSAndroid Build Coastguard Worker MakeGoto(entry_block);
535*795d594fSAndroid Build Coastguard Worker
536*795d594fSAndroid Build Coastguard Worker HBasicBlock* if_block = new (GetAllocator()) HBasicBlock(graph);
537*795d594fSAndroid Build Coastguard Worker graph->AddBlock(if_block);
538*795d594fSAndroid Build Coastguard Worker HBasicBlock* if_true_block = new (GetAllocator()) HBasicBlock(graph);
539*795d594fSAndroid Build Coastguard Worker graph->AddBlock(if_true_block);
540*795d594fSAndroid Build Coastguard Worker HBasicBlock* if_false_block = new (GetAllocator()) HBasicBlock(graph);
541*795d594fSAndroid Build Coastguard Worker graph->AddBlock(if_false_block);
542*795d594fSAndroid Build Coastguard Worker HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
543*795d594fSAndroid Build Coastguard Worker graph->AddBlock(exit_block);
544*795d594fSAndroid Build Coastguard Worker MakeExit(exit_block);
545*795d594fSAndroid Build Coastguard Worker
546*795d594fSAndroid Build Coastguard Worker graph->SetEntryBlock(entry_block);
547*795d594fSAndroid Build Coastguard Worker entry_block->AddSuccessor(if_block);
548*795d594fSAndroid Build Coastguard Worker if_block->AddSuccessor(if_true_block);
549*795d594fSAndroid Build Coastguard Worker if_block->AddSuccessor(if_false_block);
550*795d594fSAndroid Build Coastguard Worker if_true_block->AddSuccessor(exit_block);
551*795d594fSAndroid Build Coastguard Worker if_false_block->AddSuccessor(exit_block);
552*795d594fSAndroid Build Coastguard Worker graph->SetExitBlock(exit_block);
553*795d594fSAndroid Build Coastguard Worker
554*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]);
555*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
556*795d594fSAndroid Build Coastguard Worker HInstruction* cmp_lt = MakeCondition(if_block, kCondLT, cst_lhs, cst_rhs);
557*795d594fSAndroid Build Coastguard Worker // We insert a fake instruction to separate the HIf from the HLessThan
558*795d594fSAndroid Build Coastguard Worker // and force the materialization of the condition.
559*795d594fSAndroid Build Coastguard Worker HInstruction* force_materialization =
560*795d594fSAndroid Build Coastguard Worker new (GetAllocator()) HMemoryBarrier(MemBarrierKind::kAnyAny, 0);
561*795d594fSAndroid Build Coastguard Worker if_block->AddInstruction(force_materialization);
562*795d594fSAndroid Build Coastguard Worker MakeIf(if_block, cmp_lt);
563*795d594fSAndroid Build Coastguard Worker
564*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_lt = graph->GetIntConstant(1);
565*795d594fSAndroid Build Coastguard Worker MakeReturn(if_true_block, cst_lt);
566*795d594fSAndroid Build Coastguard Worker HIntConstant* cst_ge = graph->GetIntConstant(0);
567*795d594fSAndroid Build Coastguard Worker MakeReturn(if_false_block, cst_ge);
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker graph->BuildDominatorTree();
570*795d594fSAndroid Build Coastguard Worker auto hook_before_codegen = [](HGraph* graph_in) {
571*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
572*795d594fSAndroid Build Coastguard Worker HParallelMove* move =
573*795d594fSAndroid Build Coastguard Worker new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
574*795d594fSAndroid Build Coastguard Worker block->InsertInstructionBefore(move, block->GetLastInstruction());
575*795d594fSAndroid Build Coastguard Worker };
576*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
577*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
578*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
579*795d594fSAndroid Build Coastguard Worker }
580*795d594fSAndroid Build Coastguard Worker }
581*795d594fSAndroid Build Coastguard Worker }
582*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnDivIntLit8)583*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnDivIntLit8) {
584*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
585*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0 << 8,
586*795d594fSAndroid Build Coastguard Worker Instruction::DIV_INT_LIT8, 3 << 8 | 0,
587*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
588*795d594fSAndroid Build Coastguard Worker
589*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 1);
590*795d594fSAndroid Build Coastguard Worker }
591*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ReturnDivInt2Addr)592*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ReturnDivInt2Addr) {
593*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
594*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
595*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 2 << 12 | 1 << 8,
596*795d594fSAndroid Build Coastguard Worker Instruction::DIV_INT_2ADDR | 1 << 12,
597*795d594fSAndroid Build Coastguard Worker Instruction::RETURN);
598*795d594fSAndroid Build Coastguard Worker
599*795d594fSAndroid Build Coastguard Worker TestCode(data, true, 2);
600*795d594fSAndroid Build Coastguard Worker }
601*795d594fSAndroid Build Coastguard Worker
GetExpectedResultFromComparison(IfCondition condition,int64_t lhs,int64_t rhs)602*795d594fSAndroid Build Coastguard Worker static bool GetExpectedResultFromComparison(IfCondition condition, int64_t lhs, int64_t rhs) {
603*795d594fSAndroid Build Coastguard Worker const uint64_t unsigned_lhs = lhs;
604*795d594fSAndroid Build Coastguard Worker const uint64_t unsigned_rhs = rhs;
605*795d594fSAndroid Build Coastguard Worker switch (condition) {
606*795d594fSAndroid Build Coastguard Worker case kCondEQ:
607*795d594fSAndroid Build Coastguard Worker return lhs == rhs;
608*795d594fSAndroid Build Coastguard Worker case kCondNE:
609*795d594fSAndroid Build Coastguard Worker return lhs != rhs;
610*795d594fSAndroid Build Coastguard Worker case kCondLT:
611*795d594fSAndroid Build Coastguard Worker return lhs < rhs;
612*795d594fSAndroid Build Coastguard Worker case kCondLE:
613*795d594fSAndroid Build Coastguard Worker return lhs <= rhs;
614*795d594fSAndroid Build Coastguard Worker case kCondGT:
615*795d594fSAndroid Build Coastguard Worker return lhs > rhs;
616*795d594fSAndroid Build Coastguard Worker case kCondGE:
617*795d594fSAndroid Build Coastguard Worker return lhs >= rhs;
618*795d594fSAndroid Build Coastguard Worker case kCondB:
619*795d594fSAndroid Build Coastguard Worker return unsigned_lhs < unsigned_rhs;
620*795d594fSAndroid Build Coastguard Worker case kCondBE:
621*795d594fSAndroid Build Coastguard Worker return unsigned_lhs <= unsigned_rhs;
622*795d594fSAndroid Build Coastguard Worker case kCondA:
623*795d594fSAndroid Build Coastguard Worker return unsigned_lhs > unsigned_rhs;
624*795d594fSAndroid Build Coastguard Worker case kCondAE:
625*795d594fSAndroid Build Coastguard Worker return unsigned_lhs >= unsigned_rhs;
626*795d594fSAndroid Build Coastguard Worker }
627*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Condition '" << enum_cast<uint32_t>(condition) << "' not supported: ";
628*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
629*795d594fSAndroid Build Coastguard Worker }
630*795d594fSAndroid Build Coastguard Worker
631*795d594fSAndroid Build Coastguard Worker // Helper method.
TestComparison(IfCondition condition,int64_t i,int64_t j,DataType::Type type,const CodegenTargetConfig target_config)632*795d594fSAndroid Build Coastguard Worker void CodegenTest::TestComparison(IfCondition condition,
633*795d594fSAndroid Build Coastguard Worker int64_t i,
634*795d594fSAndroid Build Coastguard Worker int64_t j,
635*795d594fSAndroid Build Coastguard Worker DataType::Type type,
636*795d594fSAndroid Build Coastguard Worker const CodegenTargetConfig target_config) {
637*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = InitEntryMainExitGraph();
638*795d594fSAndroid Build Coastguard Worker
639*795d594fSAndroid Build Coastguard Worker HInstruction* op1;
640*795d594fSAndroid Build Coastguard Worker HInstruction* op2;
641*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
642*795d594fSAndroid Build Coastguard Worker op1 = graph_->GetIntConstant(i);
643*795d594fSAndroid Build Coastguard Worker op2 = graph_->GetIntConstant(j);
644*795d594fSAndroid Build Coastguard Worker } else {
645*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kInt64);
646*795d594fSAndroid Build Coastguard Worker op1 = graph_->GetLongConstant(i);
647*795d594fSAndroid Build Coastguard Worker op2 = graph_->GetLongConstant(j);
648*795d594fSAndroid Build Coastguard Worker }
649*795d594fSAndroid Build Coastguard Worker
650*795d594fSAndroid Build Coastguard Worker HInstruction* comparison = MakeCondition(block, condition, op1, op2);
651*795d594fSAndroid Build Coastguard Worker MakeReturn(block, comparison);
652*795d594fSAndroid Build Coastguard Worker
653*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
654*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
655*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
656*795d594fSAndroid Build Coastguard Worker bool expected_result = GetExpectedResultFromComparison(condition, i, j);
657*795d594fSAndroid Build Coastguard Worker RunCode(target_config, *compiler_options, graph_, [](HGraph*) {}, true, expected_result);
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ComparisonsInt)660*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ComparisonsInt) {
661*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
662*795d594fSAndroid Build Coastguard Worker for (int64_t i = -1; i <= 1; i++) {
663*795d594fSAndroid Build Coastguard Worker for (int64_t j = -1; j <= 1; j++) {
664*795d594fSAndroid Build Coastguard Worker for (int cond = kCondFirst; cond <= kCondLast; cond++) {
665*795d594fSAndroid Build Coastguard Worker TestComparison(
666*795d594fSAndroid Build Coastguard Worker static_cast<IfCondition>(cond), i, j, DataType::Type::kInt32, target_config);
667*795d594fSAndroid Build Coastguard Worker }
668*795d594fSAndroid Build Coastguard Worker }
669*795d594fSAndroid Build Coastguard Worker }
670*795d594fSAndroid Build Coastguard Worker }
671*795d594fSAndroid Build Coastguard Worker }
672*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ComparisonsLong)673*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ComparisonsLong) {
674*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
675*795d594fSAndroid Build Coastguard Worker for (int64_t i = -1; i <= 1; i++) {
676*795d594fSAndroid Build Coastguard Worker for (int64_t j = -1; j <= 1; j++) {
677*795d594fSAndroid Build Coastguard Worker for (int cond = kCondFirst; cond <= kCondLast; cond++) {
678*795d594fSAndroid Build Coastguard Worker TestComparison(
679*795d594fSAndroid Build Coastguard Worker static_cast<IfCondition>(cond), i, j, DataType::Type::kInt64, target_config);
680*795d594fSAndroid Build Coastguard Worker }
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker }
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker }
685*795d594fSAndroid Build Coastguard Worker
686*795d594fSAndroid Build Coastguard Worker // Tests a PackedSwitch in a very large HGraph; validates that the switch jump table is in
687*795d594fSAndroid Build Coastguard Worker // range for the PC-relative load in the codegen visitor.
TestPackedSwitch(const CodegenTargetConfig target_config)688*795d594fSAndroid Build Coastguard Worker void CodegenTest::TestPackedSwitch(const CodegenTargetConfig target_config) {
689*795d594fSAndroid Build Coastguard Worker HBasicBlock* return_block = InitEntryMainExitGraph();
690*795d594fSAndroid Build Coastguard Worker constexpr DataType::Type data_type = DataType::Type::kInt32;
691*795d594fSAndroid Build Coastguard Worker
692*795d594fSAndroid Build Coastguard Worker // A number of entries - we are interested to test jump table implementation.
693*795d594fSAndroid Build Coastguard Worker constexpr size_t kNumSwitchEntries = 10;
694*795d594fSAndroid Build Coastguard Worker
695*795d594fSAndroid Build Coastguard Worker // Number of jump targets (including a 'default' case).
696*795d594fSAndroid Build Coastguard Worker constexpr size_t kNumBB = kNumSwitchEntries + 1;
697*795d594fSAndroid Build Coastguard Worker // Some arbitrary value to be used as input.
698*795d594fSAndroid Build Coastguard Worker constexpr int kInputValue = kNumBB - 4;
699*795d594fSAndroid Build Coastguard Worker
700*795d594fSAndroid Build Coastguard Worker HInstruction* input = graph_->GetIntConstant(kInputValue);
701*795d594fSAndroid Build Coastguard Worker HIntConstant* constant_1 = graph_->GetIntConstant(1);
702*795d594fSAndroid Build Coastguard Worker
703*795d594fSAndroid Build Coastguard Worker HBasicBlock* switch_block = AddNewBlock();
704*795d594fSAndroid Build Coastguard Worker entry_block_->ReplaceSuccessor(return_block, switch_block);
705*795d594fSAndroid Build Coastguard Worker
706*795d594fSAndroid Build Coastguard Worker HPackedSwitch* hswitch = new (GetAllocator()) HPackedSwitch(0, kNumSwitchEntries, input);
707*795d594fSAndroid Build Coastguard Worker switch_block->AddInstruction(hswitch);
708*795d594fSAndroid Build Coastguard Worker
709*795d594fSAndroid Build Coastguard Worker std::vector<HInstruction*> phi_inputs {};
710*795d594fSAndroid Build Coastguard Worker
711*795d594fSAndroid Build Coastguard Worker // Add switch jump target blocks.
712*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < kNumBB; i++) {
713*795d594fSAndroid Build Coastguard Worker HBasicBlock* case_block = AddNewBlock();
714*795d594fSAndroid Build Coastguard Worker case_block->AddPredecessor(switch_block);
715*795d594fSAndroid Build Coastguard Worker case_block->AddSuccessor(return_block);
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker HIntConstant* case_value = graph_->GetIntConstant(i);
718*795d594fSAndroid Build Coastguard Worker HAdd* add = MakeBinOp<HAdd>(case_block, data_type, input, case_value);
719*795d594fSAndroid Build Coastguard Worker phi_inputs.emplace_back(add);
720*795d594fSAndroid Build Coastguard Worker
721*795d594fSAndroid Build Coastguard Worker MakeGoto(case_block);
722*795d594fSAndroid Build Coastguard Worker }
723*795d594fSAndroid Build Coastguard Worker
724*795d594fSAndroid Build Coastguard Worker HPhi* phi = MakePhi(return_block, phi_inputs);
725*795d594fSAndroid Build Coastguard Worker HInstruction* return_val = phi;
726*795d594fSAndroid Build Coastguard Worker
727*795d594fSAndroid Build Coastguard Worker // Emit a huge number of HAdds - to simulate a very large HGraph.
728*795d594fSAndroid Build Coastguard Worker constexpr int kNumOfAdds = 2 * 1024 * 1024;
729*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < kNumOfAdds; i++) {
730*795d594fSAndroid Build Coastguard Worker return_val = MakeBinOp<HAdd>(return_block, data_type, return_val, constant_1);
731*795d594fSAndroid Build Coastguard Worker }
732*795d594fSAndroid Build Coastguard Worker
733*795d594fSAndroid Build Coastguard Worker MakeReturn(return_block, return_val);
734*795d594fSAndroid Build Coastguard Worker
735*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
736*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(CheckGraph());
737*795d594fSAndroid Build Coastguard Worker
738*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
739*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default");
740*795d594fSAndroid Build Coastguard Worker RunCode(target_config,
741*795d594fSAndroid Build Coastguard Worker *compiler_options,
742*795d594fSAndroid Build Coastguard Worker graph_,
743*795d594fSAndroid Build Coastguard Worker [](HGraph*) {}, true, kNumOfAdds + 2 * kInputValue);
744*795d594fSAndroid Build Coastguard Worker }
745*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,PackedSwitchInHugeMethod)746*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, PackedSwitchInHugeMethod) {
747*795d594fSAndroid Build Coastguard Worker for (CodegenTargetConfig target_config : GetTargetConfigs()) {
748*795d594fSAndroid Build Coastguard Worker TestPackedSwitch(target_config);
749*795d594fSAndroid Build Coastguard Worker }
750*795d594fSAndroid Build Coastguard Worker }
751*795d594fSAndroid Build Coastguard Worker
752*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
TEST_F(CodegenTest,ARMVIXLParallelMoveResolver)753*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARMVIXLParallelMoveResolver) {
754*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
755*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kThumb2, "default");
756*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
757*795d594fSAndroid Build Coastguard Worker arm::CodeGeneratorARMVIXL codegen(graph, *compiler_options);
758*795d594fSAndroid Build Coastguard Worker
759*795d594fSAndroid Build Coastguard Worker codegen.Initialize();
760*795d594fSAndroid Build Coastguard Worker
761*795d594fSAndroid Build Coastguard Worker // This will result in calling EmitSwap -> void ParallelMoveResolverARMVIXL::Exchange(int mem1,
762*795d594fSAndroid Build Coastguard Worker // int mem2) which was faulty (before the fix). So previously GPR and FP scratch registers were
763*795d594fSAndroid Build Coastguard Worker // used as temps; however GPR scratch register is required for big stack offsets which don't fit
764*795d594fSAndroid Build Coastguard Worker // LDR encoding. So the following code is a regression test for that situation.
765*795d594fSAndroid Build Coastguard Worker HParallelMove* move = new (graph->GetAllocator()) HParallelMove(graph->GetAllocator());
766*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::StackSlot(0), Location::StackSlot(8192), DataType::Type::kInt32, nullptr);
767*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::StackSlot(8192), Location::StackSlot(0), DataType::Type::kInt32, nullptr);
768*795d594fSAndroid Build Coastguard Worker codegen.GetMoveResolver()->EmitNativeCode(move);
769*795d594fSAndroid Build Coastguard Worker
770*795d594fSAndroid Build Coastguard Worker codegen.Finalize();
771*795d594fSAndroid Build Coastguard Worker }
772*795d594fSAndroid Build Coastguard Worker #endif
773*795d594fSAndroid Build Coastguard Worker
774*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
775*795d594fSAndroid Build Coastguard Worker // Regression test for b/34760542.
TEST_F(CodegenTest,ARM64ParallelMoveResolverB34760542)776*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64ParallelMoveResolverB34760542) {
777*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
778*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
779*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
780*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
781*795d594fSAndroid Build Coastguard Worker
782*795d594fSAndroid Build Coastguard Worker codegen.Initialize();
783*795d594fSAndroid Build Coastguard Worker
784*795d594fSAndroid Build Coastguard Worker // The following ParallelMove used to fail this assertion:
785*795d594fSAndroid Build Coastguard Worker //
786*795d594fSAndroid Build Coastguard Worker // Assertion failed (!available->IsEmpty())
787*795d594fSAndroid Build Coastguard Worker //
788*795d594fSAndroid Build Coastguard Worker // in vixl::aarch64::UseScratchRegisterScope::AcquireNextAvailable,
789*795d594fSAndroid Build Coastguard Worker // because of the following situation:
790*795d594fSAndroid Build Coastguard Worker //
791*795d594fSAndroid Build Coastguard Worker // 1. a temp register (IP0) is allocated as a scratch register by
792*795d594fSAndroid Build Coastguard Worker // the parallel move resolver to solve a cycle (swap):
793*795d594fSAndroid Build Coastguard Worker //
794*795d594fSAndroid Build Coastguard Worker // [ source=DS0 destination=DS257 type=PrimDouble instruction=null ]
795*795d594fSAndroid Build Coastguard Worker // [ source=DS257 destination=DS0 type=PrimDouble instruction=null ]
796*795d594fSAndroid Build Coastguard Worker //
797*795d594fSAndroid Build Coastguard Worker // 2. within CodeGeneratorARM64::MoveLocation, another temp
798*795d594fSAndroid Build Coastguard Worker // register (IP1) is allocated to generate the swap between two
799*795d594fSAndroid Build Coastguard Worker // double stack slots;
800*795d594fSAndroid Build Coastguard Worker //
801*795d594fSAndroid Build Coastguard Worker // 3. VIXL requires a third temp register to emit the `Ldr` or
802*795d594fSAndroid Build Coastguard Worker // `Str` operation from CodeGeneratorARM64::MoveLocation (as
803*795d594fSAndroid Build Coastguard Worker // one of the stack slots' offsets cannot be encoded as an
804*795d594fSAndroid Build Coastguard Worker // immediate), but the pool of (core) temp registers is now
805*795d594fSAndroid Build Coastguard Worker // empty.
806*795d594fSAndroid Build Coastguard Worker //
807*795d594fSAndroid Build Coastguard Worker // The solution used so far is to use a floating-point temp register
808*795d594fSAndroid Build Coastguard Worker // (D31) in step #2, so that IP1 is available for step #3.
809*795d594fSAndroid Build Coastguard Worker
810*795d594fSAndroid Build Coastguard Worker HParallelMove* move = new (graph->GetAllocator()) HParallelMove(graph->GetAllocator());
811*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::DoubleStackSlot(0),
812*795d594fSAndroid Build Coastguard Worker Location::DoubleStackSlot(257),
813*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
814*795d594fSAndroid Build Coastguard Worker nullptr);
815*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::DoubleStackSlot(257),
816*795d594fSAndroid Build Coastguard Worker Location::DoubleStackSlot(0),
817*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
818*795d594fSAndroid Build Coastguard Worker nullptr);
819*795d594fSAndroid Build Coastguard Worker codegen.GetMoveResolver()->EmitNativeCode(move);
820*795d594fSAndroid Build Coastguard Worker
821*795d594fSAndroid Build Coastguard Worker codegen.Finalize();
822*795d594fSAndroid Build Coastguard Worker }
823*795d594fSAndroid Build Coastguard Worker
824*795d594fSAndroid Build Coastguard Worker // Check that ParallelMoveResolver works fine for ARM64 for both cases when SIMD is on and off.
TEST_F(CodegenTest,ARM64ParallelMoveResolverSIMD)825*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64ParallelMoveResolverSIMD) {
826*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
827*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
828*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
829*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
830*795d594fSAndroid Build Coastguard Worker
831*795d594fSAndroid Build Coastguard Worker codegen.Initialize();
832*795d594fSAndroid Build Coastguard Worker
833*795d594fSAndroid Build Coastguard Worker graph->SetHasTraditionalSIMD(true);
834*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
835*795d594fSAndroid Build Coastguard Worker HParallelMove* move = new (graph->GetAllocator()) HParallelMove(graph->GetAllocator());
836*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::SIMDStackSlot(0),
837*795d594fSAndroid Build Coastguard Worker Location::SIMDStackSlot(257),
838*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
839*795d594fSAndroid Build Coastguard Worker nullptr);
840*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::SIMDStackSlot(257),
841*795d594fSAndroid Build Coastguard Worker Location::SIMDStackSlot(0),
842*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
843*795d594fSAndroid Build Coastguard Worker nullptr);
844*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::FpuRegisterLocation(0),
845*795d594fSAndroid Build Coastguard Worker Location::FpuRegisterLocation(1),
846*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
847*795d594fSAndroid Build Coastguard Worker nullptr);
848*795d594fSAndroid Build Coastguard Worker move->AddMove(Location::FpuRegisterLocation(1),
849*795d594fSAndroid Build Coastguard Worker Location::FpuRegisterLocation(0),
850*795d594fSAndroid Build Coastguard Worker DataType::Type::kFloat64,
851*795d594fSAndroid Build Coastguard Worker nullptr);
852*795d594fSAndroid Build Coastguard Worker codegen.GetMoveResolver()->EmitNativeCode(move);
853*795d594fSAndroid Build Coastguard Worker graph->SetHasTraditionalSIMD(false);
854*795d594fSAndroid Build Coastguard Worker }
855*795d594fSAndroid Build Coastguard Worker
856*795d594fSAndroid Build Coastguard Worker codegen.Finalize();
857*795d594fSAndroid Build Coastguard Worker }
858*795d594fSAndroid Build Coastguard Worker
859*795d594fSAndroid Build Coastguard Worker // Check that ART ISA Features are propagated to VIXL for arm64 (using cortex-a75 as example).
TEST_F(CodegenTest,ARM64IsaVIXLFeaturesA75)860*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64IsaVIXLFeaturesA75) {
861*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
862*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "cortex-a75");
863*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
864*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
865*795d594fSAndroid Build Coastguard Worker vixl::CPUFeatures* features = codegen.GetVIXLAssembler()->GetCPUFeatures();
866*795d594fSAndroid Build Coastguard Worker
867*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kCRC32));
868*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kDotProduct));
869*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kFPHalf));
870*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kNEONHalf));
871*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kAtomics));
872*795d594fSAndroid Build Coastguard Worker }
873*795d594fSAndroid Build Coastguard Worker
874*795d594fSAndroid Build Coastguard Worker // Check that ART ISA Features are propagated to VIXL for arm64 (using cortex-a53 as example).
TEST_F(CodegenTest,ARM64IsaVIXLFeaturesA53)875*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64IsaVIXLFeaturesA53) {
876*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
877*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "cortex-a53");
878*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
879*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
880*795d594fSAndroid Build Coastguard Worker vixl::CPUFeatures* features = codegen.GetVIXLAssembler()->GetCPUFeatures();
881*795d594fSAndroid Build Coastguard Worker
882*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(features->Has(vixl::CPUFeatures::kCRC32));
883*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(features->Has(vixl::CPUFeatures::kDotProduct));
884*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(features->Has(vixl::CPUFeatures::kFPHalf));
885*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(features->Has(vixl::CPUFeatures::kNEONHalf));
886*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(features->Has(vixl::CPUFeatures::kAtomics));
887*795d594fSAndroid Build Coastguard Worker }
888*795d594fSAndroid Build Coastguard Worker
889*795d594fSAndroid Build Coastguard Worker constexpr static size_t kExpectedFPSpillSize = 8 * vixl::aarch64::kDRegSizeInBytes;
890*795d594fSAndroid Build Coastguard Worker
891*795d594fSAndroid Build Coastguard Worker // The following two tests check that for both SIMD and non-SIMD graphs exactly 64-bit is
892*795d594fSAndroid Build Coastguard Worker // allocated on stack per callee-saved FP register to be preserved in the frame entry as
893*795d594fSAndroid Build Coastguard Worker // ABI states.
TEST_F(CodegenTest,ARM64FrameSizeSIMD)894*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64FrameSizeSIMD) {
895*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
896*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
897*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
898*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
899*795d594fSAndroid Build Coastguard Worker
900*795d594fSAndroid Build Coastguard Worker codegen.Initialize();
901*795d594fSAndroid Build Coastguard Worker graph->SetHasTraditionalSIMD(true);
902*795d594fSAndroid Build Coastguard Worker
903*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(arm64::callee_saved_fp_registers.GetCount(), 8);
904*795d594fSAndroid Build Coastguard Worker vixl::aarch64::CPURegList reg_list = arm64::callee_saved_fp_registers;
905*795d594fSAndroid Build Coastguard Worker while (!reg_list.IsEmpty()) {
906*795d594fSAndroid Build Coastguard Worker uint32_t reg_code = reg_list.PopLowestIndex().GetCode();
907*795d594fSAndroid Build Coastguard Worker codegen.AddAllocatedRegister(Location::FpuRegisterLocation(reg_code));
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker codegen.ComputeSpillMask();
910*795d594fSAndroid Build Coastguard Worker
911*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(codegen.GetFpuSpillSize(), kExpectedFPSpillSize);
912*795d594fSAndroid Build Coastguard Worker }
913*795d594fSAndroid Build Coastguard Worker
TEST_F(CodegenTest,ARM64FrameSizeNoSIMD)914*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64FrameSizeNoSIMD) {
915*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
916*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default");
917*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateGraph();
918*795d594fSAndroid Build Coastguard Worker arm64::CodeGeneratorARM64 codegen(graph, *compiler_options);
919*795d594fSAndroid Build Coastguard Worker
920*795d594fSAndroid Build Coastguard Worker codegen.Initialize();
921*795d594fSAndroid Build Coastguard Worker graph->SetHasTraditionalSIMD(false);
922*795d594fSAndroid Build Coastguard Worker graph->SetHasPredicatedSIMD(false);
923*795d594fSAndroid Build Coastguard Worker
924*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(arm64::callee_saved_fp_registers.GetCount(), 8);
925*795d594fSAndroid Build Coastguard Worker vixl::aarch64::CPURegList reg_list = arm64::callee_saved_fp_registers;
926*795d594fSAndroid Build Coastguard Worker while (!reg_list.IsEmpty()) {
927*795d594fSAndroid Build Coastguard Worker uint32_t reg_code = reg_list.PopLowestIndex().GetCode();
928*795d594fSAndroid Build Coastguard Worker codegen.AddAllocatedRegister(Location::FpuRegisterLocation(reg_code));
929*795d594fSAndroid Build Coastguard Worker }
930*795d594fSAndroid Build Coastguard Worker codegen.ComputeSpillMask();
931*795d594fSAndroid Build Coastguard Worker
932*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(codegen.GetFpuSpillSize(), kExpectedFPSpillSize);
933*795d594fSAndroid Build Coastguard Worker }
934*795d594fSAndroid Build Coastguard Worker
935*795d594fSAndroid Build Coastguard Worker // This test checks that the result of the VecPredToBoolean instruction doesn't depend on
936*795d594fSAndroid Build Coastguard Worker // conditional flags that can be updated by other instructions. For example:
937*795d594fSAndroid Build Coastguard Worker //
938*795d594fSAndroid Build Coastguard Worker // VecPredWhile p0, opa, opb
939*795d594fSAndroid Build Coastguard Worker // Below opb, opa
940*795d594fSAndroid Build Coastguard Worker // VecPredToBoolean p0
941*795d594fSAndroid Build Coastguard Worker //
942*795d594fSAndroid Build Coastguard Worker // where Below updates conditions flags after VecPredWhile.
TEST_F(CodegenTest,ARM64SvePredicateToBoolean)943*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ARM64SvePredicateToBoolean) {
944*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options =
945*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default", "sve");
946*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
947*795d594fSAndroid Build Coastguard Worker for (int j = 0; j < 2; j++) {
948*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = InitEntryMainExitGraph();
949*795d594fSAndroid Build Coastguard Worker TestCodeGeneratorARM64 codegen(graph_, *compiler_options);
950*795d594fSAndroid Build Coastguard Worker if (!codegen.SupportsPredicatedSIMD()) {
951*795d594fSAndroid Build Coastguard Worker GTEST_SKIP() << "Predicated SIMD is not supported.";
952*795d594fSAndroid Build Coastguard Worker }
953*795d594fSAndroid Build Coastguard Worker
954*795d594fSAndroid Build Coastguard Worker HInstruction *opa = graph_->GetIntConstant(i);
955*795d594fSAndroid Build Coastguard Worker HInstruction *opb = graph_->GetIntConstant(j);
956*795d594fSAndroid Build Coastguard Worker HVecPredWhile *pred_while = MakeVecPredWhile(block,
957*795d594fSAndroid Build Coastguard Worker opa,
958*795d594fSAndroid Build Coastguard Worker opb,
959*795d594fSAndroid Build Coastguard Worker HVecPredWhile::CondKind::kLO,
960*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
961*795d594fSAndroid Build Coastguard Worker // Update condition flags by using Below instruction.
962*795d594fSAndroid Build Coastguard Worker MakeCondition(block, IfCondition::kCondB, opb, opa);
963*795d594fSAndroid Build Coastguard Worker HVecPredToBoolean *boolean = MakeVecPredToBoolean(block,
964*795d594fSAndroid Build Coastguard Worker pred_while,
965*795d594fSAndroid Build Coastguard Worker HVecPredToBoolean::PCondKind::kNFirst,
966*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
967*795d594fSAndroid Build Coastguard Worker MakeReturn(block, boolean);
968*795d594fSAndroid Build Coastguard Worker
969*795d594fSAndroid Build Coastguard Worker graph_->SetHasPredicatedSIMD(true);
970*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
971*795d594fSAndroid Build Coastguard Worker
972*795d594fSAndroid Build Coastguard Worker if (CanExecute(codegen)) {
973*795d594fSAndroid Build Coastguard Worker RunCode(&codegen, graph_, [](HGraph*) {}, true, i >= j);
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker }
976*795d594fSAndroid Build Coastguard Worker }
977*795d594fSAndroid Build Coastguard Worker }
978*795d594fSAndroid Build Coastguard Worker
TestVectorComparison(IfCondition condition,int64_t lhs_value,int64_t rhs_value,DataType::Type type,CodeGenerator * codegen)979*795d594fSAndroid Build Coastguard Worker void CodegenTest::TestVectorComparison(IfCondition condition,
980*795d594fSAndroid Build Coastguard Worker int64_t lhs_value,
981*795d594fSAndroid Build Coastguard Worker int64_t rhs_value,
982*795d594fSAndroid Build Coastguard Worker DataType::Type type,
983*795d594fSAndroid Build Coastguard Worker CodeGenerator* codegen) {
984*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = entry_block_->GetSingleSuccessor();
985*795d594fSAndroid Build Coastguard Worker
986*795d594fSAndroid Build Coastguard Worker size_t vector_size_in_bytes = codegen->GetSIMDRegisterWidth();
987*795d594fSAndroid Build Coastguard Worker
988*795d594fSAndroid Build Coastguard Worker HVecPredSetAll* predicate = MakeVecPredSetAll(block,
989*795d594fSAndroid Build Coastguard Worker graph_->GetIntConstant(1),
990*795d594fSAndroid Build Coastguard Worker type,
991*795d594fSAndroid Build Coastguard Worker vector_size_in_bytes);
992*795d594fSAndroid Build Coastguard Worker HVecReplicateScalar* op1 = MakeVecReplicateScalar(block,
993*795d594fSAndroid Build Coastguard Worker graph_->GetConstant(type, lhs_value),
994*795d594fSAndroid Build Coastguard Worker type,
995*795d594fSAndroid Build Coastguard Worker vector_size_in_bytes,
996*795d594fSAndroid Build Coastguard Worker predicate);
997*795d594fSAndroid Build Coastguard Worker HVecReplicateScalar* op2 = MakeVecReplicateScalar(block,
998*795d594fSAndroid Build Coastguard Worker graph_->GetConstant(type, rhs_value),
999*795d594fSAndroid Build Coastguard Worker type,
1000*795d594fSAndroid Build Coastguard Worker vector_size_in_bytes,
1001*795d594fSAndroid Build Coastguard Worker predicate);
1002*795d594fSAndroid Build Coastguard Worker HVecCondition* comparison = MakeVecCondition(block,
1003*795d594fSAndroid Build Coastguard Worker condition,
1004*795d594fSAndroid Build Coastguard Worker op1,
1005*795d594fSAndroid Build Coastguard Worker op2,
1006*795d594fSAndroid Build Coastguard Worker type,
1007*795d594fSAndroid Build Coastguard Worker vector_size_in_bytes,
1008*795d594fSAndroid Build Coastguard Worker predicate);
1009*795d594fSAndroid Build Coastguard Worker HInstruction* boolean_return = MakeVecPredToBoolean(block,
1010*795d594fSAndroid Build Coastguard Worker comparison,
1011*795d594fSAndroid Build Coastguard Worker HVecPredToBoolean::PCondKind::kFirst,
1012*795d594fSAndroid Build Coastguard Worker type,
1013*795d594fSAndroid Build Coastguard Worker vector_size_in_bytes);
1014*795d594fSAndroid Build Coastguard Worker MakeReturn(block, boolean_return);
1015*795d594fSAndroid Build Coastguard Worker
1016*795d594fSAndroid Build Coastguard Worker graph_->SetHasPredicatedSIMD(true);
1017*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
1018*795d594fSAndroid Build Coastguard Worker
1019*795d594fSAndroid Build Coastguard Worker if (CanExecute(*codegen)) {
1020*795d594fSAndroid Build Coastguard Worker bool expected_result = GetExpectedResultFromComparison(condition, lhs_value, rhs_value);
1021*795d594fSAndroid Build Coastguard Worker RunCode(codegen, graph_, [](HGraph*) {}, true, expected_result);
1022*795d594fSAndroid Build Coastguard Worker }
1023*795d594fSAndroid Build Coastguard Worker }
1024*795d594fSAndroid Build Coastguard Worker
1025*795d594fSAndroid Build Coastguard Worker // Define tests ensuring that all types of conditions can be generated correctly and return the
1026*795d594fSAndroid Build Coastguard Worker // expected result.
1027*795d594fSAndroid Build Coastguard Worker #define DEFINE_CONDITION_TESTS(CondType) \
1028*795d594fSAndroid Build Coastguard Worker TEST_F(CodegenTest, ComparisonsVector##CondType) { \
1029*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CompilerOptions> compiler_options = \
1030*795d594fSAndroid Build Coastguard Worker CommonCompilerTest::CreateCompilerOptions(InstructionSet::kArm64, "default", "sve"); \
1031*795d594fSAndroid Build Coastguard Worker for (int64_t i = -1; i <= 1; i++) { \
1032*795d594fSAndroid Build Coastguard Worker for (int64_t j = -1; j <= 1; j++) { \
1033*795d594fSAndroid Build Coastguard Worker for (int cond = kCondFirst; cond <= kCondLast; cond++) { \
1034*795d594fSAndroid Build Coastguard Worker InitEntryMainExitGraph(); \
1035*795d594fSAndroid Build Coastguard Worker TestCodeGeneratorARM64 codegen(graph_, *compiler_options); \
1036*795d594fSAndroid Build Coastguard Worker if (!codegen.SupportsPredicatedSIMD()) { \
1037*795d594fSAndroid Build Coastguard Worker GTEST_SKIP() << "Predicated SIMD is not supported."; \
1038*795d594fSAndroid Build Coastguard Worker } \
1039*795d594fSAndroid Build Coastguard Worker TestVectorComparison( \
1040*795d594fSAndroid Build Coastguard Worker static_cast<IfCondition>(cond), i, j, DataType::Type::k##CondType, &codegen); \
1041*795d594fSAndroid Build Coastguard Worker } \
1042*795d594fSAndroid Build Coastguard Worker } \
1043*795d594fSAndroid Build Coastguard Worker } \
1044*795d594fSAndroid Build Coastguard Worker }
1045*795d594fSAndroid Build Coastguard Worker DEFINE_CONDITION_TESTS(Uint8)
1046*795d594fSAndroid Build Coastguard Worker DEFINE_CONDITION_TESTS(Int8)
1047*795d594fSAndroid Build Coastguard Worker DEFINE_CONDITION_TESTS(Uint16)
1048*795d594fSAndroid Build Coastguard Worker DEFINE_CONDITION_TESTS(Int16)
1049*795d594fSAndroid Build Coastguard Worker DEFINE_CONDITION_TESTS(Int32)
1050*795d594fSAndroid Build Coastguard Worker #undef DEFINE_CONDITION_TESTS
1051*795d594fSAndroid Build Coastguard Worker
1052*795d594fSAndroid Build Coastguard Worker #endif
1053*795d594fSAndroid Build Coastguard Worker
1054*795d594fSAndroid Build Coastguard Worker } // namespace art
1055