Changeset 247889 in webkit
- Timestamp:
- Jul 27, 2019 12:08:01 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r247888 r247889 1 2019-07-27 Justin Michaud <justin_michaud@apple.com> 2 3 [X86] Emit BT instruction for shift + mask in B3 4 https://bugs.webkit.org/show_bug.cgi?id=199891 5 6 Reviewed by Keith Miller. 7 8 * microbenchmarks/bit-test-constant.js: Added. 9 (let.glob.0.doTest): 10 * microbenchmarks/bit-test-load.js: Added. 11 (let.glob.0.let.arr.new.Int32Array.8.doTest): 12 (i): 13 * microbenchmarks/bit-test-nonconstant.js: Added. 14 (let.glob.0.doTest): 15 1 16 2019-07-26 Yusuke Suzuki <ysuzuki@apple.com> 2 17 -
trunk/Source/JavaScriptCore/ChangeLog
r247888 r247889 1 2019-07-27 Justin Michaud <justin_michaud@apple.com> 2 3 [X86] Emit BT instruction for shift + mask in B3 4 https://bugs.webkit.org/show_bug.cgi?id=199891 5 6 Reviewed by Keith Miller. 7 8 - Add a new BranchTestBit air opcode, matching the intel bt instruction 9 - Select this instruction for the following patterns: 10 if (a & (1<<b)) 11 if ((a>>b)&1) 12 if ((~a>>b)&1) 13 if (~a & (1<<b)) 14 - 15% perf progression on the nonconstant microbenchmark, neutral otherwise. 15 - Note: we cannot fuse loads when we have bitBase=Load, bitOffset=Tmp, since the X86 instruction has 16 different behaviour in this mode. It will read past the current dword/qword instead of wrapping around. 17 18 * assembler/MacroAssemblerX86Common.h: 19 (JSC::MacroAssemblerX86Common::branchTestBit32): 20 * assembler/MacroAssemblerX86_64.h: 21 (JSC::MacroAssemblerX86_64::branchTestBit64): 22 * assembler/X86Assembler.h: 23 (JSC::X86Assembler::bt_ir): 24 (JSC::X86Assembler::bt_im): 25 (JSC::X86Assembler::btw_ir): 26 (JSC::X86Assembler::btw_im): 27 * assembler/testmasm.cpp: 28 (JSC::int64Operands): 29 (JSC::testBranchTestBit32RegReg): 30 (JSC::testBranchTestBit32RegImm): 31 (JSC::testBranchTestBit32AddrImm): 32 (JSC::testBranchTestBit64RegReg): 33 (JSC::testBranchTestBit64RegImm): 34 (JSC::testBranchTestBit64AddrImm): 35 (JSC::run): 36 * b3/B3LowerToAir.cpp: 37 * b3/air/AirOpcode.opcodes: 38 * b3/testb3.cpp: 39 (JSC::B3::testBranchBitTest32TmpImm): 40 (JSC::B3::testBranchBitTest32AddrImm): 41 (JSC::B3::testBranchBitTest32TmpTmp): 42 (JSC::B3::testBranchBitTest64TmpTmp): 43 (JSC::B3::testBranchBitTest64AddrTmp): 44 (JSC::B3::run): 45 1 46 2019-07-26 Yusuke Suzuki <ysuzuki@apple.com> 2 47 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r245127 r247889 2643 2643 m_assembler.testl_rr(reg, mask); 2644 2644 return Jump(m_assembler.jCC(x86Condition(cond))); 2645 } 2646 2647 Jump branchTestBit32(ResultCondition cond, RegisterID reg, TrustedImm32 bit) 2648 { 2649 m_assembler.bt_ir(static_cast<unsigned>(bit.m_value) % 32, reg); 2650 if (cond == NonZero) 2651 return Jump(m_assembler.jb()); 2652 if (cond == Zero) 2653 return Jump(m_assembler.jae()); 2654 RELEASE_ASSERT_NOT_REACHED(); 2655 } 2656 2657 Jump branchTestBit32(ResultCondition cond, Address testValue, TrustedImm32 bit) 2658 { 2659 m_assembler.bt_im(static_cast<unsigned>(bit.m_value) % 32, testValue.offset, testValue.base); 2660 if (cond == NonZero) 2661 return Jump(m_assembler.jb()); 2662 if (cond == Zero) 2663 return Jump(m_assembler.jae()); 2664 RELEASE_ASSERT_NOT_REACHED(); 2665 } 2666 2667 Jump branchTestBit32(ResultCondition cond, RegisterID reg, RegisterID bit) 2668 { 2669 m_assembler.bt_ir(bit, reg); 2670 if (cond == NonZero) 2671 return Jump(m_assembler.jb()); 2672 if (cond == Zero) 2673 return Jump(m_assembler.jae()); 2674 RELEASE_ASSERT_NOT_REACHED(); 2645 2675 } 2646 2676 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r235636 r247889 1104 1104 } 1105 1105 1106 Jump branchTestBit64(ResultCondition cond, RegisterID testValue, TrustedImm32 bit) 1107 { 1108 m_assembler.btw_ir(static_cast<unsigned>(bit.m_value) % 64, testValue); 1109 if (cond == NonZero) 1110 return Jump(m_assembler.jb()); 1111 if (cond == Zero) 1112 return Jump(m_assembler.jae()); 1113 RELEASE_ASSERT_NOT_REACHED(); 1114 } 1115 1116 Jump branchTestBit64(ResultCondition cond, Address testValue, TrustedImm32 bit) 1117 { 1118 m_assembler.btw_im(static_cast<unsigned>(bit.m_value) % 64, testValue.offset, testValue.base); 1119 if (cond == NonZero) 1120 return Jump(m_assembler.jb()); 1121 if (cond == Zero) 1122 return Jump(m_assembler.jae()); 1123 RELEASE_ASSERT_NOT_REACHED(); 1124 } 1125 1126 Jump branchTestBit64(ResultCondition cond, RegisterID reg, RegisterID bit) 1127 { 1128 m_assembler.btw_ir(bit, reg); 1129 if (cond == NonZero) 1130 return Jump(m_assembler.jb()); 1131 if (cond == Zero) 1132 return Jump(m_assembler.jae()); 1133 RELEASE_ASSERT_NOT_REACHED(); 1134 } 1135 1106 1136 void test64(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) 1107 1137 { -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r247097 r247889 295 295 OP2_MOVZX_GvEb = 0xB6, 296 296 OP2_POPCNT = 0xB8, 297 OP2_GROUP_BT_EvIb = 0xBA, 298 OP2_BT_EvEv = 0xA3, 297 299 OP2_BSF = 0xBC, 298 300 OP2_TZCNT = 0xBC, … … 383 385 ESCAPE_D9_FSTP_singleReal = 3, 384 386 ESCAPE_DD_FSTP_doubleReal = 3, 387 388 GROUP_BT_OP_BT = 4, 385 389 } GroupOpcodeID; 386 390 … … 2149 2153 m_formatter.immediate8(imm); 2150 2154 } 2155 2156 void bt_ir(int bitOffset, RegisterID testValue) 2157 { 2158 ASSERT(-128 <= bitOffset && bitOffset < 128); 2159 m_formatter.twoByteOp(OP2_GROUP_BT_EvIb, GROUP_BT_OP_BT, testValue); 2160 m_formatter.immediate8(bitOffset); 2161 } 2162 2163 void bt_im(int bitOffset, int offset, RegisterID base) 2164 { 2165 ASSERT(-128 <= bitOffset && bitOffset < 128); 2166 m_formatter.twoByteOp(OP2_GROUP_BT_EvIb, GROUP_BT_OP_BT, base, offset); 2167 m_formatter.immediate8(bitOffset); 2168 } 2169 2170 void bt_ir(RegisterID bitOffset, RegisterID testValue) 2171 { 2172 m_formatter.twoByteOp(OP2_BT_EvEv, bitOffset, testValue); 2173 } 2174 2175 void bt_im(RegisterID bitOffset, int offset, RegisterID base) 2176 { 2177 m_formatter.twoByteOp(OP2_BT_EvEv, bitOffset, base, offset); 2178 } 2179 2180 #if CPU(X86_64) 2181 void btw_ir(int bitOffset, RegisterID testValue) 2182 { 2183 ASSERT(-128 <= bitOffset && bitOffset < 128); 2184 m_formatter.twoByteOp64(OP2_GROUP_BT_EvIb, GROUP_BT_OP_BT, testValue); 2185 m_formatter.immediate8(bitOffset); 2186 } 2187 2188 void btw_im(int bitOffset, int offset, RegisterID base) 2189 { 2190 ASSERT(-128 <= bitOffset && bitOffset < 128); 2191 m_formatter.twoByteOp64(OP2_GROUP_BT_EvIb, GROUP_BT_OP_BT, base, offset); 2192 m_formatter.immediate8(bitOffset); 2193 } 2194 2195 void btw_ir(RegisterID bitOffset, RegisterID testValue) 2196 { 2197 m_formatter.twoByteOp64(OP2_BT_EvEv, bitOffset, testValue); 2198 } 2199 2200 void btw_im(RegisterID bitOffset, int offset, RegisterID base) 2201 { 2202 m_formatter.twoByteOp64(OP2_BT_EvEv, bitOffset, base, offset); 2203 } 2204 #endif 2151 2205 2152 2206 void setCC_r(Condition cond, RegisterID dst) -
trunk/Source/JavaScriptCore/assembler/testmasm.cpp
r247363 r247889 294 294 } 295 295 296 #if CPU(X86_64) 297 static Vector<int64_t> int64Operands() 298 { 299 return Vector<int64_t> { 300 0, 301 1, 302 -1, 303 2, 304 -2, 305 42, 306 -42, 307 64, 308 std::numeric_limits<int32_t>::max(), 309 std::numeric_limits<int32_t>::min(), 310 std::numeric_limits<int64_t>::max(), 311 std::numeric_limits<int64_t>::min(), 312 }; 313 } 314 #endif 315 316 #if CPU(X86_64) 317 void testBranchTestBit32RegReg() 318 { 319 for (uint32_t value : int32Operands()) { 320 auto test = compile([=] (CCallHelpers& jit) { 321 jit.emitFunctionPrologue(); 322 323 auto branch = jit.branchTestBit32(MacroAssembler::NonZero, GPRInfo::argumentGPR0, GPRInfo::argumentGPR1); 324 jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR); 325 auto done = jit.jump(); 326 branch.link(&jit); 327 jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR); 328 done.link(&jit); 329 330 jit.emitFunctionEpilogue(); 331 jit.ret(); 332 }); 333 334 for (uint32_t value2 : int32Operands()) 335 CHECK_EQ(invoke<int>(test, value, value2), (value>>(value2%32))&1); 336 } 337 } 338 339 void testBranchTestBit32RegImm() 340 { 341 for (uint32_t value : int32Operands()) { 342 auto test = compile([=] (CCallHelpers& jit) { 343 jit.emitFunctionPrologue(); 344 345 auto branch = jit.branchTestBit32(MacroAssembler::NonZero, GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(value)); 346 jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR); 347 auto done = jit.jump(); 348 branch.link(&jit); 349 jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR); 350 done.link(&jit); 351 352 jit.emitFunctionEpilogue(); 353 jit.ret(); 354 }); 355 356 for (uint32_t value2 : int32Operands()) 357 CHECK_EQ(invoke<int>(test, value2), (value2>>(value%32))&1); 358 } 359 } 360 361 void testBranchTestBit32AddrImm() 362 { 363 for (uint32_t value : int32Operands()) { 364 auto test = compile([=] (CCallHelpers& jit) { 365 jit.emitFunctionPrologue(); 366 367 auto branch = jit.branchTestBit32(MacroAssembler::NonZero, MacroAssembler::Address(GPRInfo::argumentGPR0, 0), CCallHelpers::TrustedImm32(value)); 368 jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR); 369 auto done = jit.jump(); 370 branch.link(&jit); 371 jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR); 372 done.link(&jit); 373 374 jit.emitFunctionEpilogue(); 375 jit.ret(); 376 }); 377 378 for (uint32_t value2 : int32Operands()) 379 CHECK_EQ(invoke<int>(test, &value2), (value2>>(value%32))&1); 380 } 381 } 382 383 void testBranchTestBit64RegReg() 384 { 385 for (uint64_t value : int64Operands()) { 386 auto test = compile([=] (CCallHelpers& jit) { 387 jit.emitFunctionPrologue(); 388 389 auto branch = jit.branchTestBit64(MacroAssembler::NonZero, GPRInfo::argumentGPR0, GPRInfo::argumentGPR1); 390 jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::returnValueGPR); 391 auto done = jit.jump(); 392 branch.link(&jit); 393 jit.move(CCallHelpers::TrustedImm64(1), GPRInfo::returnValueGPR); 394 done.link(&jit); 395 396 jit.emitFunctionEpilogue(); 397 jit.ret(); 398 }); 399 400 for (uint64_t value2 : int64Operands()) 401 CHECK_EQ(invoke<long int>(test, value, value2), (value>>(value2%64))&1); 402 } 403 } 404 405 void testBranchTestBit64RegImm() 406 { 407 for (uint64_t value : int64Operands()) { 408 auto test = compile([=] (CCallHelpers& jit) { 409 jit.emitFunctionPrologue(); 410 411 auto branch = jit.branchTestBit64(MacroAssembler::NonZero, GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(value)); 412 jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::returnValueGPR); 413 auto done = jit.jump(); 414 branch.link(&jit); 415 jit.move(CCallHelpers::TrustedImm64(1), GPRInfo::returnValueGPR); 416 done.link(&jit); 417 418 jit.emitFunctionEpilogue(); 419 jit.ret(); 420 }); 421 422 for (uint64_t value2 : int64Operands()) 423 CHECK_EQ(invoke<long int>(test, value2), (value2>>(value%64))&1); 424 } 425 } 426 427 void testBranchTestBit64AddrImm() 428 { 429 for (uint64_t value : int64Operands()) { 430 auto test = compile([=] (CCallHelpers& jit) { 431 jit.emitFunctionPrologue(); 432 433 auto branch = jit.branchTestBit64(MacroAssembler::NonZero, MacroAssembler::Address(GPRInfo::argumentGPR0, 0), CCallHelpers::TrustedImm32(value)); 434 jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::returnValueGPR); 435 auto done = jit.jump(); 436 branch.link(&jit); 437 jit.move(CCallHelpers::TrustedImm64(1), GPRInfo::returnValueGPR); 438 done.link(&jit); 439 440 jit.emitFunctionEpilogue(); 441 jit.ret(); 442 }); 443 444 for (uint64_t value2 : int64Operands()) 445 CHECK_EQ(invoke<long int>(test, &value2), (value2>>(value%64))&1); 446 } 447 } 448 449 #endif 450 296 451 void testCompareDouble(MacroAssembler::DoubleCondition condition) 297 452 { … … 1138 1293 RUN(testMul32WithImmediates()); 1139 1294 1295 #if CPU(X86_64) 1296 RUN(testBranchTestBit32RegReg()); 1297 RUN(testBranchTestBit32RegImm()); 1298 RUN(testBranchTestBit32AddrImm()); 1299 RUN(testBranchTestBit64RegReg()); 1300 RUN(testBranchTestBit64RegImm()); 1301 RUN(testBranchTestBit64AddrImm()); 1302 #endif 1303 1140 1304 #if CPU(ARM64) 1141 1305 RUN(testMul32SignExtend()); -
trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp
r247363 r247889 3326 3326 if (canBeInternal(m_value->child(0))) { 3327 3327 Value* branchChild = m_value->child(0); 3328 3328 3329 switch (branchChild->opcode()) { 3330 case BitAnd: { 3331 Value* andValue = branchChild->child(0); 3332 Value* andMask = branchChild->child(1); 3333 Air::Opcode opcode = opcodeForType(BranchTestBit32, BranchTestBit64, andValue->type()); 3334 3335 Value* testValue = nullptr; 3336 Value* bitOffset = nullptr; 3337 Value* internalNode = nullptr; 3338 Value* negationNode = nullptr; 3339 bool inverted = false; 3340 3341 // if (~(val >> x)&1) 3342 if (andMask->isInt(1) 3343 && andValue->opcode() == BitXor && (andValue->child(1)->isInt32(-1) || andValue->child(1)->isInt64(-1l)) 3344 && (andValue->child(0)->opcode() == SShr || andValue->child(0)->opcode() == ZShr)) { 3345 3346 negationNode = andValue; 3347 testValue = andValue->child(0)->child(0); 3348 bitOffset = andValue->child(0)->child(1); 3349 internalNode = andValue->child(0); 3350 inverted = !inverted; 3351 } 3352 3353 // Turn if ((val >> x)&1) -> Bt val x 3354 if (andMask->isInt(1) && (andValue->opcode() == SShr || andValue->opcode() == ZShr)) { 3355 testValue = andValue->child(0); 3356 bitOffset = andValue->child(1); 3357 internalNode = andValue; 3358 } 3359 3360 // Turn if (val & (1<<x)) -> Bt val x 3361 if ((andMask->opcode() == Shl) && andMask->child(0)->isInt(1)) { 3362 testValue = andValue; 3363 bitOffset = andMask->child(1); 3364 internalNode = andMask; 3365 } 3366 3367 // if (~val & (1<<x)) or if ((~val >> x)&1) 3368 if (!negationNode && testValue && testValue->opcode() == BitXor && (testValue->child(1)->isInt32(-1) || testValue->child(1)->isInt64(-1l))) { 3369 negationNode = testValue; 3370 testValue = testValue->child(0); 3371 inverted = !inverted; 3372 } 3373 3374 if (testValue && bitOffset) { 3375 for (auto& basePromise : Vector<ArgPromise>::from(loadPromise(testValue), tmpPromise(testValue))) { 3376 bool hasLoad = basePromise.kind() != Arg::Tmp; 3377 bool canMakeInternal = (hasLoad ? canBeInternal(testValue) : !m_locked.contains(testValue)) 3378 && (!negationNode || canBeInternal(negationNode)) 3379 && (!internalNode || canBeInternal(internalNode)); 3380 3381 if (basePromise && canMakeInternal) { 3382 if (bitOffset->hasInt() && isValidForm(opcode, Arg::ResCond, basePromise.kind(), Arg::Imm)) { 3383 commitInternal(branchChild); 3384 commitInternal(internalNode); 3385 if (hasLoad) 3386 commitInternal(testValue); 3387 commitInternal(negationNode); 3388 append(basePromise.inst(opcode, m_value, Arg::resCond(MacroAssembler::NonZero).inverted(inverted), basePromise.consume(*this), Arg::imm(bitOffset->asInt()))); 3389 return; 3390 } 3391 3392 if (!m_locked.contains(bitOffset) && isValidForm(opcode, Arg::ResCond, basePromise.kind(), Arg::Tmp)) { 3393 commitInternal(branchChild); 3394 commitInternal(internalNode); 3395 if (hasLoad) 3396 commitInternal(testValue); 3397 commitInternal(negationNode); 3398 append(basePromise.inst(opcode, m_value, Arg::resCond(MacroAssembler::NonZero).inverted(inverted), basePromise.consume(*this), tmp(bitOffset))); 3399 return; 3400 } 3401 } 3402 } 3403 } 3404 break; 3405 } 3329 3406 case AtomicWeakCAS: 3330 3407 commitInternal(branchChild); -
trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes
r247363 r247889 1162 1162 x86: ResCond, Index, BitImm 1163 1163 1164 x86_64: BranchTestBit64 U:G:32, U:G:64, U:G:8 /branch 1165 ResCond, Tmp, Imm 1166 ResCond, Addr, Imm 1167 ResCond, Tmp, Tmp 1168 1169 x86: BranchTestBit32 U:G:32, U:G:32, U:G:8 /branch 1170 ResCond, Tmp, Imm 1171 ResCond, Addr, Imm 1172 ResCond, Tmp, Tmp 1173 1164 1174 BranchDouble U:G:32, U:F:64, U:F:64 /branch 1165 1175 DoubleCond, Tmp, Tmp -
trunk/Source/JavaScriptCore/b3/testb3.cpp
r247390 r247889 8753 8753 MonotonicTime after = MonotonicTime::now(); 8754 8754 dataLog(toCString(" That took ", (after - before).milliseconds(), " ms.\n")); 8755 } 8756 8757 void testBranchBitTest32TmpImm(uint32_t value, uint32_t imm) 8758 { 8759 Procedure proc; 8760 BasicBlock* root = proc.addBlock(); 8761 BasicBlock* thenCase = proc.addBlock(); 8762 BasicBlock* elseCase = proc.addBlock(); 8763 8764 Value* testValue = root->appendNew<Value>( 8765 proc, Trunc, Origin(), 8766 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 8767 Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm); 8768 8769 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1); 8770 Value* bitTest = root->appendNew<Value>( 8771 proc, BitAnd, Origin(), 8772 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset), 8773 one); 8774 8775 root->appendNewControlValue( 8776 proc, Branch, Origin(), 8777 bitTest, 8778 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8779 8780 thenCase->appendNewControlValue( 8781 proc, Return, Origin(), 8782 thenCase->appendNew<Const32Value>(proc, Origin(), 1)); 8783 8784 elseCase->appendNewControlValue( 8785 proc, Return, Origin(), 8786 elseCase->appendNew<Const32Value>(proc, Origin(), 0)); 8787 8788 auto code = compileProc(proc); 8789 CHECK_EQ(invoke<uint32_t>(*code, value), (value>>(imm%32))&1); 8790 } 8791 8792 void testBranchBitTest32AddrImm(uint32_t value, uint32_t imm) 8793 { 8794 Procedure proc; 8795 BasicBlock* root = proc.addBlock(); 8796 BasicBlock* thenCase = proc.addBlock(); 8797 BasicBlock* elseCase = proc.addBlock(); 8798 8799 Value* testValue = root->appendNew<MemoryValue>( 8800 proc, Load, Int32, Origin(), 8801 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 8802 Value* bitOffset = root->appendNew<Const32Value>(proc, Origin(), imm); 8803 8804 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1); 8805 Value* bitTest = root->appendNew<Value>( 8806 proc, BitAnd, Origin(), 8807 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset), 8808 one); 8809 8810 root->appendNewControlValue( 8811 proc, Branch, Origin(), 8812 bitTest, 8813 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8814 8815 thenCase->appendNewControlValue( 8816 proc, Return, Origin(), 8817 thenCase->appendNew<Const32Value>(proc, Origin(), 1)); 8818 8819 elseCase->appendNewControlValue( 8820 proc, Return, Origin(), 8821 elseCase->appendNew<Const32Value>(proc, Origin(), 0)); 8822 8823 auto code = compileProc(proc); 8824 CHECK_EQ(invoke<uint32_t>(*code, &value), (value>>(imm%32))&1); 8825 } 8826 8827 void testBranchBitTest32TmpTmp(uint32_t value, uint32_t value2) 8828 { 8829 Procedure proc; 8830 BasicBlock* root = proc.addBlock(); 8831 BasicBlock* thenCase = proc.addBlock(); 8832 BasicBlock* elseCase = proc.addBlock(); 8833 8834 Value* testValue = root->appendNew<Value>( 8835 proc, Trunc, Origin(), 8836 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 8837 Value* bitOffset = root->appendNew<Value>( 8838 proc, Trunc, Origin(), 8839 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 8840 8841 Value* one = root->appendNew<Const32Value>(proc, Origin(), 1); 8842 Value* bitTest = root->appendNew<Value>( 8843 proc, BitAnd, Origin(), 8844 root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset), 8845 one); 8846 8847 root->appendNewControlValue( 8848 proc, Branch, Origin(), 8849 bitTest, 8850 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8851 8852 thenCase->appendNewControlValue( 8853 proc, Return, Origin(), 8854 thenCase->appendNew<Const32Value>(proc, Origin(), 1)); 8855 8856 elseCase->appendNewControlValue( 8857 proc, Return, Origin(), 8858 elseCase->appendNew<Const32Value>(proc, Origin(), 0)); 8859 8860 auto code = compileProc(proc); 8861 CHECK_EQ(invoke<uint32_t>(*code, value, value2), (value>>(value2%32))&1); 8862 } 8863 8864 void testBranchBitTest64TmpTmp(uint64_t value, uint64_t value2) 8865 { 8866 Procedure proc; 8867 BasicBlock* root = proc.addBlock(); 8868 BasicBlock* thenCase = proc.addBlock(); 8869 BasicBlock* elseCase = proc.addBlock(); 8870 8871 Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(), 8872 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), 8873 root->appendNew<Const64Value>(proc, Origin(), -1l)); 8874 Value* bitOffset = root->appendNew<Value>( 8875 proc, Trunc, Origin(), 8876 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 8877 8878 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1); 8879 Value* bitTest = root->appendNew<Value>( 8880 proc, BitAnd, Origin(), 8881 testValue, 8882 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset)); 8883 8884 root->appendNewControlValue( 8885 proc, Branch, Origin(), 8886 bitTest, 8887 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8888 8889 thenCase->appendNewControlValue( 8890 proc, Return, Origin(), 8891 thenCase->appendNew<Const64Value>(proc, Origin(), 0)); 8892 8893 elseCase->appendNewControlValue( 8894 proc, Return, Origin(), 8895 elseCase->appendNew<Const64Value>(proc, Origin(), 1)); 8896 8897 auto code = compileProc(proc); 8898 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1); 8899 } 8900 8901 void testBranchBitTest64AddrTmp(uint64_t value, uint64_t value2) 8902 { 8903 Procedure proc; 8904 BasicBlock* root = proc.addBlock(); 8905 BasicBlock* thenCase = proc.addBlock(); 8906 BasicBlock* elseCase = proc.addBlock(); 8907 8908 Value* testValue = root->appendNew<MemoryValue>( 8909 proc, Load, Int64, Origin(), 8910 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)); 8911 Value* bitOffset = root->appendNew<Value>( 8912 proc, Trunc, Origin(), 8913 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 8914 8915 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1); 8916 Value* bitTest = root->appendNew<Value>( 8917 proc, BitAnd, Origin(), 8918 testValue, 8919 root->appendNew<Value>(proc, Shl, Origin(), one, bitOffset)); 8920 8921 root->appendNewControlValue( 8922 proc, Branch, Origin(), 8923 bitTest, 8924 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8925 8926 thenCase->appendNewControlValue( 8927 proc, Return, Origin(), 8928 thenCase->appendNew<Const64Value>(proc, Origin(), 1)); 8929 8930 elseCase->appendNewControlValue( 8931 proc, Return, Origin(), 8932 elseCase->appendNew<Const64Value>(proc, Origin(), 0)); 8933 8934 auto code = compileProc(proc); 8935 CHECK_EQ(invoke<uint64_t>(*code, &value, value2), (value>>(value2%64))&1); 8936 } 8937 8938 void testBranchBitTestNegation(uint64_t value, uint64_t value2) 8939 { 8940 Procedure proc; 8941 BasicBlock* root = proc.addBlock(); 8942 BasicBlock* thenCase = proc.addBlock(); 8943 BasicBlock* elseCase = proc.addBlock(); 8944 8945 Value* testValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0); 8946 Value* bitOffset = root->appendNew<Value>( 8947 proc, Trunc, Origin(), 8948 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 8949 Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset); 8950 8951 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1); 8952 Value* bitTest = root->appendNew<Value>( 8953 proc, BitAnd, Origin(), 8954 root->appendNew<Value>(proc, BitXor, Origin(), shift, root->appendNew<Const64Value>(proc, Origin(), -1l)), 8955 one); 8956 8957 root->appendNewControlValue( 8958 proc, Branch, Origin(), 8959 bitTest, 8960 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8961 8962 thenCase->appendNewControlValue( 8963 proc, Return, Origin(), 8964 thenCase->appendNew<Const64Value>(proc, Origin(), 0)); 8965 8966 elseCase->appendNewControlValue( 8967 proc, Return, Origin(), 8968 elseCase->appendNew<Const64Value>(proc, Origin(), 1)); 8969 8970 auto code = compileProc(proc); 8971 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1); 8972 } 8973 8974 void testBranchBitTestNegation2(uint64_t value, uint64_t value2) 8975 { 8976 Procedure proc; 8977 BasicBlock* root = proc.addBlock(); 8978 BasicBlock* thenCase = proc.addBlock(); 8979 BasicBlock* elseCase = proc.addBlock(); 8980 8981 Value* testValue = root->appendNew<Value>(proc, BitXor, Origin(), 8982 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), 8983 root->appendNew<Const64Value>(proc, Origin(), -1l)); 8984 Value* bitOffset = root->appendNew<Value>( 8985 proc, Trunc, Origin(), 8986 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)); 8987 Value* shift = root->appendNew<Value>(proc, SShr, Origin(), testValue, bitOffset); 8988 8989 Value* one = root->appendNew<Const64Value>(proc, Origin(), 1); 8990 Value* bitTest = root->appendNew<Value>( 8991 proc, BitAnd, Origin(), 8992 shift, 8993 one); 8994 8995 root->appendNewControlValue( 8996 proc, Branch, Origin(), 8997 bitTest, 8998 FrequentedBlock(thenCase), FrequentedBlock(elseCase)); 8999 9000 thenCase->appendNewControlValue( 9001 proc, Return, Origin(), 9002 thenCase->appendNew<Const64Value>(proc, Origin(), 0)); 9003 9004 elseCase->appendNewControlValue( 9005 proc, Return, Origin(), 9006 elseCase->appendNew<Const64Value>(proc, Origin(), 1)); 9007 9008 auto code = compileProc(proc); 9009 CHECK_EQ(invoke<uint64_t>(*code, value, value2), (value>>(value2%64))&1); 8755 9010 } 8756 9011 … … 18118 18373 RUN(testComplex(4, 256)); 18119 18374 RUN(testComplex(4, 384)); 18375 18376 RUN_BINARY(testBranchBitTest32TmpImm, int32Operands(), int32Operands()); 18377 RUN_BINARY(testBranchBitTest32AddrImm, int32Operands(), int32Operands()); 18378 RUN_BINARY(testBranchBitTest32TmpTmp, int32Operands(), int32Operands()); 18379 RUN_BINARY(testBranchBitTest64TmpTmp, int64Operands(), int64Operands()); 18380 RUN_BINARY(testBranchBitTest64AddrTmp, int64Operands(), int64Operands()); 18381 RUN_BINARY(testBranchBitTestNegation, int64Operands(), int64Operands()); 18382 RUN_BINARY(testBranchBitTestNegation2, int64Operands(), int64Operands()); 18120 18383 18121 18384 RUN(testSimplePatchpoint());
Note: See TracChangeset
for help on using the changeset viewer.