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 |