Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1605103002: Subzero. X86. Refactors Address Mode formation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Minor changes. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 } 301 }
302 302
303 template <typename TraitsType> 303 template <typename TraitsType>
304 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) { 304 void TargetX86Base<TraitsType>::initNodeForLowering(CfgNode *Node) {
305 FoldingInfo.init(Node); 305 FoldingInfo.init(Node);
306 FoldingInfo.dump(Func); 306 FoldingInfo.dump(Func);
307 } 307 }
308 308
309 template <typename TraitsType> 309 template <typename TraitsType>
310 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func) 310 TargetX86Base<TraitsType>::TargetX86Base(Cfg *Func)
311 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()) { 311 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl) {
312 static_assert( 312 static_assert(
313 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == 313 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) ==
314 (TargetInstructionSet::X86InstructionSet_End - 314 (TargetInstructionSet::X86InstructionSet_End -
315 TargetInstructionSet::X86InstructionSet_Begin), 315 TargetInstructionSet::X86InstructionSet_Begin),
316 "Traits::InstructionSet range different from TargetInstructionSet"); 316 "Traits::InstructionSet range different from TargetInstructionSet");
317 if (Func->getContext()->getFlags().getTargetInstructionSet() != 317 if (Func->getContext()->getFlags().getTargetInstructionSet() !=
318 TargetInstructionSet::BaseInstructionSet) { 318 TargetInstructionSet::BaseInstructionSet) {
319 InstructionSet = static_cast<InstructionSetEnum>( 319 InstructionSet = static_cast<InstructionSetEnum>(
320 (Func->getContext()->getFlags().getTargetInstructionSet() - 320 (Func->getContext()->getFlags().getTargetInstructionSet() -
321 TargetInstructionSet::X86InstructionSet_Begin) + 321 TargetInstructionSet::X86InstructionSet_Begin) +
322 Traits::InstructionSet::Begin); 322 Traits::InstructionSet::Begin);
323 } 323 }
324 } 324 }
325 325
326 template <typename TraitsType> 326 template <typename TraitsType>
327 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) { 327 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) {
328 Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet, 328 Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet,
329 &RegisterAliases); 329 &RegisterAliases);
330 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM, 330 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM,
331 TypeToRegisterSet.data(), TypeToRegisterSet.size(), 331 TypeToRegisterSet.data(), TypeToRegisterSet.size(),
332 Traits::getRegName); 332 Traits::getRegName);
333 PcRelFixup = Traits::FK_PcRel; 333 PcRelFixup = Traits::FK_PcRel;
334 AbsFixup = 334 AbsFixup =
335 Ctx->getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; 335 Ctx->getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs;
336 } 336 }
337 337
338 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() { 338 template <typename TraitsType> void TargetX86Base<TraitsType>::translateO2() {
339 TimerMarker T(TimerStack::TT_O2, Func); 339 TimerMarker T(TimerStack::TT_O2, Func);
340 340
341 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { 341 if (SandboxingType != ST_None) {
342 GotVar = Func->makeVariable(IceType_i32); 342 initSandboxPtr();
343 }
344
345 if (NeedSandboxing) {
346 initSandbox();
347 } 343 }
348 344
349 genTargetHelperCalls(); 345 genTargetHelperCalls();
350 Func->dump("After target helper call insertion"); 346 Func->dump("After target helper call insertion");
351 347
352 // Merge Alloca instructions, and lay out the stack. 348 // Merge Alloca instructions, and lay out the stack.
353 static constexpr bool SortAndCombineAllocas = true; 349 static constexpr bool SortAndCombineAllocas = true;
354 Func->processAllocas(SortAndCombineAllocas); 350 Func->processAllocas(SortAndCombineAllocas);
355 Func->dump("After Alloca processing"); 351 Func->dump("After Alloca processing");
356 352
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 Func->dump("After x86 address mode opt"); 403 Func->dump("After x86 address mode opt");
408 404
409 // Disable constant blinding or pooling for load optimization. 405 // Disable constant blinding or pooling for load optimization.
410 { 406 {
411 BoolFlagSaver B(RandomizationPoolingPaused, true); 407 BoolFlagSaver B(RandomizationPoolingPaused, true);
412 doLoadOpt(); 408 doLoadOpt();
413 } 409 }
414 Func->genCode(); 410 Func->genCode();
415 if (Func->hasError()) 411 if (Func->hasError())
416 return; 412 return;
417 initGotVarIfNeeded(); 413 if (SandboxingType != ST_None) {
414 initSandbox();
415 }
418 Func->dump("After x86 codegen"); 416 Func->dump("After x86 codegen");
419 417
420 // Register allocation. This requires instruction renumbering and full 418 // Register allocation. This requires instruction renumbering and full
421 // liveness analysis. Loops must be identified before liveness so variable 419 // liveness analysis. Loops must be identified before liveness so variable
422 // use weights are correct. 420 // use weights are correct.
423 Func->renumberInstructions(); 421 Func->renumberInstructions();
424 if (Func->hasError()) 422 if (Func->hasError())
425 return; 423 return;
426 Func->liveness(Liveness_Intervals); 424 Func->liveness(Liveness_Intervals);
427 if (Func->hasError()) 425 if (Func->hasError())
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 465
468 // Mark nodes that require sandbox alignment 466 // Mark nodes that require sandbox alignment
469 if (NeedSandboxing) { 467 if (NeedSandboxing) {
470 Func->markNodesForSandboxing(); 468 Func->markNodesForSandboxing();
471 } 469 }
472 } 470 }
473 471
474 template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() { 472 template <typename TraitsType> void TargetX86Base<TraitsType>::translateOm1() {
475 TimerMarker T(TimerStack::TT_Om1, Func); 473 TimerMarker T(TimerStack::TT_Om1, Func);
476 474
477 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { 475 if (SandboxingType != ST_None) {
478 GotVar = Func->makeVariable(IceType_i32); 476 initSandboxPtr();
479 }
480
481 if (NeedSandboxing) {
482 initSandbox();
483 } 477 }
484 478
485 genTargetHelperCalls(); 479 genTargetHelperCalls();
486 480
487 // Do not merge Alloca instructions, and lay out the stack. 481 // Do not merge Alloca instructions, and lay out the stack.
488 static constexpr bool SortAndCombineAllocas = false; 482 static constexpr bool SortAndCombineAllocas = false;
489 Func->processAllocas(SortAndCombineAllocas); 483 Func->processAllocas(SortAndCombineAllocas);
490 Func->dump("After Alloca processing"); 484 Func->dump("After Alloca processing");
491 485
492 Func->placePhiLoads(); 486 Func->placePhiLoads();
493 if (Func->hasError()) 487 if (Func->hasError())
494 return; 488 return;
495 Func->placePhiStores(); 489 Func->placePhiStores();
496 if (Func->hasError()) 490 if (Func->hasError())
497 return; 491 return;
498 Func->deletePhis(); 492 Func->deletePhis();
499 if (Func->hasError()) 493 if (Func->hasError())
500 return; 494 return;
501 Func->dump("After Phi lowering"); 495 Func->dump("After Phi lowering");
502 496
503 Func->doArgLowering(); 497 Func->doArgLowering();
504 Func->genCode(); 498 Func->genCode();
505 if (Func->hasError()) 499 if (Func->hasError())
506 return; 500 return;
507 initGotVarIfNeeded(); 501 if (SandboxingType != ST_None) {
502 initSandbox();
503 }
508 Func->dump("After initial x8632 codegen"); 504 Func->dump("After initial x8632 codegen");
509 505
510 regAlloc(RAK_InfOnly); 506 regAlloc(RAK_InfOnly);
511 if (Func->hasError()) 507 if (Func->hasError())
512 return; 508 return;
513 Func->dump("After regalloc of infinite-weight variables"); 509 Func->dump("After regalloc of infinite-weight variables");
514 510
515 Func->genFrame(); 511 Func->genFrame();
516 if (Func->hasError()) 512 if (Func->hasError())
517 return; 513 return;
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 } 990 }
995 991
996 template <typename TraitsType> 992 template <typename TraitsType>
997 llvm::SmallBitVector 993 llvm::SmallBitVector
998 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include, 994 TargetX86Base<TraitsType>::getRegisterSet(RegSetMask Include,
999 RegSetMask Exclude) const { 995 RegSetMask Exclude) const {
1000 return Traits::getRegisterSet(Ctx->getFlags(), Include, Exclude); 996 return Traits::getRegisterSet(Ctx->getFlags(), Include, Exclude);
1001 } 997 }
1002 998
1003 template <typename TraitsType> 999 template <typename TraitsType>
1004 void TargetX86Base<TraitsType>::initGotVarIfNeeded() {
1005 if (!Func->getContext()->getFlags().getUseNonsfi())
1006 return;
1007 if (Traits::Is64Bit) {
1008 // Probably no implementation is needed, but error to be safe for now.
1009 llvm::report_fatal_error(
1010 "Need to implement initGotVarIfNeeded() for 64-bit.");
1011 }
1012 // Insert the GotVar assignment as the very first lowered instruction. Later,
1013 // it will be moved into the right place - after the stack frame is set up but
1014 // before in-args are copied into registers.
1015 Context.init(Func->getEntryNode());
1016 Context.setInsertPoint(Context.getCur());
1017 Context.insert<typename Traits::Insts::GetIP>(GotVar);
1018 }
1019
1020 template <typename TraitsType>
1021 void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Inst) { 1000 void TargetX86Base<TraitsType>::lowerAlloca(const InstAlloca *Inst) {
1022 // Conservatively require the stack to be aligned. Some stack adjustment 1001 // Conservatively require the stack to be aligned. Some stack adjustment
1023 // operations implemented below assume that the stack is aligned before the 1002 // operations implemented below assume that the stack is aligned before the
1024 // alloca. All the alloca code ensures that the stack alignment is preserved 1003 // alloca. All the alloca code ensures that the stack alignment is preserved
1025 // after the alloca. The stack alignment restriction can be relaxed in some 1004 // after the alloca. The stack alignment restriction can be relaxed in some
1026 // cases. 1005 // cases.
1027 NeedsStackAlignment = true; 1006 NeedsStackAlignment = true;
1028 1007
1029 // For default align=0, set it to the real value 1, to avoid any 1008 // For default align=0, set it to the real value 1, to avoid any
1030 // bit-manipulation problems below. 1009 // bit-manipulation problems below.
(...skipping 3550 matching lines...) Expand 10 before | Expand all | Expand 10 after
4581 lowerCast(InstCast::create(Func, InstCast::Zext, ValExtVar, Val)); 4560 lowerCast(InstCast::create(Func, InstCast::Zext, ValExtVar, Val));
4582 ValExt = ValExtVar; 4561 ValExt = ValExtVar;
4583 } 4562 }
4584 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); 4563 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3);
4585 Call->addArg(Dest); 4564 Call->addArg(Dest);
4586 Call->addArg(ValExt); 4565 Call->addArg(ValExt);
4587 Call->addArg(Count); 4566 Call->addArg(Count);
4588 lowerCall(Call); 4567 lowerCall(Call);
4589 } 4568 }
4590 4569
4591 inline bool isAdd(const Inst *Inst) { 4570 class AddressOptimizer {
4592 if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { 4571 AddressOptimizer() = delete;
4593 return (Arith->getOp() == InstArithmetic::Add); 4572 AddressOptimizer(const AddressOptimizer &) = delete;
4573 AddressOptimizer &operator=(const AddressOptimizer &) = delete;
4574
4575 public:
4576 explicit AddressOptimizer(const Cfg *Func)
4577 : Func(Func), VMetadata(Func->getVMetadata()) {}
4578
4579 inline void dumpAddressOpt(const ConstantRelocatable *const Relocatable,
4580 int32_t Offset, const Variable *Base,
4581 const Variable *Index, uint16_t Shift,
4582 const Inst *Reason) const;
4583
4584 inline const Inst *matchAssign(Variable **Var,
4585 ConstantRelocatable **Relocatable,
4586 int32_t *Offset);
4587
4588 inline const Inst *matchCombinedBaseIndex(Variable **Base, Variable **Index,
4589 uint16_t *Shift);
4590
4591 inline const Inst *matchShiftedIndex(Variable **Index, uint16_t *Shift);
4592
4593 inline const Inst *matchOffsetBase(Variable **Base,
4594 ConstantRelocatable **Relocatable,
4595 int32_t *Offset);
4596
4597 private:
4598 const Cfg *const Func;
4599 const VariablesMetadata *const VMetadata;
4600
4601 static bool isAdd(const Inst *Inst) {
4602 if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
4603 return (Arith->getOp() == InstArithmetic::Add);
4604 }
4605 return false;
4594 } 4606 }
4595 return false; 4607 };
4596 }
4597 4608
4598 inline void dumpAddressOpt(const Cfg *Func, 4609 void AddressOptimizer::dumpAddressOpt(
4599 const ConstantRelocatable *Relocatable, 4610 const ConstantRelocatable *const Relocatable, int32_t Offset,
4600 int32_t Offset, const Variable *Base, 4611 const Variable *Base, const Variable *Index, uint16_t Shift,
4601 const Variable *Index, uint16_t Shift, 4612 const Inst *Reason) const {
4602 const Inst *Reason) {
4603 if (!BuildDefs::dump()) 4613 if (!BuildDefs::dump())
4604 return; 4614 return;
4605 if (!Func->isVerbose(IceV_AddrOpt)) 4615 if (!Func->isVerbose(IceV_AddrOpt))
4606 return; 4616 return;
4607 OstreamLocker L(Func->getContext()); 4617 OstreamLocker L(Func->getContext());
4608 Ostream &Str = Func->getContext()->getStrDump(); 4618 Ostream &Str = Func->getContext()->getStrDump();
4609 Str << "Instruction: "; 4619 Str << "Instruction: ";
4610 Reason->dumpDecorated(Func); 4620 Reason->dumpDecorated(Func);
4611 Str << " results in Base="; 4621 Str << " results in Base=";
4612 if (Base) 4622 if (Base)
4613 Base->dump(Func); 4623 Base->dump(Func);
4614 else 4624 else
4615 Str << "<null>"; 4625 Str << "<null>";
4616 Str << ", Index="; 4626 Str << ", Index=";
4617 if (Index) 4627 if (Index)
4618 Index->dump(Func); 4628 Index->dump(Func);
4619 else 4629 else
4620 Str << "<null>"; 4630 Str << "<null>";
4621 Str << ", Shift=" << Shift << ", Offset=" << Offset 4631 Str << ", Shift=" << Shift << ", Offset=" << Offset
4622 << ", Relocatable=" << Relocatable << "\n"; 4632 << ", Relocatable=" << Relocatable << "\n";
4623 } 4633 }
4624 4634
4625 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar, 4635 const Inst *AddressOptimizer::matchAssign(Variable **Var,
4626 Variable *&Var, ConstantRelocatable *&Relocatable, 4636 ConstantRelocatable **Relocatable,
4627 int32_t &Offset, const Inst *&Reason) { 4637 int32_t *Offset) {
4628 // Var originates from Var=SrcVar ==> set Var:=SrcVar 4638 // Var originates from Var=SrcVar ==> set Var:=SrcVar
4629 if (Var == nullptr) 4639 if (*Var == nullptr)
4630 return false; 4640 return nullptr;
4631 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { 4641 if (const Inst *VarAssign = VMetadata->getSingleDefinition(*Var)) {
4632 assert(!VMetadata->isMultiDef(Var)); 4642 assert(!VMetadata->isMultiDef(*Var));
4633 if (llvm::isa<InstAssign>(VarAssign)) { 4643 if (llvm::isa<InstAssign>(VarAssign)) {
4634 Operand *SrcOp = VarAssign->getSrc(0); 4644 Operand *SrcOp = VarAssign->getSrc(0);
4635 assert(SrcOp); 4645 assert(SrcOp);
4636 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { 4646 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
4637 if (!VMetadata->isMultiDef(SrcVar) && 4647 if (!VMetadata->isMultiDef(SrcVar) &&
4638 // TODO: ensure SrcVar stays single-BB 4648 // TODO: ensure SrcVar stays single-BB
4639 true) { 4649 true) {
4640 Var = SrcVar; 4650 *Var = SrcVar;
4641 Reason = VarAssign; 4651 return VarAssign;
4642 return true;
4643 } 4652 }
4644 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { 4653 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
4645 int32_t MoreOffset = Const->getValue(); 4654 int32_t MoreOffset = Const->getValue();
4646 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) 4655 if (Utils::WouldOverflowAdd(*Offset, MoreOffset))
4647 return false; 4656 return nullptr;
4648 Var = nullptr; 4657 *Var = nullptr;
4649 Offset += MoreOffset; 4658 Offset += MoreOffset;
4650 Reason = VarAssign; 4659 return VarAssign;
4651 return true;
4652 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { 4660 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) {
4653 if (Relocatable == nullptr) { 4661 if (*Relocatable == nullptr) {
4654 Var = GotVar; 4662 // It is always safe to fold a relocatable through assignment -- the
4655 Relocatable = AddReloc; 4663 // assignment frees a slot in the address operand that can be used to
4656 Reason = VarAssign; 4664 // hold the Sandbox Pointer -- if any.
4657 return true; 4665 *Var = nullptr;
4666 *Relocatable = AddReloc;
4667 return VarAssign;
4658 } 4668 }
4659 } 4669 }
4660 } 4670 }
4661 } 4671 }
4662 return false; 4672 return nullptr;
4663 } 4673 }
4664 4674
4665 inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, 4675 const Inst *AddressOptimizer::matchCombinedBaseIndex(Variable **Base,
4666 Variable *&Base, Variable *&Index, 4676 Variable **Index,
4667 uint16_t &Shift, const Inst *&Reason) { 4677 uint16_t *Shift) {
4668 // Index==nullptr && Base is Base=Var1+Var2 ==> 4678 // Index==nullptr && Base is Base=Var1+Var2 ==>
4669 // set Base=Var1, Index=Var2, Shift=0 4679 // set Base=Var1, Index=Var2, Shift=0
4670 if (Base == nullptr) 4680 if (*Base == nullptr)
4671 return false; 4681 return nullptr;
4672 if (Index != nullptr) 4682 if (*Index != nullptr)
4673 return false; 4683 return nullptr;
4674 auto *BaseInst = VMetadata->getSingleDefinition(Base); 4684 auto *BaseInst = VMetadata->getSingleDefinition(*Base);
4675 if (BaseInst == nullptr) 4685 if (BaseInst == nullptr)
4676 return false; 4686 return nullptr;
4677 assert(!VMetadata->isMultiDef(Base)); 4687 assert(!VMetadata->isMultiDef(*Base));
4678 if (BaseInst->getSrcSize() < 2) 4688 if (BaseInst->getSrcSize() < 2)
4679 return false; 4689 return nullptr;
4680 if (auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { 4690 if (auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
4681 if (VMetadata->isMultiDef(Var1)) 4691 if (VMetadata->isMultiDef(Var1))
4682 return false; 4692 return nullptr;
4683 if (auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { 4693 if (auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
4684 if (VMetadata->isMultiDef(Var2)) 4694 if (VMetadata->isMultiDef(Var2))
4685 return false; 4695 return nullptr;
4686 if (isAdd(BaseInst) && 4696 if (isAdd(BaseInst) &&
4687 // TODO: ensure Var1 and Var2 stay single-BB 4697 // TODO: ensure Var1 and Var2 stay single-BB
4688 true) { 4698 true) {
4689 Base = Var1; 4699 *Base = Var1;
4690 Index = Var2; 4700 *Index = Var2;
4691 Shift = 0; // should already have been 0 4701 *Shift = 0; // should already have been 0
4692 Reason = BaseInst; 4702 return BaseInst;
4693 return true;
4694 } 4703 }
4695 } 4704 }
4696 } 4705 }
4697 return false; 4706 return nullptr;
4698 } 4707 }
4699 4708
4700 inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, 4709 const Inst *AddressOptimizer::matchShiftedIndex(Variable **Index,
4701 Variable *&Index, uint16_t &Shift, 4710 uint16_t *Shift) {
4702 const Inst *&Reason) {
4703 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> 4711 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
4704 // Index=Var, Shift+=log2(Const) 4712 // Index=Var, Shift+=log2(Const)
4705 if (Index == nullptr) 4713 if (*Index == nullptr)
4706 return false; 4714 return nullptr;
4707 auto *IndexInst = VMetadata->getSingleDefinition(Index); 4715 auto *IndexInst = VMetadata->getSingleDefinition(*Index);
4708 if (IndexInst == nullptr) 4716 if (IndexInst == nullptr)
4709 return false; 4717 return nullptr;
4710 assert(!VMetadata->isMultiDef(Index)); 4718 assert(!VMetadata->isMultiDef(*Index));
4711 if (IndexInst->getSrcSize() < 2) 4719 if (IndexInst->getSrcSize() < 2)
4712 return false; 4720 return nullptr;
4713 if (auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst)) { 4721 if (auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst)) {
4714 if (auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { 4722 if (auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
4715 if (auto *Const = 4723 if (auto *Const =
4716 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { 4724 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
4717 if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32) 4725 if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
4718 return false; 4726 return nullptr;
4719 switch (ArithInst->getOp()) { 4727 switch (ArithInst->getOp()) {
4720 default: 4728 default:
4721 return false; 4729 return nullptr;
4722 case InstArithmetic::Mul: { 4730 case InstArithmetic::Mul: {
4723 uint32_t Mult = Const->getValue(); 4731 uint32_t Mult = Const->getValue();
4724 uint32_t LogMult; 4732 uint32_t LogMult;
4725 switch (Mult) { 4733 switch (Mult) {
4726 case 1: 4734 case 1:
4727 LogMult = 0; 4735 LogMult = 0;
4728 break; 4736 break;
4729 case 2: 4737 case 2:
4730 LogMult = 1; 4738 LogMult = 1;
4731 break; 4739 break;
4732 case 4: 4740 case 4:
4733 LogMult = 2; 4741 LogMult = 2;
4734 break; 4742 break;
4735 case 8: 4743 case 8:
4736 LogMult = 3; 4744 LogMult = 3;
4737 break; 4745 break;
4738 default: 4746 default:
4739 return false; 4747 return nullptr;
4740 } 4748 }
4741 if (Shift + LogMult <= 3) { 4749 if (*Shift + LogMult <= 3) {
4742 Index = Var; 4750 *Index = Var;
4743 Shift += LogMult; 4751 *Shift += LogMult;
4744 Reason = IndexInst; 4752 return IndexInst;
4745 return true;
4746 } 4753 }
4747 } 4754 }
4748 case InstArithmetic::Shl: { 4755 case InstArithmetic::Shl: {
4749 uint32_t ShiftAmount = Const->getValue(); 4756 uint32_t ShiftAmount = Const->getValue();
4750 switch (ShiftAmount) { 4757 switch (ShiftAmount) {
4751 case 0: 4758 case 0:
4752 case 1: 4759 case 1:
4753 case 2: 4760 case 2:
4754 case 3: 4761 case 3:
4755 break; 4762 break;
4756 default: 4763 default:
4757 return false; 4764 return nullptr;
4758 } 4765 }
4759 if (Shift + ShiftAmount <= 3) { 4766 if (*Shift + ShiftAmount <= 3) {
4760 Index = Var; 4767 *Index = Var;
4761 Shift += ShiftAmount; 4768 *Shift += ShiftAmount;
4762 Reason = IndexInst; 4769 return IndexInst;
4763 return true;
4764 } 4770 }
4765 } 4771 }
4766 } 4772 }
4767 } 4773 }
4768 } 4774 }
4769 } 4775 }
4770 return false; 4776 return nullptr;
4771 } 4777 }
4772 4778
4773 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, 4779 const Inst *AddressOptimizer::matchOffsetBase(Variable **Base,
4774 Variable *GotVar, Variable *&Base, 4780 ConstantRelocatable **Relocatable,
4775 Variable *&BaseOther, 4781 int32_t *Offset) {
4776 ConstantRelocatable *&Relocatable, int32_t &Offset,
4777 const Inst *&Reason) {
4778 // Base is Base=Var+Const || Base is Base=Const+Var ==> 4782 // Base is Base=Var+Const || Base is Base=Const+Var ==>
4779 // set Base=Var, Offset+=Const 4783 // set Base=Var, Offset+=Const
4780 // Base is Base=Var-Const ==> 4784 // Base is Base=Var-Const ==>
4781 // set Base=Var, Offset-=Const 4785 // set Base=Var, Offset-=Const
4782 if (Base == nullptr) { 4786 if (*Base == nullptr) {
4783 return false; 4787 return nullptr;
4784 } 4788 }
4785 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); 4789 const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
4786 if (BaseInst == nullptr) { 4790 if (BaseInst == nullptr) {
4787 return false; 4791 return nullptr;
4788 } 4792 }
4789 assert(!VMetadata->isMultiDef(Base)); 4793 assert(!VMetadata->isMultiDef(*Base));
4790 if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst)) { 4794 if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
4791 if (ArithInst->getOp() != InstArithmetic::Add && 4795 if (ArithInst->getOp() != InstArithmetic::Add &&
4792 ArithInst->getOp() != InstArithmetic::Sub) 4796 ArithInst->getOp() != InstArithmetic::Sub)
4793 return false; 4797 return nullptr;
4794 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; 4798 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
4795 Operand *Src0 = ArithInst->getSrc(0); 4799 Operand *Src0 = ArithInst->getSrc(0);
4796 Operand *Src1 = ArithInst->getSrc(1); 4800 Operand *Src1 = ArithInst->getSrc(1);
4797 auto *Var0 = llvm::dyn_cast<Variable>(Src0); 4801 auto *Var0 = llvm::dyn_cast<Variable>(Src0);
4798 auto *Var1 = llvm::dyn_cast<Variable>(Src1); 4802 auto *Var1 = llvm::dyn_cast<Variable>(Src1);
4799 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0); 4803 auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
4800 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1); 4804 auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
4801 auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0); 4805 auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0);
4802 auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1); 4806 auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1);
4803 Variable *NewBase = nullptr; 4807 Variable *NewBase = nullptr;
4804 int32_t NewOffset = Offset; 4808 int32_t NewOffset = *Offset;
4805 ConstantRelocatable *NewRelocatable = Relocatable; 4809 ConstantRelocatable *NewRelocatable = *Relocatable;
4806 if (Var0 && Var1) 4810 if (Var0 && Var1)
4807 // TODO(sehr): merge base/index splitting into here. 4811 // TODO(sehr): merge base/index splitting into here.
4808 return false; 4812 return nullptr;
4809 if (!IsAdd && Var1) 4813 if (!IsAdd && Var1)
4810 return false; 4814 return nullptr;
4811 if (Var0) 4815 if (Var0)
4812 NewBase = Var0; 4816 NewBase = Var0;
4813 else if (Var1) 4817 else if (Var1)
4814 NewBase = Var1; 4818 NewBase = Var1;
4815 // Don't know how to add/subtract two relocatables. 4819 // Don't know how to add/subtract two relocatables.
4816 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) 4820 if ((*Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
4817 return false; 4821 return nullptr;
4818 // Don't know how to subtract a relocatable. 4822 // Don't know how to subtract a relocatable.
4819 if (!IsAdd && Reloc1) 4823 if (!IsAdd && Reloc1)
4820 return false; 4824 return nullptr;
4821 // Incorporate ConstantRelocatables. 4825 // Incorporate ConstantRelocatables.
4822 if (Reloc0) 4826 if (Reloc0)
4823 NewRelocatable = Reloc0; 4827 NewRelocatable = Reloc0;
4824 else if (Reloc1) 4828 else if (Reloc1)
4825 NewRelocatable = Reloc1; 4829 NewRelocatable = Reloc1;
4826 if ((Reloc0 || Reloc1) && BaseOther && GotVar)
4827 return false;
4828 // Compute the updated constant offset. 4830 // Compute the updated constant offset.
4829 if (Const0) { 4831 if (Const0) {
4830 const int32_t MoreOffset = 4832 const int32_t MoreOffset =
4831 IsAdd ? Const0->getValue() : -Const0->getValue(); 4833 IsAdd ? Const0->getValue() : -Const0->getValue();
4832 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4834 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4833 return false; 4835 return nullptr;
4834 NewOffset += MoreOffset; 4836 NewOffset += MoreOffset;
4835 } 4837 }
4836 if (Const1) { 4838 if (Const1) {
4837 const int32_t MoreOffset = 4839 const int32_t MoreOffset =
4838 IsAdd ? Const1->getValue() : -Const1->getValue(); 4840 IsAdd ? Const1->getValue() : -Const1->getValue();
4839 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) 4841 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
4840 return false; 4842 return nullptr;
4841 NewOffset += MoreOffset; 4843 NewOffset += MoreOffset;
4842 } 4844 }
4843 // Update the computed address parameters once we are sure optimization 4845 *Base = NewBase;
4844 // is valid. 4846 *Offset = NewOffset;
4845 if ((Reloc0 || Reloc1) && GotVar) { 4847 *Relocatable = NewRelocatable;
4846 assert(BaseOther == nullptr); 4848 return BaseInst;
4847 BaseOther = GotVar;
4848 }
4849 Base = NewBase;
4850 Offset = NewOffset;
4851 Relocatable = NewRelocatable;
4852 Reason = BaseInst;
4853 return true;
4854 } 4849 }
4855 return false; 4850 return nullptr;
4856 } 4851 }
4857 4852
4858 // Builds information for a canonical address expresion: 4853 template <typename TypeTraits>
4859 // <Relocatable + Offset>(Base, Index, Shift) 4854 typename TargetX86Base<TypeTraits>::X86OperandMem *
4860 // On entry: 4855 TargetX86Base<TypeTraits>::computeAddressOpt(const Inst *Instr, Type MemType,
4861 // Relocatable == null, 4856 Operand *Addr) {
4862 // Offset == 0,
4863 // Base is a Variable,
4864 // Index == nullptr,
4865 // Shift == 0
4866 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar,
4867 bool ReserveSlot,
4868 ConstantRelocatable *&Relocatable,
4869 int32_t &Offset, Variable *&Base,
4870 Variable *&Index, uint16_t &Shift) {
4871 bool AddressWasOptimized = false;
4872 Func->resetCurrentNode(); 4857 Func->resetCurrentNode();
4873 if (Func->isVerbose(IceV_AddrOpt)) { 4858 if (Func->isVerbose(IceV_AddrOpt)) {
4874 OstreamLocker L(Func->getContext()); 4859 OstreamLocker L(Func->getContext());
4875 Ostream &Str = Func->getContext()->getStrDump(); 4860 Ostream &Str = Func->getContext()->getStrDump();
4876 Str << "\nStarting computeAddressOpt for instruction:\n "; 4861 Str << "\nStarting computeAddressOpt for instruction:\n ";
4877 Instr->dumpDecorated(Func); 4862 Instr->dumpDecorated(Func);
4878 } 4863 }
4879 if (Base == nullptr) 4864
4880 return AddressWasOptimized; 4865 OptAddr NewAddr;
4866 NewAddr.Base = llvm::dyn_cast<Variable>(Addr);
4867 if (NewAddr.Base == nullptr)
4868 return nullptr;
4869
4881 // If the Base has more than one use or is live across multiple blocks, then 4870 // If the Base has more than one use or is live across multiple blocks, then
4882 // don't go further. Alternatively (?), never consider a transformation that 4871 // don't go further. Alternatively (?), never consider a transformation that
4883 // would change a variable that is currently *not* live across basic block 4872 // would change a variable that is currently *not* live across basic block
4884 // boundaries into one that *is*. 4873 // boundaries into one that *is*.
4885 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/) 4874 if (Func->getVMetadata()->isMultiBlock(
4886 return AddressWasOptimized; 4875 NewAddr.Base) /* || Base->getUseCount() > 1*/)
4876 return nullptr;
4887 4877
4878 AddressOptimizer AddrOpt(Func);
4888 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); 4879 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
4889 const VariablesMetadata *VMetadata = Func->getVMetadata();
4890 const Inst *Reason = nullptr; 4880 const Inst *Reason = nullptr;
4881 bool AddressWasOptimized = false;
4882 // The following unnamed struct identifies the address mode formation steps
4883 // that could potentially create an invalid memory operand (i.e., no free
4884 // slots for SandboxPtr.) We add all those variables to this struct so that we
4885 // can use memset() to reset all members to false.
4886 struct {
4887 bool AssignBase = false;
4888 bool AssignIndex = false;
4889 bool OffsetFromBase = false;
4890 bool OffsetFromIndex = false;
4891 bool CombinedBaseIndex = false;
4892 } Skip;
4893 // This points to the boolean in Skip that represents the last folding
4894 // performed. This is used to disable a pattern match that generated an
4895 // invalid address. Without this, the algorithm would never finish.
4896 bool *SkipLastFolding = nullptr;
4897 // NewAddrCheckpoint is used to rollback the address being formed in case an
4898 // invalid address is formed.
4899 OptAddr NewAddrCheckpoint;
4900 Reason = Instr;
4891 do { 4901 do {
4892 assert(!ReserveSlot || Base == nullptr || Index == nullptr); 4902 if (SandboxingType != ST_None) {
4903 // When sandboxing, we defer the sandboxing of NewAddr to the Concrete
4904 // Target. If our optimization was overly aggressive, then we simply undo
4905 // what the previous iteration did, and set the previous pattern's skip
4906 // bit to true.
4907 if (!legalizeOptAddrForSandbox(&NewAddr)) {
4908 *SkipLastFolding = true;
4909 SkipLastFolding = nullptr;
4910 NewAddr = NewAddrCheckpoint;
4911 Reason = nullptr;
4912 }
4913 }
4914
4893 if (Reason) { 4915 if (Reason) {
4894 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); 4916 AddrOpt.dumpAddressOpt(NewAddr.Relocatable, NewAddr.Offset, NewAddr.Base,
4917 NewAddr.Index, NewAddr.Shift, Reason);
4895 AddressWasOptimized = true; 4918 AddressWasOptimized = true;
4896 Reason = nullptr; 4919 Reason = nullptr;
4920 SkipLastFolding = nullptr;
4921 memset(&Skip, 0, sizeof(Skip));
4897 } 4922 }
4923
4924 NewAddrCheckpoint = NewAddr;
4925
4898 // Update Base and Index to follow through assignments to definitions. 4926 // Update Base and Index to follow through assignments to definitions.
4899 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) { 4927 if (!Skip.AssignBase &&
4928 (Reason = AddrOpt.matchAssign(&NewAddr.Base, &NewAddr.Relocatable,
4929 &NewAddr.Offset))) {
4930 SkipLastFolding = &Skip.AssignBase;
4900 // Assignments of Base from a Relocatable or ConstantInt32 can result 4931 // Assignments of Base from a Relocatable or ConstantInt32 can result
4901 // in Base becoming nullptr. To avoid code duplication in this loop we 4932 // in Base becoming nullptr. To avoid code duplication in this loop we
4902 // prefer that Base be non-nullptr if possible. 4933 // prefer that Base be non-nullptr if possible.
4903 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) 4934 if ((NewAddr.Base == nullptr) && (NewAddr.Index != nullptr) &&
4904 std::swap(Base, Index); 4935 NewAddr.Shift == 0) {
4936 std::swap(NewAddr.Base, NewAddr.Index);
4937 }
4905 continue; 4938 continue;
4906 } 4939 }
4907 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason)) 4940 if (!Skip.AssignBase &&
4941 (Reason = AddrOpt.matchAssign(&NewAddr.Index, &NewAddr.Relocatable,
4942 &NewAddr.Offset))) {
4943 SkipLastFolding = &Skip.AssignIndex;
4908 continue; 4944 continue;
4945 }
4909 4946
4910 if (!MockBounds) { 4947 if (!MockBounds) {
4911 // Transition from: 4948 // Transition from:
4912 // <Relocatable + Offset>(Base) to 4949 // <Relocatable + Offset>(Base) to
4913 // <Relocatable + Offset>(Base, Index) 4950 // <Relocatable + Offset>(Base, Index)
4914 if (!ReserveSlot && 4951 if (!Skip.CombinedBaseIndex &&
4915 matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) 4952 (Reason = AddrOpt.matchCombinedBaseIndex(
4953 &NewAddr.Base, &NewAddr.Index, &NewAddr.Shift))) {
4954 SkipLastFolding = &Skip.CombinedBaseIndex;
4916 continue; 4955 continue;
4956 }
4957
4917 // Recognize multiply/shift and update Shift amount. 4958 // Recognize multiply/shift and update Shift amount.
4918 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> 4959 // Index becomes Index=Var<<Const && Const+Shift<=3 ==>
4919 // Index=Var, Shift+=Const 4960 // Index=Var, Shift+=Const
4920 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> 4961 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
4921 // Index=Var, Shift+=log2(Const) 4962 // Index=Var, Shift+=log2(Const)
4922 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) 4963 if ((Reason =
4964 AddrOpt.matchShiftedIndex(&NewAddr.Index, &NewAddr.Shift))) {
4923 continue; 4965 continue;
4966 }
4967
4924 // If Shift is zero, the choice of Base and Index was purely arbitrary. 4968 // If Shift is zero, the choice of Base and Index was purely arbitrary.
4925 // Recognize multiply/shift and set Shift amount. 4969 // Recognize multiply/shift and set Shift amount.
4926 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> 4970 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
4927 // swap(Index,Base) 4971 // swap(Index,Base)
4928 // Similar for Base=Const*Var and Base=Var<<Const 4972 // Similar for Base=Const*Var and Base=Var<<Const
4929 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { 4973 if (NewAddr.Shift == 0 &&
4930 std::swap(Base, Index); 4974 (Reason = AddrOpt.matchShiftedIndex(&NewAddr.Base, &NewAddr.Shift))) {
4975 std::swap(NewAddr.Base, NewAddr.Index);
4931 continue; 4976 continue;
4932 } 4977 }
4933 } 4978 }
4979
4934 // Update Offset to reflect additions/subtractions with constants and 4980 // Update Offset to reflect additions/subtractions with constants and
4935 // relocatables. 4981 // relocatables.
4936 // TODO: consider overflow issues with respect to Offset. 4982 // TODO: consider overflow issues with respect to Offset.
4937 if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset, 4983 if (!Skip.OffsetFromBase &&
4938 Reason)) 4984 (Reason = AddrOpt.matchOffsetBase(&NewAddr.Base, &NewAddr.Relocatable,
4985 &NewAddr.Offset))) {
4986 SkipLastFolding = &Skip.OffsetFromBase;
4939 continue; 4987 continue;
4940 if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base, 4988 }
4941 Relocatable, Offset, Reason)) 4989 if (NewAddr.Shift == 0 && !Skip.OffsetFromIndex &&
4990 (Reason = AddrOpt.matchOffsetBase(&NewAddr.Index, &NewAddr.Relocatable,
4991 &NewAddr.Offset))) {
4992 SkipLastFolding = &Skip.OffsetFromIndex;
4942 continue; 4993 continue;
4994 }
4995
4943 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. 4996 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0.
4944 // Index is Index=Var+Const ==> 4997 // Index is Index=Var+Const ==>
4945 // set Index=Var, Offset+=(Const<<Shift) 4998 // set Index=Var, Offset+=(Const<<Shift)
4946 // Index is Index=Const+Var ==> 4999 // Index is Index=Const+Var ==>
4947 // set Index=Var, Offset+=(Const<<Shift) 5000 // set Index=Var, Offset+=(Const<<Shift)
4948 // Index is Index=Var-Const ==> 5001 // Index is Index=Var-Const ==>
4949 // set Index=Var, Offset-=(Const<<Shift) 5002 // set Index=Var, Offset-=(Const<<Shift)
4950 break; 5003 break;
4951 } while (Reason); 5004 } while (Reason);
4952 // Undo any addition of GotVar. It will be added back when the mem operand is 5005
4953 // legalized. 5006 if (!AddressWasOptimized) {
4954 if (Base == GotVar) 5007 return nullptr;
4955 Base = nullptr; 5008 }
4956 if (Index == GotVar) 5009
4957 Index = nullptr; 5010 // Undo any addition of SandboxPtr. It will be added back when the mem
4958 return AddressWasOptimized; 5011 // operand is sandboxed.
5012 if (NewAddr.Base == SandboxPtr) {
5013 NewAddr.Base = nullptr;
5014 }
5015
5016 if (NewAddr.Index == SandboxPtr) {
5017 NewAddr.Index = nullptr;
5018 NewAddr.Shift = 0;
5019 }
5020
5021 Constant *OffsetOp = nullptr;
5022 if (NewAddr.Relocatable == nullptr) {
5023 OffsetOp = Ctx->getConstantInt32(NewAddr.Offset);
5024 } else {
5025 OffsetOp =
5026 Ctx->getConstantSym(NewAddr.Relocatable->getOffset() + NewAddr.Offset,
5027 NewAddr.Relocatable->getName(),
5028 NewAddr.Relocatable->getSuppressMangling());
5029 }
5030 // Vanilla ICE load instructions should not use the segment registers, and
5031 // computeAddressOpt only works at the level of Variables and Constants, not
5032 // other X86OperandMem, so there should be no mention of segment
5033 // registers there either.
5034 static constexpr auto SegmentReg =
5035 X86OperandMem::SegmentRegisters::DefaultSegment;
5036
5037 return X86OperandMem::create(Func, MemType, NewAddr.Base, OffsetOp,
5038 NewAddr.Index, NewAddr.Shift, SegmentReg);
4959 } 5039 }
4960 5040
4961 /// Add a mock bounds check on the memory address before using it as a load or 5041 /// Add a mock bounds check on the memory address before using it as a load or
4962 /// store operand. The basic idea is that given a memory operand [reg], we 5042 /// store operand. The basic idea is that given a memory operand [reg], we
4963 /// would first add bounds-check code something like: 5043 /// would first add bounds-check code something like:
4964 /// 5044 ///
4965 /// cmp reg, <lb> 5045 /// cmp reg, <lb>
4966 /// jl out_of_line_error 5046 /// jl out_of_line_error
4967 /// cmp reg, <ub> 5047 /// cmp reg, <ub>
4968 /// jg out_of_line_error 5048 /// jg out_of_line_error
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5026 Type Ty = DestLoad->getType(); 5106 Type Ty = DestLoad->getType();
5027 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); 5107 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty);
5028 doMockBoundsCheck(Src0); 5108 doMockBoundsCheck(Src0);
5029 auto *Assign = InstAssign::create(Func, DestLoad, Src0); 5109 auto *Assign = InstAssign::create(Func, DestLoad, Src0);
5030 lowerAssign(Assign); 5110 lowerAssign(Assign);
5031 } 5111 }
5032 5112
5033 template <typename TraitsType> 5113 template <typename TraitsType>
5034 void TargetX86Base<TraitsType>::doAddressOptLoad() { 5114 void TargetX86Base<TraitsType>::doAddressOptLoad() {
5035 Inst *Inst = Context.getCur(); 5115 Inst *Inst = Context.getCur();
5116 Operand *Addr = Inst->getSrc(0);
5036 Variable *Dest = Inst->getDest(); 5117 Variable *Dest = Inst->getDest();
5037 Operand *Addr = Inst->getSrc(0); 5118 if (auto *OptAddr = computeAddressOpt(Inst, Dest->getType(), Addr)) {
5038 Variable *Index = nullptr;
5039 ConstantRelocatable *Relocatable = nullptr;
5040 uint16_t Shift = 0;
5041 int32_t Offset = 0;
5042 // Vanilla ICE load instructions should not use the segment registers, and
5043 // computeAddressOpt only works at the level of Variables and Constants, not
5044 // other X86OperandMem, so there should be no mention of segment
5045 // registers there either.
5046 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
5047 auto *Base = llvm::dyn_cast<Variable>(Addr);
5048 const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
5049 if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
5050 Base, Index, Shift)) {
5051 Inst->setDeleted(); 5119 Inst->setDeleted();
5052 Constant *OffsetOp = nullptr; 5120 Context.insert<InstLoad>(Dest, OptAddr);
5053 if (Relocatable == nullptr) {
5054 OffsetOp = Ctx->getConstantInt32(Offset);
5055 } else {
5056 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
5057 Relocatable->getName(),
5058 Relocatable->getSuppressMangling());
5059 }
5060 // The new mem operand is created without IsRebased being set, because
5061 // computeAddressOpt() doesn't include GotVar in its final result.
5062 Addr = X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Index,
5063 Shift, SegmentReg);
5064 Context.insert<InstLoad>(Dest, Addr);
5065 } 5121 }
5066 } 5122 }
5067 5123
5068 template <typename TraitsType> 5124 template <typename TraitsType>
5069 void TargetX86Base<TraitsType>::randomlyInsertNop(float Probability, 5125 void TargetX86Base<TraitsType>::randomlyInsertNop(float Probability,
5070 RandomNumberGenerator &RNG) { 5126 RandomNumberGenerator &RNG) {
5071 RandomNumberGeneratorWrapper RNGW(RNG); 5127 RandomNumberGeneratorWrapper RNGW(RNG);
5072 if (RNGW.getTrueWithProbability(Probability)) { 5128 if (RNGW.getTrueWithProbability(Probability)) {
5073 _nop(RNGW(Traits::X86_NUM_NOP_VARIANTS)); 5129 _nop(RNGW(Traits::X86_NUM_NOP_VARIANTS));
5074 } 5130 }
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
5351 _storep(legalizeToReg(Value), NewAddr); 5407 _storep(legalizeToReg(Value), NewAddr);
5352 } else { 5408 } else {
5353 Value = legalize(Value, Legal_Reg | Legal_Imm); 5409 Value = legalize(Value, Legal_Reg | Legal_Imm);
5354 _store(Value, NewAddr); 5410 _store(Value, NewAddr);
5355 } 5411 }
5356 } 5412 }
5357 5413
5358 template <typename TraitsType> 5414 template <typename TraitsType>
5359 void TargetX86Base<TraitsType>::doAddressOptStore() { 5415 void TargetX86Base<TraitsType>::doAddressOptStore() {
5360 auto *Inst = llvm::cast<InstStore>(Context.getCur()); 5416 auto *Inst = llvm::cast<InstStore>(Context.getCur());
5417 Operand *Addr = Inst->getAddr();
5361 Operand *Data = Inst->getData(); 5418 Operand *Data = Inst->getData();
5362 Operand *Addr = Inst->getAddr(); 5419 if (auto *OptAddr = computeAddressOpt(Inst, Data->getType(), Addr)) {
5363 Variable *Index = nullptr;
5364 ConstantRelocatable *Relocatable = nullptr;
5365 uint16_t Shift = 0;
5366 int32_t Offset = 0;
5367 auto *Base = llvm::dyn_cast<Variable>(Addr);
5368 // Vanilla ICE store instructions should not use the segment registers, and
5369 // computeAddressOpt only works at the level of Variables and Constants, not
5370 // other X86OperandMem, so there should be no mention of segment
5371 // registers there either.
5372 constexpr auto SegmentReg = X86OperandMem::SegmentRegisters::DefaultSegment;
5373 const bool ReserveSlot = Traits::Is64Bit && NeedSandboxing;
5374 if (computeAddressOpt(Func, Inst, GotVar, ReserveSlot, Relocatable, Offset,
5375 Base, Index, Shift)) {
5376 Inst->setDeleted(); 5420 Inst->setDeleted();
5377 Constant *OffsetOp = nullptr; 5421 auto *NewStore = Context.insert<InstStore>(Data, OptAddr);
5378 if (Relocatable == nullptr) {
5379 OffsetOp = Ctx->getConstantInt32(Offset);
5380 } else {
5381 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
5382 Relocatable->getName(),
5383 Relocatable->getSuppressMangling());
5384 }
5385 // The new mem operand is created without IsRebased being set, because
5386 // computeAddressOpt() doesn't include GotVar in its final result.
5387 Addr = X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Index,
5388 Shift, SegmentReg);
5389 auto *NewStore = Context.insert<InstStore>(Data, Addr);
5390 if (Inst->getDest()) 5422 if (Inst->getDest())
5391 NewStore->setRmwBeacon(Inst->getRmwBeacon()); 5423 NewStore->setRmwBeacon(Inst->getRmwBeacon());
5392 } 5424 }
5393 } 5425 }
5394 5426
5395 template <typename TraitsType> 5427 template <typename TraitsType>
5396 Operand *TargetX86Base<TraitsType>::lowerCmpRange(Operand *Comparison, 5428 Operand *TargetX86Base<TraitsType>::lowerCmpRange(Operand *Comparison,
5397 uint64_t Min, uint64_t Max) { 5429 uint64_t Min, uint64_t Max) {
5398 // TODO(ascull): 64-bit should not reach here but only because it is not 5430 // TODO(ascull): 64-bit should not reach here but only because it is not
5399 // implemented yet. This should be able to handle the 64-bit case. 5431 // implemented yet. This should be able to handle the 64-bit case.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
5439 const Type PointerType = getPointerType(); 5471 const Type PointerType = getPointerType();
5440 if (RangeIndex->getType() != PointerType) { 5472 if (RangeIndex->getType() != PointerType) {
5441 Index = makeReg(PointerType); 5473 Index = makeReg(PointerType);
5442 _movzx(Index, RangeIndex); 5474 _movzx(Index, RangeIndex);
5443 } else { 5475 } else {
5444 Index = legalizeToReg(RangeIndex); 5476 Index = legalizeToReg(RangeIndex);
5445 } 5477 }
5446 5478
5447 constexpr RelocOffsetT RelocOffset = 0; 5479 constexpr RelocOffsetT RelocOffset = 0;
5448 constexpr bool SuppressMangling = true; 5480 constexpr bool SuppressMangling = true;
5449 const bool IsRebased = Ctx->getFlags().getUseNonsfi();
5450 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); 5481 IceString MangledName = Ctx->mangleName(Func->getFunctionName());
5451 Variable *Base = IsRebased ? legalizeToReg(GotVar) : nullptr; 5482 constexpr Variable *NoBase = nullptr;
5452 Constant *Offset = Ctx->getConstantSym( 5483 Constant *Offset = Ctx->getConstantSym(
5453 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), 5484 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()),
5454 SuppressMangling); 5485 SuppressMangling);
5455 uint16_t Shift = typeWidthInBytesLog2(PointerType); 5486 uint16_t Shift = typeWidthInBytesLog2(PointerType);
5456 constexpr auto Segment = X86OperandMem::SegmentRegisters::DefaultSegment; 5487 constexpr auto Segment = X86OperandMem::SegmentRegisters::DefaultSegment;
5457 5488
5458 Variable *Target = nullptr; 5489 Variable *Target = nullptr;
5459 if (Traits::Is64Bit && NeedSandboxing) { 5490 if (Traits::Is64Bit && NeedSandboxing) {
5460 assert(Base == nullptr);
5461 assert(Index != nullptr && Index->getType() == IceType_i32); 5491 assert(Index != nullptr && Index->getType() == IceType_i32);
5462 } 5492 }
5463 auto *TargetInMemory = X86OperandMem::create( 5493 auto *TargetInMemory = X86OperandMem::create(Func, PointerType, NoBase,
5464 Func, PointerType, Base, Offset, Index, Shift, Segment, IsRebased); 5494 Offset, Index, Shift, Segment);
5465 _mov(Target, TargetInMemory); 5495 _mov(Target, TargetInMemory);
5466 5496
5467 lowerIndirectJump(Target); 5497 lowerIndirectJump(Target);
5468 5498
5469 if (DefaultTarget == nullptr) 5499 if (DefaultTarget == nullptr)
5470 Context.insert(SkipJumpTable); 5500 Context.insert(SkipJumpTable);
5471 return; 5501 return;
5472 } 5502 }
5473 case CaseCluster::Range: { 5503 case CaseCluster::Range: {
5474 if (Case.isUnitRange()) { 5504 if (Case.isUnitRange()) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
5781 if (const auto *RMW = llvm::dyn_cast<InstX86FakeRMW>(Instr)) { 5811 if (const auto *RMW = llvm::dyn_cast<InstX86FakeRMW>(Instr)) {
5782 lowerRMW(RMW); 5812 lowerRMW(RMW);
5783 } else { 5813 } else {
5784 TargetLowering::lowerOther(Instr); 5814 TargetLowering::lowerOther(Instr);
5785 } 5815 }
5786 } 5816 }
5787 5817
5788 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve 5818 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve
5789 /// integrity of liveness analysis. Undef values are also turned into zeroes, 5819 /// integrity of liveness analysis. Undef values are also turned into zeroes,
5790 /// since loOperand() and hiOperand() don't expect Undef input. Also, in 5820 /// since loOperand() and hiOperand() don't expect Undef input. Also, in
5791 /// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand. 5821 /// Non-SFI mode, add a FakeUse(SandboxPtr) for every pooled constant operand.
5792 template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() { 5822 template <typename TraitsType> void TargetX86Base<TraitsType>::prelowerPhis() {
5793 if (Ctx->getFlags().getUseNonsfi()) { 5823 if (Ctx->getFlags().getUseNonsfi()) {
5794 assert(GotVar); 5824 assert(SandboxPtr);
5795 CfgNode *Node = Context.getNode(); 5825 CfgNode *Node = Context.getNode();
5796 uint32_t GotVarUseCount = 0; 5826 uint32_t SandboxPtrUseCount = 0;
5797 for (Inst &I : Node->getPhis()) { 5827 for (Inst &I : Node->getPhis()) {
5798 auto *Phi = llvm::dyn_cast<InstPhi>(&I); 5828 auto *Phi = llvm::dyn_cast<InstPhi>(&I);
5799 if (Phi->isDeleted()) 5829 if (Phi->isDeleted())
5800 continue; 5830 continue;
5801 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { 5831 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) {
5802 Operand *Src = Phi->getSrc(I); 5832 Operand *Src = Phi->getSrc(I);
5803 // TODO(stichnot): This over-counts for +0.0, and under-counts for other 5833 // TODO(stichnot): This over-counts for +0.0, and under-counts for other
5804 // kinds of pooling. 5834 // kinds of pooling.
5805 if (llvm::isa<ConstantRelocatable>(Src) || 5835 if (llvm::isa<ConstantRelocatable>(Src) ||
5806 llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) { 5836 llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) {
5807 ++GotVarUseCount; 5837 ++SandboxPtrUseCount;
5808 } 5838 }
5809 } 5839 }
5810 } 5840 }
5811 if (GotVarUseCount) { 5841 if (SandboxPtrUseCount) {
5812 Node->getInsts().push_front(InstFakeUse::create(Func, GotVar)); 5842 Node->getInsts().push_front(InstFakeUse::create(Func, SandboxPtr));
5813 } 5843 }
5814 } 5844 }
5815 if (Traits::Is64Bit) { 5845 if (Traits::Is64Bit) {
5816 // On x86-64 we don't need to prelower phis -- the architecture can handle 5846 // On x86-64 we don't need to prelower phis -- the architecture can handle
5817 // 64-bit integer natively. 5847 // 64-bit integer natively.
5818 return; 5848 return;
5819 } 5849 }
5820 5850
5821 // Pause constant blinding or pooling, blinding or pooling will be done later 5851 // Pause constant blinding or pooling, blinding or pooling will be done later
5822 // during phi lowering assignments 5852 // during phi lowering assignments
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
6350 if (Base) { 6380 if (Base) {
6351 RegBase = llvm::cast<Variable>( 6381 RegBase = llvm::cast<Variable>(
6352 legalize(Base, Legal_Reg | Legal_Rematerializable)); 6382 legalize(Base, Legal_Reg | Legal_Rematerializable));
6353 } 6383 }
6354 if (Index) { 6384 if (Index) {
6355 // TODO(jpp): perhaps we should only allow Legal_Reg if 6385 // TODO(jpp): perhaps we should only allow Legal_Reg if
6356 // Base->isRematerializable. 6386 // Base->isRematerializable.
6357 RegIndex = llvm::cast<Variable>( 6387 RegIndex = llvm::cast<Variable>(
6358 legalize(Index, Legal_Reg | Legal_Rematerializable)); 6388 legalize(Index, Legal_Reg | Legal_Rematerializable));
6359 } 6389 }
6360 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we 6390
6361 // replace either Base or Index with a legalized GotVar. At emission time,
6362 // the ConstantRelocatable will be emitted with the @GOTOFF relocation.
6363 bool IsRebased = false;
6364 if (UseNonsfi && !Mem->getIsRebased() && Offset &&
6365 llvm::isa<ConstantRelocatable>(Offset)) {
6366 assert(!(Allowed & Legal_AddrAbs));
6367 IsRebased = true;
6368 if (RegBase == nullptr) {
6369 RegBase = legalizeToReg(GotVar);
6370 } else if (RegIndex == nullptr) {
6371 RegIndex = legalizeToReg(GotVar);
6372 } else {
6373 llvm::report_fatal_error(
6374 "Either Base or Index must be unused in Non-SFI mode");
6375 }
6376 }
6377 if (Base != RegBase || Index != RegIndex) { 6391 if (Base != RegBase || Index != RegIndex) {
6378 Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, Shift, 6392 Mem = X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, Shift,
6379 Mem->getSegmentRegister(), IsRebased); 6393 Mem->getSegmentRegister());
6380 } 6394 }
6381 6395
6382 // For all Memory Operands, we do randomization/pooling here 6396 // For all Memory Operands, we do randomization/pooling here.
6383 From = randomizeOrPoolImmediate(Mem); 6397 From = randomizeOrPoolImmediate(Mem);
6384 6398
6385 if (!(Allowed & Legal_Mem)) { 6399 if (!(Allowed & Legal_Mem)) {
6386 From = copyToReg(From, RegNum); 6400 From = copyToReg(From, RegNum);
6387 } 6401 }
6388 return From; 6402 return From;
6389 } 6403 }
6390 6404
6391 if (auto *Const = llvm::dyn_cast<Constant>(From)) { 6405 if (auto *Const = llvm::dyn_cast<Constant>(From)) {
6392 if (llvm::isa<ConstantUndef>(Const)) { 6406 if (llvm::isa<ConstantUndef>(Const)) {
(...skipping 18 matching lines...) Expand all
6411 6425
6412 // If the operand is an 32 bit constant integer, we should check whether we 6426 // If the operand is an 32 bit constant integer, we should check whether we
6413 // need to randomize it or pool it. 6427 // need to randomize it or pool it.
6414 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { 6428 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) {
6415 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); 6429 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum);
6416 if (NewConst != Const) { 6430 if (NewConst != Const) {
6417 return NewConst; 6431 return NewConst;
6418 } 6432 }
6419 } 6433 }
6420 6434
6421 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
6422 // specified, and UseNonsfi is indicated, we need to add GotVar.
6423 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) { 6435 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) {
6436 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not
6437 // specified, and UseNonsfi is indicated, we need to add SandboxPtr.
6424 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) { 6438 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) {
6425 assert(Ty == IceType_i32); 6439 assert(Ty == IceType_i32);
6426 Variable *RegBase = legalizeToReg(GotVar);
6427 Variable *NewVar = makeReg(Ty, RegNum); 6440 Variable *NewVar = makeReg(Ty, RegNum);
6428 static constexpr bool IsRebased = true; 6441 auto *Mem = Traits::X86OperandMem::create(Func, Ty, nullptr, CR);
6429 auto *Mem = 6442 // LEAs are not automatically sandboxed, thus we explicitly invoke
6430 Traits::X86OperandMem::create(Func, Ty, RegBase, CR, IsRebased); 6443 // _sandbox_mem_reference.
6431 _lea(NewVar, Mem); 6444 _lea(NewVar, _sandbox_mem_reference(Mem));
6432 From = NewVar; 6445 From = NewVar;
6433 } 6446 }
6434 } 6447 } else if (isScalarFloatingType(Ty)) {
6435 6448 // Convert a scalar floating point constant into an explicit memory
6436 // Convert a scalar floating point constant into an explicit memory 6449 // operand.
6437 // operand.
6438 if (isScalarFloatingType(Ty)) {
6439 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { 6450 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) {
6440 if (Utils::isPositiveZero(ConstFloat->getValue())) 6451 if (Utils::isPositiveZero(ConstFloat->getValue()))
6441 return makeZeroedRegister(Ty, RegNum); 6452 return makeZeroedRegister(Ty, RegNum);
6442 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { 6453 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) {
6443 if (Utils::isPositiveZero(ConstDouble->getValue())) 6454 if (Utils::isPositiveZero(ConstDouble->getValue()))
6444 return makeZeroedRegister(Ty, RegNum); 6455 return makeZeroedRegister(Ty, RegNum);
6445 } 6456 }
6446 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; 6457
6447 std::string Buffer; 6458 std::string Buffer;
6448 llvm::raw_string_ostream StrBuf(Buffer); 6459 llvm::raw_string_ostream StrBuf(Buffer);
6449 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 6460 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
6450 llvm::cast<Constant>(From)->setShouldBePooled(true); 6461 llvm::cast<Constant>(From)->setShouldBePooled(true);
6451 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 6462 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
6452 const bool IsRebased = Base != nullptr; 6463 auto *Mem = X86OperandMem::create(Func, Ty, nullptr, Offset);
6453 auto *Mem = X86OperandMem::create(Func, Ty, Base, Offset, IsRebased);
6454 From = Mem; 6464 From = Mem;
6455 } 6465 }
6466
6456 bool NeedsReg = false; 6467 bool NeedsReg = false;
6457 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) 6468 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty))
6458 // Immediate specifically not allowed 6469 // Immediate specifically not allowed.
6459 NeedsReg = true; 6470 NeedsReg = true;
6460 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) 6471 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty))
6461 // On x86, FP constants are lowered to mem operands. 6472 // On x86, FP constants are lowered to mem operands.
6462 NeedsReg = true; 6473 NeedsReg = true;
6463 if (NeedsReg) { 6474 if (NeedsReg) {
6464 From = copyToReg(From, RegNum); 6475 From = copyToReg(From, RegNum);
6465 } 6476 }
6466 return From; 6477 return From;
6467 } 6478 }
6468 6479
(...skipping 12 matching lines...) Expand all
6481 if (MustRematerialize) { 6492 if (MustRematerialize) {
6482 assert(Ty == IceType_i32); 6493 assert(Ty == IceType_i32);
6483 Variable *NewVar = makeReg(Ty, RegNum); 6494 Variable *NewVar = makeReg(Ty, RegNum);
6484 // Since Var is rematerializable, the offset will be added when the lea is 6495 // Since Var is rematerializable, the offset will be added when the lea is
6485 // emitted. 6496 // emitted.
6486 constexpr Constant *NoOffset = nullptr; 6497 constexpr Constant *NoOffset = nullptr;
6487 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset); 6498 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset);
6488 _lea(NewVar, Mem); 6499 _lea(NewVar, Mem);
6489 From = NewVar; 6500 From = NewVar;
6490 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || 6501 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
6491 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || 6502 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
6492 MustRematerialize) {
6493 From = copyToReg(From, RegNum); 6503 From = copyToReg(From, RegNum);
6494 } 6504 }
6495 return From; 6505 return From;
6496 } 6506 }
6497 6507
6498 llvm::report_fatal_error("Unhandled operand kind in legalize()"); 6508 llvm::report_fatal_error("Unhandled operand kind in legalize()");
6499 return From; 6509 return From;
6500 } 6510 }
6501 6511
6502 /// Provide a trivial wrapper to legalize() for this common usage. 6512 /// Provide a trivial wrapper to legalize() for this common usage.
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
6762 // assigned register as this assignment is that start of its use-def 6772 // assigned register as this assignment is that start of its use-def
6763 // chain. So we add RegNum argument here. 6773 // chain. So we add RegNum argument here.
6764 Variable *Reg = makeReg(Immediate->getType(), RegNum); 6774 Variable *Reg = makeReg(Immediate->getType(), RegNum);
6765 IceString Label; 6775 IceString Label;
6766 llvm::raw_string_ostream Label_stream(Label); 6776 llvm::raw_string_ostream Label_stream(Label);
6767 Immediate->emitPoolLabel(Label_stream, Ctx); 6777 Immediate->emitPoolLabel(Label_stream, Ctx);
6768 constexpr RelocOffsetT Offset = 0; 6778 constexpr RelocOffsetT Offset = 0;
6769 constexpr bool SuppressMangling = true; 6779 constexpr bool SuppressMangling = true;
6770 Constant *Symbol = 6780 Constant *Symbol =
6771 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); 6781 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
6772 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); 6782 constexpr Variable *NoBase = nullptr;
6773 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; 6783 X86OperandMem *MemOperand =
6774 const bool IsRebased = Base != nullptr; 6784 X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol);
6775 X86OperandMem *MemOperand = X86OperandMem::create(
6776 Func, Immediate->getType(), Base, Symbol, IsRebased);
6777 _mov(Reg, MemOperand); 6785 _mov(Reg, MemOperand);
6778 return Reg; 6786 return Reg;
6779 } 6787 }
6780 } 6788 }
6781 } 6789 }
6782 6790
6783 template <typename TraitsType> 6791 template <typename TraitsType>
6784 typename TargetX86Base<TraitsType>::X86OperandMem * 6792 typename TargetX86Base<TraitsType>::X86OperandMem *
6785 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, 6793 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand,
6786 int32_t RegNum) { 6794 int32_t RegNum) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
6872 return MemOperand; 6880 return MemOperand;
6873 Variable *RegTemp = makeReg(IceType_i32); 6881 Variable *RegTemp = makeReg(IceType_i32);
6874 IceString Label; 6882 IceString Label;
6875 llvm::raw_string_ostream Label_stream(Label); 6883 llvm::raw_string_ostream Label_stream(Label);
6876 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); 6884 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx);
6877 MemOperand->getOffset()->setShouldBePooled(true); 6885 MemOperand->getOffset()->setShouldBePooled(true);
6878 constexpr RelocOffsetT SymOffset = 0; 6886 constexpr RelocOffsetT SymOffset = 0;
6879 constexpr bool SuppressMangling = true; 6887 constexpr bool SuppressMangling = true;
6880 Constant *Symbol = 6888 Constant *Symbol =
6881 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); 6889 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling);
6882 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); 6890 constexpr Variable *NoBase = nullptr;
6883 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr;
6884 const bool IsRebased = Base != nullptr;
6885 X86OperandMem *SymbolOperand = X86OperandMem::create( 6891 X86OperandMem *SymbolOperand = X86OperandMem::create(
6886 Func, MemOperand->getOffset()->getType(), Base, Symbol, IsRebased); 6892 Func, MemOperand->getOffset()->getType(), NoBase, Symbol);
6887 _mov(RegTemp, SymbolOperand); 6893 _mov(RegTemp, SymbolOperand);
6888 // If we have a base variable here, we should add the lea instruction 6894 // If we have a base variable here, we should add the lea instruction
6889 // to add the value of the base variable to RegTemp. If there is no 6895 // to add the value of the base variable to RegTemp. If there is no
6890 // base variable, we won't need this lea instruction. 6896 // base variable, we won't need this lea instruction.
6891 if (MemOperand->getBase()) { 6897 if (MemOperand->getBase()) {
6892 X86OperandMem *CalculateOperand = X86OperandMem::create( 6898 X86OperandMem *CalculateOperand = X86OperandMem::create(
6893 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, RegTemp, 6899 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, RegTemp,
6894 0, MemOperand->getSegmentRegister()); 6900 0, MemOperand->getSegmentRegister());
6895 _lea(RegTemp, CalculateOperand); 6901 _lea(RegTemp, CalculateOperand);
6896 } 6902 }
6897 X86OperandMem *NewMemOperand = X86OperandMem::create( 6903 X86OperandMem *NewMemOperand = X86OperandMem::create(
6898 Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(), 6904 Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(),
6899 MemOperand->getShift(), MemOperand->getSegmentRegister()); 6905 MemOperand->getShift(), MemOperand->getSegmentRegister());
6900 return NewMemOperand; 6906 return NewMemOperand;
6901 } 6907 }
6902 } 6908 }
6903 } 6909 }
6904 } // end of namespace X86NAMESPACE 6910 } // end of namespace X86NAMESPACE
6905 } // end of namespace Ice 6911 } // end of namespace Ice
6906 6912
6907 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H 6913 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H
OLDNEW
« src/IceTargetLoweringX86Base.h ('K') | « src/IceTargetLoweringX86Base.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698