| 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/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| 11 #include "src/compiler/common-operator.h" | 11 #include "src/compiler/common-operator.h" |
| 12 #include "src/compiler/diamond.h" | 12 #include "src/compiler/diamond.h" |
| 13 #include "src/compiler/linkage.h" | 13 #include "src/compiler/linkage.h" |
| 14 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
| 15 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/node-properties.h" |
| 16 #include "src/compiler/operator-properties.h" | 16 #include "src/compiler/operator-properties.h" |
| 17 #include "src/compiler/representation-change.h" | 17 #include "src/compiler/representation-change.h" |
| 18 #include "src/compiler/simplified-lowering.h" | 18 #include "src/compiler/simplified-lowering.h" |
| 19 #include "src/compiler/simplified-operator.h" | 19 #include "src/compiler/simplified-operator.h" |
| 20 #include "src/compiler/source-position.h" | 20 #include "src/compiler/source-position.h" |
| 21 #include "src/objects.h" | 21 #include "src/objects.h" |
| 22 | 22 |
| 23 namespace v8 { | 23 namespace v8 { |
| 24 namespace internal { | 24 namespace internal { |
| 25 namespace compiler { | 25 namespace compiler { |
| 26 | 26 |
| 27 // Macro for outputting trace information from representation inference. | 27 // Macro for outputting trace information from representation inference. |
| 28 #define TRACE(x) \ | 28 #define TRACE(...) \ |
| 29 if (FLAG_trace_representation) PrintF x | 29 do { \ |
| 30 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \ |
| 31 } while (false) |
| 30 | 32 |
| 31 // Representation selection and lowering of {Simplified} operators to machine | 33 // Representation selection and lowering of {Simplified} operators to machine |
| 32 // operators are interwined. We use a fixpoint calculation to compute both the | 34 // operators are interwined. We use a fixpoint calculation to compute both the |
| 33 // output representation and the best possible lowering for {Simplified} nodes. | 35 // output representation and the best possible lowering for {Simplified} nodes. |
| 34 // Representation change insertion ensures that all values are in the correct | 36 // Representation change insertion ensures that all values are in the correct |
| 35 // machine representation after this phase, as dictated by the machine | 37 // machine representation after this phase, as dictated by the machine |
| 36 // operators themselves. | 38 // operators themselves. |
| 37 enum Phase { | 39 enum Phase { |
| 38 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information | 40 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information |
| 39 // backwards from uses to definitions, around cycles in phis, according | 41 // backwards from uses to definitions, around cycles in phis, according |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 queue_(zone), | 80 queue_(zone), |
| 79 source_positions_(source_positions) { | 81 source_positions_(source_positions) { |
| 80 memset(info_, 0, sizeof(NodeInfo) * count_); | 82 memset(info_, 0, sizeof(NodeInfo) * count_); |
| 81 | 83 |
| 82 safe_int_additive_range_ = | 84 safe_int_additive_range_ = |
| 83 Type::Range(-std::pow(2.0, 52.0), std::pow(2.0, 52.0), zone); | 85 Type::Range(-std::pow(2.0, 52.0), std::pow(2.0, 52.0), zone); |
| 84 } | 86 } |
| 85 | 87 |
| 86 void Run(SimplifiedLowering* lowering) { | 88 void Run(SimplifiedLowering* lowering) { |
| 87 // Run propagation phase to a fixpoint. | 89 // Run propagation phase to a fixpoint. |
| 88 TRACE(("--{Propagation phase}--\n")); | 90 TRACE("--{Propagation phase}--\n"); |
| 89 phase_ = PROPAGATE; | 91 phase_ = PROPAGATE; |
| 90 Enqueue(jsgraph_->graph()->end()); | 92 Enqueue(jsgraph_->graph()->end()); |
| 91 // Process nodes from the queue until it is empty. | 93 // Process nodes from the queue until it is empty. |
| 92 while (!queue_.empty()) { | 94 while (!queue_.empty()) { |
| 93 Node* node = queue_.front(); | 95 Node* node = queue_.front(); |
| 94 NodeInfo* info = GetInfo(node); | 96 NodeInfo* info = GetInfo(node); |
| 95 queue_.pop(); | 97 queue_.pop(); |
| 96 info->queued = false; | 98 info->queued = false; |
| 97 TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic())); | 99 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 98 VisitNode(node, info->use, NULL); | 100 VisitNode(node, info->use, NULL); |
| 99 TRACE((" ==> output ")); | 101 TRACE(" ==> output "); |
| 100 PrintInfo(info->output); | 102 PrintInfo(info->output); |
| 101 TRACE(("\n")); | 103 TRACE("\n"); |
| 102 } | 104 } |
| 103 | 105 |
| 104 // Run lowering and change insertion phase. | 106 // Run lowering and change insertion phase. |
| 105 TRACE(("--{Simplified lowering phase}--\n")); | 107 TRACE("--{Simplified lowering phase}--\n"); |
| 106 phase_ = LOWER; | 108 phase_ = LOWER; |
| 107 // Process nodes from the collected {nodes_} vector. | 109 // Process nodes from the collected {nodes_} vector. |
| 108 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { | 110 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { |
| 109 Node* node = *i; | 111 Node* node = *i; |
| 110 TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic())); | 112 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 111 // Reuse {VisitNode()} so the representation rules are in one place. | 113 // Reuse {VisitNode()} so the representation rules are in one place. |
| 112 if (FLAG_turbo_source_positions) { | 114 if (FLAG_turbo_source_positions) { |
| 113 SourcePositionTable::Scope scope( | 115 SourcePositionTable::Scope scope( |
| 114 source_positions_, source_positions_->GetSourcePosition(node)); | 116 source_positions_, source_positions_->GetSourcePosition(node)); |
| 115 VisitNode(node, GetUseInfo(node), lowering); | 117 VisitNode(node, GetUseInfo(node), lowering); |
| 116 } else { | 118 } else { |
| 117 VisitNode(node, GetUseInfo(node), lowering); | 119 VisitNode(node, GetUseInfo(node), lowering); |
| 118 } | 120 } |
| 119 } | 121 } |
| 120 | 122 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 136 // Add {node} to {nodes_} if this is the first time it's been visited. | 138 // Add {node} to {nodes_} if this is the first time it's been visited. |
| 137 void Enqueue(Node* node, MachineTypeUnion use = 0) { | 139 void Enqueue(Node* node, MachineTypeUnion use = 0) { |
| 138 if (phase_ != PROPAGATE) return; | 140 if (phase_ != PROPAGATE) return; |
| 139 NodeInfo* info = GetInfo(node); | 141 NodeInfo* info = GetInfo(node); |
| 140 if (!info->visited) { | 142 if (!info->visited) { |
| 141 // First visit of this node. | 143 // First visit of this node. |
| 142 info->visited = true; | 144 info->visited = true; |
| 143 info->queued = true; | 145 info->queued = true; |
| 144 nodes_.push_back(node); | 146 nodes_.push_back(node); |
| 145 queue_.push(node); | 147 queue_.push(node); |
| 146 TRACE((" initial: ")); | 148 TRACE(" initial: "); |
| 147 info->use |= use; | 149 info->use |= use; |
| 148 PrintUseInfo(node); | 150 PrintUseInfo(node); |
| 149 return; | 151 return; |
| 150 } | 152 } |
| 151 TRACE((" queue?: ")); | 153 TRACE(" queue?: "); |
| 152 PrintUseInfo(node); | 154 PrintUseInfo(node); |
| 153 if ((info->use & use) != use) { | 155 if ((info->use & use) != use) { |
| 154 // New usage information for the node is available. | 156 // New usage information for the node is available. |
| 155 if (!info->queued) { | 157 if (!info->queued) { |
| 156 queue_.push(node); | 158 queue_.push(node); |
| 157 info->queued = true; | 159 info->queued = true; |
| 158 TRACE((" added: ")); | 160 TRACE(" added: "); |
| 159 } else { | 161 } else { |
| 160 TRACE((" inqueue: ")); | 162 TRACE(" inqueue: "); |
| 161 } | 163 } |
| 162 info->use |= use; | 164 info->use |= use; |
| 163 PrintUseInfo(node); | 165 PrintUseInfo(node); |
| 164 } | 166 } |
| 165 } | 167 } |
| 166 | 168 |
| 167 bool lower() { return phase_ == LOWER; } | 169 bool lower() { return phase_ == LOWER; } |
| 168 | 170 |
| 169 void Enqueue(Node* node, MachineType use) { | 171 void Enqueue(Node* node, MachineType use) { |
| 170 Enqueue(node, static_cast<MachineTypeUnion>(use)); | 172 Enqueue(node, static_cast<MachineTypeUnion>(use)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 188 void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { | 190 void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { |
| 189 Node* input = node->InputAt(index); | 191 Node* input = node->InputAt(index); |
| 190 if (phase_ == PROPAGATE) { | 192 if (phase_ == PROPAGATE) { |
| 191 // In the propagate phase, propagate the usage information backward. | 193 // In the propagate phase, propagate the usage information backward. |
| 192 Enqueue(input, use); | 194 Enqueue(input, use); |
| 193 } else { | 195 } else { |
| 194 // In the change phase, insert a change before the use if necessary. | 196 // In the change phase, insert a change before the use if necessary. |
| 195 MachineTypeUnion output = GetInfo(input)->output; | 197 MachineTypeUnion output = GetInfo(input)->output; |
| 196 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { | 198 if ((output & (kRepBit | kRepWord8 | kRepWord16 | kRepWord32)) == 0) { |
| 197 // Output representation doesn't match usage. | 199 // Output representation doesn't match usage. |
| 198 TRACE((" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), | 200 TRACE(" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), |
| 199 node->op()->mnemonic(), index, input->id(), | 201 node->op()->mnemonic(), index, input->id(), |
| 200 input->op()->mnemonic())); | 202 input->op()->mnemonic()); |
| 201 TRACE((" from ")); | 203 TRACE(" from "); |
| 202 PrintInfo(output); | 204 PrintInfo(output); |
| 203 TRACE((" to ")); | 205 TRACE(" to "); |
| 204 PrintInfo(use); | 206 PrintInfo(use); |
| 205 TRACE(("\n")); | 207 TRACE("\n"); |
| 206 Node* n = changer_->GetTruncatedWord32For(input, output); | 208 Node* n = changer_->GetTruncatedWord32For(input, output); |
| 207 node->ReplaceInput(index, n); | 209 node->ReplaceInput(index, n); |
| 208 } | 210 } |
| 209 } | 211 } |
| 210 } | 212 } |
| 211 | 213 |
| 212 void ProcessInput(Node* node, int index, MachineTypeUnion use) { | 214 void ProcessInput(Node* node, int index, MachineTypeUnion use) { |
| 213 Node* input = node->InputAt(index); | 215 Node* input = node->InputAt(index); |
| 214 if (phase_ == PROPAGATE) { | 216 if (phase_ == PROPAGATE) { |
| 215 // In the propagate phase, propagate the usage information backward. | 217 // In the propagate phase, propagate the usage information backward. |
| 216 Enqueue(input, use); | 218 Enqueue(input, use); |
| 217 } else { | 219 } else { |
| 218 // In the change phase, insert a change before the use if necessary. | 220 // In the change phase, insert a change before the use if necessary. |
| 219 if ((use & kRepMask) == 0) return; // No input requirement on the use. | 221 if ((use & kRepMask) == 0) return; // No input requirement on the use. |
| 220 MachineTypeUnion output = GetInfo(input)->output; | 222 MachineTypeUnion output = GetInfo(input)->output; |
| 221 if ((output & kRepMask & use) == 0) { | 223 if ((output & kRepMask & use) == 0) { |
| 222 // Output representation doesn't match usage. | 224 // Output representation doesn't match usage. |
| 223 TRACE((" change: #%d:%s(@%d #%d:%s) ", node->id(), | 225 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), |
| 224 node->op()->mnemonic(), index, input->id(), | 226 node->op()->mnemonic(), index, input->id(), |
| 225 input->op()->mnemonic())); | 227 input->op()->mnemonic()); |
| 226 TRACE((" from ")); | 228 TRACE(" from "); |
| 227 PrintInfo(output); | 229 PrintInfo(output); |
| 228 TRACE((" to ")); | 230 TRACE(" to "); |
| 229 PrintInfo(use); | 231 PrintInfo(use); |
| 230 TRACE(("\n")); | 232 TRACE("\n"); |
| 231 Node* n = changer_->GetRepresentationFor(input, output, use); | 233 Node* n = changer_->GetRepresentationFor(input, output, use); |
| 232 node->ReplaceInput(index, n); | 234 node->ReplaceInput(index, n); |
| 233 } | 235 } |
| 234 } | 236 } |
| 235 } | 237 } |
| 236 | 238 |
| 237 void ProcessRemainingInputs(Node* node, int index) { | 239 void ProcessRemainingInputs(Node* node, int index) { |
| 238 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); | 240 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); |
| 239 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); | 241 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); |
| 240 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); | 242 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 } | 1044 } |
| 1043 SetOutput(node, kMachAnyTagged); | 1045 SetOutput(node, kMachAnyTagged); |
| 1044 break; | 1046 break; |
| 1045 default: | 1047 default: |
| 1046 VisitInputs(node); | 1048 VisitInputs(node); |
| 1047 break; | 1049 break; |
| 1048 } | 1050 } |
| 1049 } | 1051 } |
| 1050 | 1052 |
| 1051 void DeferReplacement(Node* node, Node* replacement) { | 1053 void DeferReplacement(Node* node, Node* replacement) { |
| 1052 if (FLAG_trace_representation) { | 1054 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), |
| 1053 TRACE(("defer replacement #%d:%s with #%d:%s\n", node->id(), | 1055 node->op()->mnemonic(), replacement->id(), |
| 1054 node->op()->mnemonic(), replacement->id(), | 1056 replacement->op()->mnemonic()); |
| 1055 replacement->op()->mnemonic())); | 1057 |
| 1056 } | |
| 1057 if (replacement->id() < count_ && | 1058 if (replacement->id() < count_ && |
| 1058 GetInfo(replacement)->output == GetInfo(node)->output) { | 1059 GetInfo(replacement)->output == GetInfo(node)->output) { |
| 1059 // Replace with a previously existing node eagerly only if the type is the | 1060 // Replace with a previously existing node eagerly only if the type is the |
| 1060 // same. | 1061 // same. |
| 1061 node->ReplaceUses(replacement); | 1062 node->ReplaceUses(replacement); |
| 1062 } else { | 1063 } else { |
| 1063 // Otherwise, we are replacing a node with a representation change. | 1064 // Otherwise, we are replacing a node with a representation change. |
| 1064 // Such a substitution must be done after all lowering is done, because | 1065 // Such a substitution must be done after all lowering is done, because |
| 1065 // changing the type could confuse the representation change | 1066 // changing the type could confuse the representation change |
| 1066 // insertion for uses of the node. | 1067 // insertion for uses of the node. |
| 1067 replacements_.push_back(node); | 1068 replacements_.push_back(node); |
| 1068 replacements_.push_back(replacement); | 1069 replacements_.push_back(replacement); |
| 1069 } | 1070 } |
| 1070 node->RemoveAllInputs(); // Node is now dead. | 1071 node->RemoveAllInputs(); // Node is now dead. |
| 1071 } | 1072 } |
| 1072 | 1073 |
| 1073 void PrintUseInfo(Node* node) { | 1074 void PrintUseInfo(Node* node) { |
| 1074 TRACE(("#%d:%-20s ", node->id(), node->op()->mnemonic())); | 1075 TRACE("#%d:%-20s ", node->id(), node->op()->mnemonic()); |
| 1075 PrintInfo(GetUseInfo(node)); | 1076 PrintInfo(GetUseInfo(node)); |
| 1076 TRACE(("\n")); | 1077 TRACE("\n"); |
| 1077 } | 1078 } |
| 1078 | 1079 |
| 1079 void PrintInfo(MachineTypeUnion info) { | 1080 void PrintInfo(MachineTypeUnion info) { |
| 1080 if (FLAG_trace_representation) { | 1081 if (FLAG_trace_representation) { |
| 1081 OFStream os(stdout); | 1082 OFStream os(stdout); |
| 1082 os << static_cast<MachineType>(info); | 1083 os << static_cast<MachineType>(info); |
| 1083 } | 1084 } |
| 1084 } | 1085 } |
| 1085 | 1086 |
| 1086 private: | 1087 private: |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1593 | 1594 |
| 1594 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1595 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 1595 node->set_op(machine()->IntLessThanOrEqual()); | 1596 node->set_op(machine()->IntLessThanOrEqual()); |
| 1596 node->ReplaceInput(0, StringComparison(node, true)); | 1597 node->ReplaceInput(0, StringComparison(node, true)); |
| 1597 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1598 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1598 } | 1599 } |
| 1599 | 1600 |
| 1600 } // namespace compiler | 1601 } // namespace compiler |
| 1601 } // namespace internal | 1602 } // namespace internal |
| 1602 } // namespace v8 | 1603 } // namespace v8 |
| OLD | NEW |