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

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1257283004: Iasm and obj lowering for advanced switch lowering. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 4 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 4497 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698