Changeset 280583 in webkit
- Timestamp:
- Aug 2, 2021, 9:18:22 PM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
-
ChangeLog (modified) (1 diff)
-
assembler/MacroAssemblerARM64.h (modified) (1 diff)
-
assembler/testmasm.cpp (modified) (2 diffs)
-
b3/B3LowerToAir.cpp (modified) (11 diffs)
-
b3/air/AirOpcode.opcodes (modified) (1 diff)
-
b3/testb3.h (modified) (1 diff)
-
b3/testb3_2.cpp (modified) (2 diffs)
-
b3/testb3_3.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r280579 r280583 1 2021-08-02 Yijia Huang <yijia_huang@apple.com> 2 3 Add a new pattern to instruction selector to utilize UMULL supported by ARM64 4 https://bugs.webkit.org/show_bug.cgi?id=228721 5 6 Reviewed by Saam Barati. 7 8 Unsigned Multiply Long (UMULL) multiplies two 32-bit register values, and writes the 9 result to the destination register. This instruction is an alias of the UMADDL instruction. 10 11 umull xd wn wm 12 13 The equivalent pattern is: d = ZExt32(n) * ZExt32(m) 14 15 Given B3 IR: 16 Int @0 = ArgumentReg(%x0) 17 Int @1 = Trunc(@0) 18 Int @2 = ArgumentReg(%x1) 19 Int @3 = Trunc(@2) 20 Int @4 = ZExt32(@1) 21 Int @5 = ZExt32(@3) 22 Int @6 = Mul(@4, @5) 23 Void@7 = Return(@6, Terminal) 24 25 // Old optimized AIR 26 Move %x0, %x0, @4 27 Move %x1, %x1, @5 28 Mul %x0, %x1, %x0, @6 29 Ret %x0, @7 30 31 // New optimized AIR 32 MultiplyZeroExtend %x0, %x1, %x0, @6 33 Ret %x0, @7 34 35 * assembler/MacroAssemblerARM64.h: 36 (JSC::MacroAssemblerARM64::multiplyZeroExtend32): 37 * assembler/testmasm.cpp: 38 (JSC::testMultiplyZeroExtend32): 39 * b3/B3LowerToAir.cpp: 40 * b3/air/AirOpcode.opcodes: 41 * b3/testb3.h: 42 * b3/testb3_2.cpp: 43 (testMulArgs32SignExtend): 44 (testMulArgs32ZeroExtend): 45 * b3/testb3_3.cpp: 46 (addArgTests): 47 1 48 2021-08-02 Yijia Huang <yijia_huang@apple.com> 2 49 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r280579 r280583 954 954 } 955 955 956 void multiplyZeroExtend32(RegisterID left, RegisterID right, RegisterID dest) 957 { 958 m_assembler.umull(dest, left, right); 959 } 960 956 961 void div32(RegisterID dividend, RegisterID divisor, RegisterID dest) 957 962 { -
trunk/Source/JavaScriptCore/assembler/testmasm.cpp
r280579 r280583 922 922 } 923 923 924 void testMultiplyZeroExtend32() 925 { 926 for (auto nOperand : int32Operands()) { 927 auto mul = compile([=] (CCallHelpers& jit) { 928 emitFunctionPrologue(jit); 929 930 jit.multiplyZeroExtend32(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::returnValueGPR); 931 932 emitFunctionEpilogue(jit); 933 jit.ret(); 934 }); 935 936 for (auto mOperand : int32Operands()) { 937 uint32_t n = nOperand; 938 uint32_t m = mOperand; 939 CHECK_EQ(invoke<uint64_t>(mul, n, m), static_cast<uint64_t>(n) * static_cast<uint64_t>(m)); 940 } 941 } 942 } 943 924 944 void testMultiplyAddSignExtend32() 925 945 { … … 5650 5670 RUN(testLoadStorePair64Double()); 5651 5671 RUN(testMultiplySignExtend32()); 5672 RUN(testMultiplyZeroExtend32()); 5652 5673 5653 5674 RUN(testSub32Args()); -
trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp
r280579 r280583 500 500 } 501 501 502 bool isMergeableValue(Value* v, B3::Opcode b3Opcode, bool checkCanBeInternal )502 bool isMergeableValue(Value* v, B3::Opcode b3Opcode, bool checkCanBeInternal = false) 503 503 { 504 504 if (v->opcode() != b3Opcode) … … 517 517 // Maybe, the ideal approach is to introduce a decorator (Index@EXT) to the Air operand 518 518 // to provide an extension opportunity for the specific form under the Air opcode. 519 if (isMergeableValue(index, ZExt32 , false))519 if (isMergeableValue(index, ZExt32)) 520 520 return Arg::index(base, tmp(index->child(0)), scale, offset, MacroAssembler::Extend::ZExt32); 521 if (isMergeableValue(index, SExt32 , false))521 if (isMergeableValue(index, SExt32)) 522 522 return Arg::index(base, tmp(index->child(0)), scale, offset, MacroAssembler::Extend::SExt32); 523 523 #endif … … 2690 2690 return Air::Oops; 2691 2691 // SMADDL: d = SExt32(n) * SExt32(m) + a 2692 if (isMergeableValue(multiplyLeft, SExt32 , true) && isMergeableValue(multiplyRight, SExt32, true))2692 if (isMergeableValue(multiplyLeft, SExt32) && isMergeableValue(multiplyRight, SExt32)) 2693 2693 return MultiplyAddSignExtend32; 2694 2694 // UMADDL: d = ZExt32(n) * ZExt32(m) + a 2695 if (isMergeableValue(multiplyLeft, ZExt32 , true) && isMergeableValue(multiplyRight, ZExt32, true))2695 if (isMergeableValue(multiplyLeft, ZExt32) && isMergeableValue(multiplyRight, ZExt32)) 2696 2696 return MultiplyAddZeroExtend32; 2697 2697 return Air::Oops; … … 2701 2701 if (isValidForm(newAirOpcode, Arg::Tmp, Arg::Tmp, Arg::Tmp, Arg::Tmp)) { 2702 2702 append(newAirOpcode, tmp(multiplyLeft->child(0)), tmp(multiplyRight->child(0)), tmp(right), tmp(m_value)); 2703 commitInternal(multiplyLeft);2704 commitInternal(multiplyRight);2705 2703 commitInternal(left); 2706 2704 return true; … … 2756 2754 return Air::Oops; 2757 2755 // SMSUBL: d = a - SExt32(n) * SExt32(m) 2758 if (isMergeableValue(multiplyLeft, SExt32 , true) && isMergeableValue(multiplyRight, SExt32, true))2756 if (isMergeableValue(multiplyLeft, SExt32) && isMergeableValue(multiplyRight, SExt32)) 2759 2757 return MultiplySubSignExtend32; 2760 2758 // UMSUBL: d = a - ZExt32(n) * ZExt32(m) 2761 if (isMergeableValue(multiplyLeft, ZExt32 , true) && isMergeableValue(multiplyRight, ZExt32, true))2759 if (isMergeableValue(multiplyLeft, ZExt32) && isMergeableValue(multiplyRight, ZExt32)) 2762 2760 return MultiplySubZeroExtend32; 2763 2761 return Air::Oops; … … 2767 2765 if (isValidForm(newAirOpcode, Arg::Tmp, Arg::Tmp, Arg::Tmp, Arg::Tmp)) { 2768 2766 append(newAirOpcode, tmp(multiplyLeft->child(0)), tmp(multiplyRight->child(0)), tmp(left), tmp(m_value)); 2769 commitInternal(multiplyLeft);2770 commitInternal(multiplyRight);2771 2767 commitInternal(right); 2772 2768 return true; … … 2809 2805 return Air::Oops; 2810 2806 // SMNEGL: d = -(SExt32(n) * SExt32(m)) 2811 if (isMergeableValue(multiplyLeft, SExt32 , true) && isMergeableValue(multiplyRight, SExt32, true))2807 if (isMergeableValue(multiplyLeft, SExt32) && isMergeableValue(multiplyRight, SExt32)) 2812 2808 return MultiplyNegSignExtend32; 2813 2809 // UMNEGL: d = -(ZExt32(n) * ZExt32(m)) 2814 if (isMergeableValue(multiplyLeft, ZExt32 , true) && isMergeableValue(multiplyRight, ZExt32, true))2810 if (isMergeableValue(multiplyLeft, ZExt32) && isMergeableValue(multiplyRight, ZExt32)) 2815 2811 return MultiplyNegZeroExtend32; 2816 2812 return Air::Oops; … … 2820 2816 if (isValidForm(newAirOpcode, Arg::Tmp, Arg::Tmp, Arg::Tmp)) { 2821 2817 append(newAirOpcode, tmp(multiplyLeft->child(0)), tmp(multiplyRight->child(0)), tmp(m_value)); 2822 commitInternal(multiplyLeft);2823 commitInternal(multiplyRight);2824 2818 commitInternal(m_value->child(0)); 2825 2819 return true; … … 2843 2837 2844 2838 case Mul: { 2845 if (m_value->type() == Int64 2846 && isValidForm(MultiplySignExtend32, Arg::Tmp, Arg::Tmp, Arg::Tmp) 2847 && m_value->child(0)->opcode() == SExt32 2848 && !m_locked.contains(m_value->child(0))) { 2849 Value* opLeft = m_value->child(0); 2850 Value* left = opLeft->child(0); 2851 Value* opRight = m_value->child(1); 2852 Value* right = nullptr; 2853 2854 if (opRight->opcode() == SExt32 && !m_locked.contains(opRight->child(0))) { 2855 right = opRight->child(0); 2856 } else if (m_value->child(1)->isRepresentableAs<int32_t>() && !m_locked.contains(m_value->child(1))) { 2857 // We just use the 64-bit const int as a 32 bit const int directly 2858 right = opRight; 2859 } 2860 2861 if (right) { 2862 append(MultiplySignExtend32, tmp(left), tmp(right), tmp(m_value)); 2863 return; 2864 } 2865 } 2866 appendBinOp<Mul32, Mul64, MulDouble, MulFloat, Commutative>( 2867 m_value->child(0), m_value->child(1)); 2839 Value* left = m_value->child(0); 2840 Value* right = m_value->child(1); 2841 2842 auto tryAppendMultiplyWithExtend = [&] () -> bool { 2843 auto tryAirOpcode = [&] () -> Air::Opcode { 2844 if (m_value->type() != Int64) 2845 return Air::Oops; 2846 // SMULL: d = SExt32(n) * SExt32(m) 2847 if (isMergeableValue(left, SExt32) && isMergeableValue(right, SExt32)) 2848 return MultiplySignExtend32; 2849 // UMULL: d = ZExt32(n) * ZExt32(m) 2850 if (isMergeableValue(left, ZExt32) && isMergeableValue(right, ZExt32)) 2851 return MultiplyZeroExtend32; 2852 return Air::Oops; 2853 }; 2854 2855 Air::Opcode opcode = tryAirOpcode(); 2856 if (isValidForm(opcode, Arg::Tmp, Arg::Tmp, Arg::Tmp)) { 2857 append(opcode, tmp(left->child(0)), tmp(right->child(0)), tmp(m_value)); 2858 return true; 2859 } 2860 return false; 2861 }; 2862 2863 if (tryAppendMultiplyWithExtend()) 2864 return; 2865 2866 appendBinOp<Mul32, Mul64, MulDouble, MulFloat, Commutative>(left, right); 2868 2867 return; 2869 2868 } … … 3003 3002 auto tryAppendEXTR = [&] (Value* left, Value* right) -> bool { 3004 3003 Air::Opcode opcode = opcodeForType(ExtractRegister32, ExtractRegister64, m_value->type()); 3005 if (!isValidForm(opcode, Arg::Tmp, Arg::Tmp, Arg::Imm, Arg::Tmp)) 3004 if (!isValidForm(opcode, Arg::Tmp, Arg::Tmp, Arg::Imm, Arg::Tmp)) 3006 3005 return false; 3007 3006 if (left->opcode() != Shl || left->child(0)->opcode() != BitAnd || right->opcode() != ZShr) … … 3209 3208 XorNotRightShift32, XorNotRightShift64, 3210 3209 XorNotUnsignedRightShift32, XorNotUnsignedRightShift64); 3211 if (!isValidForm(opcode, Arg::Tmp, Arg::Tmp, Arg::Imm, Arg::Tmp)) 3210 if (!isValidForm(opcode, Arg::Tmp, Arg::Tmp, Arg::Imm, Arg::Tmp)) 3212 3211 return false; 3213 3212 Value* mValue = shiftValue->child(0); -
trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes
r280579 r280583 285 285 Tmp, Tmp, Tmp 286 286 287 arm64: MultiplyZeroExtend32 U:G:32, U:G:32, D:G:64 288 Tmp, Tmp, Tmp 289 287 290 arm64: Div32 U:G:32, U:G:32, ZD:G:32 288 291 Tmp, Tmp, Tmp -
trunk/Source/JavaScriptCore/b3/testb3.h
r280579 r280583 940 940 void testMulImmArg(int, int); 941 941 void testMulArgs32(int, int); 942 void testMulArgs32SignExtend(int, int); 942 void testMulArgs32SignExtend(); 943 void testMulArgs32ZeroExtend(); 943 944 void testMulImm32SignExtend(const int, int); 944 945 void testMulLoadTwice(); -
trunk/Source/JavaScriptCore/b3/testb3_2.cpp
r280579 r280583 1229 1229 } 1230 1230 1231 void testMulArgs32SignExtend( int a, int b)1232 { 1233 Procedure proc; 1234 if (proc.optLevel() < 1)1231 void testMulArgs32SignExtend() 1232 { 1233 Procedure proc; 1234 if (proc.optLevel() < 2) 1235 1235 return; 1236 1236 BasicBlock* root = proc.addBlock(); … … 1247 1247 1248 1248 auto code = compileProc(proc); 1249 1250 CHECK(invoke<long int>(*code, a, b) == ((long int) a) * ((long int) b)); 1249 if (isARM64()) 1250 checkUsesInstruction(*code, "smull"); 1251 1252 for (auto nOperand : int32Operands()) { 1253 for (auto mOperand : int32Operands()) { 1254 int32_t n = nOperand.value; 1255 int32_t m = mOperand.value; 1256 CHECK_EQ(invoke<int64_t>(*code, n, m), static_cast<int64_t>(n) * static_cast<int64_t>(m)); 1257 } 1258 } 1259 } 1260 1261 void testMulArgs32ZeroExtend() 1262 { 1263 Procedure proc; 1264 if (proc.optLevel() < 2) 1265 return; 1266 BasicBlock* root = proc.addBlock(); 1267 Value* arg1 = root->appendNew<Value>( 1268 proc, Trunc, Origin(), 1269 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 1270 Value* arg2 = root->appendNew<Value>( 1271 proc, Trunc, Origin(), 1272 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 1273 Value* left = root->appendNew<Value>(proc, ZExt32, Origin(), arg1); 1274 Value* right = root->appendNew<Value>(proc, ZExt32, Origin(), arg2); 1275 Value* mul = root->appendNew<Value>(proc, Mul, Origin(), left, right); 1276 root->appendNewControlValue(proc, Return, Origin(), mul); 1277 1278 auto code = compileProc(proc); 1279 if (isARM64()) 1280 checkUsesInstruction(*code, "umull"); 1281 1282 for (auto nOperand : int32Operands()) { 1283 for (auto mOperand : int32Operands()) { 1284 uint32_t n = nOperand.value; 1285 uint32_t m = mOperand.value; 1286 CHECK_EQ(invoke<uint64_t>(*code, n, m), static_cast<uint64_t>(n) * static_cast<uint64_t>(m)); 1287 } 1288 } 1251 1289 } 1252 1290 -
trunk/Source/JavaScriptCore/b3/testb3_3.cpp
r280493 r280583 3731 3731 RUN(testMulArgs32(0xFFFFFFFF, 0xFFFFFFFF)); 3732 3732 RUN(testMulArgs32(0xFFFFFFFE, 0xFFFFFFFF)); 3733 RUN(testMulArgs32SignExtend(1, 1)); 3734 RUN(testMulArgs32SignExtend(1, 2)); 3735 RUN(testMulArgs32SignExtend(0xFFFFFFFF, 0xFFFFFFFF)); 3736 RUN(testMulArgs32SignExtend(0xFFFFFFFE, 0xFFFFFFFF)); 3733 RUN(testMulArgs32SignExtend()); 3734 RUN(testMulArgs32ZeroExtend()); 3737 3735 RUN(testMulLoadTwice()); 3738 3736 RUN(testMulAddArgsLeft());
Note:
See TracChangeset
for help on using the changeset viewer.