Revision: 24942
Author:   [email protected]
Date:     Tue Oct 28 13:56:26 2014 UTC
Log: [turbofan] Complete support for integer division/modulus in simplified lowering.

Also add backend flags that tell whether integer division/modulus is
generally safe, i.e. does not trap on overflow or divide by zero.

TEST=unittests
[email protected]

Review URL: https://codereview.chromium.org/681133004
https://code.google.com/p/v8/source/detail?r=24942

Modified:
 /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
 /branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
 /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
 /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc
 /branches/bleeding_edge/src/compiler/machine-operator.h
 /branches/bleeding_edge/src/compiler/node-matchers.h
 /branches/bleeding_edge/src/compiler/operator-properties-inl.h
 /branches/bleeding_edge/src/compiler/simplified-lowering.cc
 /branches/bleeding_edge/src/compiler/simplified-lowering.h
 /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
 /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc
/branches/bleeding_edge/test/unittests/compiler/machine-operator-unittest.cc

=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc Fri Oct 24 13:06:48 2014 UTC +++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc Tue Oct 28 13:56:26 2014 UTC
@@ -1139,8 +1139,12 @@
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  return MachineOperatorBuilder::Flag::kNoFlags;
+  return MachineOperatorBuilder::kInt32DivIsSafe |
+         MachineOperatorBuilder::kInt32ModIsSafe |
+         MachineOperatorBuilder::kUint32DivIsSafe |
+         MachineOperatorBuilder::kUint32ModIsSafe;
 }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc Fri Oct 24 15:29:19 2014 UTC +++ /branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc Tue Oct 28 13:56:26 2014 UTC
@@ -1300,8 +1300,9 @@
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  return MachineOperatorBuilder::Flag::kNoFlags;
+  return MachineOperatorBuilder::kNoFlags;
 }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc Fri Oct 24 13:06:48 2014 UTC +++ /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc Tue Oct 28 13:56:26 2014 UTC
@@ -881,8 +881,9 @@
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  return MachineOperatorBuilder::Flag::kNoFlags;
+  return MachineOperatorBuilder::kNoFlags;
 }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Tue Oct 28 11:57:20 2014 UTC +++ /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Tue Oct 28 13:56:26 2014 UTC
@@ -555,6 +555,7 @@
     node->set_op(machine()->Int32Sub());
     node->ReplaceInput(0, Int32Constant(0));
     node->ReplaceInput(1, m.left().node());
+    node->TrimInputCount(2);
     return Changed(node);
   }
   if (m.right().HasValue()) {
@@ -576,6 +577,7 @@
       node->set_op(machine()->Int32Sub());
       node->ReplaceInput(0, Int32Constant(0));
       node->ReplaceInput(1, quotient);
+      node->TrimInputCount(2);
       return Changed(node);
     }
     return Replace(quotient);
@@ -644,6 +646,7 @@
       node->set_op(machine()->Int32Sub());
       DCHECK_EQ(dividend, node->InputAt(0));
       node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
+      node->TrimInputCount(2);
       return Changed(node);
     }
   }
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator.h Mon Oct 27 09:36:51 2014 UTC +++ /branches/bleeding_edge/src/compiler/machine-operator.h Tue Oct 28 13:56:26 2014 UTC
@@ -60,17 +60,21 @@
  public:
   // Flags that specify which operations are available. This is useful
   // for operations that are unsupported by some back-ends.
-  enum class Flag : unsigned {
-    kNoFlags = 0,
-    kFloat64Floor = 1 << 0,
-    kFloat64Ceil = 1 << 1,
-    kFloat64RoundTruncate = 1 << 2,
-    kFloat64RoundTiesAway = 1 << 3
+  enum Flag {
+    kNoFlags = 0u,
+    kFloat64Floor = 1u << 0,
+    kFloat64Ceil = 1u << 1,
+    kFloat64RoundTruncate = 1u << 2,
+    kFloat64RoundTiesAway = 1u << 3,
+    kInt32DivIsSafe = 1u << 4,
+    kInt32ModIsSafe = 1u << 5,
+    kUint32DivIsSafe = 1u << 6,
+    kUint32ModIsSafe = 1u << 7
   };
   typedef base::Flags<Flag, unsigned> Flags;

   explicit MachineOperatorBuilder(MachineType word = kMachPtr,
- Flags supportedOperators = Flag::kNoFlags);
+                                  Flags supportedOperators = kNoFlags);

   const Operator* Word32And();
   const Operator* Word32Or();
