| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 } | 345 } |
| 346 | 346 |
| 347 template <typename TraitsType> | 347 template <typename TraitsType> |
| 348 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) | 348 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) |
| 349 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) { | 349 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) { |
| 350 static_assert( | 350 static_assert( |
| 351 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == | 351 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == |
| 352 (TargetInstructionSet::X86InstructionSet_End - | 352 (TargetInstructionSet::X86InstructionSet_End - |
| 353 TargetInstructionSet::X86InstructionSet_Begin), | 353 TargetInstructionSet::X86InstructionSet_Begin), |
| 354 "Traits::InstructionSet range different from TargetInstructionSet"); | 354 "Traits::InstructionSet range different from TargetInstructionSet"); |
| 355 if (Func->getContext()->getFlags().getTargetInstructionSet() != | 355 if (getFlags().getTargetInstructionSet() != |
| 356 TargetInstructionSet::BaseInstructionSet) { | 356 TargetInstructionSet::BaseInstructionSet) { |
| 357 InstructionSet = static_cast<InstructionSetEnum>( | 357 InstructionSet = static_cast<InstructionSetEnum>( |
| 358 (Func->getContext()->getFlags().getTargetInstructionSet() - | 358 (getFlags().getTargetInstructionSet() - |
| 359 TargetInstructionSet::X86InstructionSet_Begin) + | 359 TargetInstructionSet::X86InstructionSet_Begin) + |
| 360 Traits::InstructionSet::Begin); | 360 Traits::InstructionSet::Begin); |
| 361 } | 361 } |
| 362 } | 362 } |
| 363 | 363 |
| 364 template <typename TraitsType> | 364 template <typename TraitsType> |
| 365 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) { | 365 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) { |
| 366 RegNumT::setLimit(Traits::RegisterSet::Reg_NUM); | 366 RegNumT::setLimit(Traits::RegisterSet::Reg_NUM); |
| 367 Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet, | 367 Traits::initRegisterSet(getFlags(), &TypeToRegisterSet, &RegisterAliases); |
| 368 &RegisterAliases); | |
| 369 for (size_t i = 0; i < TypeToRegisterSet.size(); ++i) | 368 for (size_t i = 0; i < TypeToRegisterSet.size(); ++i) |
| 370 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 369 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
| 371 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM, | 370 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM, |
| 372 TypeToRegisterSet.data(), TypeToRegisterSet.size(), | 371 TypeToRegisterSet.data(), TypeToRegisterSet.size(), |
| 373 Traits::getRegName, getRegClassName); | 372 Traits::getRegName, getRegClassName); |
| 374 PcRelFixup = Traits::FK_PcRel; | 373 PcRelFixup = Traits::FK_PcRel; |
| 375 AbsFixup = | 374 AbsFixup = getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; |
| 376 Ctx->getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; | |
| 377 } | 375 } |
| 378 | 376 |
| 379 template <typename TraitsType> | 377 template <typename TraitsType> |
| 380 bool TargetX86Base<TraitsType>::shouldBePooled(const Constant *C) { | 378 bool TargetX86Base<TraitsType>::shouldBePooled(const Constant *C) { |
| 381 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(C)) { | 379 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(C)) { |
| 382 return !Utils::isPositiveZero(ConstFloat->getValue()); | 380 return !Utils::isPositiveZero(ConstFloat->getValue()); |
| 383 } | 381 } |
| 384 if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) { | 382 if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) { |
| 385 return !Utils::isPositiveZero(ConstDouble->getValue()); | 383 return !Utils::isPositiveZero(ConstDouble->getValue()); |
| 386 } | 384 } |
| 387 if (GlobalContext::getFlags().getRandomizeAndPoolImmediatesOption() != | 385 if (getFlags().getRandomizeAndPoolImmediatesOption() != RPI_Pool) { |
| 388 RPI_Pool) { | |
| 389 return false; | 386 return false; |
| 390 } | 387 } |
| 391 return C->shouldBeRandomizedOrPooled(); | 388 return C->shouldBeRandomizedOrPooled(); |
| 392 } | 389 } |
| 393 | 390 |
| 394 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { | 391 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { |
| 395 TimerMarker T(TimerStack::TT_O2, Func); | 392 TimerMarker T(TimerStack::TT_O2, Func); |
| 396 | 393 |
| 397 if (SandboxingType != ST_None) { | 394 if (SandboxingType != ST_None) { |
| 398 initRebasePtr(); | 395 initRebasePtr(); |
| 399 } | 396 } |
| 400 | 397 |
| 401 genTargetHelperCalls(); | 398 genTargetHelperCalls(); |
| 402 Func->dump("After target helper call insertion"); | 399 Func->dump("After target helper call insertion"); |
| 403 | 400 |
| 404 // Merge Alloca instructions, and lay out the stack. | 401 // Merge Alloca instructions, and lay out the stack. |
| 405 static constexpr bool SortAndCombineAllocas = true; | 402 static constexpr bool SortAndCombineAllocas = true; |
| 406 Func->processAllocas(SortAndCombineAllocas); | 403 Func->processAllocas(SortAndCombineAllocas); |
| 407 Func->dump("After Alloca processing"); | 404 Func->dump("After Alloca processing"); |
| 408 | 405 |
| 409 if (!Ctx->getFlags().getEnablePhiEdgeSplit()) { | 406 if (!getFlags().getEnablePhiEdgeSplit()) { |
| 410 // Lower Phi instructions. | 407 // Lower Phi instructions. |
| 411 Func->placePhiLoads(); | 408 Func->placePhiLoads(); |
| 412 if (Func->hasError()) | 409 if (Func->hasError()) |
| 413 return; | 410 return; |
| 414 Func->placePhiStores(); | 411 Func->placePhiStores(); |
| 415 if (Func->hasError()) | 412 if (Func->hasError()) |
| 416 return; | 413 return; |
| 417 Func->deletePhis(); | 414 Func->deletePhis(); |
| 418 if (Func->hasError()) | 415 if (Func->hasError()) |
| 419 return; | 416 return; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 assert(Func->validateLiveness()); | 482 assert(Func->validateLiveness()); |
| 486 // The post-codegen dump is done here, after liveness analysis and associated | 483 // The post-codegen dump is done here, after liveness analysis and associated |
| 487 // cleanup, to make the dump cleaner and more useful. | 484 // cleanup, to make the dump cleaner and more useful. |
| 488 Func->dump("After initial x8632 codegen"); | 485 Func->dump("After initial x8632 codegen"); |
| 489 Func->getVMetadata()->init(VMK_All); | 486 Func->getVMetadata()->init(VMK_All); |
| 490 regAlloc(RAK_Global); | 487 regAlloc(RAK_Global); |
| 491 if (Func->hasError()) | 488 if (Func->hasError()) |
| 492 return; | 489 return; |
| 493 Func->dump("After linear scan regalloc"); | 490 Func->dump("After linear scan regalloc"); |
| 494 | 491 |
| 495 if (Ctx->getFlags().getEnablePhiEdgeSplit()) { | 492 if (getFlags().getEnablePhiEdgeSplit()) { |
| 496 Func->advancedPhiLowering(); | 493 Func->advancedPhiLowering(); |
| 497 Func->dump("After advanced Phi lowering"); | 494 Func->dump("After advanced Phi lowering"); |
| 498 } | 495 } |
| 499 | 496 |
| 500 // Stack frame mapping. | 497 // Stack frame mapping. |
| 501 Func->genFrame(); | 498 Func->genFrame(); |
| 502 if (Func->hasError()) | 499 if (Func->hasError()) |
| 503 return; | 500 return; |
| 504 Func->dump("After stack frame mapping"); | 501 Func->dump("After stack frame mapping"); |
| 505 | 502 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 ") has no register assigned - function " + | 890 ") has no register assigned - function " + |
| 894 Func->getFunctionName()); | 891 Func->getFunctionName()); |
| 895 } | 892 } |
| 896 const int32_t Offset = Var->getStackOffset(); | 893 const int32_t Offset = Var->getStackOffset(); |
| 897 auto BaseRegNum = Var->getBaseRegNum(); | 894 auto BaseRegNum = Var->getBaseRegNum(); |
| 898 if (BaseRegNum.hasNoValue()) | 895 if (BaseRegNum.hasNoValue()) |
| 899 BaseRegNum = getFrameOrStackReg(); | 896 BaseRegNum = getFrameOrStackReg(); |
| 900 // Print in the form "Offset(%reg)", taking care that: | 897 // Print in the form "Offset(%reg)", taking care that: |
| 901 // - Offset is never printed when it is 0 | 898 // - Offset is never printed when it is 0 |
| 902 | 899 |
| 903 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); | 900 const bool DecorateAsm = getFlags().getDecorateAsm(); |
| 904 // Only print Offset when it is nonzero, regardless of DecorateAsm. | 901 // Only print Offset when it is nonzero, regardless of DecorateAsm. |
| 905 if (Offset) { | 902 if (Offset) { |
| 906 if (DecorateAsm) { | 903 if (DecorateAsm) { |
| 907 Str << Var->getSymbolicStackOffset(Func); | 904 Str << Var->getSymbolicStackOffset(Func); |
| 908 } else { | 905 } else { |
| 909 Str << Offset; | 906 Str << Offset; |
| 910 } | 907 } |
| 911 } | 908 } |
| 912 const Type FrameSPTy = Traits::WordType; | 909 const Type FrameSPTy = Traits::WordType; |
| 913 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; | 910 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1372 return legalize(MemOperand); | 1369 return legalize(MemOperand); |
| 1373 } | 1370 } |
| 1374 llvm_unreachable("Unsupported operand type"); | 1371 llvm_unreachable("Unsupported operand type"); |
| 1375 return nullptr; | 1372 return nullptr; |
| 1376 } | 1373 } |
| 1377 | 1374 |
| 1378 template <typename TraitsType> | 1375 template <typename TraitsType> |
| 1379 SmallBitVector | 1376 SmallBitVector |
| 1380 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, | 1377 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, |
| 1381 RegSetMask Exclude) const { | 1378 RegSetMask Exclude) const { |
| 1382 return Traits::getRegisterSet(Ctx->getFlags(), Include, Exclude); | 1379 return Traits::getRegisterSet(getFlags(), Include, Exclude); |
| 1383 } | 1380 } |
| 1384 | 1381 |
| 1385 template <typename TraitsType> | 1382 template <typename TraitsType> |
| 1386 void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Instr) { | 1383 void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Instr) { |
| 1387 // Conservatively require the stack to be aligned. Some stack adjustment | 1384 // Conservatively require the stack to be aligned. Some stack adjustment |
| 1388 // operations implemented below assume that the stack is aligned before the | 1385 // operations implemented below assume that the stack is aligned before the |
| 1389 // alloca. All the alloca code ensures that the stack alignment is preserved | 1386 // alloca. All the alloca code ensures that the stack alignment is preserved |
| 1390 // after the alloca. The stack alignment restriction can be relaxed in some | 1387 // after the alloca. The stack alignment restriction can be relaxed in some |
| 1391 // cases. | 1388 // cases. |
| 1392 NeedsStackAlignment = true; | 1389 NeedsStackAlignment = true; |
| 1393 | 1390 |
| 1394 // For default align=0, set it to the real value 1, to avoid any | 1391 // For default align=0, set it to the real value 1, to avoid any |
| 1395 // bit-manipulation problems below. | 1392 // bit-manipulation problems below. |
| 1396 const uint32_t AlignmentParam = std::max(1u, Instr->getAlignInBytes()); | 1393 const uint32_t AlignmentParam = std::max(1u, Instr->getAlignInBytes()); |
| 1397 | 1394 |
| 1398 // LLVM enforces power of 2 alignment. | 1395 // LLVM enforces power of 2 alignment. |
| 1399 assert(llvm::isPowerOf2_32(AlignmentParam)); | 1396 assert(llvm::isPowerOf2_32(AlignmentParam)); |
| 1400 assert(llvm::isPowerOf2_32(Traits::X86_STACK_ALIGNMENT_BYTES)); | 1397 assert(llvm::isPowerOf2_32(Traits::X86_STACK_ALIGNMENT_BYTES)); |
| 1401 | 1398 |
| 1402 const uint32_t Alignment = | 1399 const uint32_t Alignment = |
| 1403 std::max(AlignmentParam, Traits::X86_STACK_ALIGNMENT_BYTES); | 1400 std::max(AlignmentParam, Traits::X86_STACK_ALIGNMENT_BYTES); |
| 1404 const bool OverAligned = Alignment > Traits::X86_STACK_ALIGNMENT_BYTES; | 1401 const bool OverAligned = Alignment > Traits::X86_STACK_ALIGNMENT_BYTES; |
| 1405 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 1402 const bool OptM1 = getFlags().getOptLevel() == Opt_m1; |
| 1406 const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset(); | 1403 const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset(); |
| 1407 const bool UseFramePointer = | 1404 const bool UseFramePointer = |
| 1408 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; | 1405 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; |
| 1409 | 1406 |
| 1410 if (UseFramePointer) | 1407 if (UseFramePointer) |
| 1411 setHasFramePointer(); | 1408 setHasFramePointer(); |
| 1412 | 1409 |
| 1413 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); | 1410 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); |
| 1414 if (OverAligned) { | 1411 if (OverAligned) { |
| 1415 _and(esp, Ctx->getConstantInt32(-Alignment)); | 1412 _and(esp, Ctx->getConstantInt32(-Alignment)); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 /// Strength-reduce scalar integer multiplication by a constant (for i32 or | 1522 /// Strength-reduce scalar integer multiplication by a constant (for i32 or |
| 1526 /// narrower) for certain constants. The lea instruction can be used to multiply | 1523 /// narrower) for certain constants. The lea instruction can be used to multiply |
| 1527 /// by 3, 5, or 9, and the lsh instruction can be used to multiply by powers of | 1524 /// by 3, 5, or 9, and the lsh instruction can be used to multiply by powers of |
| 1528 /// 2. These can be combined such that e.g. multiplying by 100 can be done as 2 | 1525 /// 2. These can be combined such that e.g. multiplying by 100 can be done as 2 |
| 1529 /// lea-based multiplies by 5, combined with left-shifting by 2. | 1526 /// lea-based multiplies by 5, combined with left-shifting by 2. |
| 1530 template <typename TraitsType> | 1527 template <typename TraitsType> |
| 1531 bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, | 1528 bool TargetX86Base<TraitsType>::optimizeScalarMul(Variable *Dest, Operand *Src0, |
| 1532 int32_t Src1) { | 1529 int32_t Src1) { |
| 1533 // Disable this optimization for Om1 and O0, just to keep things simple | 1530 // Disable this optimization for Om1 and O0, just to keep things simple |
| 1534 // there. | 1531 // there. |
| 1535 if (Ctx->getFlags().getOptLevel() < Opt_1) | 1532 if (getFlags().getOptLevel() < Opt_1) |
| 1536 return false; | 1533 return false; |
| 1537 Type Ty = Dest->getType(); | 1534 Type Ty = Dest->getType(); |
| 1538 if (Src1 == -1) { | 1535 if (Src1 == -1) { |
| 1539 Variable *T = nullptr; | 1536 Variable *T = nullptr; |
| 1540 _mov(T, Src0); | 1537 _mov(T, Src0); |
| 1541 _neg(T); | 1538 _neg(T); |
| 1542 _mov(Dest, T); | 1539 _mov(Dest, T); |
| 1543 return true; | 1540 return true; |
| 1544 } | 1541 } |
| 1545 if (Src1 == 0) { | 1542 if (Src1 == 0) { |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2219 } | 2216 } |
| 2220 T_edx = makeReg(Ty, Edx); | 2217 T_edx = makeReg(Ty, Edx); |
| 2221 _mov(T, Src0, Eax); | 2218 _mov(T, Src0, Eax); |
| 2222 _mov(T_edx, Ctx->getConstantZero(Ty)); | 2219 _mov(T_edx, Ctx->getConstantZero(Ty)); |
| 2223 _div(T, Src1, T_edx); | 2220 _div(T, Src1, T_edx); |
| 2224 _mov(Dest, T); | 2221 _mov(Dest, T); |
| 2225 } break; | 2222 } break; |
| 2226 case InstArithmetic::Sdiv: | 2223 case InstArithmetic::Sdiv: |
| 2227 // TODO(stichnot): Enable this after doing better performance and cross | 2224 // TODO(stichnot): Enable this after doing better performance and cross |
| 2228 // testing. | 2225 // testing. |
| 2229 if (false && Ctx->getFlags().getOptLevel() >= Opt_1) { | 2226 if (false && getFlags().getOptLevel() >= Opt_1) { |
| 2230 // Optimize division by constant power of 2, but not for Om1 or O0, just | 2227 // Optimize division by constant power of 2, but not for Om1 or O0, just |
| 2231 // to keep things simple there. | 2228 // to keep things simple there. |
| 2232 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | 2229 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { |
| 2233 const int32_t Divisor = C->getValue(); | 2230 const int32_t Divisor = C->getValue(); |
| 2234 const uint32_t UDivisor = Divisor; | 2231 const uint32_t UDivisor = Divisor; |
| 2235 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { | 2232 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { |
| 2236 uint32_t LogDiv = llvm::Log2_32(UDivisor); | 2233 uint32_t LogDiv = llvm::Log2_32(UDivisor); |
| 2237 // LLVM does the following for dest=src/(1<<log): | 2234 // LLVM does the following for dest=src/(1<<log): |
| 2238 // t=src | 2235 // t=src |
| 2239 // sar t,typewidth-1 // -1 if src is negative, 0 if not | 2236 // sar t,typewidth-1 // -1 if src is negative, 0 if not |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2309 } | 2306 } |
| 2310 T_edx = makeReg(Ty, Edx); | 2307 T_edx = makeReg(Ty, Edx); |
| 2311 _mov(T_edx, Ctx->getConstantZero(Ty)); | 2308 _mov(T_edx, Ctx->getConstantZero(Ty)); |
| 2312 _mov(T, Src0, Eax); | 2309 _mov(T, Src0, Eax); |
| 2313 _div(T_edx, Src1, T); | 2310 _div(T_edx, Src1, T); |
| 2314 _mov(Dest, T_edx); | 2311 _mov(Dest, T_edx); |
| 2315 } break; | 2312 } break; |
| 2316 case InstArithmetic::Srem: { | 2313 case InstArithmetic::Srem: { |
| 2317 // TODO(stichnot): Enable this after doing better performance and cross | 2314 // TODO(stichnot): Enable this after doing better performance and cross |
| 2318 // testing. | 2315 // testing. |
| 2319 if (false && Ctx->getFlags().getOptLevel() >= Opt_1) { | 2316 if (false && getFlags().getOptLevel() >= Opt_1) { |
| 2320 // Optimize mod by constant power of 2, but not for Om1 or O0, just to | 2317 // Optimize mod by constant power of 2, but not for Om1 or O0, just to |
| 2321 // keep things simple there. | 2318 // keep things simple there. |
| 2322 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { | 2319 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) { |
| 2323 const int32_t Divisor = C->getValue(); | 2320 const int32_t Divisor = C->getValue(); |
| 2324 const uint32_t UDivisor = Divisor; | 2321 const uint32_t UDivisor = Divisor; |
| 2325 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { | 2322 if (Divisor > 0 && llvm::isPowerOf2_32(UDivisor)) { |
| 2326 uint32_t LogDiv = llvm::Log2_32(UDivisor); | 2323 uint32_t LogDiv = llvm::Log2_32(UDivisor); |
| 2327 // LLVM does the following for dest=src%(1<<log): | 2324 // LLVM does the following for dest=src%(1<<log): |
| 2328 // t=src | 2325 // t=src |
| 2329 // sar t,typewidth-1 // -1 if src is negative, 0 if not | 2326 // sar t,typewidth-1 // -1 if src is negative, 0 if not |
| (...skipping 1972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4302 constexpr bool Locked = true; | 4299 constexpr bool Locked = true; |
| 4303 _cmpxchg(Addr, T_eax, DesiredReg, Locked); | 4300 _cmpxchg(Addr, T_eax, DesiredReg, Locked); |
| 4304 _mov(DestPrev, T_eax); | 4301 _mov(DestPrev, T_eax); |
| 4305 } | 4302 } |
| 4306 | 4303 |
| 4307 template <typename TraitsType> | 4304 template <typename TraitsType> |
| 4308 bool TargetX86Base<TraitsType>::tryOptimizedCmpxchgCmpBr(Variable *Dest, | 4305 bool TargetX86Base<TraitsType>::tryOptimizedCmpxchgCmpBr(Variable *Dest, |
| 4309 Operand *PtrToMem, | 4306 Operand *PtrToMem, |
| 4310 Operand *Expected, | 4307 Operand *Expected, |
| 4311 Operand *Desired) { | 4308 Operand *Desired) { |
| 4312 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 4309 if (getFlags().getOptLevel() == Opt_m1) |
| 4313 return false; | 4310 return false; |
| 4314 // Peek ahead a few instructions and see how Dest is used. | 4311 // Peek ahead a few instructions and see how Dest is used. |
| 4315 // It's very common to have: | 4312 // It's very common to have: |
| 4316 // | 4313 // |
| 4317 // %x = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* ptr, i32 %expected, ...) | 4314 // %x = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* ptr, i32 %expected, ...) |
| 4318 // [%y_phi = ...] // list of phi stores | 4315 // [%y_phi = ...] // list of phi stores |
| 4319 // %p = icmp eq i32 %x, %expected | 4316 // %p = icmp eq i32 %x, %expected |
| 4320 // br i1 %p, label %l1, label %l2 | 4317 // br i1 %p, label %l1, label %l2 |
| 4321 // | 4318 // |
| 4322 // which we can optimize into: | 4319 // which we can optimize into: |
| (...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5272 | 5269 |
| 5273 // If the Base has more than one use or is live across multiple blocks, then | 5270 // If the Base has more than one use or is live across multiple blocks, then |
| 5274 // don't go further. Alternatively (?), never consider a transformation that | 5271 // don't go further. Alternatively (?), never consider a transformation that |
| 5275 // would change a variable that is currently *not* live across basic block | 5272 // would change a variable that is currently *not* live across basic block |
| 5276 // boundaries into one that *is*. | 5273 // boundaries into one that *is*. |
| 5277 if (Func->getVMetadata()->isMultiBlock( | 5274 if (Func->getVMetadata()->isMultiBlock( |
| 5278 NewAddr.Base) /* || Base->getUseCount() > 1*/) | 5275 NewAddr.Base) /* || Base->getUseCount() > 1*/) |
| 5279 return nullptr; | 5276 return nullptr; |
| 5280 | 5277 |
| 5281 AddressOptimizer AddrOpt(Func); | 5278 AddressOptimizer AddrOpt(Func); |
| 5282 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); | 5279 const bool MockBounds = getFlags().getMockBoundsCheck(); |
| 5283 const Inst *Reason = nullptr; | 5280 const Inst *Reason = nullptr; |
| 5284 bool AddressWasOptimized = false; | 5281 bool AddressWasOptimized = false; |
| 5285 // The following unnamed struct identifies the address mode formation steps | 5282 // The following unnamed struct identifies the address mode formation steps |
| 5286 // that could potentially create an invalid memory operand (i.e., no free | 5283 // that could potentially create an invalid memory operand (i.e., no free |
| 5287 // slots for RebasePtr.) We add all those variables to this struct so that we | 5284 // slots for RebasePtr.) We add all those variables to this struct so that we |
| 5288 // can use memset() to reset all members to false. | 5285 // can use memset() to reset all members to false. |
| 5289 struct { | 5286 struct { |
| 5290 bool AssignBase = false; | 5287 bool AssignBase = false; |
| 5291 bool AssignIndex = false; | 5288 bool AssignIndex = false; |
| 5292 bool OffsetFromBase = false; | 5289 bool OffsetFromBase = false; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5464 /// cmp reg, 0 | 5461 /// cmp reg, 0 |
| 5465 /// je label | 5462 /// je label |
| 5466 /// cmp reg, 1 | 5463 /// cmp reg, 1 |
| 5467 /// je label | 5464 /// je label |
| 5468 /// label: | 5465 /// label: |
| 5469 /// | 5466 /// |
| 5470 /// Also note that we don't need to add a bounds check to a dereference of a | 5467 /// Also note that we don't need to add a bounds check to a dereference of a |
| 5471 /// simple global variable address. | 5468 /// simple global variable address. |
| 5472 template <typename TraitsType> | 5469 template <typename TraitsType> |
| 5473 void TargetX86Base<TraitsType>::doMockBoundsCheck(Operand *Opnd) { | 5470 void TargetX86Base<TraitsType>::doMockBoundsCheck(Operand *Opnd) { |
| 5474 if (!Ctx->getFlags().getMockBoundsCheck()) | 5471 if (!getFlags().getMockBoundsCheck()) |
| 5475 return; | 5472 return; |
| 5476 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(Opnd)) { | 5473 if (auto *Mem = llvm::dyn_cast<X86OperandMem>(Opnd)) { |
| 5477 if (Mem->getIndex()) { | 5474 if (Mem->getIndex()) { |
| 5478 llvm::report_fatal_error("doMockBoundsCheck: Opnd contains index reg"); | 5475 llvm::report_fatal_error("doMockBoundsCheck: Opnd contains index reg"); |
| 5479 } | 5476 } |
| 5480 Opnd = Mem->getBase(); | 5477 Opnd = Mem->getBase(); |
| 5481 } | 5478 } |
| 5482 // At this point Opnd could be nullptr, or Variable, or Constant, or perhaps | 5479 // At this point Opnd could be nullptr, or Variable, or Constant, or perhaps |
| 5483 // something else. We only care if it is Variable. | 5480 // something else. We only care if it is Variable. |
| 5484 auto *Var = llvm::dyn_cast_or_null<Variable>(Opnd); | 5481 auto *Var = llvm::dyn_cast_or_null<Variable>(Opnd); |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6184 } else { | 6181 } else { |
| 6185 TargetLowering::lowerOther(Instr); | 6182 TargetLowering::lowerOther(Instr); |
| 6186 } | 6183 } |
| 6187 } | 6184 } |
| 6188 | 6185 |
| 6189 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 6186 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
| 6190 /// integrity of liveness analysis. Undef values are also turned into zeroes, | 6187 /// integrity of liveness analysis. Undef values are also turned into zeroes, |
| 6191 /// since loOperand() and hiOperand() don't expect Undef input. Also, in | 6188 /// since loOperand() and hiOperand() don't expect Undef input. Also, in |
| 6192 /// Non-SFI mode, add a FakeUse(RebasePtr) for every pooled constant operand. | 6189 /// Non-SFI mode, add a FakeUse(RebasePtr) for every pooled constant operand. |
| 6193 template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() { | 6190 template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() { |
| 6194 if (Ctx->getFlags().getUseNonsfi()) { | 6191 if (getFlags().getUseNonsfi()) { |
| 6195 assert(RebasePtr); | 6192 assert(RebasePtr); |
| 6196 CfgNode *Node = Context.getNode(); | 6193 CfgNode *Node = Context.getNode(); |
| 6197 uint32_t RebasePtrUseCount = 0; | 6194 uint32_t RebasePtrUseCount = 0; |
| 6198 for (Inst &I : Node->getPhis()) { | 6195 for (Inst &I : Node->getPhis()) { |
| 6199 auto *Phi = llvm::dyn_cast<InstPhi>(&I); | 6196 auto *Phi = llvm::dyn_cast<InstPhi>(&I); |
| 6200 if (Phi->isDeleted()) | 6197 if (Phi->isDeleted()) |
| 6201 continue; | 6198 continue; |
| 6202 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { | 6199 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { |
| 6203 Operand *Src = Phi->getSrc(I); | 6200 Operand *Src = Phi->getSrc(I); |
| 6204 // TODO(stichnot): This over-counts for +0.0, and under-counts for other | 6201 // TODO(stichnot): This over-counts for +0.0, and under-counts for other |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6711 _movp(Reg, Src); | 6708 _movp(Reg, Src); |
| 6712 } else { | 6709 } else { |
| 6713 _mov(Reg, Src); | 6710 _mov(Reg, Src); |
| 6714 } | 6711 } |
| 6715 return Reg; | 6712 return Reg; |
| 6716 } | 6713 } |
| 6717 | 6714 |
| 6718 template <typename TraitsType> | 6715 template <typename TraitsType> |
| 6719 Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, | 6716 Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| 6720 RegNumT RegNum) { | 6717 RegNumT RegNum) { |
| 6721 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); | 6718 const bool UseNonsfi = getFlags().getUseNonsfi(); |
| 6722 const Type Ty = From->getType(); | 6719 const Type Ty = From->getType(); |
| 6723 // Assert that a physical register is allowed. To date, all calls to | 6720 // Assert that a physical register is allowed. To date, all calls to |
| 6724 // legalize() allow a physical register. If a physical register needs to be | 6721 // legalize() allow a physical register. If a physical register needs to be |
| 6725 // explicitly disallowed, then new code will need to be written to force a | 6722 // explicitly disallowed, then new code will need to be written to force a |
| 6726 // spill. | 6723 // spill. |
| 6727 assert(Allowed & Legal_Reg); | 6724 assert(Allowed & Legal_Reg); |
| 6728 // If we're asking for a specific physical register, make sure we're not | 6725 // If we're asking for a specific physical register, make sure we're not |
| 6729 // allowing any other operand kinds. (This could be future work, e.g. allow | 6726 // allowing any other operand kinds. (This could be future work, e.g. allow |
| 6730 // the shl shift amount to be either an immediate or in ecx.) | 6727 // the shl shift amount to be either an immediate or in ecx.) |
| 6731 assert(RegNum.hasNoValue() || Allowed == Legal_Reg); | 6728 assert(RegNum.hasNoValue() || Allowed == Legal_Reg); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7008 uint32_t TyIndex = llvm::findLastSet(Size, llvm::ZB_Undefined); | 7005 uint32_t TyIndex = llvm::findLastSet(Size, llvm::ZB_Undefined); |
| 7009 if (!llvm::isPowerOf2_32(Size)) | 7006 if (!llvm::isPowerOf2_32(Size)) |
| 7010 ++TyIndex; | 7007 ++TyIndex; |
| 7011 uint32_t MaxIndex = MaxSize == NoSizeLimit | 7008 uint32_t MaxIndex = MaxSize == NoSizeLimit |
| 7012 ? llvm::array_lengthof(TypeForSize) - 1 | 7009 ? llvm::array_lengthof(TypeForSize) - 1 |
| 7013 : llvm::findLastSet(MaxSize, llvm::ZB_Undefined); | 7010 : llvm::findLastSet(MaxSize, llvm::ZB_Undefined); |
| 7014 return TypeForSize[std::min(TyIndex, MaxIndex)]; | 7011 return TypeForSize[std::min(TyIndex, MaxIndex)]; |
| 7015 } | 7012 } |
| 7016 | 7013 |
| 7017 template <typename TraitsType> void TargetX86Base<TraitsType>::postLower() { | 7014 template <typename TraitsType> void TargetX86Base<TraitsType>::postLower() { |
| 7018 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 7015 if (getFlags().getOptLevel() == Opt_m1) |
| 7019 return; | 7016 return; |
| 7020 markRedefinitions(); | 7017 markRedefinitions(); |
| 7021 Context.availabilityUpdate(); | 7018 Context.availabilityUpdate(); |
| 7022 } | 7019 } |
| 7023 | 7020 |
| 7024 template <typename TraitsType> | 7021 template <typename TraitsType> |
| 7025 void TargetX86Base<TraitsType>::makeRandomRegisterPermutation( | 7022 void TargetX86Base<TraitsType>::makeRandomRegisterPermutation( |
| 7026 llvm::SmallVectorImpl<RegNumT> &Permutation, | 7023 llvm::SmallVectorImpl<RegNumT> &Permutation, |
| 7027 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 7024 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
| 7028 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, | 7025 Traits::makeRandomRegisterPermutation(Func, Permutation, ExcludeRegisters, |
| 7029 ExcludeRegisters, Salt); | 7026 Salt); |
| 7030 } | 7027 } |
| 7031 | 7028 |
| 7032 template <typename TraitsType> | 7029 template <typename TraitsType> |
| 7033 void TargetX86Base<TraitsType>::emit(const ConstantInteger32 *C) const { | 7030 void TargetX86Base<TraitsType>::emit(const ConstantInteger32 *C) const { |
| 7034 if (!BuildDefs::dump()) | 7031 if (!BuildDefs::dump()) |
| 7035 return; | 7032 return; |
| 7036 Ostream &Str = Ctx->getStrEmit(); | 7033 Ostream &Str = Ctx->getStrEmit(); |
| 7037 Str << "$" << C->getValue(); | 7034 Str << "$" << C->getValue(); |
| 7038 } | 7035 } |
| 7039 | 7036 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 7067 | 7064 |
| 7068 template <typename TraitsType> | 7065 template <typename TraitsType> |
| 7069 void TargetX86Base<TraitsType>::emit(const ConstantUndef *) const { | 7066 void TargetX86Base<TraitsType>::emit(const ConstantUndef *) const { |
| 7070 llvm::report_fatal_error("undef value encountered by emitter."); | 7067 llvm::report_fatal_error("undef value encountered by emitter."); |
| 7071 } | 7068 } |
| 7072 | 7069 |
| 7073 template <class Machine> | 7070 template <class Machine> |
| 7074 void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const { | 7071 void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const { |
| 7075 if (!BuildDefs::dump()) | 7072 if (!BuildDefs::dump()) |
| 7076 return; | 7073 return; |
| 7077 assert(!Ctx->getFlags().getUseNonsfi() || | 7074 assert(!getFlags().getUseNonsfi() || |
| 7078 C->getName().toString() == GlobalOffsetTable); | 7075 C->getName().toString() == GlobalOffsetTable); |
| 7079 Ostream &Str = Ctx->getStrEmit(); | 7076 Ostream &Str = Ctx->getStrEmit(); |
| 7080 Str << "$"; | 7077 Str << "$"; |
| 7081 emitWithoutPrefix(C); | 7078 emitWithoutPrefix(C); |
| 7082 } | 7079 } |
| 7083 | 7080 |
| 7084 /// Randomize or pool an Immediate. | 7081 /// Randomize or pool an Immediate. |
| 7085 template <typename TraitsType> | 7082 template <typename TraitsType> |
| 7086 Operand * | 7083 Operand * |
| 7087 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, | 7084 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, |
| 7088 RegNumT RegNum) { | 7085 RegNumT RegNum) { |
| 7089 assert(llvm::isa<ConstantInteger32>(Immediate) || | 7086 assert(llvm::isa<ConstantInteger32>(Immediate) || |
| 7090 llvm::isa<ConstantRelocatable>(Immediate)); | 7087 llvm::isa<ConstantRelocatable>(Immediate)); |
| 7091 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 7088 if (getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
| 7092 RandomizationPoolingPaused == true) { | 7089 RandomizationPoolingPaused == true) { |
| 7093 // Immediates randomization/pooling off or paused | 7090 // Immediates randomization/pooling off or paused |
| 7094 return Immediate; | 7091 return Immediate; |
| 7095 } | 7092 } |
| 7096 | 7093 |
| 7097 if (Traits::Is64Bit && NeedSandboxing) { | 7094 if (Traits::Is64Bit && NeedSandboxing) { |
| 7098 // Immediate randomization/pooling is currently disabled for x86-64 | 7095 // Immediate randomization/pooling is currently disabled for x86-64 |
| 7099 // sandboxing for it could generate invalid memory operands. | 7096 // sandboxing for it could generate invalid memory operands. |
| 7100 assert(false && | 7097 assert(false && |
| 7101 "Constant pooling/randomization is disabled for x8664 sandbox."); | 7098 "Constant pooling/randomization is disabled for x8664 sandbox."); |
| 7102 return Immediate; | 7099 return Immediate; |
| 7103 } | 7100 } |
| 7104 | 7101 |
| 7105 if (!Immediate->shouldBeRandomizedOrPooled()) { | 7102 if (!Immediate->shouldBeRandomizedOrPooled()) { |
| 7106 // the constant Immediate is not eligible for blinding/pooling | 7103 // the constant Immediate is not eligible for blinding/pooling |
| 7107 return Immediate; | 7104 return Immediate; |
| 7108 } | 7105 } |
| 7109 Ctx->statsUpdateRPImms(); | 7106 Ctx->statsUpdateRPImms(); |
| 7110 switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) { | 7107 switch (getFlags().getRandomizeAndPoolImmediatesOption()) { |
| 7111 default: | 7108 default: |
| 7112 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); | 7109 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); |
| 7113 case RPI_Randomize: { | 7110 case RPI_Randomize: { |
| 7114 // blind the constant | 7111 // blind the constant |
| 7115 // FROM: | 7112 // FROM: |
| 7116 // imm | 7113 // imm |
| 7117 // TO: | 7114 // TO: |
| 7118 // insert: mov imm+cookie, Reg | 7115 // insert: mov imm+cookie, Reg |
| 7119 // insert: lea -cookie[Reg], Reg | 7116 // insert: lea -cookie[Reg], Reg |
| 7120 // => Reg | 7117 // => Reg |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7137 _mov(TruncReg, Reg); | 7134 _mov(TruncReg, Reg); |
| 7138 return TruncReg; | 7135 return TruncReg; |
| 7139 } | 7136 } |
| 7140 case RPI_Pool: { | 7137 case RPI_Pool: { |
| 7141 // pool the constant | 7138 // pool the constant |
| 7142 // FROM: | 7139 // FROM: |
| 7143 // imm | 7140 // imm |
| 7144 // TO: | 7141 // TO: |
| 7145 // insert: mov $label, Reg | 7142 // insert: mov $label, Reg |
| 7146 // => Reg | 7143 // => Reg |
| 7147 assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool); | 7144 assert(getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool); |
| 7148 assert(Immediate->getShouldBePooled()); | 7145 assert(Immediate->getShouldBePooled()); |
| 7149 // if we have already assigned a phy register, we must come from | 7146 // if we have already assigned a phy register, we must come from |
| 7150 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the | 7147 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse the |
| 7151 // assigned register as this assignment is that start of its use-def | 7148 // assigned register as this assignment is that start of its use-def |
| 7152 // chain. So we add RegNum argument here. | 7149 // chain. So we add RegNum argument here. |
| 7153 Variable *Reg = makeReg(Immediate->getType(), RegNum); | 7150 Variable *Reg = makeReg(Immediate->getType(), RegNum); |
| 7154 constexpr RelocOffsetT Offset = 0; | 7151 constexpr RelocOffsetT Offset = 0; |
| 7155 Constant *Symbol = Ctx->getConstantSym(Offset, Immediate->getLabelName()); | 7152 Constant *Symbol = Ctx->getConstantSym(Offset, Immediate->getLabelName()); |
| 7156 constexpr Variable *NoBase = nullptr; | 7153 constexpr Variable *NoBase = nullptr; |
| 7157 X86OperandMem *MemOperand = | 7154 X86OperandMem *MemOperand = |
| 7158 X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol); | 7155 X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol); |
| 7159 _mov(Reg, MemOperand); | 7156 _mov(Reg, MemOperand); |
| 7160 return Reg; | 7157 return Reg; |
| 7161 } | 7158 } |
| 7162 } | 7159 } |
| 7163 } | 7160 } |
| 7164 | 7161 |
| 7165 template <typename TraitsType> | 7162 template <typename TraitsType> |
| 7166 typename TargetX86Base<TraitsType>::X86OperandMem * | 7163 typename TargetX86Base<TraitsType>::X86OperandMem * |
| 7167 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, | 7164 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, |
| 7168 RegNumT RegNum) { | 7165 RegNumT RegNum) { |
| 7169 assert(MemOperand); | 7166 assert(MemOperand); |
| 7170 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 7167 if (getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
| 7171 RandomizationPoolingPaused == true) { | 7168 RandomizationPoolingPaused == true) { |
| 7172 // immediates randomization/pooling is turned off | 7169 // immediates randomization/pooling is turned off |
| 7173 return MemOperand; | 7170 return MemOperand; |
| 7174 } | 7171 } |
| 7175 | 7172 |
| 7176 if (Traits::Is64Bit && NeedSandboxing) { | 7173 if (Traits::Is64Bit && NeedSandboxing) { |
| 7177 // Immediate randomization/pooling is currently disabled for x86-64 | 7174 // Immediate randomization/pooling is currently disabled for x86-64 |
| 7178 // sandboxing for it could generate invalid memory operands. | 7175 // sandboxing for it could generate invalid memory operands. |
| 7179 assert(false && | 7176 assert(false && |
| 7180 "Constant pooling/randomization is disabled for x8664 sandbox."); | 7177 "Constant pooling/randomization is disabled for x8664 sandbox."); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7191 if (C == nullptr) { | 7188 if (C == nullptr) { |
| 7192 return MemOperand; | 7189 return MemOperand; |
| 7193 } | 7190 } |
| 7194 | 7191 |
| 7195 if (!C->shouldBeRandomizedOrPooled()) { | 7192 if (!C->shouldBeRandomizedOrPooled()) { |
| 7196 return MemOperand; | 7193 return MemOperand; |
| 7197 } | 7194 } |
| 7198 | 7195 |
| 7199 // The offset of this mem operand should be blinded or pooled | 7196 // The offset of this mem operand should be blinded or pooled |
| 7200 Ctx->statsUpdateRPImms(); | 7197 Ctx->statsUpdateRPImms(); |
| 7201 switch (Ctx->getFlags().getRandomizeAndPoolImmediatesOption()) { | 7198 switch (getFlags().getRandomizeAndPoolImmediatesOption()) { |
| 7202 default: | 7199 default: |
| 7203 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); | 7200 llvm::report_fatal_error("Unsupported -randomize-pool-immediates option"); |
| 7204 case RPI_Randomize: { | 7201 case RPI_Randomize: { |
| 7205 // blind the constant offset | 7202 // blind the constant offset |
| 7206 // FROM: | 7203 // FROM: |
| 7207 // offset[base, index, shift] | 7204 // offset[base, index, shift] |
| 7208 // TO: | 7205 // TO: |
| 7209 // insert: lea offset+cookie[base], RegTemp | 7206 // insert: lea offset+cookie[base], RegTemp |
| 7210 // => -cookie[RegTemp, index, shift] | 7207 // => -cookie[RegTemp, index, shift] |
| 7211 uint32_t Value = | 7208 uint32_t Value = |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7277 } | 7274 } |
| 7278 } | 7275 } |
| 7279 } | 7276 } |
| 7280 | 7277 |
| 7281 template <typename TraitsType> | 7278 template <typename TraitsType> |
| 7282 void TargetX86Base<TraitsType>::emitJumpTable( | 7279 void TargetX86Base<TraitsType>::emitJumpTable( |
| 7283 const Cfg *Func, const InstJumpTable *JumpTable) const { | 7280 const Cfg *Func, const InstJumpTable *JumpTable) const { |
| 7284 if (!BuildDefs::dump()) | 7281 if (!BuildDefs::dump()) |
| 7285 return; | 7282 return; |
| 7286 Ostream &Str = Ctx->getStrEmit(); | 7283 Ostream &Str = Ctx->getStrEmit(); |
| 7287 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | 7284 const bool UseNonsfi = getFlags().getUseNonsfi(); |
| 7288 GlobalString FunctionName = Func->getFunctionName(); | 7285 GlobalString FunctionName = Func->getFunctionName(); |
| 7289 const char *Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; | 7286 const char *Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; |
| 7290 Str << "\t.section\t" << Prefix << FunctionName | 7287 Str << "\t.section\t" << Prefix << FunctionName |
| 7291 << "$jumptable,\"a\",@progbits\n"; | 7288 << "$jumptable,\"a\",@progbits\n"; |
| 7292 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 7289 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 7293 Str << InstJumpTable::makeName(FunctionName, JumpTable->getId()) << ":"; | 7290 Str << InstJumpTable::makeName(FunctionName, JumpTable->getId()) << ":"; |
| 7294 | 7291 |
| 7295 // On X86 ILP32 pointers are 32-bit hence the use of .long | 7292 // On X86 ILP32 pointers are 32-bit hence the use of .long |
| 7296 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | 7293 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) |
| 7297 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | 7294 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); |
| 7298 Str << "\n"; | 7295 Str << "\n"; |
| 7299 } | 7296 } |
| 7300 | 7297 |
| 7301 template <typename TraitsType> | 7298 template <typename TraitsType> |
| 7302 template <typename T> | 7299 template <typename T> |
| 7303 void TargetDataX86<TraitsType>::emitConstantPool(GlobalContext *Ctx) { | 7300 void TargetDataX86<TraitsType>::emitConstantPool(GlobalContext *Ctx) { |
| 7304 if (!BuildDefs::dump()) | 7301 if (!BuildDefs::dump()) |
| 7305 return; | 7302 return; |
| 7306 Ostream &Str = Ctx->getStrEmit(); | 7303 Ostream &Str = Ctx->getStrEmit(); |
| 7307 Type Ty = T::Ty; | 7304 Type Ty = T::Ty; |
| 7308 SizeT Align = typeAlignInBytes(Ty); | 7305 SizeT Align = typeAlignInBytes(Ty); |
| 7309 ConstantList Pool = Ctx->getConstantPool(Ty); | 7306 ConstantList Pool = Ctx->getConstantPool(Ty); |
| 7310 | 7307 |
| 7311 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | 7308 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
| 7312 << "\n"; | 7309 << "\n"; |
| 7313 Str << "\t.align\t" << Align << "\n"; | 7310 Str << "\t.align\t" << Align << "\n"; |
| 7314 | 7311 |
| 7315 // If reorder-pooled-constants option is set to true, we need to shuffle the | 7312 // If reorder-pooled-constants option is set to true, we need to shuffle the |
| 7316 // constant pool before emitting it. | 7313 // constant pool before emitting it. |
| 7317 if (Ctx->getFlags().getReorderPooledConstants() && !Pool.empty()) { | 7314 if (getFlags().getReorderPooledConstants() && !Pool.empty()) { |
| 7318 // Use the constant's kind value as the salt for creating random number | 7315 // Use the constant's kind value as the salt for creating random number |
| 7319 // generator. | 7316 // generator. |
| 7320 Operand::OperandKind K = (*Pool.begin())->getKind(); | 7317 Operand::OperandKind K = (*Pool.begin())->getKind(); |
| 7321 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), | 7318 RandomNumberGenerator RNG(getFlags().getRandomSeed(), |
| 7322 RPE_PooledConstantReordering, K); | 7319 RPE_PooledConstantReordering, K); |
| 7323 RandomShuffle(Pool.begin(), Pool.end(), | 7320 RandomShuffle(Pool.begin(), Pool.end(), |
| 7324 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | 7321 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 7325 } | 7322 } |
| 7326 | 7323 |
| 7327 for (Constant *C : Pool) { | 7324 for (Constant *C : Pool) { |
| 7328 if (!C->getShouldBePooled()) | 7325 if (!C->getShouldBePooled()) |
| 7329 continue; | 7326 continue; |
| 7330 auto *Const = llvm::cast<typename T::IceType>(C); | 7327 auto *Const = llvm::cast<typename T::IceType>(C); |
| 7331 typename T::IceType::PrimType Value = Const->getValue(); | 7328 typename T::IceType::PrimType Value = Const->getValue(); |
| 7332 // Use memcpy() to copy bits from Value into RawValue in a way that avoids | 7329 // Use memcpy() to copy bits from Value into RawValue in a way that avoids |
| 7333 // breaking strict-aliasing rules. | 7330 // breaking strict-aliasing rules. |
| 7334 typename T::PrimitiveIntType RawValue; | 7331 typename T::PrimitiveIntType RawValue; |
| 7335 memcpy(&RawValue, &Value, sizeof(Value)); | 7332 memcpy(&RawValue, &Value, sizeof(Value)); |
| 7336 char buf[30]; | 7333 char buf[30]; |
| 7337 int CharsPrinted = | 7334 int CharsPrinted = |
| 7338 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | 7335 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); |
| 7339 assert(CharsPrinted >= 0); | 7336 assert(CharsPrinted >= 0); |
| 7340 assert((size_t)CharsPrinted < llvm::array_lengthof(buf)); | 7337 assert((size_t)CharsPrinted < llvm::array_lengthof(buf)); |
| 7341 (void)CharsPrinted; // avoid warnings if asserts are disabled | 7338 (void)CharsPrinted; // avoid warnings if asserts are disabled |
| 7342 Str << Const->getLabelName(); | 7339 Str << Const->getLabelName(); |
| 7343 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " " | 7340 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " " |
| 7344 << Value << " */\n"; | 7341 << Value << " */\n"; |
| 7345 } | 7342 } |
| 7346 } | 7343 } |
| 7347 | 7344 |
| 7348 template <typename TraitsType> | 7345 template <typename TraitsType> |
| 7349 void TargetDataX86<TraitsType>::lowerConstants() { | 7346 void TargetDataX86<TraitsType>::lowerConstants() { |
| 7350 if (Ctx->getFlags().getDisableTranslation()) | 7347 if (getFlags().getDisableTranslation()) |
| 7351 return; | 7348 return; |
| 7352 switch (Ctx->getFlags().getOutFileType()) { | 7349 switch (getFlags().getOutFileType()) { |
| 7353 case FT_Elf: { | 7350 case FT_Elf: { |
| 7354 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 7351 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 7355 | 7352 |
| 7356 Writer->writeConstantPool<ConstantInteger32>(IceType_i8); | 7353 Writer->writeConstantPool<ConstantInteger32>(IceType_i8); |
| 7357 Writer->writeConstantPool<ConstantInteger32>(IceType_i16); | 7354 Writer->writeConstantPool<ConstantInteger32>(IceType_i16); |
| 7358 Writer->writeConstantPool<ConstantInteger32>(IceType_i32); | 7355 Writer->writeConstantPool<ConstantInteger32>(IceType_i32); |
| 7359 | 7356 |
| 7360 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 7357 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 7361 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 7358 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 7362 } break; | 7359 } break; |
| 7363 case FT_Asm: | 7360 case FT_Asm: |
| 7364 case FT_Iasm: { | 7361 case FT_Iasm: { |
| 7365 OstreamLocker L(Ctx); | 7362 OstreamLocker L(Ctx); |
| 7366 | 7363 |
| 7367 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); | 7364 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); |
| 7368 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | 7365 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); |
| 7369 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | 7366 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); |
| 7370 | 7367 |
| 7371 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 7368 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 7372 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 7369 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 7373 } break; | 7370 } break; |
| 7374 } | 7371 } |
| 7375 } | 7372 } |
| 7376 | 7373 |
| 7377 template <typename TraitsType> | 7374 template <typename TraitsType> |
| 7378 void TargetDataX86<TraitsType>::lowerJumpTables() { | 7375 void TargetDataX86<TraitsType>::lowerJumpTables() { |
| 7379 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | 7376 const bool IsPIC = getFlags().getUseNonsfi(); |
| 7380 switch (Ctx->getFlags().getOutFileType()) { | 7377 switch (getFlags().getOutFileType()) { |
| 7381 case FT_Elf: { | 7378 case FT_Elf: { |
| 7382 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 7379 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 7383 for (const JumpTableData &JT : Ctx->getJumpTables()) | 7380 for (const JumpTableData &JT : Ctx->getJumpTables()) |
| 7384 Writer->writeJumpTable(JT, Traits::FK_Abs, IsPIC); | 7381 Writer->writeJumpTable(JT, Traits::FK_Abs, IsPIC); |
| 7385 } break; | 7382 } break; |
| 7386 case FT_Asm: | 7383 case FT_Asm: |
| 7387 // Already emitted from Cfg | 7384 // Already emitted from Cfg |
| 7388 break; | 7385 break; |
| 7389 case FT_Iasm: { | 7386 case FT_Iasm: { |
| 7390 if (!BuildDefs::dump()) | 7387 if (!BuildDefs::dump()) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 7402 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | 7399 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; |
| 7403 Str << "\n"; | 7400 Str << "\n"; |
| 7404 } | 7401 } |
| 7405 } break; | 7402 } break; |
| 7406 } | 7403 } |
| 7407 } | 7404 } |
| 7408 | 7405 |
| 7409 template <typename TraitsType> | 7406 template <typename TraitsType> |
| 7410 void TargetDataX86<TraitsType>::lowerGlobals( | 7407 void TargetDataX86<TraitsType>::lowerGlobals( |
| 7411 const VariableDeclarationList &Vars, const std::string &SectionSuffix) { | 7408 const VariableDeclarationList &Vars, const std::string &SectionSuffix) { |
| 7412 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | 7409 const bool IsPIC = getFlags().getUseNonsfi(); |
| 7413 switch (Ctx->getFlags().getOutFileType()) { | 7410 switch (getFlags().getOutFileType()) { |
| 7414 case FT_Elf: { | 7411 case FT_Elf: { |
| 7415 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 7412 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 7416 Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC); | 7413 Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC); |
| 7417 } break; | 7414 } break; |
| 7418 case FT_Asm: | 7415 case FT_Asm: |
| 7419 case FT_Iasm: { | 7416 case FT_Iasm: { |
| 7420 const std::string TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 7417 const std::string TranslateOnly = getFlags().getTranslateOnly(); |
| 7421 OstreamLocker L(Ctx); | 7418 OstreamLocker L(Ctx); |
| 7422 for (const VariableDeclaration *Var : Vars) { | 7419 for (const VariableDeclaration *Var : Vars) { |
| 7423 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 7420 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
| 7424 emitGlobal(*Var, SectionSuffix); | 7421 emitGlobal(*Var, SectionSuffix); |
| 7425 } | 7422 } |
| 7426 } | 7423 } |
| 7427 } break; | 7424 } break; |
| 7428 } | 7425 } |
| 7429 } | 7426 } |
| 7430 } // end of namespace X86NAMESPACE | 7427 } // end of namespace X86NAMESPACE |
| 7431 } // end of namespace Ice | 7428 } // end of namespace Ice |
| 7432 | 7429 |
| 7433 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 7430 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |