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

Side by Side Diff: src/crankshaft/arm64/lithium-codegen-arm64.cc

Issue 2622643005: ARM64: Add NEON support (Closed)
Patch Set: Created 3 years, 11 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
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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/crankshaft/arm64/lithium-codegen-arm64.h" 5 #include "src/crankshaft/arm64/lithium-codegen-arm64.h"
6 6
7 #include "src/arm64/frames-arm64.h" 7 #include "src/arm64/frames-arm64.h"
8 #include "src/base/bits.h" 8 #include "src/base/bits.h"
9 #include "src/builtins/builtins-constructor.h" 9 #include "src/builtins/builtins-constructor.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 private: 170 private:
171 Condition cond_; 171 Condition cond_;
172 const Register& value_; 172 const Register& value_;
173 uint64_t mask_; 173 uint64_t mask_;
174 }; 174 };
175 175
176 176
177 // Test the input and branch if it is non-zero and not a NaN. 177 // Test the input and branch if it is non-zero and not a NaN.
178 class BranchIfNonZeroNumber : public BranchGenerator { 178 class BranchIfNonZeroNumber : public BranchGenerator {
179 public: 179 public:
180 BranchIfNonZeroNumber(LCodeGen* codegen, const FPRegister& value, 180 BranchIfNonZeroNumber(LCodeGen* codegen, const VRegister& value,
181 const FPRegister& scratch) 181 const VRegister& scratch)
182 : BranchGenerator(codegen), value_(value), scratch_(scratch) { } 182 : BranchGenerator(codegen), value_(value), scratch_(scratch) {}
183 183
184 virtual void Emit(Label* label) const { 184 virtual void Emit(Label* label) const {
185 __ Fabs(scratch_, value_); 185 __ Fabs(scratch_, value_);
186 // Compare with 0.0. Because scratch_ is positive, the result can be one of 186 // Compare with 0.0. Because scratch_ is positive, the result can be one of
187 // nZCv (equal), nzCv (greater) or nzCV (unordered). 187 // nZCv (equal), nzCv (greater) or nzCV (unordered).
188 __ Fcmp(scratch_, 0.0); 188 __ Fcmp(scratch_, 0.0);
189 __ B(gt, label); 189 __ B(gt, label);
190 } 190 }
191 191
192 virtual void EmitInverted(Label* label) const { 192 virtual void EmitInverted(Label* label) const {
193 __ Fabs(scratch_, value_); 193 __ Fabs(scratch_, value_);
194 __ Fcmp(scratch_, 0.0); 194 __ Fcmp(scratch_, 0.0);
195 __ B(le, label); 195 __ B(le, label);
196 } 196 }
197 197
198 private: 198 private:
199 const FPRegister& value_; 199 const VRegister& value_;
200 const FPRegister& scratch_; 200 const VRegister& scratch_;
201 }; 201 };
202 202
203 203
204 // Test the input and branch if it is a heap number. 204 // Test the input and branch if it is a heap number.
205 class BranchIfHeapNumber : public BranchGenerator { 205 class BranchIfHeapNumber : public BranchGenerator {
206 public: 206 public:
207 BranchIfHeapNumber(LCodeGen* codegen, const Register& value) 207 BranchIfHeapNumber(LCodeGen* codegen, const Register& value)
208 : BranchGenerator(codegen), value_(value) { } 208 : BranchGenerator(codegen), value_(value) { }
209 209
210 virtual void Emit(Label* label) const { 210 virtual void Emit(Label* label) const {
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 void LCodeGen::SaveCallerDoubles() { 538 void LCodeGen::SaveCallerDoubles() {
539 DCHECK(info()->saves_caller_doubles()); 539 DCHECK(info()->saves_caller_doubles());
540 DCHECK(NeedsEagerFrame()); 540 DCHECK(NeedsEagerFrame());
541 Comment(";;; Save clobbered callee double registers"); 541 Comment(";;; Save clobbered callee double registers");
542 BitVector* doubles = chunk()->allocated_double_registers(); 542 BitVector* doubles = chunk()->allocated_double_registers();
543 BitVector::Iterator iterator(doubles); 543 BitVector::Iterator iterator(doubles);
544 int count = 0; 544 int count = 0;
545 while (!iterator.Done()) { 545 while (!iterator.Done()) {
546 // TODO(all): Is this supposed to save just the callee-saved doubles? It 546 // TODO(all): Is this supposed to save just the callee-saved doubles? It
547 // looks like it's saving all of them. 547 // looks like it's saving all of them.
548 FPRegister value = FPRegister::from_code(iterator.Current()); 548 VRegister value = VRegister::from_code(iterator.Current());
549 __ Poke(value, count * kDoubleSize); 549 __ Poke(value, count * kDoubleSize);
550 iterator.Advance(); 550 iterator.Advance();
551 count++; 551 count++;
552 } 552 }
553 } 553 }
554 554
555 555
556 void LCodeGen::RestoreCallerDoubles() { 556 void LCodeGen::RestoreCallerDoubles() {
557 DCHECK(info()->saves_caller_doubles()); 557 DCHECK(info()->saves_caller_doubles());
558 DCHECK(NeedsEagerFrame()); 558 DCHECK(NeedsEagerFrame());
559 Comment(";;; Restore clobbered callee double registers"); 559 Comment(";;; Restore clobbered callee double registers");
560 BitVector* doubles = chunk()->allocated_double_registers(); 560 BitVector* doubles = chunk()->allocated_double_registers();
561 BitVector::Iterator iterator(doubles); 561 BitVector::Iterator iterator(doubles);
562 int count = 0; 562 int count = 0;
563 while (!iterator.Done()) { 563 while (!iterator.Done()) {
564 // TODO(all): Is this supposed to restore just the callee-saved doubles? It 564 // TODO(all): Is this supposed to restore just the callee-saved doubles? It
565 // looks like it's restoring all of them. 565 // looks like it's restoring all of them.
566 FPRegister value = FPRegister::from_code(iterator.Current()); 566 VRegister value = VRegister::from_code(iterator.Current());
567 __ Peek(value, count * kDoubleSize); 567 __ Peek(value, count * kDoubleSize);
568 iterator.Advance(); 568 iterator.Advance();
569 count++; 569 count++;
570 } 570 }
571 } 571 }
572 572
573 573
574 bool LCodeGen::GeneratePrologue() { 574 bool LCodeGen::GeneratePrologue() {
575 DCHECK(is_generating()); 575 DCHECK(is_generating());
576 576
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 // references the end of the double registers and not the end of the stack 1127 // references the end of the double registers and not the end of the stack
1128 // slots. 1128 // slots.
1129 // In both of the cases above, we _could_ add the tracking information 1129 // In both of the cases above, we _could_ add the tracking information
1130 // required so that we can use jssp here, but in practice it isn't worth it. 1130 // required so that we can use jssp here, but in practice it isn't worth it.
1131 if ((stack_mode == kCanUseStackPointer) && 1131 if ((stack_mode == kCanUseStackPointer) &&
1132 !info()->saves_caller_doubles()) { 1132 !info()->saves_caller_doubles()) {
1133 int jssp_offset_to_fp = 1133 int jssp_offset_to_fp =
1134 (pushed_arguments_ + GetTotalFrameSlotCount()) * kPointerSize - 1134 (pushed_arguments_ + GetTotalFrameSlotCount()) * kPointerSize -
1135 StandardFrameConstants::kFixedFrameSizeAboveFp; 1135 StandardFrameConstants::kFixedFrameSizeAboveFp;
1136 int jssp_offset = fp_offset + jssp_offset_to_fp; 1136 int jssp_offset = fp_offset + jssp_offset_to_fp;
1137 if (masm()->IsImmLSScaled(jssp_offset, LSDoubleWord)) { 1137 if (masm()->IsImmLSScaled(jssp_offset, 3)) {
bbudge 2017/01/31 01:41:31 nit: replace magic number with named constant
martyn.capewell 2017/02/03 11:01:31 Done.
1138 return MemOperand(masm()->StackPointer(), jssp_offset); 1138 return MemOperand(masm()->StackPointer(), jssp_offset);
1139 } 1139 }
1140 } 1140 }
1141 return MemOperand(fp, fp_offset); 1141 return MemOperand(fp, fp_offset);
1142 } else { 1142 } else {
1143 // Retrieve parameter without eager stack-frame relative to the 1143 // Retrieve parameter without eager stack-frame relative to the
1144 // stack-pointer. 1144 // stack-pointer.
1145 return MemOperand(masm()->StackPointer(), 1145 return MemOperand(masm()->StackPointer(),
1146 ArgumentsOffsetWithoutFrame(op->index())); 1146 ArgumentsOffsetWithoutFrame(op->index()));
1147 } 1147 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 template<class InstrType> 1266 template<class InstrType>
1267 void LCodeGen::EmitTestAndBranch(InstrType instr, 1267 void LCodeGen::EmitTestAndBranch(InstrType instr,
1268 Condition condition, 1268 Condition condition,
1269 const Register& value, 1269 const Register& value,
1270 uint64_t mask) { 1270 uint64_t mask) {
1271 DCHECK((condition != al) && (condition != nv)); 1271 DCHECK((condition != al) && (condition != nv));
1272 TestAndBranch branch(this, condition, value, mask); 1272 TestAndBranch branch(this, condition, value, mask);
1273 EmitBranchGeneric(instr, branch); 1273 EmitBranchGeneric(instr, branch);
1274 } 1274 }
1275 1275
1276 1276 template <class InstrType>
1277 template<class InstrType>
1278 void LCodeGen::EmitBranchIfNonZeroNumber(InstrType instr, 1277 void LCodeGen::EmitBranchIfNonZeroNumber(InstrType instr,
1279 const FPRegister& value, 1278 const VRegister& value,
1280 const FPRegister& scratch) { 1279 const VRegister& scratch) {
1281 BranchIfNonZeroNumber branch(this, value, scratch); 1280 BranchIfNonZeroNumber branch(this, value, scratch);
1282 EmitBranchGeneric(instr, branch); 1281 EmitBranchGeneric(instr, branch);
1283 } 1282 }
1284 1283
1285 1284
1286 template<class InstrType> 1285 template<class InstrType>
1287 void LCodeGen::EmitBranchIfHeapNumber(InstrType instr, 1286 void LCodeGen::EmitBranchIfHeapNumber(InstrType instr,
1288 const Register& value) { 1287 const Register& value) {
1289 BranchIfHeapNumber branch(this, value); 1288 BranchIfHeapNumber branch(this, value);
1290 EmitBranchGeneric(instr, branch); 1289 EmitBranchGeneric(instr, branch);
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
2267 // is booted. This routine isn't expected to work for random API-created 2266 // is booted. This routine isn't expected to work for random API-created
2268 // classes and it doesn't have to because you can't access it with natives 2267 // classes and it doesn't have to because you can't access it with natives
2269 // syntax. Since both sides are internalized it is sufficient to use an 2268 // syntax. Since both sides are internalized it is sufficient to use an
2270 // identity comparison. 2269 // identity comparison.
2271 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name)); 2270 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name));
2272 } 2271 }
2273 2272
2274 2273
2275 void LCodeGen::DoCmpHoleAndBranchD(LCmpHoleAndBranchD* instr) { 2274 void LCodeGen::DoCmpHoleAndBranchD(LCmpHoleAndBranchD* instr) {
2276 DCHECK(instr->hydrogen()->representation().IsDouble()); 2275 DCHECK(instr->hydrogen()->representation().IsDouble());
2277 FPRegister object = ToDoubleRegister(instr->object()); 2276 VRegister object = ToDoubleRegister(instr->object());
2278 Register temp = ToRegister(instr->temp()); 2277 Register temp = ToRegister(instr->temp());
2279 2278
2280 // If we don't have a NaN, we don't have the hole, so branch now to avoid the 2279 // If we don't have a NaN, we don't have the hole, so branch now to avoid the
2281 // (relatively expensive) hole-NaN check. 2280 // (relatively expensive) hole-NaN check.
2282 __ Fcmp(object, object); 2281 __ Fcmp(object, object);
2283 __ B(vc, instr->FalseLabel(chunk_)); 2282 __ B(vc, instr->FalseLabel(chunk_));
2284 2283
2285 // We have a NaN, but is it the hole? 2284 // We have a NaN, but is it the hole?
2286 __ Fmov(temp, object); 2285 __ Fmov(temp, object);
2287 EmitCompareAndBranch(instr, eq, temp, kHoleNanInt64); 2286 EmitCompareAndBranch(instr, eq, temp, kHoleNanInt64);
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 Register object = ToRegister(instr->object()); 3262 Register object = ToRegister(instr->object());
3264 3263
3265 if (access.IsExternalMemory()) { 3264 if (access.IsExternalMemory()) {
3266 Register result = ToRegister(instr->result()); 3265 Register result = ToRegister(instr->result());
3267 __ Load(result, MemOperand(object, offset), access.representation()); 3266 __ Load(result, MemOperand(object, offset), access.representation());
3268 return; 3267 return;
3269 } 3268 }
3270 3269
3271 if (instr->hydrogen()->representation().IsDouble()) { 3270 if (instr->hydrogen()->representation().IsDouble()) {
3272 DCHECK(access.IsInobject()); 3271 DCHECK(access.IsInobject());
3273 FPRegister result = ToDoubleRegister(instr->result()); 3272 VRegister result = ToDoubleRegister(instr->result());
3274 __ Ldr(result, FieldMemOperand(object, offset)); 3273 __ Ldr(result, FieldMemOperand(object, offset));
3275 return; 3274 return;
3276 } 3275 }
3277 3276
3278 Register result = ToRegister(instr->result()); 3277 Register result = ToRegister(instr->result());
3279 Register source; 3278 Register source;
3280 if (access.IsInobject()) { 3279 if (access.IsInobject()) {
3281 source = object; 3280 source = object;
3282 } else { 3281 } else {
3283 // Load the properties array, using result as a scratch register. 3282 // Load the properties array, using result as a scratch register.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
3423 // never get set by the negation. This is therefore the same as the Integer32 3422 // never get set by the negation. This is therefore the same as the Integer32
3424 // case in DoMathAbs, except that it operates on 64-bit values. 3423 // case in DoMathAbs, except that it operates on 64-bit values.
3425 STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && (kSmiTag == 0)); 3424 STATIC_ASSERT((kSmiValueSize == 32) && (kSmiShift == 32) && (kSmiTag == 0));
3426 3425
3427 __ JumpIfNotSmi(input, deferred->entry()); 3426 __ JumpIfNotSmi(input, deferred->entry());
3428 3427
3429 __ Abs(result, input, NULL, &done); 3428 __ Abs(result, input, NULL, &done);
3430 3429
3431 // The result is the magnitude (abs) of the smallest value a smi can 3430 // The result is the magnitude (abs) of the smallest value a smi can
3432 // represent, encoded as a double. 3431 // represent, encoded as a double.
3433 __ Mov(result_bits, double_to_rawbits(0x80000000)); 3432 __ Mov(result_bits, bit_cast<uint64_t>(static_cast<double>(INT64_MIN)));
3434 __ B(deferred->allocation_entry()); 3433 __ B(deferred->allocation_entry());
3435 3434
3436 __ Bind(deferred->exit()); 3435 __ Bind(deferred->exit());
3437 __ Str(result_bits, FieldMemOperand(result, HeapNumber::kValueOffset)); 3436 __ Str(result_bits, FieldMemOperand(result, HeapNumber::kValueOffset));
3438 3437
3439 __ Bind(&done); 3438 __ Bind(&done);
3440 } 3439 }
3441 3440
3442 void LCodeGen::DoMathCos(LMathCos* instr) { 3441 void LCodeGen::DoMathCos(LMathCos* instr) {
3443 DCHECK(instr->IsMarkedAsCall()); 3442 DCHECK(instr->IsMarkedAsCall());
(...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after
4965 __ Store(value, MemOperand(object, offset), representation); 4964 __ Store(value, MemOperand(object, offset), representation);
4966 return; 4965 return;
4967 } 4966 }
4968 4967
4969 __ AssertNotSmi(object); 4968 __ AssertNotSmi(object);
4970 4969
4971 if (!FLAG_unbox_double_fields && representation.IsDouble()) { 4970 if (!FLAG_unbox_double_fields && representation.IsDouble()) {
4972 DCHECK(access.IsInobject()); 4971 DCHECK(access.IsInobject());
4973 DCHECK(!instr->hydrogen()->has_transition()); 4972 DCHECK(!instr->hydrogen()->has_transition());
4974 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); 4973 DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4975 FPRegister value = ToDoubleRegister(instr->value()); 4974 VRegister value = ToDoubleRegister(instr->value());
4976 __ Str(value, FieldMemOperand(object, offset)); 4975 __ Str(value, FieldMemOperand(object, offset));
4977 return; 4976 return;
4978 } 4977 }
4979 4978
4980 DCHECK(!representation.IsSmi() || 4979 DCHECK(!representation.IsSmi() ||
4981 !instr->value()->IsConstantOperand() || 4980 !instr->value()->IsConstantOperand() ||
4982 IsInteger32Constant(LConstantOperand::cast(instr->value()))); 4981 IsInteger32Constant(LConstantOperand::cast(instr->value())));
4983 4982
4984 if (instr->hydrogen()->has_transition()) { 4983 if (instr->hydrogen()->has_transition()) {
4985 Handle<Map> transition = instr->hydrogen()->transition_map(); 4984 Handle<Map> transition = instr->hydrogen()->transition_map();
(...skipping 17 matching lines...) Expand all
5003 if (access.IsInobject()) { 5002 if (access.IsInobject()) {
5004 destination = object; 5003 destination = object;
5005 } else { 5004 } else {
5006 Register temp0 = ToRegister(instr->temp0()); 5005 Register temp0 = ToRegister(instr->temp0());
5007 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5006 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset));
5008 destination = temp0; 5007 destination = temp0;
5009 } 5008 }
5010 5009
5011 if (FLAG_unbox_double_fields && representation.IsDouble()) { 5010 if (FLAG_unbox_double_fields && representation.IsDouble()) {
5012 DCHECK(access.IsInobject()); 5011 DCHECK(access.IsInobject());
5013 FPRegister value = ToDoubleRegister(instr->value()); 5012 VRegister value = ToDoubleRegister(instr->value());
5014 __ Str(value, FieldMemOperand(object, offset)); 5013 __ Str(value, FieldMemOperand(object, offset));
5015 } else if (representation.IsSmi() && 5014 } else if (representation.IsSmi() &&
5016 instr->hydrogen()->value()->representation().IsInteger32()) { 5015 instr->hydrogen()->value()->representation().IsInteger32()) {
5017 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); 5016 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
5018 #ifdef DEBUG 5017 #ifdef DEBUG
5019 Register temp0 = ToRegister(instr->temp0()); 5018 Register temp0 = ToRegister(instr->temp0());
5020 __ Ldr(temp0, FieldMemOperand(destination, offset)); 5019 __ Ldr(temp0, FieldMemOperand(destination, offset));
5021 __ AssertSmi(temp0); 5020 __ AssertSmi(temp0);
5022 // If destination aliased temp0, restore it to the address calculated 5021 // If destination aliased temp0, restore it to the address calculated
5023 // earlier. 5022 // earlier.
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
5591 // Index is equal to negated out of object property index plus 1. 5590 // Index is equal to negated out of object property index plus 1.
5592 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5591 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5593 __ Ldr(result, FieldMemOperand(result, 5592 __ Ldr(result, FieldMemOperand(result,
5594 FixedArray::kHeaderSize - kPointerSize)); 5593 FixedArray::kHeaderSize - kPointerSize));
5595 __ Bind(deferred->exit()); 5594 __ Bind(deferred->exit());
5596 __ Bind(&done); 5595 __ Bind(&done);
5597 } 5596 }
5598 5597
5599 } // namespace internal 5598 } // namespace internal
5600 } // namespace v8 5599 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698