Index: src/compiler/machine-operator-reducer.cc |
diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc |
index cdb21822a8fe5d66c6dbf8e368d122851256e893..6d02272a3405baac24f6a9da1018867157de82de 100644 |
--- a/src/compiler/machine-operator-reducer.cc |
+++ b/src/compiler/machine-operator-reducer.cc |
@@ -5,6 +5,7 @@ |
#include "src/compiler/machine-operator-reducer.h" |
#include "src/base/bits.h" |
+#include "src/base/division-by-constant.h" |
#include "src/codegen.h" |
#include "src/compiler/generic-node-inl.h" |
#include "src/compiler/graph.h" |
@@ -42,6 +43,54 @@ Node* MachineOperatorReducer::Int64Constant(int64_t value) { |
} |
+Node* MachineOperatorReducer::Word32And(Node* lhs, uint32_t rhs) { |
+ return graph()->NewNode(machine()->Word32And(), lhs, Uint32Constant(rhs)); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { |
+ return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { |
+ return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { |
+ return graph()->NewNode(machine()->Int32Add(), lhs, rhs); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { |
+ return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) { |
+ return graph()->NewNode(machine()->Int32Mul(), lhs, rhs); |
+} |
+ |
+ |
+Node* MachineOperatorReducer::TruncatingDiv(Node* dividend, int32_t divisor) { |
+ DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor); |
+ base::MagicNumbersForDivision<uint32_t> const mag = |
+ base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor)); |
+ Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend, |
+ Uint32Constant(mag.multiplier)); |
+ if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) { |
+ quotient = Int32Add(quotient, dividend); |
+ } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) { |
+ quotient = Int32Sub(quotient, dividend); |
+ } |
+ if (mag.shift) { |
+ quotient = Word32Sar(quotient, mag.shift); |
+ } |
+ return Int32Add(quotient, Word32Shr(dividend, 31)); |
+} |
+ |
+ |
// Perform constant folding and strength reduction on machine operators. |
Reduction MachineOperatorReducer::Reduce(Node* node) { |
switch (node->opcode()) { |
@@ -227,25 +276,8 @@ Reduction MachineOperatorReducer::Reduce(Node* node) { |
} |
break; |
} |
- case IrOpcode::kInt32Div: { |
- Int32BinopMatcher m(node); |
- if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
- // TODO(turbofan): if (m.left().Is(0)) |
- // TODO(turbofan): if (m.right().IsPowerOf2()) |
- // TODO(turbofan): if (m.right().Is(0)) |
- // TODO(turbofan): if (m.LeftEqualsRight()) |
- if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K |
- if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); |
- return ReplaceInt32(m.left().Value() / m.right().Value()); |
- } |
- if (m.right().Is(-1)) { // x / -1 => 0 - x |
- node->set_op(machine()->Int32Sub()); |
- node->ReplaceInput(0, Int32Constant(0)); |
- node->ReplaceInput(1, m.left().node()); |
- return Changed(node); |
- } |
- break; |
- } |
+ case IrOpcode::kInt32Div: |
+ return ReduceInt32Div(node); |
case IrOpcode::kUint32Div: { |
Uint32BinopMatcher m(node); |
if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
@@ -499,7 +531,50 @@ Reduction MachineOperatorReducer::Reduce(Node* node) { |
} |
-Reduction MachineOperatorReducer::ReduceInt32Mod(Node* const node) { |
+Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { |
+ Int32BinopMatcher m(node); |
+ if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 |
+ if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
+ // TODO(turbofan): if (m.left().Is(0)) |
+ // TODO(turbofan): if (m.LeftEqualsRight()) |
+ if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K |
+ if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); |
+ return ReplaceInt32(m.left().Value() / m.right().Value()); |
+ } |
+ if (m.right().Is(-1)) { // x / -1 => 0 - x |
+ node->set_op(machine()->Int32Sub()); |
+ node->ReplaceInput(0, Int32Constant(0)); |
+ node->ReplaceInput(1, m.left().node()); |
+ return Changed(node); |
+ } |
+ if (m.right().HasValue()) { |
+ int32_t const divisor = m.right().Value(); |
+ Node* const dividend = m.left().node(); |
+ Node* quotient = dividend; |
+ if (base::bits::IsPowerOfTwo32(Abs(divisor))) { |
+ uint32_t const shift = WhichPowerOf2Abs(divisor); |
+ DCHECK_NE(0, shift); |
+ if (shift > 1) { |
+ quotient = Word32Sar(quotient, 31); |
+ } |
+ quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend); |
+ quotient = Word32Sar(quotient, shift); |
+ } else { |
+ quotient = TruncatingDiv(quotient, Abs(divisor)); |
+ } |
+ if (divisor < 0) { |
+ node->set_op(machine()->Int32Sub()); |
+ node->ReplaceInput(0, Int32Constant(0)); |
+ node->ReplaceInput(1, quotient); |
+ return Changed(node); |
+ } |
+ return Replace(quotient); |
+ } |
+ return NoChange(); |
+} |
+ |
+ |
+Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) { |
Int32BinopMatcher m(node); |
if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 |
if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 |
@@ -509,29 +584,35 @@ Reduction MachineOperatorReducer::ReduceInt32Mod(Node* const node) { |
if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K |
return ReplaceInt32(m.left().Value() % m.right().Value()); |
} |
- if (m.right().IsPowerOf2()) { |
- int32_t const divisor = m.right().Value(); |
- Node* zero = Int32Constant(0); |
- Node* mask = Int32Constant(divisor - 1); |
- Node* dividend = m.left().node(); |
- |
- Node* check = graph()->NewNode(machine()->Int32LessThan(), dividend, zero); |
- Node* branch = |
- graph()->NewNode(common()->Branch(), check, graph()->start()); |
- |
- Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
- Node* neg = graph()->NewNode( |
- machine()->Int32Sub(), zero, |
- graph()->NewNode( |
- machine()->Word32And(), |
- graph()->NewNode(machine()->Int32Sub(), zero, dividend), mask)); |
- |
- Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
- Node* pos = graph()->NewNode(machine()->Word32And(), dividend, mask); |
- |
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
- Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 2), neg, pos, merge); |
- return Replace(phi); |
+ if (m.right().HasValue()) { |
+ Node* const dividend = m.left().node(); |
+ int32_t const divisor = Abs(m.right().Value()); |
+ if (base::bits::IsPowerOfTwo32(divisor)) { |
+ uint32_t const mask = divisor - 1; |
+ Node* const zero = Int32Constant(0); |
+ |
+ Node* check = |
+ graph()->NewNode(machine()->Int32LessThan(), dividend, zero); |
+ Node* branch = |
+ graph()->NewNode(common()->Branch(), check, graph()->start()); |
+ |
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* neg = Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)); |
+ |
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* pos = Word32And(dividend, mask); |
+ |
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
+ Node* phi = |
+ graph()->NewNode(common()->Phi(kMachInt32, 2), neg, pos, merge); |
+ return Replace(phi); |
+ } else { |
+ Node* quotient = TruncatingDiv(dividend, divisor); |
+ node->set_op(machine()->Int32Sub()); |
+ DCHECK_EQ(dividend, node->InputAt(0)); |
+ node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor))); |
+ return Changed(node); |
+ } |
} |
return NoChange(); |
} |