[arm] Prefer BIC over BFC.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 17 Oct 2014 07:07:54 +0000 (07:07 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 17 Oct 2014 07:07:54 +0000 (07:07 +0000)
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
test/mjsunit/asm/word32and.js [new file with mode: 0644]
test/unittests/compiler/arm/instruction-selector-arm-unittest.cc

index 19ba71c..ed58bba 100644 (file)
@@ -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);
diff --git a/test/mjsunit/asm/word32and.js b/test/mjsunit/asm/word32and.js
new file mode 100644 (file)
index 0000000..6c41f88
--- /dev/null
@@ -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));
+  }
+}
index 0c71d2f..9d87900 100644 (file)
@@ -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)),