From fe6656fbfebb3221a1405dc410bc986ed51c7a9e Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Fri, 17 Oct 2014 07:07:54 +0000 Subject: [PATCH] [arm] Prefer BIC over BFC. BFC requires same register for input and output and causes introduction of some unneccesary gap moves. TEST=unittests,mjsunit R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/658283003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24678 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/arm/instruction-selector-arm.cc | 33 ++++++---- test/mjsunit/asm/word32and.js | 29 +++++++++ .../arm/instruction-selector-arm-unittest.cc | 61 +++++++++++-------- 3 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 test/mjsunit/asm/word32and.js diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc index 19ba71c43..ed58bbabe 100644 --- a/src/compiler/arm/instruction-selector-arm.cc +++ b/src/compiler/arm/instruction-selector-arm.cc @@ -23,6 +23,14 @@ class ArmOperandGenerator : public OperandGenerator { return UseRegister(node); } + bool CanBeImmediate(int32_t value) const { + return Assembler::ImmediateFitsAddrMode1Instruction(value); + } + + bool CanBeImmediate(uint32_t value) const { + return CanBeImmediate(bit_cast(value)); + } + bool CanBeImmediate(Node* node, InstructionCode opcode) { Int32Matcher m(node); if (!m.HasValue()) return false; @@ -32,22 +40,20 @@ class ArmOperandGenerator : public OperandGenerator { case kArmMov: case kArmMvn: case kArmBic: - return ImmediateFitsAddrMode1Instruction(value) || - ImmediateFitsAddrMode1Instruction(~value); + return CanBeImmediate(value) || CanBeImmediate(~value); case kArmAdd: case kArmSub: case kArmCmp: case kArmCmn: - return ImmediateFitsAddrMode1Instruction(value) || - ImmediateFitsAddrMode1Instruction(-value); + return CanBeImmediate(value) || CanBeImmediate(-value); case kArmTst: case kArmTeq: case kArmOrr: case kArmEor: case kArmRsb: - return ImmediateFitsAddrMode1Instruction(value); + return CanBeImmediate(value); case kArmVldrF32: case kArmVstrF32: @@ -106,11 +112,6 @@ class ArmOperandGenerator : public OperandGenerator { UNREACHABLE(); return false; } - - private: - bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { - return Assembler::ImmediateFitsAddrMode1Instruction(imm); - } }; @@ -417,7 +418,8 @@ void InstructionSelector::VisitWord32And(Node* node) { } } if (IsSupported(ARMv7) && m.right().HasValue()) { - uint32_t value = m.right().Value(); + // Try to interpret this AND as UBFX. + uint32_t const value = m.right().Value(); uint32_t width = base::bits::CountPopulation32(value); uint32_t msb = base::bits::CountLeadingZeros32(value); if (width != 0 && msb + width == 32) { @@ -435,6 +437,15 @@ void InstructionSelector::VisitWord32And(Node* node) { g.TempImmediate(0), g.TempImmediate(width)); return; } + + // Try to interpret this AND as BIC. + if (g.CanBeImmediate(~value)) { + Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), + g.DefineAsRegister(node), g.UseRegister(m.left().node()), + g.TempImmediate(~value)); + return; + } + // Try to interpret this AND as BFC. width = 32 - width; msb = base::bits::CountLeadingZeros32(~value); diff --git a/test/mjsunit/asm/word32and.js b/test/mjsunit/asm/word32and.js new file mode 100644 index 000000000..6c41f882a --- /dev/null +++ b/test/mjsunit/asm/word32and.js @@ -0,0 +1,29 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var stdlib = {}; +var foreign = {}; +var heap = new ArrayBuffer(64 * 1024); + +function Word32And(rhs) { + var name = "and_0x" + Number(rhs).toString(16); + var m = eval("function Module(stdlib, foreign, heap) {\n" + + " \"use asm\";\n" + + " function " + name + "(lhs) {\n" + + " return (lhs | 0) & 0x" + Number(rhs).toString(16) + ";\n" + + " }\n" + + " return { f: " + name + "}\n" + + "}; Module"); + return m(stdlib, foreign, heap).f; +} + +var masks = [0xffffffff, 0xf0f0f0f0, 0x80ffffff, 0x07f77f0f, 0xdeadbeef, + 0x0fffff00, 0x0ff0, 0xff, 0x00]; +for (var i in masks) { + var rhs = masks[i]; + var and = Word32And(rhs); + for (var lhs = -2147483648; lhs < 2147483648; lhs += 3999773) { + assertEquals(lhs & rhs, and(lhs)); + } +} diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc index 0c71d2f24..9d87900d6 100644 --- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc +++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "test/unittests/compiler/instruction-selector-unittest.h" namespace v8 { @@ -86,30 +88,37 @@ static const Shift kShifts[] = { // Immediates (random subset). static const int32_t kImmediates[] = { - -2147483617, -2147483606, -2113929216, -2080374784, -1996488704, - -1879048192, -1459617792, -1358954496, -1342177265, -1275068414, - -1073741818, -1073741777, -855638016, -805306368, -402653184, - -268435444, -16777216, 0, 35, 61, - 105, 116, 171, 245, 255, - 692, 1216, 1248, 1520, 1600, - 1888, 3744, 4080, 5888, 8384, - 9344, 9472, 9792, 13312, 15040, - 15360, 20736, 22272, 23296, 32000, - 33536, 37120, 45824, 47872, 56320, - 59392, 65280, 72704, 101376, 147456, - 161792, 164864, 167936, 173056, 195584, - 209920, 212992, 356352, 655360, 704512, - 716800, 851968, 901120, 1044480, 1523712, - 2572288, 3211264, 3588096, 3833856, 3866624, - 4325376, 5177344, 6488064, 7012352, 7471104, - 14090240, 16711680, 19398656, 22282240, 28573696, - 30408704, 30670848, 43253760, 54525952, 55312384, - 56623104, 68157440, 115343360, 131072000, 187695104, - 188743680, 195035136, 197132288, 203423744, 218103808, - 267386880, 268435470, 285212672, 402653185, 415236096, - 595591168, 603979776, 603979778, 629145600, 1073741835, - 1073741855, 1073741861, 1073741884, 1157627904, 1476395008, - 1476395010, 1610612741, 2030043136, 2080374785, 2097152000}; + std::numeric_limits::min(), -2147483617, -2147483606, -2113929216, + -2080374784, -1996488704, -1879048192, -1459617792, + -1358954496, -1342177265, -1275068414, -1073741818, + -1073741777, -855638016, -805306368, -402653184, + -268435444, -16777216, 0, 35, + 61, 105, 116, 171, + 245, 255, 692, 1216, + 1248, 1520, 1600, 1888, + 3744, 4080, 5888, 8384, + 9344, 9472, 9792, 13312, + 15040, 15360, 20736, 22272, + 23296, 32000, 33536, 37120, + 45824, 47872, 56320, 59392, + 65280, 72704, 101376, 147456, + 161792, 164864, 167936, 173056, + 195584, 209920, 212992, 356352, + 655360, 704512, 716800, 851968, + 901120, 1044480, 1523712, 2572288, + 3211264, 3588096, 3833856, 3866624, + 4325376, 5177344, 6488064, 7012352, + 7471104, 14090240, 16711680, 19398656, + 22282240, 28573696, 30408704, 30670848, + 43253760, 54525952, 55312384, 56623104, + 68157440, 115343360, 131072000, 187695104, + 188743680, 195035136, 197132288, 203423744, + 218103808, 267386880, 268435470, 285212672, + 402653185, 415236096, 595591168, 603979776, + 603979778, 629145600, 1073741835, 1073741855, + 1073741861, 1073741884, 1157627904, 1476395008, + 1476395010, 1610612741, 2030043136, 2080374785, + 2097152000}; } // namespace @@ -1774,7 +1783,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { TRACED_FORRANGE(int32_t, lsb, 0, 31) { - TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { + TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) { StreamBuilder m(this, kMachInt32, kMachInt32); m.Return(m.Word32And( m.Parameter(0), @@ -1791,7 +1800,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { } } TRACED_FORRANGE(int32_t, lsb, 0, 31) { - TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { + TRACED_FORRANGE(int32_t, width, 9, (32 - lsb) - 1) { StreamBuilder m(this, kMachInt32, kMachInt32); m.Return( m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)), -- 2.34.1