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

Side by Side Diff: src/compiler/change-lowering.cc

Issue 1018873002: [turbofan] Improve ChangeLowering. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « src/compiler/change-lowering.h ('k') | test/unittests/compiler/change-lowering-unittest.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 #include "src/compiler/change-lowering.h" 5 #include "src/compiler/change-lowering.h"
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/compiler/diamond.h"
9 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
10 #include "src/compiler/linkage.h" 9 #include "src/compiler/linkage.h"
11 #include "src/compiler/machine-operator.h" 10 #include "src/compiler/machine-operator.h"
12 #include "src/compiler/node-properties.h" 11 #include "src/compiler/node-properties.h"
13 #include "src/compiler/operator-properties.h" 12 #include "src/compiler/operator-properties.h"
14 13
15 namespace v8 { 14 namespace v8 {
16 namespace internal { 15 namespace internal {
17 namespace compiler { 16 namespace compiler {
18 17
(...skipping 21 matching lines...) Expand all
40 return ChangeUint32ToTagged(node->InputAt(0), control); 39 return ChangeUint32ToTagged(node->InputAt(0), control);
41 default: 40 default:
42 return NoChange(); 41 return NoChange();
43 } 42 }
44 UNREACHABLE(); 43 UNREACHABLE();
45 return NoChange(); 44 return NoChange();
46 } 45 }
47 46
48 47
49 Node* ChangeLowering::HeapNumberValueIndexConstant() { 48 Node* ChangeLowering::HeapNumberValueIndexConstant() {
50 STATIC_ASSERT(HeapNumber::kValueOffset % kPointerSize == 0); 49 return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
51 const int heap_number_value_offset =
52 ((HeapNumber::kValueOffset / kPointerSize) * (machine()->Is64() ? 8 : 4));
53 return jsgraph()->IntPtrConstant(heap_number_value_offset - kHeapObjectTag);
54 } 50 }
55 51
56 52
57 Node* ChangeLowering::SmiMaxValueConstant() { 53 Node* ChangeLowering::SmiMaxValueConstant() {
58 const int smi_value_size = machine()->Is32() ? SmiTagging<4>::SmiValueSize() 54 return jsgraph()->Int32Constant(Smi::kMaxValue);
59 : SmiTagging<8>::SmiValueSize();
60 return jsgraph()->Int32Constant(
61 -(static_cast<int>(0xffffffffu << (smi_value_size - 1)) + 1));
62 } 55 }
63 56
64 57
65 Node* ChangeLowering::SmiShiftBitsConstant() { 58 Node* ChangeLowering::SmiShiftBitsConstant() {
66 const int smi_shift_size = machine()->Is32() ? SmiTagging<4>::SmiShiftSize() 59 return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
67 : SmiTagging<8>::SmiShiftSize();
68 return jsgraph()->IntPtrConstant(smi_shift_size + kSmiTagSize);
69 } 60 }
70 61
71 62
72 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { 63 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) {
73 // The AllocateHeapNumberStub does not use the context, so we can safely pass 64 // The AllocateHeapNumberStub does not use the context, so we can safely pass
74 // in Smi zero here. 65 // in Smi zero here.
75 Callable callable = CodeFactory::AllocateHeapNumber(isolate()); 66 Callable callable = CodeFactory::AllocateHeapNumber(isolate());
76 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( 67 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
77 isolate(), jsgraph()->zone(), callable.descriptor(), 0, 68 isolate(), jsgraph()->zone(), callable.descriptor(), 0,
78 CallDescriptor::kNoFlags); 69 CallDescriptor::kNoFlags);
79 Node* target = jsgraph()->HeapConstant(callable.code()); 70 Node* target = jsgraph()->HeapConstant(callable.code());
80 Node* context = jsgraph()->NoContextConstant(); 71 Node* context = jsgraph()->NoContextConstant();
81 Node* effect = graph()->NewNode(common()->ValueEffect(1), value); 72 Node* effect = graph()->NewNode(common()->ValueEffect(1), value);
82 Node* heap_number = graph()->NewNode(common()->Call(descriptor), target, 73 Node* heap_number = graph()->NewNode(common()->Call(descriptor), target,
83 context, effect, control); 74 context, effect, control);
84 Node* store = graph()->NewNode( 75 Node* store = graph()->NewNode(
85 machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)), 76 machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)),
86 heap_number, HeapNumberValueIndexConstant(), value, heap_number, control); 77 heap_number, HeapNumberValueIndexConstant(), value, heap_number, control);
87 return graph()->NewNode(common()->Finish(1), heap_number, store); 78 return graph()->NewNode(common()->Finish(1), heap_number, store);
88 } 79 }
89 80
90 81
91 Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) { 82 Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) {
92 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value); 83 return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
93 } 84 }
94 85
95 86
87 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) {
88 if (machine()->Is64()) {
89 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
90 }
91 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
92 }
93
94
96 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { 95 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) {
97 return ChangeInt32ToFloat64(ChangeSmiToInt32(value)); 96 return ChangeInt32ToFloat64(ChangeSmiToInt32(value));
98 } 97 }
99 98
100 99
101 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { 100 Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
102 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); 101 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
103 if (machine()->Is64()) { 102 if (machine()->Is64()) {
104 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); 103 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
105 } 104 }
(...skipping 22 matching lines...) Expand all
128 127
129 128
130 Node* ChangeLowering::TestNotSmi(Node* value) { 129 Node* ChangeLowering::TestNotSmi(Node* value) {
131 STATIC_ASSERT(kSmiTag == 0); 130 STATIC_ASSERT(kSmiTag == 0);
132 STATIC_ASSERT(kSmiTagMask == 1); 131 STATIC_ASSERT(kSmiTagMask == 1);
133 return graph()->NewNode(machine()->WordAnd(), value, 132 return graph()->NewNode(machine()->WordAnd(), value,
134 jsgraph()->IntPtrConstant(kSmiTagMask)); 133 jsgraph()->IntPtrConstant(kSmiTagMask));
135 } 134 }
136 135
137 136
138 Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) { 137 Reduction ChangeLowering::ChangeBitToBool(Node* value, Node* control) {
139 return graph()->NewNode(machine()->Uint32LessThanOrEqual(), lhs, rhs); 138 return Replace(graph()->NewNode(common()->Select(kMachAnyTagged), value,
140 }
141
142
143 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
144 MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
145 return Replace(graph()->NewNode(common()->Select(type), val,
146 jsgraph()->TrueConstant(), 139 jsgraph()->TrueConstant(),
147 jsgraph()->FalseConstant())); 140 jsgraph()->FalseConstant()));
148 } 141 }
149 142
150 143
151 Reduction ChangeLowering::ChangeBoolToBit(Node* val) { 144 Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
152 return Replace( 145 return Replace(graph()->NewNode(machine()->WordEqual(), value,
153 graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant())); 146 jsgraph()->TrueConstant()));
154 } 147 }
155 148
156 149
157 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) { 150 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) {
158 return Replace(AllocateHeapNumberWithValue(val, control)); 151 return Replace(AllocateHeapNumberWithValue(value, control));
159 } 152 }
160 153
161 154
162 Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) { 155 Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
163 if (machine()->Is64()) { 156 if (machine()->Is64() ||
164 return Replace(graph()->NewNode( 157 NodeProperties::GetBounds(value).upper->Is(Type::SignedSmall())) {
165 machine()->Word64Shl(), 158 return Replace(ChangeInt32ToSmi(value));
166 graph()->NewNode(machine()->ChangeInt32ToInt64(), value),
167 SmiShiftBitsConstant()));
168 } else if (NodeProperties::GetBounds(value).upper->Is(Type::SignedSmall())) {
169 return Replace(
170 graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()));
171 } 159 }
172 160
173 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value); 161 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
162
174 Node* ovf = graph()->NewNode(common()->Projection(1), add); 163 Node* ovf = graph()->NewNode(common()->Projection(1), add);
164 Node* branch =
165 graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
175 166
176 Diamond d(graph(), common(), ovf, BranchHint::kFalse); 167 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
177 d.Chain(control); 168 Node* vtrue =
178 return Replace( 169 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), if_true);
179 d.Phi(kMachAnyTagged, 170
180 AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), d.if_true), 171 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
181 graph()->NewNode(common()->Projection(0), add))); 172 Node* vfalse = graph()->NewNode(common()->Projection(0), add);
173
174 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
175 Node* phi =
176 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge);
177
178 return Replace(phi);
182 } 179 }
183 180
184 181
185 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, 182 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control,
186 Signedness signedness) { 183 Signedness signedness) {
184 if (NodeProperties::GetBounds(value).upper->Is(Type::TaggedSigned())) {
185 return Replace(ChangeSmiToInt32(value));
186 }
187
187 const MachineType type = (signedness == kSigned) ? kMachInt32 : kMachUint32; 188 const MachineType type = (signedness == kSigned) ? kMachInt32 : kMachUint32;
188 const Operator* op = (signedness == kSigned) 189 const Operator* op = (signedness == kSigned)
189 ? machine()->ChangeFloat64ToInt32() 190 ? machine()->ChangeFloat64ToInt32()
190 : machine()->ChangeFloat64ToUint32(); 191 : machine()->ChangeFloat64ToUint32();
191 Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse); 192
192 d.Chain(control); 193 if (NodeProperties::GetBounds(value).upper->Is(Type::TaggedPointer())) {
193 return Replace( 194 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control)));
194 d.Phi(type, graph()->NewNode(op, LoadHeapNumberValue(value, d.if_true)), 195 }
195 ChangeSmiToInt32(value))); 196
197 Node* check = TestNotSmi(value);
198 Node* branch =
199 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
200
201 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
202 Node* vtrue = graph()->NewNode(op, LoadHeapNumberValue(value, if_true));
203
204 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
205 Node* vfalse = ChangeSmiToInt32(value);
206
207 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
208 Node* phi = graph()->NewNode(common()->Phi(type, 2), vtrue, vfalse, merge);
209
210 return Replace(phi);
196 } 211 }
197 212
198 213
199 namespace { 214 namespace {
200 215
201 bool CanCover(Node* value, IrOpcode::Value opcode) { 216 bool CanCover(Node* value, IrOpcode::Value opcode) {
202 if (value->opcode() != opcode) return false; 217 if (value->opcode() != opcode) return false;
203 bool first = true; 218 bool first = true;
204 for (Edge const edge : value->use_edges()) { 219 for (Edge const edge : value->use_edges()) {
205 if (NodeProperties::IsControlEdge(edge)) continue; 220 if (NodeProperties::IsControlEdge(edge)) continue;
(...skipping 13 matching lines...) Expand all
219 // ChangeTaggedToFloat64(JSToNumber(x)) => 234 // ChangeTaggedToFloat64(JSToNumber(x)) =>
220 // if IsSmi(x) then ChangeSmiToFloat64(x) 235 // if IsSmi(x) then ChangeSmiToFloat64(x)
221 // else let y = JSToNumber(x) in 236 // else let y = JSToNumber(x) in
222 // if IsSmi(y) then ChangeSmiToFloat64(y) 237 // if IsSmi(y) then ChangeSmiToFloat64(y)
223 // else LoadHeapNumberValue(y) 238 // else LoadHeapNumberValue(y)
224 Node* const object = NodeProperties::GetValueInput(value, 0); 239 Node* const object = NodeProperties::GetValueInput(value, 0);
225 Node* const context = NodeProperties::GetContextInput(value); 240 Node* const context = NodeProperties::GetContextInput(value);
226 Node* const effect = NodeProperties::GetEffectInput(value); 241 Node* const effect = NodeProperties::GetEffectInput(value);
227 Node* const control = NodeProperties::GetControlInput(value); 242 Node* const control = NodeProperties::GetControlInput(value);
228 243
229 Diamond d1(graph(), common(), TestNotSmi(object), BranchHint::kFalse); 244 const Operator* merge_op = common()->Merge(2);
230 d1.Chain(control); 245 const Operator* ephi_op = common()->EffectPhi(2);
246 const Operator* phi_op = common()->Phi(kMachFloat64, 2);
231 247
232 DCHECK_EQ(FLAG_turbo_deoptimization, 248 Node* check1 = TestNotSmi(object);
233 OperatorProperties::GetFrameStateInputCount(value->op()) == 1); 249 Node* branch1 =
234 Node* number = 250 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
251
252 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
253 Node* vtrue1 =
235 FLAG_turbo_deoptimization 254 FLAG_turbo_deoptimization
236 ? graph()->NewNode(value->op(), object, context, 255 ? graph()->NewNode(value->op(), object, context,
237 NodeProperties::GetFrameStateInput(value, 0), 256 NodeProperties::GetFrameStateInput(value, 0),
238 effect, d1.if_true) 257 effect, if_true1)
239 : graph()->NewNode(value->op(), object, context, effect, 258 : graph()->NewNode(value->op(), object, context, effect, if_true1);
240 d1.if_true); 259 Node* etrue1 = vtrue1;
241 Diamond d2(graph(), common(), TestNotSmi(number)); 260 {
242 d2.Nest(d1, true); 261 Node* check2 = TestNotSmi(vtrue1);
243 Node* phi2 = d2.Phi(kMachFloat64, LoadHeapNumberValue(number, d2.if_true), 262 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1);
244 ChangeSmiToFloat64(number));
245 263
246 Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object)); 264 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
247 Node* ephi1 = d1.EffectPhi(number, effect); 265 Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2);
248 266
249 for (Edge edge : value->use_edges()) { 267 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
250 if (NodeProperties::IsEffectEdge(edge)) { 268 Node* vfalse2 = ChangeSmiToFloat64(vtrue1);
251 edge.UpdateTo(ephi1); 269
252 } 270 if_true1 = graph()->NewNode(merge_op, if_true2, if_false2);
271 vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1);
253 } 272 }
273
274 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
275 Node* vfalse1 = ChangeSmiToFloat64(object);
276 Node* efalse1 = effect;
277
278 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
279 Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
280 Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
281
282 NodeProperties::ReplaceWithValue(value, phi1, ephi1, merge1);
254 return Replace(phi1); 283 return Replace(phi1);
255 } 284 }
256 285
257 Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse); 286 Node* check = TestNotSmi(value);
258 d.Chain(control); 287 Node* branch =
259 Node* load = LoadHeapNumberValue(value, d.if_true); 288 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
260 Node* number = ChangeSmiToFloat64(value); 289
261 return Replace(d.Phi(kMachFloat64, load, number)); 290 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
291 Node* vtrue = LoadHeapNumberValue(value, if_true);
292
293 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
294 Node* vfalse = ChangeSmiToFloat64(value);
295
296 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
297 Node* phi =
298 graph()->NewNode(common()->Phi(kMachFloat64, 2), vtrue, vfalse, merge);
299
300 return Replace(phi);
262 } 301 }
263 302
264 303
265 Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) { 304 Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) {
266 Diamond d(graph(), common(), 305 if (NodeProperties::GetBounds(value).upper->Is(Type::UnsignedSmall())) {
267 Uint32LessThanOrEqual(value, SmiMaxValueConstant()), 306 return Replace(ChangeUint32ToSmi(value));
268 BranchHint::kTrue); 307 }
269 d.Chain(control); 308
270 return Replace(d.Phi( 309 Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
271 kMachAnyTagged, ChangeUint32ToSmi(value), 310 SmiMaxValueConstant());
272 AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), d.if_false))); 311 Node* branch =
312 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
313
314 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
315 Node* vtrue = ChangeUint32ToSmi(value);
316
317 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
318 Node* vfalse =
319 AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), if_false);
320
321 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
322 Node* phi =
323 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge);
324
325 return Replace(phi);
273 } 326 }
274 327
275 328
276 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } 329 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); }
277 330
278 331
279 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } 332 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); }
280 333
281 334
282 CommonOperatorBuilder* ChangeLowering::common() const { 335 CommonOperatorBuilder* ChangeLowering::common() const {
283 return jsgraph()->common(); 336 return jsgraph()->common();
284 } 337 }
285 338
286 339
287 MachineOperatorBuilder* ChangeLowering::machine() const { 340 MachineOperatorBuilder* ChangeLowering::machine() const {
288 return jsgraph()->machine(); 341 return jsgraph()->machine();
289 } 342 }
290 343
291 } // namespace compiler 344 } // namespace compiler
292 } // namespace internal 345 } // namespace internal
293 } // namespace v8 346 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/change-lowering.h ('k') | test/unittests/compiler/change-lowering-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698