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 {
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) {
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);
......
// 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 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <limits>
#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<int32_t>::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)),
......
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