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 |