OLD | NEW |
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/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 public: | 190 public: |
191 OutOfLineLoadInteger(CodeGenerator* gen, Register result) | 191 OutOfLineLoadInteger(CodeGenerator* gen, Register result) |
192 : OutOfLineCode(gen), result_(result) {} | 192 : OutOfLineCode(gen), result_(result) {} |
193 | 193 |
194 void Generate() final { __ xor_(result_, result_); } | 194 void Generate() final { __ xor_(result_, result_); } |
195 | 195 |
196 private: | 196 private: |
197 Register const result_; | 197 Register const result_; |
198 }; | 198 }; |
199 | 199 |
200 | 200 class OutOfLineLoadNaN final : public OutOfLineCode { |
201 class OutOfLineLoadFloat final : public OutOfLineCode { | |
202 public: | 201 public: |
203 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result) | 202 OutOfLineLoadNaN(CodeGenerator* gen, XMMRegister result) |
204 : OutOfLineCode(gen), result_(result) {} | 203 : OutOfLineCode(gen), result_(result) {} |
205 | 204 |
206 void Generate() final { __ pcmpeqd(result_, result_); } | 205 void Generate() final { __ pcmpeqd(result_, result_); } |
207 | 206 |
208 private: | 207 private: |
209 XMMRegister const result_; | 208 XMMRegister const result_; |
210 }; | 209 }; |
211 | 210 |
212 | 211 |
213 class OutOfLineTruncateDoubleToI final : public OutOfLineCode { | 212 class OutOfLineTruncateDoubleToI final : public OutOfLineCode { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 Register const object_; | 263 Register const object_; |
265 Operand const operand_; | 264 Operand const operand_; |
266 Register const value_; | 265 Register const value_; |
267 Register const scratch0_; | 266 Register const scratch0_; |
268 Register const scratch1_; | 267 Register const scratch1_; |
269 RecordWriteMode const mode_; | 268 RecordWriteMode const mode_; |
270 }; | 269 }; |
271 | 270 |
272 } // namespace | 271 } // namespace |
273 | 272 |
274 | 273 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ | 274 do { \ |
276 do { \ | 275 auto result = i.OutputDoubleRegister(); \ |
277 auto result = i.OutputDoubleRegister(); \ | 276 auto offset = i.InputRegister(0); \ |
278 auto offset = i.InputRegister(0); \ | 277 if (instr->InputAt(1)->IsRegister()) { \ |
279 if (instr->InputAt(1)->IsRegister()) { \ | 278 __ cmp(offset, i.InputRegister(1)); \ |
280 __ cmp(offset, i.InputRegister(1)); \ | 279 } else { \ |
281 } else { \ | 280 __ cmp(offset, i.InputImmediate(1)); \ |
282 __ cmp(offset, i.InputImmediate(1)); \ | 281 } \ |
283 } \ | 282 OutOfLineCode* ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
284 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ | 283 __ j(above_equal, ool->entry()); \ |
285 __ j(above_equal, ool->entry()); \ | 284 __ asm_instr(result, i.MemoryOperand(2)); \ |
286 __ asm_instr(result, i.MemoryOperand(2)); \ | 285 __ bind(ool->exit()); \ |
287 __ bind(ool->exit()); \ | |
288 } while (false) | 286 } while (false) |
289 | 287 |
290 | |
291 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ | 288 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
292 do { \ | 289 do { \ |
293 auto result = i.OutputRegister(); \ | 290 auto result = i.OutputRegister(); \ |
294 auto offset = i.InputRegister(0); \ | 291 auto offset = i.InputRegister(0); \ |
295 if (instr->InputAt(1)->IsRegister()) { \ | 292 if (instr->InputAt(1)->IsRegister()) { \ |
296 __ cmp(offset, i.InputRegister(1)); \ | 293 __ cmp(offset, i.InputRegister(1)); \ |
297 } else { \ | 294 } else { \ |
298 __ cmp(offset, i.InputImmediate(1)); \ | 295 __ cmp(offset, i.InputImmediate(1)); \ |
299 } \ | 296 } \ |
300 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ | 297 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 break; | 980 break; |
984 case kSSEFloat32Mul: | 981 case kSSEFloat32Mul: |
985 __ mulss(i.InputDoubleRegister(0), i.InputOperand(1)); | 982 __ mulss(i.InputDoubleRegister(0), i.InputOperand(1)); |
986 break; | 983 break; |
987 case kSSEFloat32Div: | 984 case kSSEFloat32Div: |
988 __ divss(i.InputDoubleRegister(0), i.InputOperand(1)); | 985 __ divss(i.InputDoubleRegister(0), i.InputOperand(1)); |
989 // Don't delete this mov. It may improve performance on some CPUs, | 986 // Don't delete this mov. It may improve performance on some CPUs, |
990 // when there is a (v)mulss depending on the result. | 987 // when there is a (v)mulss depending on the result. |
991 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 988 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
992 break; | 989 break; |
993 case kSSEFloat32Max: | |
994 __ maxss(i.InputDoubleRegister(0), i.InputOperand(1)); | |
995 break; | |
996 case kSSEFloat32Min: | |
997 __ minss(i.InputDoubleRegister(0), i.InputOperand(1)); | |
998 break; | |
999 case kSSEFloat32Sqrt: | 990 case kSSEFloat32Sqrt: |
1000 __ sqrtss(i.OutputDoubleRegister(), i.InputOperand(0)); | 991 __ sqrtss(i.OutputDoubleRegister(), i.InputOperand(0)); |
1001 break; | 992 break; |
1002 case kSSEFloat32Abs: { | 993 case kSSEFloat32Abs: { |
1003 // TODO(bmeurer): Use 128-bit constants. | 994 // TODO(bmeurer): Use 128-bit constants. |
1004 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); | 995 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); |
1005 __ psrlq(kScratchDoubleReg, 33); | 996 __ psrlq(kScratchDoubleReg, 33); |
1006 __ andps(i.OutputDoubleRegister(), kScratchDoubleReg); | 997 __ andps(i.OutputDoubleRegister(), kScratchDoubleReg); |
1007 break; | 998 break; |
1008 } | 999 } |
(...skipping 22 matching lines...) Expand all Loading... |
1031 break; | 1022 break; |
1032 case kSSEFloat64Mul: | 1023 case kSSEFloat64Mul: |
1033 __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1)); | 1024 __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1)); |
1034 break; | 1025 break; |
1035 case kSSEFloat64Div: | 1026 case kSSEFloat64Div: |
1036 __ divsd(i.InputDoubleRegister(0), i.InputOperand(1)); | 1027 __ divsd(i.InputDoubleRegister(0), i.InputOperand(1)); |
1037 // Don't delete this mov. It may improve performance on some CPUs, | 1028 // Don't delete this mov. It may improve performance on some CPUs, |
1038 // when there is a (v)mulsd depending on the result. | 1029 // when there is a (v)mulsd depending on the result. |
1039 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 1030 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
1040 break; | 1031 break; |
1041 case kSSEFloat64Max: | 1032 case kSSEFloat64Max: { |
1042 __ maxsd(i.InputDoubleRegister(0), i.InputOperand(1)); | 1033 Label compare_nan, compare_swap, done_compare; |
| 1034 if (instr->InputAt(1)->IsFPRegister()) { |
| 1035 __ ucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1036 } else { |
| 1037 __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); |
| 1038 } |
| 1039 auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
| 1040 __ j(parity_even, ool->entry()); |
| 1041 __ j(above, &done_compare, Label::kNear); |
| 1042 __ j(below, &compare_swap, Label::kNear); |
| 1043 __ movmskpd(i.TempRegister(0), i.InputDoubleRegister(0)); |
| 1044 __ test(i.TempRegister(0), Immediate(1)); |
| 1045 __ j(zero, &done_compare, Label::kNear); |
| 1046 __ bind(&compare_swap); |
| 1047 if (instr->InputAt(1)->IsFPRegister()) { |
| 1048 __ movsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1049 } else { |
| 1050 __ movsd(i.InputDoubleRegister(0), i.InputOperand(1)); |
| 1051 } |
| 1052 __ bind(&done_compare); |
| 1053 __ bind(ool->exit()); |
1043 break; | 1054 break; |
1044 case kSSEFloat64Min: | 1055 } |
1045 __ minsd(i.InputDoubleRegister(0), i.InputOperand(1)); | 1056 case kSSEFloat64Min: { |
| 1057 Label compare_swap, done_compare; |
| 1058 if (instr->InputAt(1)->IsFPRegister()) { |
| 1059 __ ucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1060 } else { |
| 1061 __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); |
| 1062 } |
| 1063 auto ool = new (zone()) OutOfLineLoadNaN(this, i.OutputDoubleRegister()); |
| 1064 __ j(parity_even, ool->entry()); |
| 1065 __ j(below, &done_compare, Label::kNear); |
| 1066 __ j(above, &compare_swap, Label::kNear); |
| 1067 if (instr->InputAt(1)->IsFPRegister()) { |
| 1068 __ movmskpd(i.TempRegister(0), i.InputDoubleRegister(1)); |
| 1069 } else { |
| 1070 __ movsd(kScratchDoubleReg, i.InputOperand(1)); |
| 1071 __ movmskpd(i.TempRegister(0), kScratchDoubleReg); |
| 1072 } |
| 1073 __ test(i.TempRegister(0), Immediate(1)); |
| 1074 __ j(zero, &done_compare, Label::kNear); |
| 1075 __ bind(&compare_swap); |
| 1076 if (instr->InputAt(1)->IsFPRegister()) { |
| 1077 __ movsd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); |
| 1078 } else { |
| 1079 __ movsd(i.InputDoubleRegister(0), i.InputOperand(1)); |
| 1080 } |
| 1081 __ bind(&done_compare); |
| 1082 __ bind(ool->exit()); |
1046 break; | 1083 break; |
| 1084 } |
1047 case kSSEFloat64Mod: { | 1085 case kSSEFloat64Mod: { |
1048 // TODO(dcarney): alignment is wrong. | 1086 // TODO(dcarney): alignment is wrong. |
1049 __ sub(esp, Immediate(kDoubleSize)); | 1087 __ sub(esp, Immediate(kDoubleSize)); |
1050 // Move values to st(0) and st(1). | 1088 // Move values to st(0) and st(1). |
1051 __ movsd(Operand(esp, 0), i.InputDoubleRegister(1)); | 1089 __ movsd(Operand(esp, 0), i.InputDoubleRegister(1)); |
1052 __ fld_d(Operand(esp, 0)); | 1090 __ fld_d(Operand(esp, 0)); |
1053 __ movsd(Operand(esp, 0), i.InputDoubleRegister(0)); | 1091 __ movsd(Operand(esp, 0), i.InputDoubleRegister(0)); |
1054 __ fld_d(Operand(esp, 0)); | 1092 __ fld_d(Operand(esp, 0)); |
1055 // Loop while fprem isn't done. | 1093 // Loop while fprem isn't done. |
1056 Label mod_loop; | 1094 Label mod_loop; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 } | 1221 } |
1184 case kAVXFloat32Div: { | 1222 case kAVXFloat32Div: { |
1185 CpuFeatureScope avx_scope(masm(), AVX); | 1223 CpuFeatureScope avx_scope(masm(), AVX); |
1186 __ vdivss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 1224 __ vdivss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1187 i.InputOperand(1)); | 1225 i.InputOperand(1)); |
1188 // Don't delete this mov. It may improve performance on some CPUs, | 1226 // Don't delete this mov. It may improve performance on some CPUs, |
1189 // when there is a (v)mulss depending on the result. | 1227 // when there is a (v)mulss depending on the result. |
1190 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 1228 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
1191 break; | 1229 break; |
1192 } | 1230 } |
1193 case kAVXFloat32Max: { | |
1194 CpuFeatureScope avx_scope(masm(), AVX); | |
1195 __ vmaxss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | |
1196 i.InputOperand(1)); | |
1197 break; | |
1198 } | |
1199 case kAVXFloat32Min: { | |
1200 CpuFeatureScope avx_scope(masm(), AVX); | |
1201 __ vminss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | |
1202 i.InputOperand(1)); | |
1203 break; | |
1204 } | |
1205 case kAVXFloat64Add: { | 1231 case kAVXFloat64Add: { |
1206 CpuFeatureScope avx_scope(masm(), AVX); | 1232 CpuFeatureScope avx_scope(masm(), AVX); |
1207 __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 1233 __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1208 i.InputOperand(1)); | 1234 i.InputOperand(1)); |
1209 break; | 1235 break; |
1210 } | 1236 } |
1211 case kAVXFloat64Sub: { | 1237 case kAVXFloat64Sub: { |
1212 CpuFeatureScope avx_scope(masm(), AVX); | 1238 CpuFeatureScope avx_scope(masm(), AVX); |
1213 __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 1239 __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1214 i.InputOperand(1)); | 1240 i.InputOperand(1)); |
1215 break; | 1241 break; |
1216 } | 1242 } |
1217 case kAVXFloat64Mul: { | 1243 case kAVXFloat64Mul: { |
1218 CpuFeatureScope avx_scope(masm(), AVX); | 1244 CpuFeatureScope avx_scope(masm(), AVX); |
1219 __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 1245 __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1220 i.InputOperand(1)); | 1246 i.InputOperand(1)); |
1221 break; | 1247 break; |
1222 } | 1248 } |
1223 case kAVXFloat64Div: { | 1249 case kAVXFloat64Div: { |
1224 CpuFeatureScope avx_scope(masm(), AVX); | 1250 CpuFeatureScope avx_scope(masm(), AVX); |
1225 __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 1251 __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
1226 i.InputOperand(1)); | 1252 i.InputOperand(1)); |
1227 // Don't delete this mov. It may improve performance on some CPUs, | 1253 // Don't delete this mov. It may improve performance on some CPUs, |
1228 // when there is a (v)mulsd depending on the result. | 1254 // when there is a (v)mulsd depending on the result. |
1229 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); | 1255 __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
1230 break; | 1256 break; |
1231 } | 1257 } |
1232 case kAVXFloat64Max: { | |
1233 CpuFeatureScope avx_scope(masm(), AVX); | |
1234 __ vmaxsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | |
1235 i.InputOperand(1)); | |
1236 break; | |
1237 } | |
1238 case kAVXFloat64Min: { | |
1239 CpuFeatureScope avx_scope(masm(), AVX); | |
1240 __ vminsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | |
1241 i.InputOperand(1)); | |
1242 break; | |
1243 } | |
1244 case kAVXFloat32Abs: { | 1258 case kAVXFloat32Abs: { |
1245 // TODO(bmeurer): Use RIP relative 128-bit constants. | 1259 // TODO(bmeurer): Use RIP relative 128-bit constants. |
1246 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); | 1260 __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); |
1247 __ psrlq(kScratchDoubleReg, 33); | 1261 __ psrlq(kScratchDoubleReg, 33); |
1248 CpuFeatureScope avx_scope(masm(), AVX); | 1262 CpuFeatureScope avx_scope(masm(), AVX); |
1249 __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0)); | 1263 __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0)); |
1250 break; | 1264 break; |
1251 } | 1265 } |
1252 case kAVXFloat32Neg: { | 1266 case kAVXFloat32Neg: { |
1253 // TODO(bmeurer): Use RIP relative 128-bit constants. | 1267 // TODO(bmeurer): Use RIP relative 128-bit constants. |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2177 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2191 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2178 __ Nop(padding_size); | 2192 __ Nop(padding_size); |
2179 } | 2193 } |
2180 } | 2194 } |
2181 | 2195 |
2182 #undef __ | 2196 #undef __ |
2183 | 2197 |
2184 } // namespace compiler | 2198 } // namespace compiler |
2185 } // namespace internal | 2199 } // namespace internal |
2186 } // namespace v8 | 2200 } // namespace v8 |
OLD | NEW |