@@ -104,6 +108,10 @@
   const Operator* Uint32LessThan();
   const Operator* Uint32LessThanOrEqual();
   const Operator* Uint32Mod();
+  bool Int32DivIsSafe() const { return flags_ & kInt32DivIsSafe; }
+  bool Int32ModIsSafe() const { return flags_ & kInt32ModIsSafe; }
+  bool Uint32DivIsSafe() const { return flags_ & kUint32DivIsSafe; }
+  bool Uint32ModIsSafe() const { return flags_ & kUint32ModIsSafe; }

   const Operator* Int64Add();
   const Operator* Int64Sub();
@@ -153,14 +161,10 @@
   const Operator* Float64Ceil();
   const Operator* Float64RoundTruncate();
   const Operator* Float64RoundTiesAway();
-  bool HasFloat64Floor() { return flags_ & Flag::kFloat64Floor; }
-  bool HasFloat64Ceil() { return flags_ & Flag::kFloat64Ceil; }
-  bool HasFloat64RoundTruncate() {
-    return flags_ & Flag::kFloat64RoundTruncate;
-  }
-  bool HasFloat64RoundTiesAway() {
-    return flags_ & Flag::kFloat64RoundTiesAway;
-  }
+  bool HasFloat64Floor() { return flags_ & kFloat64Floor; }
+  bool HasFloat64Ceil() { return flags_ & kFloat64Ceil; }
+  bool HasFloat64RoundTruncate() { return flags_ & kFloat64RoundTruncate; }
+  bool HasFloat64RoundTiesAway() { return flags_ & kFloat64RoundTiesAway; }

   // load [base + index]
   const Operator* Load(LoadRepresentation rep);
=======================================
--- /branches/bleeding_edge/src/compiler/node-matchers.h Tue Oct 28 08:28:36 2014 UTC +++ /branches/bleeding_edge/src/compiler/node-matchers.h Tue Oct 28 13:56:26 2014 UTC
@@ -139,6 +139,7 @@
 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher;
 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher;
 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
+typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;


 // Fairly intel-specify node matcher used for matching scale factors in
=======================================
--- /branches/bleeding_edge/src/compiler/operator-properties-inl.h Tue Oct 28 13:00:11 2014 UTC +++ /branches/bleeding_edge/src/compiler/operator-properties-inl.h Tue Oct 28 13:56:26 2014 UTC
@@ -123,6 +123,10 @@
     case IrOpcode::kEffectPhi:
     case IrOpcode::kLoad:
     case IrOpcode::kLoadField:
+    case IrOpcode::kInt32Div:
+    case IrOpcode::kInt32Mod:
+    case IrOpcode::kUint32Div:
+    case IrOpcode::kUint32Mod:
       return 1;
 #define OPCODE_CASE(x) case IrOpcode::k##x:
       CONTROL_OP_LIST(OPCODE_CASE)
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-lowering.cc Tue Oct 28 13:00:11 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-lowering.cc Tue Oct 28 13:56:26 2014 UTC
@@ -605,19 +605,17 @@
         break;
       }
       case IrOpcode::kNumberDivide: {
-        NumberMatcher right(node->InputAt(1));
-        if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
-          if (CanLowerToInt32Binop(node, use)) {
-            // => signed Int32Div
-            VisitInt32Binop(node);
-            if (lower()) node->set_op(Int32Op(node));
-            break;
-          } else if (CanLowerToUint32Binop(node, use)) {
-            // => unsigned Uint32Div
-            VisitUint32Binop(node);
-            if (lower()) node->set_op(Uint32Op(node));
-            break;
-          }
+        if (CanLowerToInt32Binop(node, use)) {
+          // => signed Int32Div
+          VisitInt32Binop(node);
+          if (lower()) DeferReplacement(node, lowering->Int32Div(node));
+          break;
+        }
+        if (CanLowerToUint32Binop(node, use)) {
+          // => unsigned Uint32Div
+          VisitUint32Binop(node);
+          if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
+          break;
         }
         // => Float64Div
         VisitFloat64Binop(node);
@@ -625,20 +623,17 @@
         break;
       }
       case IrOpcode::kNumberModulus: {
-        NumberMatcher right(node->InputAt(1));
-        if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
-          if (BothInputsAre(node, Type::Signed32()) &&
-              !CanObserveMinusZero(use)) {
-            // => signed Int32Mod
-            VisitInt32Binop(node);
-            if (lower()) node->set_op(Int32Op(node));
-            break;
-          } else if (BothInputsAre(node, Type::Unsigned32())) {
-            // => unsigned Uint32Mod
-            VisitUint32Binop(node);
-            if (lower()) node->set_op(Uint32Op(node));
-            break;
-          }
+        if (CanLowerToInt32Binop(node, use)) {
+          // => signed Int32Mod
+          VisitInt32Binop(node);
+          if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
+          break;
+        }
+        if (CanLowerToUint32Binop(node, use)) {
+          // => unsigned Uint32Mod
+          VisitUint32Binop(node);
+          if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
+          break;
         }
         // => Float64Mod
         VisitFloat64Binop(node);
@@ -1216,6 +1211,148 @@
                           jsgraph()->Int32Constant(2),
                           jsgraph()->UndefinedConstant());
 }
