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

Side by Side Diff: src/compiler/typed-optimization.cc

Issue 2280673003: [turbofan] Separate typed optimizations from JSTypedLowering. (Closed)
Patch Set: Created 4 years, 3 months 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
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "src/compiler/typed-optimization.h"
6
7 #include "src/compilation-dependencies.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h"
11 #include "src/isolate-inl.h"
12 #include "src/type-cache.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18 TypedOptimization::TypedOptimization(Editor* editor,
19 CompilationDependencies* dependencies,
20 Flags flags, JSGraph* jsgraph)
21 : AdvancedReducer(editor),
22 dependencies_(dependencies),
23 flags_(flags),
24 jsgraph_(jsgraph),
25 true_type_(Type::Constant(factory()->true_value(), graph()->zone())),
26 false_type_(Type::Constant(factory()->false_value(), graph()->zone())),
27 type_cache_(TypeCache::Get()) {}
28
29 TypedOptimization::~TypedOptimization() {}
30
31 Reduction TypedOptimization::Reduce(Node* node) {
32 // Check if the output type is a singleton. In that case we already know the
33 // result value and can simply replace the node if it's eliminable.
34 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
35 node->op()->HasProperty(Operator::kEliminatable)) {
36 // We can only constant-fold nodes here, that are known to not cause any
37 // side-effect, may it be a JavaScript observable side-effect or a possible
38 // eager deoptimization exit (i.e. {node} has an operator that doesn't have
39 // the Operator::kNoDeopt property).
40 Type* upper = NodeProperties::GetType(node);
41 if (upper->IsInhabited()) {
42 if (upper->IsConstant()) {
43 Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
44 ReplaceWithValue(node, replacement);
45 return Changed(replacement);
46 } else if (upper->Is(Type::MinusZero())) {
47 Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
48 ReplaceWithValue(node, replacement);
49 return Changed(replacement);
50 } else if (upper->Is(Type::NaN())) {
51 Node* replacement = jsgraph()->NaNConstant();
52 ReplaceWithValue(node, replacement);
53 return Changed(replacement);
54 } else if (upper->Is(Type::Null())) {
55 Node* replacement = jsgraph()->NullConstant();
56 ReplaceWithValue(node, replacement);
57 return Changed(replacement);
58 } else if (upper->Is(Type::PlainNumber()) &&
59 upper->Min() == upper->Max()) {
60 Node* replacement = jsgraph()->Constant(upper->Min());
61 ReplaceWithValue(node, replacement);
62 return Changed(replacement);
63 } else if (upper->Is(Type::Undefined())) {
64 Node* replacement = jsgraph()->UndefinedConstant();
65 ReplaceWithValue(node, replacement);
66 return Changed(replacement);
67 }
68 }
69 }
70 switch (node->opcode()) {
71 case IrOpcode::kCheckMaps:
72 return ReduceCheckMaps(node);
73 case IrOpcode::kCheckString:
74 return ReduceCheckString(node);
75 case IrOpcode::kLoadField:
76 return ReduceLoadField(node);
77 case IrOpcode::kNumberCeil:
78 case IrOpcode::kNumberFloor:
79 case IrOpcode::kNumberRound:
80 case IrOpcode::kNumberTrunc:
81 return ReduceNumberRoundop(node);
82 case IrOpcode::kPhi:
83 return ReducePhi(node);
84 case IrOpcode::kSelect:
85 return ReduceSelect(node);
86 default:
87 break;
88 }
89 return NoChange();
90 }
91
92 namespace {
93
94 MaybeHandle<Map> GetStableMapFromObjectType(Type* object_type) {
95 if (object_type->IsConstant() &&
96 object_type->AsConstant()->Value()->IsHeapObject()) {
97 Handle<Map> object_map(
98 Handle<HeapObject>::cast(object_type->AsConstant()->Value())->map());
99 if (object_map->is_stable()) return object_map;
100 } else if (object_type->IsClass()) {
101 Handle<Map> object_map = object_type->AsClass()->Map();
102 if (object_map->is_stable()) return object_map;
103 }
104 return MaybeHandle<Map>();
105 }
106
107 } // namespace
108
109 Reduction TypedOptimization::ReduceCheckMaps(Node* node) {
110 // The CheckMaps(o, ...map...) can be eliminated if map is stable and
111 // either
112 // (a) o has type Constant(object) and map == object->map, or
113 // (b) o has type Class(map),
114 // and either
115 // (1) map cannot transition further, or
116 // (2) we can add a code dependency on the stability of map
117 // (to guard the Constant type information).
118 Node* const object = NodeProperties::GetValueInput(node, 0);
119 Type* const object_type = NodeProperties::GetType(object);
120 Node* const effect = NodeProperties::GetEffectInput(node);
121 Handle<Map> object_map;
122 if (GetStableMapFromObjectType(object_type).ToHandle(&object_map)) {
123 for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
124 Node* const map = NodeProperties::GetValueInput(node, i);
125 Type* const map_type = NodeProperties::GetType(map);
126 if (map_type->IsConstant() &&
127 map_type->AsConstant()->Value().is_identical_to(object_map)) {
128 if (object_map->CanTransition()) {
129 dependencies()->AssumeMapStable(object_map);
130 }
131 return Replace(effect);
132 }
133 }
134 }
135 return NoChange();
136 }
137
138 Reduction TypedOptimization::ReduceCheckString(Node* node) {
139 Node* const input = NodeProperties::GetValueInput(node, 0);
140 Type* const input_type = NodeProperties::GetType(input);
141 if (input_type->Is(Type::String())) {
142 ReplaceWithValue(node, input);
143 return Replace(input);
144 }
145 return NoChange();
146 }
147
148 Reduction TypedOptimization::ReduceLoadField(Node* node) {
149 Node* const object = NodeProperties::GetValueInput(node, 0);
150 Type* const object_type = NodeProperties::GetType(object);
151 FieldAccess const& access = FieldAccessOf(node->op());
152 if (access.base_is_tagged == kTaggedBase &&
153 access.offset == HeapObject::kMapOffset) {
154 // We can replace LoadField[Map](o) with map if is stable and either
155 // (a) o has type Constant(object) and map == object->map, or
156 // (b) o has type Class(map),
157 // and either
158 // (1) map cannot transition further, or
159 // (2) deoptimization is enabled and we can add a code dependency on the
160 // stability of map (to guard the Constant type information).
161 Handle<Map> object_map;
162 if (GetStableMapFromObjectType(object_type).ToHandle(&object_map)) {
163 if (object_map->CanTransition()) {
164 if (flags() & kDeoptimizationEnabled) {
165 dependencies()->AssumeMapStable(object_map);
166 } else {
167 return NoChange();
168 }
169 }
170 Node* const value = jsgraph()->HeapConstant(object_map);
171 ReplaceWithValue(node, value);
172 return Replace(value);
173 }
174 }
175 return NoChange();
176 }
177
178 Reduction TypedOptimization::ReduceNumberRoundop(Node* node) {
179 Node* const input = NodeProperties::GetValueInput(node, 0);
180 Type* const input_type = NodeProperties::GetType(input);
181 if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
182 return Replace(input);
183 }
184 return NoChange();
185 }
186
187 Reduction TypedOptimization::ReducePhi(Node* node) {
188 // Try to narrow the type of the Phi {node}, which might be more precise now
189 // after lowering based on types, i.e. a SpeculativeNumberAdd has a more
190 // precise type than the JSAdd that was in the graph when the Typer was run.
191 DCHECK_EQ(IrOpcode::kPhi, node->opcode());
192 int arity = node->op()->ValueInputCount();
193 Type* type = NodeProperties::GetType(node->InputAt(0));
194 for (int i = 1; i < arity; ++i) {
195 type = Type::Union(type, NodeProperties::GetType(node->InputAt(i)),
196 graph()->zone());
197 }
198 Type* const node_type = NodeProperties::GetType(node);
199 if (!node_type->Is(type)) {
200 type = Type::Intersect(node_type, type, graph()->zone());
201 NodeProperties::SetType(node, type);
202 return Changed(node);
203 }
204 return NoChange();
205 }
206
207 Reduction TypedOptimization::ReduceSelect(Node* node) {
208 DCHECK_EQ(IrOpcode::kSelect, node->opcode());
209 Node* const condition = NodeProperties::GetValueInput(node, 0);
210 Type* const condition_type = NodeProperties::GetType(condition);
211 Node* const vtrue = NodeProperties::GetValueInput(node, 1);
212 Type* const vtrue_type = NodeProperties::GetType(vtrue);
213 Node* const vfalse = NodeProperties::GetValueInput(node, 2);
214 Type* const vfalse_type = NodeProperties::GetType(vfalse);
215 if (condition_type->Is(true_type_)) {
216 // Select(condition:true, vtrue, vfalse) => vtrue
217 return Replace(vtrue);
218 }
219 if (condition_type->Is(false_type_)) {
220 // Select(condition:false, vtrue, vfalse) => vfalse
221 return Replace(vfalse);
222 }
223 if (vtrue_type->Is(true_type_) && vfalse_type->Is(false_type_)) {
224 // Select(condition, vtrue:true, vfalse:false) => condition
225 return Replace(condition);
226 }
227 if (vtrue_type->Is(false_type_) && vfalse_type->Is(true_type_)) {
228 // Select(condition, vtrue:false, vfalse:true) => BooleanNot(condition)
229 node->TrimInputCount(1);
230 NodeProperties::ChangeOp(node, simplified()->BooleanNot());
231 return Changed(node);
232 }
233 // Try to narrow the type of the Select {node}, which might be more precise
234 // now after lowering based on types.
235 Type* type = Type::Union(vtrue_type, vfalse_type, graph()->zone());
236 Type* const node_type = NodeProperties::GetType(node);
237 if (!node_type->Is(type)) {
238 type = Type::Intersect(node_type, type, graph()->zone());
239 NodeProperties::SetType(node, type);
240 return Changed(node);
241 }
242 return NoChange();
243 }
244
245 Factory* TypedOptimization::factory() const { return isolate()->factory(); }
246
247 Graph* TypedOptimization::graph() const { return jsgraph()->graph(); }
248
249 Isolate* TypedOptimization::isolate() const { return jsgraph()->isolate(); }
250
251 SimplifiedOperatorBuilder* TypedOptimization::simplified() const {
252 return jsgraph()->simplified();
253 }
254
255 } // namespace compiler
256 } // namespace internal
257 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698