Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc

Issue 2065243005: [arm64] Generate adds/ands. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove static Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/compiler/test-branch-combine.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "test/unittests/compiler/instruction-selector-unittest.h" 5 #include "test/unittests/compiler/instruction-selector-unittest.h"
6 6
7 namespace v8 { 7 namespace v8 {
8 namespace internal { 8 namespace internal {
9 namespace compiler { 9 namespace compiler {
10 10
(...skipping 3224 matching lines...) Expand 10 before | Expand all | Expand 10 after
3235 EXPECT_EQ(3U, s[0]->InputCount()); 3235 EXPECT_EQ(3U, s[0]->InputCount());
3236 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); 3236 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
3237 EXPECT_EQ(1U, s[0]->OutputCount()); 3237 EXPECT_EQ(1U, s[0]->OutputCount());
3238 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 3238 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3239 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); 3239 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3240 } 3240 }
3241 } 3241 }
3242 } 3242 }
3243 } 3243 }
3244 3244
3245 // -----------------------------------------------------------------------------
3246 // Flag-setting add and and instructions.
3247
3248 const IntegerCmp kBinopCmpZeroRightInstructions[] = {
3249 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
3250 MachineType::Int32()},
3251 kEqual,
3252 kEqual},
3253 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kArm64Cmp32,
3254 MachineType::Int32()},
3255 kNotEqual,
3256 kNotEqual},
3257 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
3258 MachineType::Int32()},
3259 kNegative,
3260 kNegative},
3261 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
3262 kArm64Cmp32, MachineType::Int32()},
3263 kPositiveOrZero,
3264 kPositiveOrZero},
3265 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
3266 kArm64Cmp32, MachineType::Int32()},
3267 kEqual,
3268 kEqual},
3269 {{&RawMachineAssembler::Uint32GreaterThan, "Uint32GreaterThan", kArm64Cmp32,
3270 MachineType::Int32()},
3271 kNotEqual,
3272 kNotEqual}};
3273
3274 const IntegerCmp kBinopCmpZeroLeftInstructions[] = {
3275 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
3276 MachineType::Int32()},
3277 kEqual,
3278 kEqual},
3279 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kArm64Cmp32,
3280 MachineType::Int32()},
3281 kNotEqual,
3282 kNotEqual},
3283 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kArm64Cmp32,
3284 MachineType::Int32()},
3285 kNegative,
3286 kNegative},
3287 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
3288 kArm64Cmp32, MachineType::Int32()},
3289 kPositiveOrZero,
3290 kPositiveOrZero},
3291 {{&RawMachineAssembler::Uint32GreaterThanOrEqual,
3292 "Uint32GreaterThanOrEqual", kArm64Cmp32, MachineType::Int32()},
3293 kEqual,
3294 kEqual},
3295 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
3296 MachineType::Int32()},
3297 kNotEqual,
3298 kNotEqual}};
3299
3300 struct FlagSettingInst {
3301 MachInst2 mi;
3302 ArchOpcode no_output_opcode;
3303 };
3304
3305 std::ostream& operator<<(std::ostream& os, const FlagSettingInst& inst) {
3306 return os << inst.mi.constructor_name;
3307 }
3308
3309 const FlagSettingInst kFlagSettingInstructions[] = {
3310 {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
3311 MachineType::Int32()},
3312 kArm64Cmn32},
3313 {{&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
3314 MachineType::Int32()},
3315 kArm64Tst32}};
3316
3317 typedef InstructionSelectorTestWithParam<FlagSettingInst>
3318 InstructionSelectorFlagSettingTest;
3319
3320 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroRight) {
3321 const FlagSettingInst inst = GetParam();
3322 // Add with single user : a cmp instruction.
3323 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3324 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3325 MachineType::Int32());
3326 RawMachineLabel a, b;
3327 Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
3328 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3329 m.Branch(comp, &a, &b);
3330 m.Bind(&a);
3331 m.Return(m.Int32Constant(1));
3332 m.Bind(&b);
3333 m.Return(m.Int32Constant(0));
3334 Stream s = m.Build();
3335 ASSERT_EQ(1U, s.size());
3336 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
3337 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
3338 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
3339 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
3340 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3341 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3342 }
3343 }
3344
3345 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroLeft) {
3346 const FlagSettingInst inst = GetParam();
3347 // Test a cmp with zero on the left-hand side.
3348 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroLeftInstructions) {
3349 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3350 MachineType::Int32());
3351 RawMachineLabel a, b;
3352 Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
3353 Node* comp = (m.*cmp.mi.constructor)(m.Int32Constant(0), binop);
3354 m.Branch(comp, &a, &b);
3355 m.Bind(&a);
3356 m.Return(m.Int32Constant(1));
3357 m.Bind(&b);
3358 m.Return(m.Int32Constant(0));
3359 Stream s = m.Build();
3360 ASSERT_EQ(1U, s.size());
3361 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
3362 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
3363 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
3364 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
3365 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3366 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3367 }
3368 }
3369
3370 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroOnlyUserInBasicBlock) {
3371 const FlagSettingInst inst = GetParam();
3372 // Binop with additional users, but in a different basic block.
3373 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3374 // For kEqual and kNotEqual, we generate a cbz or cbnz.
3375 if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
3376 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3377 MachineType::Int32());
3378 RawMachineLabel a, b;
3379 Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
3380 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3381 m.Branch(comp, &a, &b);
3382 m.Bind(&a);
3383 m.Return(binop);
3384 m.Bind(&b);
3385 m.Return(m.Int32Constant(0));
3386 Stream s = m.Build();
3387 ASSERT_EQ(1U, s.size());
3388 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
3389 EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
3390 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
3391 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
3392 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3393 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3394 }
3395 }
3396
3397 TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
3398 const FlagSettingInst inst = GetParam();
3399 // Like the test above, but with a shifted input to the binary operator.
3400 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3401 // For kEqual and kNotEqual, we generate a cbz or cbnz.
3402 if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
3403 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3404 MachineType::Int32());
3405 RawMachineLabel a, b;
3406 Node* imm = m.Int32Constant(5);
3407 Node* shift = m.Word32Shl(m.Parameter(1), imm);
3408 Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), shift);
3409 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3410 m.Branch(comp, &a, &b);
3411 m.Bind(&a);
3412 m.Return(binop);
3413 m.Bind(&b);
3414 m.Return(m.Int32Constant(0));
3415 Stream s = m.Build();
3416 ASSERT_EQ(1U, s.size());
3417 ASSERT_EQ(5U, s[0]->InputCount()); // The labels are also inputs.
3418 EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
3419 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
3420 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
3421 EXPECT_EQ(5, s.ToInt32(s[0]->InputAt(2)));
3422 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
3423 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3424 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3425 }
3426 }
3427
3428 TEST_P(InstructionSelectorFlagSettingTest, UsersInSameBasicBlock) {
3429 const FlagSettingInst inst = GetParam();
3430 // Binop with additional users, in the same basic block. We need to make sure
3431 // we don't try to optimise this case.
3432 TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
3433 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3434 MachineType::Int32());
3435 RawMachineLabel a, b;
3436 Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
3437 Node* mul = m.Int32Mul(m.Parameter(0), binop);
3438 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3439 m.Branch(comp, &a, &b);
3440 m.Bind(&a);
3441 m.Return(mul);
3442 m.Bind(&b);
3443 m.Return(m.Int32Constant(0));
3444 Stream s = m.Build();
3445 ASSERT_EQ(3U, s.size());
3446 EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
3447 EXPECT_NE(kFlags_branch, s[0]->flags_mode());
3448 EXPECT_EQ(kArm64Mul32, s[1]->arch_opcode());
3449 EXPECT_EQ(cmp.cond == kEqual ? kArm64CompareAndBranch32 : kArm64Cmp32,
3450 s[2]->arch_opcode());
3451 EXPECT_EQ(kFlags_branch, s[2]->flags_mode());
3452 EXPECT_EQ(cmp.cond, s[2]->flags_condition());
3453 }
3454 }
3455
3456 TEST_P(InstructionSelectorFlagSettingTest, CommuteImmediate) {
3457 const FlagSettingInst inst = GetParam();
3458 // Immediate on left hand side of the binary operator.
3459 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3460 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3461 RawMachineLabel a, b;
3462 // 3 can be an immediate on both arithmetic and logical instructions.
3463 Node* imm = m.Int32Constant(3);
3464 Node* binop = (m.*inst.mi.constructor)(imm, m.Parameter(0));
3465 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3466 m.Branch(comp, &a, &b);
3467 m.Bind(&a);
3468 m.Return(m.Int32Constant(1));
3469 m.Bind(&b);
3470 m.Return(m.Int32Constant(0));
3471 Stream s = m.Build();
3472 ASSERT_EQ(1U, s.size());
3473 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
3474 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
3475 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
3476 EXPECT_EQ(3, s.ToInt32(s[0]->InputAt(1)));
3477 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3478 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3479 }
3480 }
3481
3482 TEST_P(InstructionSelectorFlagSettingTest, CommuteShift) {
3483 const FlagSettingInst inst = GetParam();
3484 // Left-hand side operand shifted by immediate.
3485 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3486 TRACED_FOREACH(Shift, shift, kShiftInstructions) {
3487 // Only test relevant shifted operands.
3488 if (shift.mi.machine_type != MachineType::Int32()) continue;
3489
3490 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3491 MachineType::Int32());
3492 Node* imm = m.Int32Constant(5);
3493 Node* shifted_operand = (m.*shift.mi.constructor)(m.Parameter(0), imm);
3494 Node* binop = (m.*inst.mi.constructor)(shifted_operand, m.Parameter(1));
3495 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3496 m.Return(comp);
3497 Stream s = m.Build();
3498 // Cmn does not support ROR shifts.
3499 if (inst.no_output_opcode == kArm64Cmn32 &&
3500 shift.mi.arch_opcode == kArm64Ror32) {
3501 ASSERT_EQ(2U, s.size());
3502 continue;
3503 }
3504 ASSERT_EQ(1U, s.size());
3505 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
3506 EXPECT_EQ(shift.mode, s[0]->addressing_mode());
3507 EXPECT_EQ(3U, s[0]->InputCount());
3508 EXPECT_EQ(5, s.ToInt64(s[0]->InputAt(2)));
3509 EXPECT_EQ(1U, s[0]->OutputCount());
3510 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3511 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3512 }
3513 }
3514 }
3515
3516 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
3517 InstructionSelectorFlagSettingTest,
3518 ::testing::ValuesIn(kFlagSettingInstructions));
3519
3520 TEST_F(InstructionSelectorTest, TstInvalidImmediate) {
3521 // Make sure we do not generate an invalid immediate for TST.
3522 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3523 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
3524 RawMachineLabel a, b;
3525 // 5 is not a valid constant for TST.
3526 Node* imm = m.Int32Constant(5);
3527 Node* binop = m.Word32And(imm, m.Parameter(0));
3528 Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
3529 m.Branch(comp, &a, &b);
3530 m.Bind(&a);
3531 m.Return(m.Int32Constant(1));
3532 m.Bind(&b);
3533 m.Return(m.Int32Constant(0));
3534 Stream s = m.Build();
3535 ASSERT_EQ(1U, s.size());
3536 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
3537 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
3538 EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
3539 EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
3540 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
3541 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3542 }
3543 }
3544
3545 TEST_F(InstructionSelectorTest, CommuteAddsExtend) {
3546 // Extended left-hand side operand.
3547 TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
3548 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
3549 MachineType::Int32());
3550 Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
3551 m.Int32Constant(24));
3552 Node* binop = m.Int32Add(extend, m.Parameter(1));
3553 m.Return((m.*cmp.mi.constructor)(binop, m.Int32Constant(0)));
3554 Stream s = m.Build();
3555 ASSERT_EQ(1U, s.size());
3556 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
3557 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
3558 EXPECT_EQ(cmp.cond, s[0]->flags_condition());
3559 EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
3560 }
3561 }
3245 3562
3246 // ----------------------------------------------------------------------------- 3563 // -----------------------------------------------------------------------------
3247 // Miscellaneous 3564 // Miscellaneous
3248 3565
3249 3566
3250 static const MachInst2 kLogicalWithNotRHSs[] = { 3567 static const MachInst2 kLogicalWithNotRHSs[] = {
3251 {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32, 3568 {&RawMachineAssembler::Word32And, "Word32And", kArm64Bic32,
3252 MachineType::Int32()}, 3569 MachineType::Int32()},
3253 {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic, 3570 {&RawMachineAssembler::Word64And, "Word64And", kArm64Bic,
3254 MachineType::Int64()}, 3571 MachineType::Int64()},
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
3935 EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode()); 4252 EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
3936 ASSERT_EQ(1U, s[0]->InputCount()); 4253 ASSERT_EQ(1U, s[0]->InputCount());
3937 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 4254 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3938 ASSERT_EQ(1U, s[0]->OutputCount()); 4255 ASSERT_EQ(1U, s[0]->OutputCount());
3939 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 4256 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3940 } 4257 }
3941 4258
3942 } // namespace compiler 4259 } // namespace compiler
3943 } // namespace internal 4260 } // namespace internal
3944 } // namespace v8 4261 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/compiler/test-branch-combine.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698