+
+
+Node* SimplifiedLowering::Int32Div(Node* const node) {
+  Int32BinopMatcher m(node);
+  Node* const zero = jsgraph()->Int32Constant(0);
+  Node* const lhs = m.left().node();
+  Node* const rhs = m.right().node();
+
+  if (m.right().Is(-1)) {
+    return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
+  } else if (m.right().Is(0)) {
+    return rhs;
+  } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
+ return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
+  }
+
+  Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
+ Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
+                                   graph()->start());
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* true0 = zero;
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* false0 = nullptr;
+  {
+    Node* check1 = graph()->NewNode(machine()->Word32Equal(), rhs,
+                                    jsgraph()->Int32Constant(-1));
+    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                     check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* true1 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* false1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_false1);
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    false0 = graph()->NewNode(common()->Phi(kMachInt32, 2), true1, false1,
+                              if_false0);
+  }
+
+  Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ return graph()->NewNode(common()->Phi(kMachInt32, 2), true0, false0, merge0);
+}
+
+
+Node* SimplifiedLowering::Int32Mod(Node* const node) {
+  Int32BinopMatcher m(node);
+  Node* const zero = jsgraph()->Int32Constant(0);
+  Node* const lhs = m.left().node();
+  Node* const rhs = m.right().node();
+
+  if (m.right().Is(-1) || m.right().Is(0)) {
+    return zero;
+  } else if (machine()->Int32ModIsSafe() || m.right().HasValue()) {
+ return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
+  }
+
+  Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
+ Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
+                                   graph()->start());
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* true0 = zero;
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* false0 = nullptr;
+  {
+    Node* check1 = graph()->NewNode(machine()->Word32Equal(), rhs,
+                                    jsgraph()->Int32Constant(-1));
+    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                     check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* true1 = zero;
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* false1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false1);
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    false0 = graph()->NewNode(common()->Phi(kMachInt32, 2), true1, false1,
+                              if_false0);
+  }
+
+  Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ return graph()->NewNode(common()->Phi(kMachInt32, 2), true0, false0, merge0);
+}
+
+
+Node* SimplifiedLowering::Uint32Div(Node* const node) {
+  Uint32BinopMatcher m(node);
+  Node* const zero = jsgraph()->Uint32Constant(0);
+  Node* const lhs = m.left().node();
+  Node* const rhs = m.right().node();
+
+  if (m.right().Is(0)) {
+    return zero;
+  } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
+ return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
+  }
+
+  Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
+ Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), check,
+                                  graph()->start());
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* vtrue = zero;
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* vfalse = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, if_false);
+
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ return graph()->NewNode(common()->Phi(kMachUint32, 2), vtrue, vfalse, merge);
+}
+
+
+Node* SimplifiedLowering::Uint32Mod(Node* const node) {
+  Uint32BinopMatcher m(node);
+  Node* const zero = jsgraph()->Uint32Constant(0);
+  Node* const lhs = m.left().node();
+  Node* const rhs = m.right().node();
+
+  if (m.right().Is(0)) {
+    return zero;
+  } else if (machine()->Uint32ModIsSafe() || m.right().HasValue()) {
+ return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
+  }
+
+  Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
+ Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), check,
+                                  graph()->start());
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* vtrue = zero;
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* vfalse = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_false);
+
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ return graph()->NewNode(common()->Phi(kMachUint32, 2), vtrue, vfalse, merge);
+}


 void SimplifiedLowering::DoStringEqual(Node* node) {
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-lowering.h Wed Oct 8 11:16:45 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-lowering.h Tue Oct 28 13:56:26 2014 UTC
@@ -42,6 +42,10 @@
   Node* OffsetMinusTagConstant(int32_t offset);
   Node* ComputeIndex(const ElementAccess& access, Node* index);
   Node* StringComparison(Node* node, bool requires_ordering);
+  Node* Int32Div(Node* const node);
+  Node* Int32Mod(Node* const node);
+  Node* Uint32Div(Node* const node);
+  Node* Uint32Mod(Node* const node);

   friend class RepresentationSelector;

=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc Mon Oct 27 22:33:52 2014 UTC +++ /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc Tue Oct 28 13:56:26 2014 UTC
@@ -1112,8 +1112,9 @@
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  return MachineOperatorBuilder::Flag::kNoFlags;
+  return MachineOperatorBuilder::kNoFlags;
 }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc Mon Oct 27 22:33:52 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc Tue Oct 28 13:56:26 2014 UTC
