Commit fe6656fb authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[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
parent e918a842
...@@ -23,6 +23,14 @@ class ArmOperandGenerator : public OperandGenerator { ...@@ -23,6 +23,14 @@ class ArmOperandGenerator : public OperandGenerator {
return UseRegister(node); return UseRegister(node);
} }
bool CanBeImmediate(int32_t value) const {
return Assembler::ImmediateFitsAddrMode1Instruction(value);
}
bool CanBeImmediate(uint32_t value) const {
return CanBeImmediate(bit_cast<int32_t>(value));
}
bool CanBeImmediate(Node* node, InstructionCode opcode) { bool CanBeImmediate(Node* node, InstructionCode opcode) {
Int32Matcher m(node); Int32Matcher m(node);
if (!m.HasValue()) return false; if (!m.HasValue()) return false;
...@@ -32,22 +40,20 @@ class ArmOperandGenerator : public OperandGenerator { ...@@ -32,22 +40,20 @@ class ArmOperandGenerator : public OperandGenerator {
case kArmMov: case kArmMov:
case kArmMvn: case kArmMvn:
case kArmBic: case kArmBic:
return ImmediateFitsAddrMode1Instruction(value) || return CanBeImmediate(value) || CanBeImmediate(~value);
ImmediateFitsAddrMode1Instruction(~value);
case kArmAdd: case kArmAdd:
case kArmSub: case kArmSub:
case kArmCmp: case kArmCmp:
case kArmCmn: case kArmCmn:
return ImmediateFitsAddrMode1Instruction(value) || return CanBeImmediate(value) || CanBeImmediate(-value);
ImmediateFitsAddrMode1Instruction(-value);
case kArmTst: case kArmTst:
case kArmTeq: case kArmTeq:
case kArmOrr: case kArmOrr:
case kArmEor: case kArmEor:
case kArmRsb: case kArmRsb:
return ImmediateFitsAddrMode1Instruction(value); return CanBeImmediate(value);
case kArmVldrF32: case kArmVldrF32:
case kArmVstrF32: case kArmVstrF32:
...@@ -106,11 +112,6 @@ class ArmOperandGenerator : public OperandGenerator { ...@@ -106,11 +112,6 @@ class ArmOperandGenerator : public OperandGenerator {
UNREACHABLE(); UNREACHABLE();
return false; return false;
} }
private:
bool ImmediateFitsAddrMode1Instruction(int32_t imm) const {
return Assembler::ImmediateFitsAddrMode1Instruction(imm);
}
}; };
...@@ -417,7 +418,8 @@ void InstructionSelector::VisitWord32And(Node* node) { ...@@ -417,7 +418,8 @@ void InstructionSelector::VisitWord32And(Node* node) {
} }
} }
if (IsSupported(ARMv7) && m.right().HasValue()) { 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 width = base::bits::CountPopulation32(value);
uint32_t msb = base::bits::CountLeadingZeros32(value); uint32_t msb = base::bits::CountLeadingZeros32(value);
if (width != 0 && msb + width == 32) { if (width != 0 && msb + width == 32) {
...@@ -435,6 +437,15 @@ void InstructionSelector::VisitWord32And(Node* node) { ...@@ -435,6 +437,15 @@ void InstructionSelector::VisitWord32And(Node* node) {
g.TempImmediate(0), g.TempImmediate(width)); g.TempImmediate(0), g.TempImmediate(width));
return; 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. // Try to interpret this AND as BFC.
width = 32 - width; width = 32 - width;
msb = base::bits::CountLeadingZeros32(~value); msb = base::bits::CountLeadingZeros32(~value);
......
// 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));
}
}
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <limits>
#include "test/unittests/compiler/instruction-selector-unittest.h" #include "test/unittests/compiler/instruction-selector-unittest.h"
namespace v8 { namespace v8 {
...@@ -86,30 +88,37 @@ static const Shift kShifts[] = { ...@@ -86,30 +88,37 @@ static const Shift kShifts[] = {
// Immediates (random subset). // Immediates (random subset).
static const int32_t kImmediates[] = { static const int32_t kImmediates[] = {
-2147483617, -2147483606, -2113929216, -2080374784, -1996488704, std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216,
-1879048192, -1459617792, -1358954496, -1342177265, -1275068414, -2080374784, -1996488704, -1879048192, -1459617792,
-1073741818, -1073741777, -855638016, -805306368, -402653184, -1358954496, -1342177265, -1275068414, -1073741818,
-268435444, -16777216, 0, 35, 61, -1073741777, -855638016, -805306368, -402653184,
105, 116, 171, 245, 255, -268435444, -16777216, 0, 35,
692, 1216, 1248, 1520, 1600, 61, 105, 116, 171,
1888, 3744, 4080, 5888, 8384, 245, 255, 692, 1216,
9344, 9472, 9792, 13312, 15040, 1248, 1520, 1600, 1888,
15360, 20736, 22272, 23296, 32000, 3744, 4080, 5888, 8384,
33536, 37120, 45824, 47872, 56320, 9344, 9472, 9792, 13312,
59392, 65280, 72704, 101376, 147456, 15040, 15360, 20736, 22272,
161792, 164864, 167936, 173056, 195584, 23296, 32000, 33536, 37120,
209920, 212992, 356352, 655360, 704512, 45824, 47872, 56320, 59392,
716800, 851968, 901120, 1044480, 1523712, 65280, 72704, 101376, 147456,
2572288, 3211264, 3588096, 3833856, 3866624, 161792, 164864, 167936, 173056,
4325376, 5177344, 6488064, 7012352, 7471104, 195584, 209920, 212992, 356352,
14090240, 16711680, 19398656, 22282240, 28573696, 655360, 704512, 716800, 851968,
30408704, 30670848, 43253760, 54525952, 55312384, 901120, 1044480, 1523712, 2572288,
56623104, 68157440, 115343360, 131072000, 187695104, 3211264, 3588096, 3833856, 3866624,
188743680, 195035136, 197132288, 203423744, 218103808, 4325376, 5177344, 6488064, 7012352,
267386880, 268435470, 285212672, 402653185, 415236096, 7471104, 14090240, 16711680, 19398656,
595591168, 603979776, 603979778, 629145600, 1073741835, 22282240, 28573696, 30408704, 30670848,
1073741855, 1073741861, 1073741884, 1157627904, 1476395008, 43253760, 54525952, 55312384, 56623104,
1476395010, 1610612741, 2030043136, 2080374785, 2097152000}; 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 } // namespace
...@@ -1774,7 +1783,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { ...@@ -1774,7 +1783,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
TRACED_FORRANGE(int32_t, lsb, 0, 31) { 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); StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Word32And( m.Return(m.Word32And(
m.Parameter(0), m.Parameter(0),
...@@ -1791,7 +1800,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { ...@@ -1791,7 +1800,7 @@ TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) {
} }
} }
TRACED_FORRANGE(int32_t, lsb, 0, 31) { 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); StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return( m.Return(
m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)), m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment