blob: 8a38644e9495e0e35bb86ace049b3dc32f01cb7b [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
6#define V8_COMPILER_REPRESENTATION_CHANGE_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/js-graph.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/compiler/simplified-operator.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015class Truncation final {
16 public:
17 // Constructors.
18 static Truncation None() { return Truncation(TruncationKind::kNone); }
19 static Truncation Bool() { return Truncation(TruncationKind::kBool); }
20 static Truncation Word32() { return Truncation(TruncationKind::kWord32); }
21 static Truncation Word64() { return Truncation(TruncationKind::kWord64); }
22 static Truncation Float32() { return Truncation(TruncationKind::kFloat32); }
23 static Truncation Float64() { return Truncation(TruncationKind::kFloat64); }
24 static Truncation Any() { return Truncation(TruncationKind::kAny); }
25
26 static Truncation Generalize(Truncation t1, Truncation t2) {
27 return Truncation(Generalize(t1.kind(), t2.kind()));
28 }
29
30 // Queries.
31 bool TruncatesToWord32() const {
32 return LessGeneral(kind_, TruncationKind::kWord32);
33 }
Ben Murdochc5610432016-08-08 18:44:38 +010034 bool TruncatesToFloat64() const {
35 return LessGeneral(kind_, TruncationKind::kFloat64);
36 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 bool TruncatesNaNToZero() {
38 return LessGeneral(kind_, TruncationKind::kWord32) ||
39 LessGeneral(kind_, TruncationKind::kBool);
40 }
41 bool TruncatesUndefinedToZeroOrNaN() {
42 return LessGeneral(kind_, TruncationKind::kFloat64) ||
43 LessGeneral(kind_, TruncationKind::kWord64);
44 }
45
46 // Operators.
47 bool operator==(Truncation other) const { return kind() == other.kind(); }
48 bool operator!=(Truncation other) const { return !(*this == other); }
49
50 // Debug utilities.
51 const char* description() const;
52 bool IsLessGeneralThan(Truncation other) {
53 return LessGeneral(kind(), other.kind());
54 }
55
56 private:
57 enum class TruncationKind : uint8_t {
58 kNone,
59 kBool,
60 kWord32,
61 kWord64,
62 kFloat32,
63 kFloat64,
64 kAny
65 };
66
67 explicit Truncation(TruncationKind kind) : kind_(kind) {}
68 TruncationKind kind() const { return kind_; }
69
70 TruncationKind kind_;
71
72 static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
73 static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
74};
75
Ben Murdoch61f157c2016-09-16 13:49:30 +010076enum class TypeCheckKind : uint8_t {
77 kNone,
78 kSigned32,
79 kNumberOrUndefined,
80 kNumber
81};
82
83// The {UseInfo} class is used to describe a use of an input of a node.
84//
85// This information is used in two different ways, based on the phase:
86//
87// 1. During propagation, the use info is used to inform the input node
88// about what part of the input is used (we call this truncation) and what
89// is the preferred representation.
90//
91// 2. During lowering, the use info is used to properly convert the input
92// to the preferred representation. The preferred representation might be
93// insufficient to do the conversion (e.g. word32->float64 conv), so we also
94// need the signedness information to produce the correct value.
95class UseInfo {
96 public:
97 UseInfo(MachineRepresentation representation, Truncation truncation,
98 TypeCheckKind type_check = TypeCheckKind::kNone)
99 : representation_(representation),
100 truncation_(truncation),
101 type_check_(type_check) {}
102 static UseInfo TruncatingWord32() {
103 return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
104 }
105 static UseInfo TruncatingWord64() {
106 return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
107 }
108 static UseInfo Bool() {
109 return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
110 }
111 static UseInfo TruncatingFloat32() {
112 return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
113 }
114 static UseInfo TruncatingFloat64() {
115 return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
116 }
117 static UseInfo PointerInt() {
118 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
119 }
120 static UseInfo AnyTagged() {
121 return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
122 }
123
124 // Possibly deoptimizing conversions.
125 static UseInfo CheckedSigned32AsWord32() {
126 return UseInfo(MachineRepresentation::kWord32, Truncation::Any(),
127 TypeCheckKind::kSigned32);
128 }
129 static UseInfo CheckedNumberOrUndefinedAsFloat64() {
130 return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
131 TypeCheckKind::kNumberOrUndefined);
132 }
133
134 // Undetermined representation.
135 static UseInfo Any() {
136 return UseInfo(MachineRepresentation::kNone, Truncation::Any());
137 }
138 static UseInfo AnyTruncatingToBool() {
139 return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
140 }
141
142 // Value not used.
143 static UseInfo None() {
144 return UseInfo(MachineRepresentation::kNone, Truncation::None());
145 }
146
147 MachineRepresentation representation() const { return representation_; }
148 Truncation truncation() const { return truncation_; }
149 TypeCheckKind type_check() const { return type_check_; }
150
151 private:
152 MachineRepresentation representation_;
153 Truncation truncation_;
154 TypeCheckKind type_check_;
155};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157// Contains logic related to changing the representation of values for constants
158// and other nodes, as well as lowering Simplified->Machine operators.
159// Eagerly folds any representation changes for constants.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160class RepresentationChanger final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 : jsgraph_(jsgraph),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 isolate_(isolate),
165 testing_type_errors_(false),
166 type_error_(false) {}
167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 // Changes representation from {output_type} to {use_rep}. The {truncation}
169 // parameter is only used for sanity checking - if the changer cannot figure
170 // out signedness for the word32->float64 conversion, then we check that the
171 // uses truncate to word32 (so they do not care about signedness).
172 Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100173 Type* output_type, Node* use_node,
174 UseInfo use_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 const Operator* Int32OperatorFor(IrOpcode::Value opcode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100176 const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
178 const Operator* Float64OperatorFor(IrOpcode::Value opcode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179
180 MachineType TypeForBasePointer(const FieldAccess& access) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 return access.tag() != 0 ? MachineType::AnyTagged()
182 : MachineType::Pointer();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 }
184
185 MachineType TypeForBasePointer(const ElementAccess& access) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 return access.tag() != 0 ? MachineType::AnyTagged()
187 : MachineType::Pointer();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 }
189
190 private:
191 JSGraph* jsgraph_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 Isolate* isolate_;
193
194 friend class RepresentationChangerTester; // accesses the below fields.
195
196 bool testing_type_errors_; // If {true}, don't abort on a type error.
197 bool type_error_; // Set when a type error is detected.
198
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
200 Type* output_type);
201 Node* GetFloat32RepresentationFor(Node* node,
202 MachineRepresentation output_rep,
203 Type* output_type, Truncation truncation);
204 Node* GetFloat64RepresentationFor(Node* node,
205 MachineRepresentation output_rep,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100206 Type* output_type, Node* use_node,
207 UseInfo use_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100209 Type* output_type, Node* use_node,
210 UseInfo use_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
212 Type* output_type);
213 Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
214 Type* output_type);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100215 Node* GetCheckedWord32RepresentationFor(Node* node,
216 MachineRepresentation output_rep,
217 Type* output_type, Node* use_node,
218 Truncation truncation,
219 TypeCheckKind check);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 Node* TypeError(Node* node, MachineRepresentation output_rep,
221 Type* output_type, MachineRepresentation use);
222 Node* MakeTruncatedInt32Constant(double value);
223 Node* InsertChangeFloat32ToFloat64(Node* node);
Ben Murdochc5610432016-08-08 18:44:38 +0100224 Node* InsertChangeFloat64ToInt32(Node* node);
225 Node* InsertChangeFloat64ToUint32(Node* node);
226 Node* InsertChangeTaggedSignedToInt32(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 Node* InsertChangeTaggedToFloat64(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228
Ben Murdoch61f157c2016-09-16 13:49:30 +0100229 Node* InsertConversion(Node* node, const Operator* op, Node* use_node);
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 JSGraph* jsgraph() const { return jsgraph_; }
232 Isolate* isolate() const { return isolate_; }
233 Factory* factory() const { return isolate()->factory(); }
234 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
236};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400237
238} // namespace compiler
239} // namespace internal
240} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241
242#endif // V8_COMPILER_REPRESENTATION_CHANGE_H_