Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/compiler/representation-change.h

Issue 1464763003: [turbofan] Replace information about uses by UseInfo in representation selection. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: final goodness Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ 5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ 6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_
7 7
8 #include <sstream> 8 #include <sstream>
9 9
10 #include "src/base/bits.h" 10 #include "src/base/bits.h"
11 #include "src/compiler/js-graph.h" 11 #include "src/compiler/js-graph.h"
12 #include "src/compiler/machine-operator.h" 12 #include "src/compiler/machine-operator.h"
13 #include "src/compiler/simplified-operator.h" 13 #include "src/compiler/simplified-operator.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace compiler { 17 namespace compiler {
18 18
19 class Truncation final {
20 public:
21 // Constructors.
22 static Truncation None() { return Truncation(TruncationKind::kNone); }
23 static Truncation Bool() { return Truncation(TruncationKind::kBool); }
24 static Truncation Word32() { return Truncation(TruncationKind::kWord32); }
25 static Truncation Word64() { return Truncation(TruncationKind::kWord64); }
26 static Truncation Float32() { return Truncation(TruncationKind::kFloat32); }
27 static Truncation Float64() { return Truncation(TruncationKind::kFloat64); }
28 static Truncation Any() { return Truncation(TruncationKind::kAny); }
29
30 static Truncation Generalize(Truncation t1, Truncation t2) {
31 return Truncation(Generalize(t1.kind(), t2.kind()));
32 }
33
34 // Queries.
35 bool TruncatesToWord32() const {
36 return LessGeneral(kind_, TruncationKind::kWord32);
37 }
38
39 bool TruncatesNaNToZero() {
40 return LessGeneral(kind_, TruncationKind::kWord32) ||
41 LessGeneral(kind_, TruncationKind::kBool);
42 }
43
44 bool TruncatesUndefinedToZeroOrNaN() {
45 return LessGeneral(kind_, TruncationKind::kFloat64) ||
46 LessGeneral(kind_, TruncationKind::kWord64);
47 }
48
49 // Operators.
50 bool operator==(Truncation other) const { return kind() == other.kind(); }
51 bool operator!=(Truncation other) const { return !(*this == other); }
52
53 // Debug utilities.
54 const char* description() {
55 switch (kind()) {
56 case TruncationKind::kNone:
57 return "no-value-use";
58 case TruncationKind::kBool:
59 return "truncate-to-bool";
60 case TruncationKind::kWord32:
61 return "truncate-to-word32";
62 case TruncationKind::kWord64:
63 return "truncate-to-word64";
64 case TruncationKind::kFloat32:
65 return "truncate-to-float32";
66 case TruncationKind::kFloat64:
67 return "truncate-to-float64";
68 case TruncationKind::kAny:
69 return "no-truncation";
70 }
71 UNREACHABLE();
72 return nullptr;
73 }
74
75 private:
76 enum class TruncationKind : uint8_t {
77 kNone,
78 kBool,
79 kWord32,
80 kWord64,
81 kFloat32,
82 kFloat64,
83 kAny
84 };
85
86 explicit Truncation(TruncationKind kind) : kind_(kind) {}
87 TruncationKind kind() const { return kind_; }
88
89 TruncationKind kind_;
90
91 // Partial order for truncations:
92 //
93 // kWord64 kAny
94 // ^ ^
95 // \ |
96 // \ kFloat64 <--+
97 // \ ^ ^ |
98 // \ / | |
99 // kWord32 kFloat32 kBool
100 // ^ ^ ^
101 // \ | /
102 // \ | /
103 // \ | /
104 // \ | /
105 // \ | /
106 // kNone
107 static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2) {
108 if (LessGeneral(rep1, rep2)) return rep2;
109 if (LessGeneral(rep2, rep1)) return rep1;
110 // Handle the generalization of float64-representable values.
111 if (LessGeneral(rep1, TruncationKind::kFloat64) &&
112 LessGeneral(rep2, TruncationKind::kFloat64)) {
113 return TruncationKind::kFloat64;
114 }
115 // All other combinations are illegal.
116 FATAL("Tried to combine incompatible representations");
117 return TruncationKind::kNone;
118 }
119
120 static bool LessGeneral(TruncationKind rep1, TruncationKind rep2) {
121 switch (rep1) {
122 case TruncationKind::kNone:
123 return true;
124 case TruncationKind::kBool:
125 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
126 case TruncationKind::kWord32:
127 return rep2 == TruncationKind::kWord32 ||
128 rep2 == TruncationKind::kWord64 ||
129 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
130 case TruncationKind::kWord64:
131 return rep2 == TruncationKind::kWord64;
132 case TruncationKind::kFloat32:
133 return rep2 == TruncationKind::kFloat32 ||
134 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
135 case TruncationKind::kFloat64:
136 return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
137 case TruncationKind::kAny:
138 return rep2 == TruncationKind::kAny;
139 }
140 UNREACHABLE();
141 return false;
142 }
143 };
144
145
19 // Contains logic related to changing the representation of values for constants 146 // Contains logic related to changing the representation of values for constants
20 // and other nodes, as well as lowering Simplified->Machine operators. 147 // and other nodes, as well as lowering Simplified->Machine operators.
21 // Eagerly folds any representation changes for constants. 148 // Eagerly folds any representation changes for constants.
22 class RepresentationChanger { 149 class RepresentationChanger final {
23 public: 150 public:
24 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate) 151 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
25 : jsgraph_(jsgraph), 152 : jsgraph_(jsgraph),
26 isolate_(isolate), 153 isolate_(isolate),
27 testing_type_errors_(false), 154 testing_type_errors_(false),
28 type_error_(false) {} 155 type_error_(false) {}
29 156
30 // TODO(titzer): should Word64 also be implicitly convertable to others? 157 // TODO(titzer): should Word64 also be implicitly convertable to others?
31 static bool IsWord(MachineTypeUnion type) { 158 static bool IsWord(MachineTypeUnion type) {
32 return (type & (kRepWord8 | kRepWord16 | kRepWord32)) != 0; 159 return (type & (kRepWord8 | kRepWord16 | kRepWord32)) != 0;
33 } 160 }
34 161
162 // Changes representation from {output_type} to {use_rep}. The {truncation}
163 // parameter is only used for sanity checking - if the changer cannot figure
164 // out signedness for the word32->float64 conversion, then we check that the
165 // uses truncate to word32 (so they do not care about signedness).
35 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, 166 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type,
36 MachineTypeUnion use_type) { 167 MachineTypeUnion use_rep,
168 Truncation truncation = Truncation::None()) {
169 DCHECK((use_rep & kRepMask) == use_rep);
37 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { 170 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) {
38 // There should be only one output representation. 171 // There should be only one output representation.
39 return TypeError(node, output_type, use_type); 172 return TypeError(node, output_type, use_rep);
40 } 173 }
41 if ((use_type & kRepMask) == (output_type & kRepMask)) { 174 if (use_rep == (output_type & kRepMask)) {
42 // Representations are the same. That's a no-op. 175 // Representations are the same. That's a no-op.
43 return node; 176 return node;
44 } 177 }
45 if (IsWord(use_type) && IsWord(output_type)) { 178 if (IsWord(use_rep) && IsWord(output_type)) {
46 // Both are words less than or equal to 32-bits. 179 // Both are words less than or equal to 32-bits.
47 // Since loads of integers from memory implicitly sign or zero extend the 180 // Since loads of integers from memory implicitly sign or zero extend the
48 // value to the full machine word size and stores implicitly truncate, 181 // value to the full machine word size and stores implicitly truncate,
49 // no representation change is necessary. 182 // no representation change is necessary.
50 return node; 183 return node;
51 } 184 }
52 if (use_type & kRepTagged) { 185 if (use_rep & kRepTagged) {
53 return GetTaggedRepresentationFor(node, output_type); 186 return GetTaggedRepresentationFor(node, output_type);
54 } else if (use_type & kRepFloat32) { 187 } else if (use_rep & kRepFloat32) {
55 return GetFloat32RepresentationFor(node, output_type, use_type); 188 return GetFloat32RepresentationFor(node, output_type, truncation);
56 } else if (use_type & kRepFloat64) { 189 } else if (use_rep & kRepFloat64) {
57 return GetFloat64RepresentationFor(node, output_type, use_type); 190 return GetFloat64RepresentationFor(node, output_type, truncation);
58 } else if (use_type & kRepBit) { 191 } else if (use_rep & kRepBit) {
59 return GetBitRepresentationFor(node, output_type); 192 return GetBitRepresentationFor(node, output_type);
60 } else if (IsWord(use_type)) { 193 } else if (IsWord(use_rep)) {
61 return GetWord32RepresentationFor(node, output_type); 194 return GetWord32RepresentationFor(node, output_type);
62 } else if (use_type & kRepWord64) { 195 } else if (use_rep & kRepWord64) {
63 return GetWord64RepresentationFor(node, output_type); 196 return GetWord64RepresentationFor(node, output_type);
64 } else { 197 } else {
65 return node; 198 return node;
66 } 199 }
67 } 200 }
68 201
69 Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion output_type) { 202 Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion output_type) {
70 // Eagerly fold representation changes for constants. 203 // Eagerly fold representation changes for constants.
71 switch (node->opcode()) { 204 switch (node->opcode()) {
72 case IrOpcode::kNumberConstant: 205 case IrOpcode::kNumberConstant:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 op = simplified()->ChangeFloat64ToTagged(); 242 op = simplified()->ChangeFloat64ToTagged();
110 } else if (output_type & kRepFloat64) { 243 } else if (output_type & kRepFloat64) {
111 op = simplified()->ChangeFloat64ToTagged(); 244 op = simplified()->ChangeFloat64ToTagged();
112 } else { 245 } else {
113 return TypeError(node, output_type, kRepTagged); 246 return TypeError(node, output_type, kRepTagged);
114 } 247 }
115 return jsgraph()->graph()->NewNode(op, node); 248 return jsgraph()->graph()->NewNode(op, node);
116 } 249 }
117 250
118 Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type, 251 Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type,
119 MachineTypeUnion truncation) { 252 Truncation truncation) {
120 // Eagerly fold representation changes for constants. 253 // Eagerly fold representation changes for constants.
121 switch (node->opcode()) { 254 switch (node->opcode()) {
122 case IrOpcode::kFloat64Constant: 255 case IrOpcode::kFloat64Constant:
123 case IrOpcode::kNumberConstant: 256 case IrOpcode::kNumberConstant:
124 return jsgraph()->Float32Constant( 257 return jsgraph()->Float32Constant(
125 DoubleToFloat32(OpParameter<double>(node))); 258 DoubleToFloat32(OpParameter<double>(node)));
126 case IrOpcode::kInt32Constant: 259 case IrOpcode::kInt32Constant:
127 if (output_type & kTypeUint32) { 260 if (output_type & kTypeUint32) {
128 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); 261 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
129 return jsgraph()->Float32Constant(static_cast<float>(value)); 262 return jsgraph()->Float32Constant(static_cast<float>(value));
130 } else { 263 } else {
131 int32_t value = OpParameter<int32_t>(node); 264 int32_t value = OpParameter<int32_t>(node);
132 return jsgraph()->Float32Constant(static_cast<float>(value)); 265 return jsgraph()->Float32Constant(static_cast<float>(value));
133 } 266 }
134 case IrOpcode::kFloat32Constant: 267 case IrOpcode::kFloat32Constant:
135 return node; // No change necessary. 268 return node; // No change necessary.
136 default: 269 default:
137 break; 270 break;
138 } 271 }
139 // Select the correct X -> Float32 operator. 272 // Select the correct X -> Float32 operator.
140 const Operator* op; 273 const Operator* op;
141 if (output_type & kRepBit) { 274 if (output_type & kRepBit) {
142 return TypeError(node, output_type, kRepFloat32); 275 return TypeError(node, output_type, kRepFloat32);
143 } else if (IsWord(output_type)) { 276 } else if (IsWord(output_type)) {
144 if (output_type & kTypeUint32) { 277 if (output_type & kTypeUint32) {
145 op = machine()->ChangeUint32ToFloat64(); 278 op = machine()->ChangeUint32ToFloat64();
146 } else { 279 } else {
147 // Either the output is int32 or the uses only care about the 280 // Either the output is int32 or the uses only care about the
148 // low 32 bits (so we can pick int32 safely). 281 // low 32 bits (so we can pick int32 safely).
149 DCHECK(output_type & kTypeInt32 || 282 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
150 !(truncation & ~(kTypeInt32 | kTypeUint32 | kRepMask)));
151 op = machine()->ChangeInt32ToFloat64(); 283 op = machine()->ChangeInt32ToFloat64();
152 } 284 }
153 // int32 -> float64 -> float32 285 // int32 -> float64 -> float32
154 node = jsgraph()->graph()->NewNode(op, node); 286 node = jsgraph()->graph()->NewNode(op, node);
155 op = machine()->TruncateFloat64ToFloat32(); 287 op = machine()->TruncateFloat64ToFloat32();
156 } else if (output_type & kRepTagged) { 288 } else if (output_type & kRepTagged) {
157 op = simplified() 289 op = simplified()
158 ->ChangeTaggedToFloat64(); // tagged -> float64 -> float32 290 ->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
159 node = jsgraph()->graph()->NewNode(op, node); 291 node = jsgraph()->graph()->NewNode(op, node);
160 op = machine()->TruncateFloat64ToFloat32(); 292 op = machine()->TruncateFloat64ToFloat32();
161 } else if (output_type & kRepFloat64) { 293 } else if (output_type & kRepFloat64) {
162 op = machine()->TruncateFloat64ToFloat32(); 294 op = machine()->TruncateFloat64ToFloat32();
163 } else { 295 } else {
164 return TypeError(node, output_type, kRepFloat32); 296 return TypeError(node, output_type, kRepFloat32);
165 } 297 }
166 return jsgraph()->graph()->NewNode(op, node); 298 return jsgraph()->graph()->NewNode(op, node);
167 } 299 }
168 300
169 Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type, 301 Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type,
170 MachineTypeUnion use_type) { 302 Truncation truncation) {
171 // Eagerly fold representation changes for constants. 303 // Eagerly fold representation changes for constants.
172 switch (node->opcode()) { 304 switch (node->opcode()) {
173 case IrOpcode::kNumberConstant: 305 case IrOpcode::kNumberConstant:
174 return jsgraph()->Float64Constant(OpParameter<double>(node)); 306 return jsgraph()->Float64Constant(OpParameter<double>(node));
175 case IrOpcode::kInt32Constant: 307 case IrOpcode::kInt32Constant:
176 if (output_type & kTypeUint32) { 308 if (output_type & kTypeUint32) {
177 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); 309 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
178 return jsgraph()->Float64Constant(static_cast<double>(value)); 310 return jsgraph()->Float64Constant(static_cast<double>(value));
179 } else { 311 } else {
180 int32_t value = OpParameter<int32_t>(node); 312 int32_t value = OpParameter<int32_t>(node);
181 return jsgraph()->Float64Constant(value); 313 return jsgraph()->Float64Constant(value);
182 } 314 }
183 case IrOpcode::kFloat64Constant: 315 case IrOpcode::kFloat64Constant:
184 return node; // No change necessary. 316 return node; // No change necessary.
185 case IrOpcode::kFloat32Constant: 317 case IrOpcode::kFloat32Constant:
186 return jsgraph()->Float64Constant(OpParameter<float>(node)); 318 return jsgraph()->Float64Constant(OpParameter<float>(node));
187 default: 319 default:
188 break; 320 break;
189 } 321 }
190 // Select the correct X -> Float64 operator. 322 // Select the correct X -> Float64 operator.
191 const Operator* op; 323 const Operator* op;
192 if (output_type & kRepBit) { 324 if (output_type & kRepBit) {
193 return TypeError(node, output_type, kRepFloat64); 325 return TypeError(node, output_type, kRepFloat64);
194 } else if (IsWord(output_type)) { 326 } else if (IsWord(output_type)) {
195 if (output_type & kTypeUint32) { 327 if (output_type & kTypeUint32) {
196 op = machine()->ChangeUint32ToFloat64(); 328 op = machine()->ChangeUint32ToFloat64();
197 } else { 329 } else {
198 // Either the output is int32 or the uses only care about the 330 // Either the output is int32 or the uses only care about the
199 // low 32 bits (so we can pick int32 safely). 331 // low 32 bits (so we can pick int32 safely).
200 DCHECK(output_type & kTypeInt32 || 332 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
201 !(use_type & ~(kTypeInt32 | kTypeUint32 | kRepMask)));
202 op = machine()->ChangeInt32ToFloat64(); 333 op = machine()->ChangeInt32ToFloat64();
203 } 334 }
204 } else if (output_type & kRepTagged) { 335 } else if (output_type & kRepTagged) {
205 op = simplified()->ChangeTaggedToFloat64(); 336 op = simplified()->ChangeTaggedToFloat64();
206 } else if (output_type & kRepFloat32) { 337 } else if (output_type & kRepFloat32) {
207 op = machine()->ChangeFloat32ToFloat64(); 338 op = machine()->ChangeFloat32ToFloat64();
208 } else { 339 } else {
209 return TypeError(node, output_type, kRepFloat64); 340 return TypeError(node, output_type, kRepFloat64);
210 } 341 }
211 return jsgraph()->graph()->NewNode(op, node); 342 return jsgraph()->graph()->NewNode(op, node);
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 Factory* factory() const { return isolate()->factory(); } 598 Factory* factory() const { return isolate()->factory(); }
468 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); } 599 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
469 MachineOperatorBuilder* machine() { return jsgraph()->machine(); } 600 MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
470 }; 601 };
471 602
472 } // namespace compiler 603 } // namespace compiler
473 } // namespace internal 604 } // namespace internal
474 } // namespace v8 605 } // namespace v8
475 606
476 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ 607 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_
OLDNEW
« no previous file with comments | « no previous file | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698