Changeset 160205 in webkit
- Timestamp:
- Dec 5, 2013 5:47:19 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 12 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r160200 r160205 1 2013-12-04 Filip Pizlo <fpizlo@apple.com> 2 3 FTL should use cvttsd2si directly for double-to-int32 conversions 4 https://bugs.webkit.org/show_bug.cgi?id=125275 5 6 Reviewed by Michael Saboff. 7 8 * js/regress/double-to-int32-typed-array-expected.txt: Added. 9 * js/regress/double-to-int32-typed-array-no-inline-expected.txt: Added. 10 * js/regress/double-to-int32-typed-array-no-inline.html: Added. 11 * js/regress/double-to-int32-typed-array.html: Added. 12 * js/regress/double-to-uint32-typed-array-expected.txt: Added. 13 * js/regress/double-to-uint32-typed-array-no-inline-expected.txt: Added. 14 * js/regress/double-to-uint32-typed-array-no-inline.html: Added. 15 * js/regress/double-to-uint32-typed-array.html: Added. 16 * js/regress/script-tests/double-to-int32-typed-array-no-inline.js: Added. 17 (foo): 18 (test): 19 * js/regress/script-tests/double-to-int32-typed-array.js: Added. 20 (foo): 21 (test): 22 * js/regress/script-tests/double-to-uint32-typed-array-no-inline.js: Added. 23 (foo): 24 (test): 25 * js/regress/script-tests/double-to-uint32-typed-array.js: Added. 26 (foo): 27 (test): 28 1 29 2013-12-05 Bear Travis <betravis@adobe.com> 2 30 -
trunk/Source/JavaScriptCore/ChangeLog
r160204 r160205 1 2013-12-04 Filip Pizlo <fpizlo@apple.com> 2 3 FTL should use cvttsd2si directly for double-to-int32 conversions 4 https://bugs.webkit.org/show_bug.cgi?id=125275 5 6 Reviewed by Michael Saboff. 7 8 Wow. This was an ordeal. Using cvttsd2si was actually easy, but I learned, and 9 sometimes even fixed, some interesting things: 10 11 - The llvm.x86.sse2.cvttsd2si intrinsic can actually result in LLVM emitting a 12 vcvttsd2si. I guess the intrinsic doesn't actually imply the instruction. 13 14 - That whole thing about branchTruncateDoubleToUint32? Yeah we don't need that. It's 15 better to use branchTruncateDoubleToInt32 instead. It has the right semantics for 16 all of its callers (err, its one-and-only caller), and it's more likely to take 17 fast path. This patch kills branchTruncateDoubleToUint32. 18 19 - "a[i] = v; v = a[i]". Does this change v? OK, assume that 'a[i]' is a pure-ish 20 operation - like an array access with 'i' being an integer index and we're not 21 having a bad time. Now does this change v? CSE assumes that it doesn't. That's 22 wrong. If 'a' is a typed array - the most sensible and pure kind of array - then 23 this can be a truncating cast. For example 'v' could be a double and 'a' could be 24 an integer array. 25 26 - "v1 = a[i]; v2 = a[i]". Is v1 === v2 assuming that 'a[i]' is pure-ish? The answer 27 is no. You could have a different arrayMode in each access. I know this sounds 28 weird, but with concurrent JIT that might happen. 29 30 This patch adds tests for all of this stuff, except for the first issue (it's weird 31 but probably doesn't matter) and the last issue (it's too much of a freakshow). 32 33 * assembler/MacroAssemblerARM64.h: 34 * assembler/MacroAssemblerARMv7.h: 35 * assembler/MacroAssemblerX86Common.h: 36 * dfg/DFGCSEPhase.cpp: 37 (JSC::DFG::CSEPhase::getByValLoadElimination): 38 (JSC::DFG::CSEPhase::performNodeCSE): 39 * dfg/DFGSpeculativeJIT.cpp: 40 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 41 * ftl/FTLAbbreviations.h: 42 (JSC::FTL::vectorType): 43 (JSC::FTL::getUndef): 44 (JSC::FTL::buildInsertElement): 45 * ftl/FTLIntrinsicRepository.h: 46 * ftl/FTLLowerDFGToLLVM.cpp: 47 (JSC::FTL::LowerDFGToLLVM::doubleToInt32): 48 (JSC::FTL::LowerDFGToLLVM::doubleToUInt32): 49 (JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32): 50 * ftl/FTLOutput.h: 51 (JSC::FTL::Output::insertElement): 52 (JSC::FTL::Output::hasSensibleDoubleToInt): 53 (JSC::FTL::Output::sensibleDoubleToInt): 54 1 55 2013-12-05 Commit Queue <commit-queue@webkit.org> 2 56 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r160056 r160205 1197 1197 } 1198 1198 1199 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)1200 {1201 // Truncate to a 64-bit integer in dataTempRegister, copy the low 32-bit to dest.1202 m_assembler.fcvtzs<64, 64>(dest, src);1203 // Check thlow 32-bits zero extend to be equal to the full value.1204 m_assembler.cmp<64>(dest, dest, ARM64Assembler::UXTW, 0);1205 return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));1206 }1207 1208 1199 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest) 1209 1200 { -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r159564 r160205 1075 1075 } 1076 1076 1077 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)1078 {1079 m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);1080 m_assembler.vmov(dest, fpTempRegisterAsSingle());1081 1082 Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff));1083 Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0));1084 overflow.link(this);1085 1086 if (branchType == BranchIfTruncateSuccessful)1087 return success;1088 1089 Jump failure = jump();1090 success.link(this);1091 return failure;1092 }1093 1094 1077 // Result is undefined if the value is outside of the integer range. 1095 1078 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r159855 r160205 884 884 m_assembler.cvttsd2si_rr(src, dest); 885 885 return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000)); 886 }887 888 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)889 {890 ASSERT(isSSE2Present());891 m_assembler.cvttsd2si_rr(src, dest);892 return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));893 886 } 894 887 -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r159886 r160205 332 332 } 333 333 334 Node* getByValLoadElimination(Node* child1, Node* child2 )334 Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode) 335 335 { 336 336 for (unsigned i = m_indexInBlock; i--;) { … … 343 343 if (!m_graph.byValIsPure(node)) 344 344 return 0; 345 if (node->child1() == child1 && node->child2() == child2) 345 if (node->child1() == child1 346 && node->child2() == child2 347 && node->arrayMode().type() == arrayMode.type()) 346 348 return node; 347 349 break; … … 352 354 if (!m_graph.byValIsPure(node)) 353 355 return 0; 354 if (m_graph.varArgChild(node, 0) == child1 && m_graph.varArgChild(node, 1) == child2) 356 // Typed arrays 357 if (arrayMode.typedArrayType() != NotTypedArray) 358 return 0; 359 if (m_graph.varArgChild(node, 0) == child1 360 && m_graph.varArgChild(node, 1) == child2 361 && node->arrayMode().type() == arrayMode.type()) 355 362 return m_graph.varArgChild(node, 2).node(); 356 363 // We must assume that the PutByVal will clobber the location we're getting from. … … 1217 1224 break; 1218 1225 if (m_graph.byValIsPure(node)) 1219 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node() ));1226 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node(), node->arrayMode())); 1220 1227 break; 1221 1228 … … 1227 1234 Edge child2 = m_graph.varArgChild(node, 1); 1228 1235 if (node->arrayMode().canCSEStorage()) { 1229 Node* replacement = getByValLoadElimination(child1.node(), child2.node() );1236 Node* replacement = getByValLoadElimination(child1.node(), child2.node(), node->arrayMode()); 1230 1237 if (!replacement) 1231 1238 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r160150 r160205 2507 2507 notNaN.link(&m_jit); 2508 2508 2509 MacroAssembler::Jump failed; 2510 if (isSigned(type)) 2511 failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2512 else 2513 failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2509 MacroAssembler::Jump failed = m_jit.branchTruncateDoubleToInt32( 2510 fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2514 2511 2515 2512 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr)); -
trunk/Source/JavaScriptCore/ftl/FTLAbbreviations.h
r159545 r160205 59 59 60 60 static inline LType pointerType(LType type) { return llvm->PointerType(type, 0); } 61 static inline LType vectorType(LType type, unsigned count) { return llvm->VectorType(type, count); } 61 62 62 63 enum PackingMode { NotPacked, Packed }; … … 141 142 142 143 static inline LValue getParam(LValue function, unsigned index) { return llvm->GetParam(function, index); } 144 static inline LValue getUndef(LType type) { return llvm->GetUndef(type); } 143 145 144 146 enum BitExtension { ZeroExtend, SignExtend }; … … 218 220 static inline LValue buildICmp(LBuilder builder, LIntPredicate cond, LValue left, LValue right) { return llvm->BuildICmp(builder, cond, left, right, ""); } 219 221 static inline LValue buildFCmp(LBuilder builder, LRealPredicate cond, LValue left, LValue right) { return llvm->BuildFCmp(builder, cond, left, right, ""); } 222 static inline LValue buildInsertElement(LBuilder builder, LValue vector, LValue element, LValue index) { return llvm->BuildInsertElement(builder, vector, element, index, ""); } 220 223 221 224 enum SynchronizationScope { SingleThread, CrossThread }; -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r159798 r160205 43 43 macro(mulWithOverflow32, "llvm.smul.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ 44 44 macro(mulWithOverflow64, "llvm.smul.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \ 45 macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \46 macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \47 45 macro(patchpointInt64, "llvm.experimental.patchpoint.i64", functionType(int64, int32, int32, ref8, int32, Variadic)) \ 48 46 macro(patchpointVoid, "llvm.experimental.patchpoint.void", functionType(voidType, int32, int32, ref8, int32, Variadic)) \ 49 47 macro(stackmap, "llvm.experimental.stackmap", functionType(voidType, int32, int32, Variadic)) \ 50 macro(trap, "llvm.trap", functionType(voidType)) 48 macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ 49 macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \ 50 macro(trap, "llvm.trap", functionType(voidType)) \ 51 macro(x86SSE2CvtTSD2SI, "llvm.x86.sse2.cvttsd2si", functionType(int32, vectorType(doubleType, 2))) 51 52 52 53 #define FOR_EACH_FUNCTION_TYPE(macro) \ -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r160150 r160205 3012 3012 LValue doubleToInt32(LValue doubleValue) 3013 3013 { 3014 if (Output::hasSensibleDoubleToInt()) 3015 return sensibleDoubleToInt32(doubleValue); 3016 3014 3017 double limit = pow(2, 31) - 1; 3015 3018 return doubleToInt32(doubleValue, -limit, limit); … … 3018 3021 LValue doubleToUInt32(LValue doubleValue) 3019 3022 { 3023 if (Output::hasSensibleDoubleToInt()) 3024 return sensibleDoubleToInt32(doubleValue); 3025 3020 3026 return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false); 3027 } 3028 3029 LValue sensibleDoubleToInt32(LValue doubleValue) 3030 { 3031 LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 slow path")); 3032 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 continuation")); 3033 3034 ValueFromBlock fastResult = m_out.anchor( 3035 m_out.sensibleDoubleToInt(doubleValue)); 3036 m_out.branch( 3037 m_out.equal(fastResult.value(), m_out.constInt32(0x80000000)), 3038 slowPath, continuation); 3039 3040 LBasicBlock lastNext = m_out.appendTo(slowPath, continuation); 3041 ValueFromBlock slowResult = m_out.anchor( 3042 m_out.call(m_out.operation(toInt32), doubleValue)); 3043 m_out.jump(continuation); 3044 3045 m_out.appendTo(continuation, lastNext); 3046 return m_out.phi(m_out.int32, fastResult, slowResult); 3021 3047 } 3022 3048 -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r159545 r160205 155 155 LValue bitNot(LValue value) { return buildNot(m_builder, value); } 156 156 157 LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); } 158 157 159 LValue addWithOverflow32(LValue left, LValue right) 158 160 { … … 182 184 { 183 185 return call(doubleAbsIntrinsic(), value); 186 } 187 188 static bool hasSensibleDoubleToInt() { return isX86(); } 189 LValue sensibleDoubleToInt(LValue value) 190 { 191 RELEASE_ASSERT(isX86()); 192 return call( 193 x86SSE2CvtTSD2SIIntrinsic(), 194 insertElement( 195 insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero), 196 doubleZero, int32One)); 184 197 } 185 198
Note: See TracChangeset
for help on using the changeset viewer.