@@ -1720,11 +1720,11 @@
     TestingGraph t(Type::Signed32());
     Node* k = t.jsgraph.Constant(constants[i]);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
-    Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div);
-    t.Return(trunc);
+    Node* use = t.Use(div, kMachInt32);
+    t.Return(use);
     t.Lower();

-    CHECK_EQ(IrOpcode::kInt32Div, div->opcode());
+    CHECK_EQ(IrOpcode::kInt32Div, use->InputAt(0)->opcode());
   }
 }

@@ -1761,11 +1761,11 @@
     TestingGraph t(Type::Unsigned32());
     Node* k = t.jsgraph.Constant(constants[i]);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); - Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div);
-    t.Return(trunc);
+    Node* use = t.Use(div, kMachUint32);
+    t.Return(use);
     t.Lower();

-    CHECK_EQ(IrOpcode::kUint32Div, div->opcode());
+    CHECK_EQ(IrOpcode::kUint32Div, use->InputAt(0)->opcode());
   }
 }

@@ -1795,28 +1795,39 @@


 TEST(NumberDivide_BadConstants) {
-  int32_t constants[] = {-1, 0};
+  {
+    TestingGraph t(Type::Signed32());
+    Node* k = t.jsgraph.Constant(-1);
+ Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
+    Node* use = t.Use(div, kMachInt32);
+    t.Return(use);
+    t.Lower();

-  for (size_t i = 0; i < arraysize(constants); i++) {
+    CHECK_EQ(IrOpcode::kInt32Sub, use->InputAt(0)->opcode());
+  }
+
+  {
     TestingGraph t(Type::Signed32());
-    Node* k = t.jsgraph.Constant(constants[i]);
+    Node* k = t.jsgraph.Constant(0);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
-    Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div);
-    t.Return(trunc);
+    Node* use = t.Use(div, kMachInt32);
+    t.Return(use);
     t.Lower();

-    CHECK_EQ(IrOpcode::kFloat64Div, div->opcode());
+    CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
+    CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
   }

   {
     TestingGraph t(Type::Unsigned32());
     Node* k = t.jsgraph.Constant(0);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); - Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div);
-    t.Return(trunc);
+    Node* use = t.Use(div, kMachUint32);
+    t.Return(use);
     t.Lower();

-    CHECK_EQ(IrOpcode::kFloat64Div, div->opcode());
+    CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
+    CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
   }
 }

@@ -1828,11 +1839,11 @@
     TestingGraph t(Type::Signed32());
     Node* k = t.jsgraph.Constant(constants[i]);
Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
-    Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod);
-    t.Return(trunc);
+    Node* use = t.Use(mod, kMachInt32);
+    t.Return(use);
     t.Lower();

-    CHECK_EQ(IrOpcode::kInt32Mod, mod->opcode());
+    CHECK_EQ(IrOpcode::kInt32Mod, use->InputAt(0)->opcode());
   }
 }

@@ -1870,10 +1881,10 @@
     Node* k = t.jsgraph.Constant(constants[i]);
Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
-    t.Return(trunc);
+    Node* ret = t.Return(trunc);
     t.Lower();

-    CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode());
+    CHECK_EQ(IrOpcode::kUint32Mod, ret->InputAt(0)->opcode());
   }
 }

@@ -1916,45 +1927,3 @@
     CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode());  // Pesky -0 behavior.
   }
 }
