| 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 4497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4508 } | 4508 } |
| 4509 | 4509 |
| 4510 _cmp(Comparison, Ctx->getConstantInt32(Max - Min)); | 4510 _cmp(Comparison, Ctx->getConstantInt32(Max - Min)); |
| 4511 | 4511 |
| 4512 return Comparison; | 4512 return Comparison; |
| 4513 } | 4513 } |
| 4514 | 4514 |
| 4515 template <class Machine> | 4515 template <class Machine> |
| 4516 void TargetX86Base<Machine>::lowerCaseCluster(const CaseCluster &Case, | 4516 void TargetX86Base<Machine>::lowerCaseCluster(const CaseCluster &Case, |
| 4517 Operand *Comparison, bool DoneCmp, | 4517 Operand *Comparison, bool DoneCmp, |
| 4518 CfgNode *DefaultLabel) { | 4518 CfgNode *DefaultTarget) { |
| 4519 switch (Case.getKind()) { | 4519 switch (Case.getKind()) { |
| 4520 case CaseCluster::JumpTable: { | 4520 case CaseCluster::JumpTable: { |
| 4521 typename Traits::Insts::Label *SkipJumpTable; | 4521 typename Traits::Insts::Label *SkipJumpTable; |
| 4522 | 4522 |
| 4523 Operand *RangeIndex = | 4523 Operand *RangeIndex = |
| 4524 lowerCmpRange(Comparison, Case.getLow(), Case.getHigh()); | 4524 lowerCmpRange(Comparison, Case.getLow(), Case.getHigh()); |
| 4525 if (DefaultLabel != nullptr) { | 4525 if (DefaultTarget == nullptr) { |
| 4526 _br(Traits::Cond::Br_a, DefaultLabel); | |
| 4527 } else { | |
| 4528 // Skip over jump table logic if comparison not in range and no default | 4526 // Skip over jump table logic if comparison not in range and no default |
| 4529 SkipJumpTable = Traits::Insts::Label::create(Func, this); | 4527 SkipJumpTable = Traits::Insts::Label::create(Func, this); |
| 4530 _br(Traits::Cond::Br_a, SkipJumpTable); | 4528 _br(Traits::Cond::Br_a, SkipJumpTable); |
| 4529 } else { |
| 4530 _br(Traits::Cond::Br_a, DefaultTarget); |
| 4531 } | 4531 } |
| 4532 | 4532 |
| 4533 InstJumpTable *JumpTable = Case.getJumpTable(); | 4533 InstJumpTable *JumpTable = Case.getJumpTable(); |
| 4534 Context.insert(JumpTable); | 4534 Context.insert(JumpTable); |
| 4535 | 4535 |
| 4536 // Make sure the index is a register of the same width as the base | 4536 // Make sure the index is a register of the same width as the base |
| 4537 Variable *Index; | 4537 Variable *Index; |
| 4538 if (RangeIndex->getType() != getPointerType()) { | 4538 if (RangeIndex->getType() != getPointerType()) { |
| 4539 Index = makeReg(getPointerType()); | 4539 Index = makeReg(getPointerType()); |
| 4540 _movzx(Index, RangeIndex); | 4540 _movzx(Index, RangeIndex); |
| 4541 } else { | 4541 } else { |
| 4542 Index = legalizeToReg(RangeIndex); | 4542 Index = legalizeToReg(RangeIndex); |
| 4543 } | 4543 } |
| 4544 | 4544 |
| 4545 constexpr RelocOffsetT RelocOffset = 0; | 4545 constexpr RelocOffsetT RelocOffset = 0; |
| 4546 constexpr bool SuppressMangling = true; | 4546 constexpr bool SuppressMangling = true; |
| 4547 Constant *Base = Ctx->getConstantSym(RelocOffset, JumpTable->getName(Func), | 4547 Constant *Base = Ctx->getConstantSym(RelocOffset, JumpTable->getName(Func), |
| 4548 SuppressMangling); | 4548 SuppressMangling); |
| 4549 Constant *Offset = nullptr; | 4549 Constant *Offset = nullptr; |
| 4550 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); | 4550 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); |
| 4551 // TODO(ascull): remove need for legalize by allowing null base in memop | 4551 // TODO(ascull): remove need for legalize by allowing null base in memop |
| 4552 auto *MemTarget = Traits::X86OperandMem::create( | 4552 auto *TargetInMemory = Traits::X86OperandMem::create( |
| 4553 Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); | 4553 Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); |
| 4554 Variable *Target = nullptr; | 4554 Variable *Target = nullptr; |
| 4555 _mov(Target, MemTarget); | 4555 _mov(Target, TargetInMemory); |
| 4556 |
| 4557 // Sandbox the indirect jump |
| 4558 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| 4559 if (NeedSandboxing) { |
| 4560 _bundle_lock(); |
| 4561 const SizeT BundleSize = |
| 4562 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
| 4563 _and(Target, Ctx->getConstantInt32(~(BundleSize - 1))); |
| 4564 } |
| 4556 _jmp(Target); | 4565 _jmp(Target); |
| 4557 // TODO(ascull): sandboxing for indirect jump | 4566 if (NeedSandboxing) |
| 4567 _bundle_unlock(); |
| 4558 | 4568 |
| 4559 if (DefaultLabel == nullptr) | 4569 if (DefaultTarget == nullptr) |
| 4560 Context.insert(SkipJumpTable); | 4570 Context.insert(SkipJumpTable); |
| 4561 return; | 4571 return; |
| 4562 } | 4572 } |
| 4563 case CaseCluster::Range: { | 4573 case CaseCluster::Range: { |
| 4564 if (Case.getHigh() == Case.getLow()) { | 4574 if (Case.isUnitRange()) { |
| 4565 // Single item | 4575 // Single item |
| 4566 Constant *Value = Ctx->getConstantInt32(Case.getLow()); | 4576 if (!DoneCmp) { |
| 4567 if (!DoneCmp) | 4577 Constant *Value = Ctx->getConstantInt32(Case.getLow()); |
| 4568 _cmp(Comparison, Value); | 4578 _cmp(Comparison, Value); |
| 4569 _br(Traits::Cond::Br_e, Case.getLabel()); | 4579 } |
| 4570 if (DefaultLabel != nullptr) | 4580 _br(Traits::Cond::Br_e, Case.getTarget()); |
| 4571 _br(DefaultLabel); | 4581 } else if (DoneCmp && Case.isPairRange()) { |
| 4582 // Range of two items with first item aleady compared against |
| 4583 _br(Traits::Cond::Br_e, Case.getTarget()); |
| 4584 Constant *Value = Ctx->getConstantInt32(Case.getHigh()); |
| 4585 _cmp(Comparison, Value); |
| 4586 _br(Traits::Cond::Br_e, Case.getTarget()); |
| 4572 } else { | 4587 } else { |
| 4573 // Range | 4588 // Range |
| 4574 lowerCmpRange(Comparison, Case.getLow(), Case.getHigh()); | 4589 lowerCmpRange(Comparison, Case.getLow(), Case.getHigh()); |
| 4575 _br(Traits::Cond::Br_be, Case.getLabel()); | 4590 _br(Traits::Cond::Br_be, Case.getTarget()); |
| 4576 if (DefaultLabel != nullptr) | |
| 4577 _br(DefaultLabel); | |
| 4578 } | 4591 } |
| 4592 if (DefaultTarget != nullptr) |
| 4593 _br(DefaultTarget); |
| 4579 return; | 4594 return; |
| 4580 } | 4595 } |
| 4581 } | 4596 } |
| 4582 } | 4597 } |
| 4583 | 4598 |
| 4584 template <class Machine> | 4599 template <class Machine> |
| 4585 void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) { | 4600 void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) { |
| 4586 // Do it the old fashioned way unless asked for the advanced method | 4601 // Do it the old fashioned way unless asked for the advanced method |
| 4587 if (!Ctx->getFlags().getUseAdvancedSwitchLowering()) { | 4602 if (!Ctx->getFlags().getUseAdvancedSwitchLowering()) { |
| 4588 // This implements the most naive possible lowering. | 4603 // This implements the most naive possible lowering. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4626 _br(Traits::Cond::Br_e, Inst->getLabel(I)); | 4641 _br(Traits::Cond::Br_e, Inst->getLabel(I)); |
| 4627 } | 4642 } |
| 4628 | 4643 |
| 4629 _br(Inst->getLabelDefault()); | 4644 _br(Inst->getLabelDefault()); |
| 4630 return; | 4645 return; |
| 4631 } | 4646 } |
| 4632 | 4647 |
| 4633 // Group cases together and navigate through them with a binary search | 4648 // Group cases together and navigate through them with a binary search |
| 4634 CaseClusterArray CaseClusters = CaseCluster::clusterizeSwitch(Func, Inst); | 4649 CaseClusterArray CaseClusters = CaseCluster::clusterizeSwitch(Func, Inst); |
| 4635 Operand *Src0 = Inst->getComparison(); | 4650 Operand *Src0 = Inst->getComparison(); |
| 4636 CfgNode *DefaultLabel = Inst->getLabelDefault(); | 4651 CfgNode *DefaultTarget = Inst->getLabelDefault(); |
| 4637 | 4652 |
| 4638 assert(CaseClusters.size() != 0); // Should always be at least one | 4653 assert(CaseClusters.size() != 0); // Should always be at least one |
| 4639 | 4654 |
| 4640 if (Src0->getType() == IceType_i64) { | 4655 if (Src0->getType() == IceType_i64) { |
| 4641 Src0 = legalize(Src0); // get Base/Index into physical registers | 4656 Src0 = legalize(Src0); // get Base/Index into physical registers |
| 4642 Operand *Src0Lo = loOperand(Src0); | 4657 Operand *Src0Lo = loOperand(Src0); |
| 4643 Operand *Src0Hi = hiOperand(Src0); | 4658 Operand *Src0Hi = hiOperand(Src0); |
| 4644 if (CaseClusters.back().getHigh() > UINT32_MAX) { | 4659 if (CaseClusters.back().getHigh() > UINT32_MAX) { |
| 4645 // TODO(ascull): handle 64-bit case properly (currently naive version) | 4660 // TODO(ascull): handle 64-bit case properly (currently naive version) |
| 4646 // This might be handled by a higher level lowering of switches. | 4661 // This might be handled by a higher level lowering of switches. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4664 Context.insert(Label); | 4679 Context.insert(Label); |
| 4665 } | 4680 } |
| 4666 _br(Inst->getLabelDefault()); | 4681 _br(Inst->getLabelDefault()); |
| 4667 return; | 4682 return; |
| 4668 } else { | 4683 } else { |
| 4669 // All the values are 32-bit so just check the operand is too and then | 4684 // All the values are 32-bit so just check the operand is too and then |
| 4670 // fall through to the 32-bit implementation. This is a common case. | 4685 // fall through to the 32-bit implementation. This is a common case. |
| 4671 Src0Hi = legalize(Src0Hi, Legal_Reg | Legal_Mem); | 4686 Src0Hi = legalize(Src0Hi, Legal_Reg | Legal_Mem); |
| 4672 Constant *Zero = Ctx->getConstantInt32(0); | 4687 Constant *Zero = Ctx->getConstantInt32(0); |
| 4673 _cmp(Src0Hi, Zero); | 4688 _cmp(Src0Hi, Zero); |
| 4674 _br(Traits::Cond::Br_ne, DefaultLabel); | 4689 _br(Traits::Cond::Br_ne, DefaultTarget); |
| 4675 Src0 = Src0Lo; | 4690 Src0 = Src0Lo; |
| 4676 } | 4691 } |
| 4677 } | 4692 } |
| 4678 | 4693 |
| 4679 // 32-bit lowering | 4694 // 32-bit lowering |
| 4680 | 4695 |
| 4681 if (CaseClusters.size() == 1) { | 4696 if (CaseClusters.size() == 1) { |
| 4682 // Jump straight to default if needed. Currently a common case as jump | 4697 // Jump straight to default if needed. Currently a common case as jump |
| 4683 // tables occur on their own. | 4698 // tables occur on their own. |
| 4684 constexpr bool DoneCmp = false; | 4699 constexpr bool DoneCmp = false; |
| 4685 lowerCaseCluster(CaseClusters.front(), Src0, DoneCmp, DefaultLabel); | 4700 lowerCaseCluster(CaseClusters.front(), Src0, DoneCmp, DefaultTarget); |
| 4686 return; | 4701 return; |
| 4687 } | 4702 } |
| 4688 | 4703 |
| 4689 // Going to be using multiple times so get it in a register early | 4704 // Going to be using multiple times so get it in a register early |
| 4690 Variable *Comparison = legalizeToReg(Src0); | 4705 Variable *Comparison = legalizeToReg(Src0); |
| 4691 | 4706 |
| 4692 // A span is over the clusters | 4707 // A span is over the clusters |
| 4693 struct SearchSpan { | 4708 struct SearchSpan { |
| 4694 SearchSpan(SizeT Begin, SizeT Size, typename Traits::Insts::Label *Label) | 4709 SearchSpan(SizeT Begin, SizeT Size, typename Traits::Insts::Label *Label) |
| 4695 : Begin(Begin), Size(Size), Label(Label) {} | 4710 : Begin(Begin), Size(Size), Label(Label) {} |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4710 if (Span.Label != nullptr) | 4725 if (Span.Label != nullptr) |
| 4711 Context.insert(Span.Label); | 4726 Context.insert(Span.Label); |
| 4712 | 4727 |
| 4713 switch (Span.Size) { | 4728 switch (Span.Size) { |
| 4714 case 0: | 4729 case 0: |
| 4715 llvm::report_fatal_error("Invalid SearchSpan size"); | 4730 llvm::report_fatal_error("Invalid SearchSpan size"); |
| 4716 break; | 4731 break; |
| 4717 | 4732 |
| 4718 case 1: | 4733 case 1: |
| 4719 lowerCaseCluster(CaseClusters[Span.Begin], Comparison, DoneCmp, | 4734 lowerCaseCluster(CaseClusters[Span.Begin], Comparison, DoneCmp, |
| 4720 SearchSpanStack.empty() ? nullptr : DefaultLabel); | 4735 SearchSpanStack.empty() ? nullptr : DefaultTarget); |
| 4721 DoneCmp = false; | 4736 DoneCmp = false; |
| 4722 break; | 4737 break; |
| 4723 | 4738 |
| 4724 case 2: | 4739 case 2: { |
| 4725 lowerCaseCluster(CaseClusters[Span.Begin], Comparison, DoneCmp); | 4740 const CaseCluster *CaseA = &CaseClusters[Span.Begin]; |
| 4741 const CaseCluster *CaseB = &CaseClusters[Span.Begin + 1]; |
| 4742 |
| 4743 // Placing a range last may allow register clobbering during the range |
| 4744 // test. That means there is no need to clone the register. If it is a |
| 4745 // unit range the comparison may have already been done in the binary |
| 4746 // search (DoneCmp) and so it should be placed first. If this is a range |
| 4747 // of two items and the comparison with the low value has already been |
| 4748 // done, comparing with the other element is cheaper than a range test. |
| 4749 // If the low end of the range is zero then there is no subtraction and |
| 4750 // nothing to be gained. |
| 4751 if (!CaseA->isUnitRange() && |
| 4752 !(CaseA->getLow() == 0 || (DoneCmp && CaseA->isPairRange()))) { |
| 4753 std::swap(CaseA, CaseB); |
| 4754 DoneCmp = false; |
| 4755 } |
| 4756 |
| 4757 lowerCaseCluster(*CaseA, Comparison, DoneCmp); |
| 4726 DoneCmp = false; | 4758 DoneCmp = false; |
| 4727 lowerCaseCluster(CaseClusters[Span.Begin + 1], Comparison, DoneCmp, | 4759 lowerCaseCluster(*CaseB, Comparison, DoneCmp, |
| 4728 SearchSpanStack.empty() ? nullptr : DefaultLabel); | 4760 SearchSpanStack.empty() ? nullptr : DefaultTarget); |
| 4729 break; | 4761 } break; |
| 4730 | 4762 |
| 4731 default: | 4763 default: |
| 4732 // Pick the middle item and branch b or ae | 4764 // Pick the middle item and branch b or ae |
| 4733 SizeT PivotIndex = Span.Begin + (Span.Size / 2); | 4765 SizeT PivotIndex = Span.Begin + (Span.Size / 2); |
| 4734 const CaseCluster &Pivot = CaseClusters[PivotIndex]; | 4766 const CaseCluster &Pivot = CaseClusters[PivotIndex]; |
| 4735 Constant *Value = Ctx->getConstantInt32(Pivot.getLow()); | 4767 Constant *Value = Ctx->getConstantInt32(Pivot.getLow()); |
| 4736 // TODO(ascull): what if this jump is too big? | |
| 4737 typename Traits::Insts::Label *Label = | 4768 typename Traits::Insts::Label *Label = |
| 4738 Traits::Insts::Label::create(Func, this); | 4769 Traits::Insts::Label::create(Func, this); |
| 4739 _cmp(Comparison, Value); | 4770 _cmp(Comparison, Value); |
| 4740 _br(Traits::Cond::Br_b, Label); | 4771 // TODO(ascull): does it alway have to be far? |
| 4772 _br(Traits::Cond::Br_b, Label, Traits::Insts::Br::Far); |
| 4741 // Lower the left and (pivot+right) sides, falling through to the right | 4773 // Lower the left and (pivot+right) sides, falling through to the right |
| 4742 SearchSpanStack.emplace(Span.Begin, Span.Size / 2, Label); | 4774 SearchSpanStack.emplace(Span.Begin, Span.Size / 2, Label); |
| 4743 SearchSpanStack.emplace(PivotIndex, Span.Size - (Span.Size / 2), nullptr); | 4775 SearchSpanStack.emplace(PivotIndex, Span.Size - (Span.Size / 2), nullptr); |
| 4744 DoneCmp = true; | 4776 DoneCmp = true; |
| 4745 break; | 4777 break; |
| 4746 } | 4778 } |
| 4747 } | 4779 } |
| 4748 | 4780 |
| 4749 _br(DefaultLabel); | 4781 _br(DefaultTarget); |
| 4750 } | 4782 } |
| 4751 | 4783 |
| 4752 template <class Machine> | 4784 template <class Machine> |
| 4753 void TargetX86Base<Machine>::scalarizeArithmetic(InstArithmetic::OpKind Kind, | 4785 void TargetX86Base<Machine>::scalarizeArithmetic(InstArithmetic::OpKind Kind, |
| 4754 Variable *Dest, Operand *Src0, | 4786 Variable *Dest, Operand *Src0, |
| 4755 Operand *Src1) { | 4787 Operand *Src1) { |
| 4756 assert(isVectorType(Dest->getType())); | 4788 assert(isVectorType(Dest->getType())); |
| 4757 Type Ty = Dest->getType(); | 4789 Type Ty = Dest->getType(); |
| 4758 Type ElementTy = typeElementType(Ty); | 4790 Type ElementTy = typeElementType(Ty); |
| 4759 SizeT NumElements = typeNumElements(Ty); | 4791 SizeT NumElements = typeNumElements(Ty); |
| (...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5616 } | 5648 } |
| 5617 // the offset is not eligible for blinding or pooling, return the original | 5649 // the offset is not eligible for blinding or pooling, return the original |
| 5618 // mem operand | 5650 // mem operand |
| 5619 return MemOperand; | 5651 return MemOperand; |
| 5620 } | 5652 } |
| 5621 | 5653 |
| 5622 } // end of namespace X86Internal | 5654 } // end of namespace X86Internal |
| 5623 } // end of namespace Ice | 5655 } // end of namespace Ice |
| 5624 | 5656 |
| 5625 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 5657 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |