| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/machine-operator-reducer.h" | 5 #include "src/compiler/machine-operator-reducer.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/compiler/common-node-cache.h" | |
| 9 #include "src/compiler/generic-node-inl.h" | 8 #include "src/compiler/generic-node-inl.h" |
| 10 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
| 10 #include "src/compiler/js-graph.h" |
| 11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 namespace compiler { | 15 namespace compiler { |
| 16 | 16 |
| 17 MachineOperatorReducer::MachineOperatorReducer(Graph* graph) | 17 MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph) |
| 18 : graph_(graph), | 18 : jsgraph_(jsgraph), machine_(jsgraph->zone()) {} |
| 19 cache_(new (graph->zone()) CommonNodeCache(graph->zone())), | |
| 20 common_(graph->zone()), | |
| 21 machine_(graph->zone()) {} | |
| 22 | 19 |
| 23 | 20 |
| 24 MachineOperatorReducer::MachineOperatorReducer(Graph* graph, | 21 MachineOperatorReducer::~MachineOperatorReducer() {} |
| 25 CommonNodeCache* cache) | |
| 26 : graph_(graph), | |
| 27 cache_(cache), | |
| 28 common_(graph->zone()), | |
| 29 machine_(graph->zone()) {} | |
| 30 | 22 |
| 31 | 23 |
| 32 Node* MachineOperatorReducer::Float64Constant(volatile double value) { | 24 Node* MachineOperatorReducer::Float64Constant(volatile double value) { |
| 33 Node** loc = cache_->FindFloat64Constant(value); | 25 return jsgraph()->Float64Constant(value); |
| 34 if (*loc == NULL) { | |
| 35 *loc = graph_->NewNode(common_.Float64Constant(value)); | |
| 36 } | |
| 37 return *loc; | |
| 38 } | 26 } |
| 39 | 27 |
| 40 | 28 |
| 41 Node* MachineOperatorReducer::Int32Constant(int32_t value) { | 29 Node* MachineOperatorReducer::Int32Constant(int32_t value) { |
| 42 Node** loc = cache_->FindInt32Constant(value); | 30 return jsgraph()->Int32Constant(value); |
| 43 if (*loc == NULL) { | |
| 44 *loc = graph_->NewNode(common_.Int32Constant(value)); | |
| 45 } | |
| 46 return *loc; | |
| 47 } | 31 } |
| 48 | 32 |
| 49 | 33 |
| 50 Node* MachineOperatorReducer::Int64Constant(int64_t value) { | 34 Node* MachineOperatorReducer::Int64Constant(int64_t value) { |
| 51 return graph_->NewNode(common_.Int64Constant(value)); | 35 return graph()->NewNode(common()->Int64Constant(value)); |
| 52 } | 36 } |
| 53 | 37 |
| 54 | 38 |
| 55 // Perform constant folding and strength reduction on machine operators. | 39 // Perform constant folding and strength reduction on machine operators. |
| 56 Reduction MachineOperatorReducer::Reduce(Node* node) { | 40 Reduction MachineOperatorReducer::Reduce(Node* node) { |
| 57 switch (node->opcode()) { | 41 switch (node->opcode()) { |
| 58 case IrOpcode::kWord32And: { | 42 case IrOpcode::kWord32And: { |
| 59 Int32BinopMatcher m(node); | 43 Int32BinopMatcher m(node); |
| 60 if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0 | 44 if (m.right().Is(0)) return Replace(m.right().node()); // x & 0 => 0 |
| 61 if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x | 45 if (m.right().Is(-1)) return Replace(m.left().node()); // x & -1 => x |
| (...skipping 13 matching lines...) Expand all Loading... |
| 75 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x | 59 if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x |
| 76 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) { | 60 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) { |
| 77 Int32BinopMatcher mleft(m.left().node()); | 61 Int32BinopMatcher mleft(m.left().node()); |
| 78 Int32BinopMatcher mright(m.right().node()); | 62 Int32BinopMatcher mright(m.right().node()); |
| 79 if (mleft.left().node() == mright.left().node()) { | 63 if (mleft.left().node() == mright.left().node()) { |
| 80 // (x << y) | (x >> (32 - y)) => x ror y | 64 // (x << y) | (x >> (32 - y)) => x ror y |
| 81 if (mright.right().IsInt32Sub()) { | 65 if (mright.right().IsInt32Sub()) { |
| 82 Int32BinopMatcher mrightright(mright.right().node()); | 66 Int32BinopMatcher mrightright(mright.right().node()); |
| 83 if (mrightright.left().Is(32) && | 67 if (mrightright.left().Is(32) && |
| 84 mrightright.right().node() == mleft.right().node()) { | 68 mrightright.right().node() == mleft.right().node()) { |
| 85 graph_->ChangeOperator(node, machine_.Word32Ror()); | 69 graph()->ChangeOperator(node, machine()->Word32Ror()); |
| 86 node->ReplaceInput(0, mleft.left().node()); | 70 node->ReplaceInput(0, mleft.left().node()); |
| 87 node->ReplaceInput(1, mleft.right().node()); | 71 node->ReplaceInput(1, mleft.right().node()); |
| 88 return Changed(node); | 72 return Changed(node); |
| 89 } | 73 } |
| 90 } | 74 } |
| 91 // (x << K) | (x >> (32 - K)) => x ror K | 75 // (x << K) | (x >> (32 - K)) => x ror K |
| 92 if (mleft.right().IsInRange(0, 31) && | 76 if (mleft.right().IsInRange(0, 31) && |
| 93 mright.right().Is(32 - mleft.right().Value())) { | 77 mright.right().Is(32 - mleft.right().Value())) { |
| 94 graph_->ChangeOperator(node, machine_.Word32Ror()); | 78 graph()->ChangeOperator(node, machine()->Word32Ror()); |
| 95 node->ReplaceInput(0, mleft.left().node()); | 79 node->ReplaceInput(0, mleft.left().node()); |
| 96 node->ReplaceInput(1, mleft.right().node()); | 80 node->ReplaceInput(1, mleft.right().node()); |
| 97 return Changed(node); | 81 return Changed(node); |
| 98 } | 82 } |
| 99 } | 83 } |
| 100 } | 84 } |
| 101 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) { | 85 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) { |
| 102 // (x >> (32 - y)) | (x << y) => x ror y | 86 // (x >> (32 - y)) | (x << y) => x ror y |
| 103 Int32BinopMatcher mleft(m.left().node()); | 87 Int32BinopMatcher mleft(m.left().node()); |
| 104 Int32BinopMatcher mright(m.right().node()); | 88 Int32BinopMatcher mright(m.right().node()); |
| 105 if (mleft.left().node() == mright.left().node()) { | 89 if (mleft.left().node() == mright.left().node()) { |
| 106 if (mleft.right().IsInt32Sub()) { | 90 if (mleft.right().IsInt32Sub()) { |
| 107 Int32BinopMatcher mleftright(mleft.right().node()); | 91 Int32BinopMatcher mleftright(mleft.right().node()); |
| 108 if (mleftright.left().Is(32) && | 92 if (mleftright.left().Is(32) && |
| 109 mleftright.right().node() == mright.right().node()) { | 93 mleftright.right().node() == mright.right().node()) { |
| 110 graph_->ChangeOperator(node, machine_.Word32Ror()); | 94 graph()->ChangeOperator(node, machine()->Word32Ror()); |
| 111 node->ReplaceInput(0, mright.left().node()); | 95 node->ReplaceInput(0, mright.left().node()); |
| 112 node->ReplaceInput(1, mright.right().node()); | 96 node->ReplaceInput(1, mright.right().node()); |
| 113 return Changed(node); | 97 return Changed(node); |
| 114 } | 98 } |
| 115 } | 99 } |
| 116 // (x >> (32 - K)) | (x << K) => x ror K | 100 // (x >> (32 - K)) | (x << K) => x ror K |
| 117 if (mright.right().IsInRange(0, 31) && | 101 if (mright.right().IsInRange(0, 31) && |
| 118 mleft.right().Is(32 - mright.right().Value())) { | 102 mleft.right().Is(32 - mright.right().Value())) { |
| 119 graph_->ChangeOperator(node, machine_.Word32Ror()); | 103 graph()->ChangeOperator(node, machine()->Word32Ror()); |
| 120 node->ReplaceInput(0, mright.left().node()); | 104 node->ReplaceInput(0, mright.left().node()); |
| 121 node->ReplaceInput(1, mright.right().node()); | 105 node->ReplaceInput(1, mright.right().node()); |
| 122 return Changed(node); | 106 return Changed(node); |
| 123 } | 107 } |
| 124 } | 108 } |
| 125 } | 109 } |
| 126 break; | 110 break; |
| 127 } | 111 } |
| 128 case IrOpcode::kWord32Xor: { | 112 case IrOpcode::kWord32Xor: { |
| 129 Int32BinopMatcher m(node); | 113 Int32BinopMatcher m(node); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 break; | 186 break; |
| 203 } | 187 } |
| 204 case IrOpcode::kInt32Mul: { | 188 case IrOpcode::kInt32Mul: { |
| 205 Int32BinopMatcher m(node); | 189 Int32BinopMatcher m(node); |
| 206 if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0 | 190 if (m.right().Is(0)) return Replace(m.right().node()); // x * 0 => 0 |
| 207 if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x | 191 if (m.right().Is(1)) return Replace(m.left().node()); // x * 1 => x |
| 208 if (m.IsFoldable()) { // K * K => K | 192 if (m.IsFoldable()) { // K * K => K |
| 209 return ReplaceInt32(m.left().Value() * m.right().Value()); | 193 return ReplaceInt32(m.left().Value() * m.right().Value()); |
| 210 } | 194 } |
| 211 if (m.right().Is(-1)) { // x * -1 => 0 - x | 195 if (m.right().Is(-1)) { // x * -1 => 0 - x |
| 212 graph_->ChangeOperator(node, machine_.Int32Sub()); | 196 graph()->ChangeOperator(node, machine()->Int32Sub()); |
| 213 node->ReplaceInput(0, Int32Constant(0)); | 197 node->ReplaceInput(0, Int32Constant(0)); |
| 214 node->ReplaceInput(1, m.left().node()); | 198 node->ReplaceInput(1, m.left().node()); |
| 215 return Changed(node); | 199 return Changed(node); |
| 216 } | 200 } |
| 217 if (m.right().IsPowerOf2()) { // x * 2^n => x << n | 201 if (m.right().IsPowerOf2()) { // x * 2^n => x << n |
| 218 graph_->ChangeOperator(node, machine_.Word32Shl()); | 202 graph()->ChangeOperator(node, machine()->Word32Shl()); |
| 219 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); | 203 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); |
| 220 return Changed(node); | 204 return Changed(node); |
| 221 } | 205 } |
| 222 break; | 206 break; |
| 223 } | 207 } |
| 224 case IrOpcode::kInt32Div: { | 208 case IrOpcode::kInt32Div: { |
| 225 Int32BinopMatcher m(node); | 209 Int32BinopMatcher m(node); |
| 226 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x | 210 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
| 227 // TODO(turbofan): if (m.left().Is(0)) | 211 // TODO(turbofan): if (m.left().Is(0)) |
| 228 // TODO(turbofan): if (m.right().IsPowerOf2()) | 212 // TODO(turbofan): if (m.right().IsPowerOf2()) |
| 229 // TODO(turbofan): if (m.right().Is(0)) | 213 // TODO(turbofan): if (m.right().Is(0)) |
| 230 // TODO(turbofan): if (m.LeftEqualsRight()) | 214 // TODO(turbofan): if (m.LeftEqualsRight()) |
| 231 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K | 215 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K |
| 232 if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); | 216 if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); |
| 233 return ReplaceInt32(m.left().Value() / m.right().Value()); | 217 return ReplaceInt32(m.left().Value() / m.right().Value()); |
| 234 } | 218 } |
| 235 if (m.right().Is(-1)) { // x / -1 => 0 - x | 219 if (m.right().Is(-1)) { // x / -1 => 0 - x |
| 236 graph_->ChangeOperator(node, machine_.Int32Sub()); | 220 graph()->ChangeOperator(node, machine()->Int32Sub()); |
| 237 node->ReplaceInput(0, Int32Constant(0)); | 221 node->ReplaceInput(0, Int32Constant(0)); |
| 238 node->ReplaceInput(1, m.left().node()); | 222 node->ReplaceInput(1, m.left().node()); |
| 239 return Changed(node); | 223 return Changed(node); |
| 240 } | 224 } |
| 241 break; | 225 break; |
| 242 } | 226 } |
| 243 case IrOpcode::kInt32UDiv: { | 227 case IrOpcode::kInt32UDiv: { |
| 244 Uint32BinopMatcher m(node); | 228 Uint32BinopMatcher m(node); |
| 245 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x | 229 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x |
| 246 // TODO(turbofan): if (m.left().Is(0)) | 230 // TODO(turbofan): if (m.left().Is(0)) |
| 247 // TODO(turbofan): if (m.right().Is(0)) | 231 // TODO(turbofan): if (m.right().Is(0)) |
| 248 // TODO(turbofan): if (m.LeftEqualsRight()) | 232 // TODO(turbofan): if (m.LeftEqualsRight()) |
| 249 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K | 233 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K |
| 250 return ReplaceInt32(m.left().Value() / m.right().Value()); | 234 return ReplaceInt32(m.left().Value() / m.right().Value()); |
| 251 } | 235 } |
| 252 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n | 236 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n |
| 253 graph_->ChangeOperator(node, machine_.Word32Shr()); | 237 graph()->ChangeOperator(node, machine()->Word32Shr()); |
| 254 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); | 238 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); |
| 255 return Changed(node); | 239 return Changed(node); |
| 256 } | 240 } |
| 257 break; | 241 break; |
| 258 } | 242 } |
| 259 case IrOpcode::kInt32Mod: { | 243 case IrOpcode::kInt32Mod: { |
| 260 Int32BinopMatcher m(node); | 244 Int32BinopMatcher m(node); |
| 261 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 | 245 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 |
| 262 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 | 246 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 |
| 263 // TODO(turbofan): if (m.left().Is(0)) | 247 // TODO(turbofan): if (m.left().Is(0)) |
| 264 // TODO(turbofan): if (m.right().IsPowerOf2()) | 248 // TODO(turbofan): if (m.right().IsPowerOf2()) |
| 265 // TODO(turbofan): if (m.right().Is(0)) | 249 // TODO(turbofan): if (m.right().Is(0)) |
| 266 // TODO(turbofan): if (m.LeftEqualsRight()) | 250 // TODO(turbofan): if (m.LeftEqualsRight()) |
| 267 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K | 251 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K |
| 268 return ReplaceInt32(m.left().Value() % m.right().Value()); | 252 return ReplaceInt32(m.left().Value() % m.right().Value()); |
| 269 } | 253 } |
| 270 break; | 254 break; |
| 271 } | 255 } |
| 272 case IrOpcode::kInt32UMod: { | 256 case IrOpcode::kInt32UMod: { |
| 273 Uint32BinopMatcher m(node); | 257 Uint32BinopMatcher m(node); |
| 274 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 | 258 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 |
| 275 // TODO(turbofan): if (m.left().Is(0)) | 259 // TODO(turbofan): if (m.left().Is(0)) |
| 276 // TODO(turbofan): if (m.right().Is(0)) | 260 // TODO(turbofan): if (m.right().Is(0)) |
| 277 // TODO(turbofan): if (m.LeftEqualsRight()) | 261 // TODO(turbofan): if (m.LeftEqualsRight()) |
| 278 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K | 262 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K |
| 279 return ReplaceInt32(m.left().Value() % m.right().Value()); | 263 return ReplaceInt32(m.left().Value() % m.right().Value()); |
| 280 } | 264 } |
| 281 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1 | 265 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1 |
| 282 graph_->ChangeOperator(node, machine_.Word32And()); | 266 graph()->ChangeOperator(node, machine()->Word32And()); |
| 283 node->ReplaceInput(1, Int32Constant(m.right().Value() - 1)); | 267 node->ReplaceInput(1, Int32Constant(m.right().Value() - 1)); |
| 284 return Changed(node); | 268 return Changed(node); |
| 285 } | 269 } |
| 286 break; | 270 break; |
| 287 } | 271 } |
| 288 case IrOpcode::kInt32LessThan: { | 272 case IrOpcode::kInt32LessThan: { |
| 289 Int32BinopMatcher m(node); | 273 Int32BinopMatcher m(node); |
| 290 if (m.IsFoldable()) { // K < K => K | 274 if (m.IsFoldable()) { // K < K => K |
| 291 return ReplaceBool(m.left().Value() < m.right().Value()); | 275 return ReplaceBool(m.left().Value() < m.right().Value()); |
| 292 } | 276 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value())); | 424 if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value())); |
| 441 if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0)); | 425 if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0)); |
| 442 break; | 426 break; |
| 443 } | 427 } |
| 444 // TODO(turbofan): strength-reduce and fold floating point operations. | 428 // TODO(turbofan): strength-reduce and fold floating point operations. |
| 445 default: | 429 default: |
| 446 break; | 430 break; |
| 447 } | 431 } |
| 448 return NoChange(); | 432 return NoChange(); |
| 449 } | 433 } |
| 434 |
| 435 |
| 436 CommonOperatorBuilder* MachineOperatorReducer::common() const { |
| 437 return jsgraph()->common(); |
| 450 } | 438 } |
| 451 } | 439 |
| 452 } // namespace v8::internal::compiler | 440 |
| 441 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
| 442 |
| 443 } // namespace compiler |
| 444 } // namespace internal |
| 445 } // namespace v8 |
| OLD | NEW |