-
-
-TEST(NumberModulus_Uint32) {
-  double constants[] = {1, 3, 100, 1000, 100998348};
-
-  for (size_t i = 0; i < arraysize(constants); i++) {
-    TestingGraph t(Type::Unsigned32());
-    Node* k = t.jsgraph.Constant(constants[i]);
- Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
-    t.Return(mod);
-    t.Lower();
-
-    CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode());
-  }
-}
-
-
-TEST(NumberModulus_BadConstants) {
-  int32_t constants[] = {-1, 0};
-
-  for (size_t i = 0; i < arraysize(constants); i++) {
-    TestingGraph t(Type::Signed32());
-    Node* k = t.jsgraph.Constant(constants[i]);
- Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
-    Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod);
-    t.Return(trunc);
-    t.Lower();
-
-    CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode());
-  }
-
-  {
-    TestingGraph t(Type::Unsigned32());
-    Node* k = t.jsgraph.Constant(0);
- Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); - Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
-    t.Return(trunc);
-    t.Lower();
-
-    CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode());
-  }
-}
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/machine-operator-unittest.cc Fri Oct 24 13:06:48 2014 UTC +++ /branches/bleeding_edge/test/unittests/compiler/machine-operator-unittest.cc Tue Oct 28 13:56:26 2014 UTC
@@ -158,6 +158,7 @@
   const Operator* (MachineOperatorBuilder::*constructor)();
   IrOpcode::Value opcode;
   int value_input_count;
+  int control_input_count;
   int value_output_count;
 };

@@ -168,43 +169,41 @@


 const PureOperator kPureOperators[] = {
-#define PURE(Name, input_count, output_count)                      \
-  {                                                                \
-    &MachineOperatorBuilder::Name, IrOpcode::k##Name, input_count, \
-        output_count                                               \
+#define PURE(Name, value_input_count, control_input_count, value_output_count) \ + { \ + &MachineOperatorBuilder::Name, IrOpcode::k##Name, value_input_count, \ + control_input_count, value_output_count \
   }
-    PURE(Word32And, 2, 1),                PURE(Word32Or, 2, 1),
-    PURE(Word32Xor, 2, 1),                PURE(Word32Shl, 2, 1),
-    PURE(Word32Shr, 2, 1),                PURE(Word32Sar, 2, 1),
-    PURE(Word32Ror, 2, 1),                PURE(Word32Equal, 2, 1),
-    PURE(Word64And, 2, 1),                PURE(Word64Or, 2, 1),
-    PURE(Word64Xor, 2, 1),                PURE(Word64Shl, 2, 1),
-    PURE(Word64Shr, 2, 1),                PURE(Word64Sar, 2, 1),
-    PURE(Word64Ror, 2, 1),                PURE(Word64Equal, 2, 1),
-    PURE(Int32Add, 2, 1),                 PURE(Int32AddWithOverflow, 2, 2),
-    PURE(Int32Sub, 2, 1),                 PURE(Int32SubWithOverflow, 2, 2),
-    PURE(Int32Mul, 2, 1),                 PURE(Int32MulHigh, 2, 1),
-    PURE(Int32Div, 2, 1),                 PURE(Uint32Div, 2, 1),
-    PURE(Int32Mod, 2, 1),                 PURE(Uint32Mod, 2, 1),
-    PURE(Int32LessThan, 2, 1),            PURE(Int32LessThanOrEqual, 2, 1),
- PURE(Uint32LessThan, 2, 1), PURE(Uint32LessThanOrEqual, 2, 1),
-    PURE(Int64Add, 2, 1),                 PURE(Int64Sub, 2, 1),
-    PURE(Int64Mul, 2, 1),                 PURE(Int64Div, 2, 1),
-    PURE(Uint64Div, 2, 1),                PURE(Int64Mod, 2, 1),
-    PURE(Uint64Mod, 2, 1),                PURE(Int64LessThan, 2, 1),
-    PURE(Int64LessThanOrEqual, 2, 1),     PURE(Uint64LessThan, 2, 1),
-    PURE(ChangeFloat32ToFloat64, 1, 1),   PURE(ChangeFloat64ToInt32, 1, 1),
-    PURE(ChangeFloat64ToUint32, 1, 1),    PURE(ChangeInt32ToInt64, 1, 1),
-    PURE(ChangeUint32ToFloat64, 1, 1),    PURE(ChangeUint32ToUint64, 1, 1),
- PURE(TruncateFloat64ToFloat32, 1, 1), PURE(TruncateFloat64ToInt32, 1, 1),
-    PURE(TruncateInt64ToInt32, 1, 1),     PURE(Float64Add, 2, 1),
-    PURE(Float64Sub, 2, 1),               PURE(Float64Mul, 2, 1),
-    PURE(Float64Div, 2, 1),               PURE(Float64Mod, 2, 1),
-    PURE(Float64Sqrt, 1, 1),              PURE(Float64Equal, 2, 1),
- PURE(Float64LessThan, 2, 1), PURE(Float64LessThanOrEqual, 2, 1),
-    PURE(LoadStackPointer, 0, 1),         PURE(Float64Floor, 1, 1),
-    PURE(Float64Ceil, 1, 1),              PURE(Float64RoundTruncate, 1, 1),
-    PURE(Float64RoundTiesAway, 1, 1),
+ PURE(Word32And, 2, 0, 1), PURE(Word32Or, 2, 0, 1), PURE(Word32Xor, 2, 0, 1),
+    PURE(Word32Shl, 2, 0, 1), PURE(Word32Shr, 2, 0, 1),
+    PURE(Word32Sar, 2, 0, 1), PURE(Word32Ror, 2, 0, 1),
+    PURE(Word32Equal, 2, 0, 1), PURE(Word64And, 2, 0, 1),
+ PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1), PURE(Word64Shl, 2, 0, 1),
+    PURE(Word64Shr, 2, 0, 1), PURE(Word64Sar, 2, 0, 1),
+    PURE(Word64Ror, 2, 0, 1), PURE(Word64Equal, 2, 0, 1),
+    PURE(Int32Add, 2, 0, 1), PURE(Int32AddWithOverflow, 2, 0, 2),
+    PURE(Int32Sub, 2, 0, 1), PURE(Int32SubWithOverflow, 2, 0, 2),
+    PURE(Int32Mul, 2, 0, 1), PURE(Int32MulHigh, 2, 0, 1),
+ PURE(Int32Div, 2, 1, 1), PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1),
+    PURE(Uint32Mod, 2, 1, 1), PURE(Int32LessThan, 2, 0, 1),
+    PURE(Int32LessThanOrEqual, 2, 0, 1), PURE(Uint32LessThan, 2, 0, 1),
+    PURE(Uint32LessThanOrEqual, 2, 0, 1), PURE(Int64Add, 2, 0, 1),
+ PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1), PURE(Int64Div, 2, 0, 1), + PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1), PURE(Uint64Mod, 2, 0, 1),
+    PURE(Int64LessThan, 2, 0, 1), PURE(Int64LessThanOrEqual, 2, 0, 1),
+    PURE(Uint64LessThan, 2, 0, 1), PURE(ChangeFloat32ToFloat64, 1, 0, 1),
+ PURE(ChangeFloat64ToInt32, 1, 0, 1), PURE(ChangeFloat64ToUint32, 1, 0, 1), + PURE(ChangeInt32ToInt64, 1, 0, 1), PURE(ChangeUint32ToFloat64, 1, 0, 1),
+    PURE(ChangeUint32ToUint64, 1, 0, 1),
+    PURE(TruncateFloat64ToFloat32, 1, 0, 1),
+ PURE(TruncateFloat64ToInt32, 1, 0, 1), PURE(TruncateInt64ToInt32, 1, 0, 1),
+    PURE(Float64Add, 2, 0, 1), PURE(Float64Sub, 2, 0, 1),
+    PURE(Float64Mul, 2, 0, 1), PURE(Float64Div, 2, 0, 1),
+    PURE(Float64Mod, 2, 0, 1), PURE(Float64Sqrt, 1, 0, 1),
+    PURE(Float64Equal, 2, 0, 1), PURE(Float64LessThan, 2, 0, 1),
+    PURE(Float64LessThanOrEqual, 2, 0, 1), PURE(LoadStackPointer, 0, 0, 1),
+    PURE(Float64Floor, 1, 0, 1), PURE(Float64Ceil, 1, 0, 1),
+ PURE(Float64RoundTruncate, 1, 0, 1), PURE(Float64RoundTiesAway, 1, 0, 1)
 #undef PURE
 };

@@ -229,8 +228,10 @@

EXPECT_EQ(pop.value_input_count, OperatorProperties::GetValueInputCount(op));
   EXPECT_EQ(0, OperatorProperties::GetEffectInputCount(op));
-  EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op));
- EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op));
+  EXPECT_EQ(pop.control_input_count,
+            OperatorProperties::GetControlInputCount(op));
+  EXPECT_EQ(pop.value_input_count + pop.control_input_count,
+            OperatorProperties::GetTotalInputCount(op));

   EXPECT_EQ(pop.value_output_count,
             OperatorProperties::GetValueOutputCount(op));

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to