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

Unified 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, 5 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 side-by-side diff with in-line comments
Download patch
Index: src/IceTargetLoweringX86BaseImpl.h
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 77048b089c1a4c9934568f8dd973429138e36f9c..2962ec7715513bf6794d58ce3cfa5f0417d341a6 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -4515,19 +4515,19 @@ Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison,
template <class Machine>
void TargetX86Base<Machine>::lowerCaseCluster(const CaseCluster &Case,
Operand *Comparison, bool DoneCmp,
- CfgNode *DefaultLabel) {
+ CfgNode *DefaultTarget) {
switch (Case.getKind()) {
case CaseCluster::JumpTable: {
typename Traits::Insts::Label *SkipJumpTable;
Operand *RangeIndex =
lowerCmpRange(Comparison, Case.getLow(), Case.getHigh());
- if (DefaultLabel != nullptr) {
- _br(Traits::Cond::Br_a, DefaultLabel);
- } else {
+ if (DefaultTarget == nullptr) {
// Skip over jump table logic if comparison not in range and no default
SkipJumpTable = Traits::Insts::Label::create(Func, this);
_br(Traits::Cond::Br_a, SkipJumpTable);
+ } else {
+ _br(Traits::Cond::Br_a, DefaultTarget);
}
InstJumpTable *JumpTable = Case.getJumpTable();
@@ -4549,33 +4549,48 @@ void TargetX86Base<Machine>::lowerCaseCluster(const CaseCluster &Case,
Constant *Offset = nullptr;
uint16_t Shift = typeWidthInBytesLog2(getPointerType());
// TODO(ascull): remove need for legalize by allowing null base in memop
- auto *MemTarget = Traits::X86OperandMem::create(
+ auto *TargetInMemory = Traits::X86OperandMem::create(
Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift);
Variable *Target = nullptr;
- _mov(Target, MemTarget);
+ _mov(Target, TargetInMemory);
+
+ // Sandbox the indirect jump
+ const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
+ if (NeedSandboxing) {
+ _bundle_lock();
+ const SizeT BundleSize =
+ 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes();
+ _and(Target, Ctx->getConstantInt32(~(BundleSize - 1)));
+ }
_jmp(Target);
- // TODO(ascull): sandboxing for indirect jump
+ if (NeedSandboxing)
+ _bundle_unlock();
- if (DefaultLabel == nullptr)
+ if (DefaultTarget == nullptr)
Context.insert(SkipJumpTable);
return;
}
case CaseCluster::Range: {
- if (Case.getHigh() == Case.getLow()) {
+ if (Case.isUnitRange()) {
// Single item
- Constant *Value = Ctx->getConstantInt32(Case.getLow());
- if (!DoneCmp)
+ if (!DoneCmp) {
+ Constant *Value = Ctx->getConstantInt32(Case.getLow());
_cmp(Comparison, Value);
- _br(Traits::Cond::Br_e, Case.getLabel());
- if (DefaultLabel != nullptr)
- _br(DefaultLabel);
+ }
+ _br(Traits::Cond::Br_e, Case.getTarget());
+ } else if (DoneCmp && Case.isPairRange()) {
+ // Range of two items with first item aleady compared against
+ _br(Traits::Cond::Br_e, Case.getTarget());
+ Constant *Value = Ctx->getConstantInt32(Case.getHigh());
+ _cmp(Comparison, Value);
+ _br(Traits::Cond::Br_e, Case.getTarget());
} else {
// Range
lowerCmpRange(Comparison, Case.getLow(), Case.getHigh());
- _br(Traits::Cond::Br_be, Case.getLabel());
- if (DefaultLabel != nullptr)
- _br(DefaultLabel);
+ _br(Traits::Cond::Br_be, Case.getTarget());
}
+ if (DefaultTarget != nullptr)
+ _br(DefaultTarget);
return;
}
}
@@ -4633,7 +4648,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
// Group cases together and navigate through them with a binary search
CaseClusterArray CaseClusters = CaseCluster::clusterizeSwitch(Func, Inst);
Operand *Src0 = Inst->getComparison();
- CfgNode *DefaultLabel = Inst->getLabelDefault();
+ CfgNode *DefaultTarget = Inst->getLabelDefault();
assert(CaseClusters.size() != 0); // Should always be at least one
@@ -4671,7 +4686,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
Src0Hi = legalize(Src0Hi, Legal_Reg | Legal_Mem);
Constant *Zero = Ctx->getConstantInt32(0);
_cmp(Src0Hi, Zero);
- _br(Traits::Cond::Br_ne, DefaultLabel);
+ _br(Traits::Cond::Br_ne, DefaultTarget);
Src0 = Src0Lo;
}
}
@@ -4682,7 +4697,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
// Jump straight to default if needed. Currently a common case as jump
// tables occur on their own.
constexpr bool DoneCmp = false;
- lowerCaseCluster(CaseClusters.front(), Src0, DoneCmp, DefaultLabel);
+ lowerCaseCluster(CaseClusters.front(), Src0, DoneCmp, DefaultTarget);
return;
}
@@ -4717,27 +4732,44 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
case 1:
lowerCaseCluster(CaseClusters[Span.Begin], Comparison, DoneCmp,
- SearchSpanStack.empty() ? nullptr : DefaultLabel);
+ SearchSpanStack.empty() ? nullptr : DefaultTarget);
DoneCmp = false;
break;
- case 2:
- lowerCaseCluster(CaseClusters[Span.Begin], Comparison, DoneCmp);
+ case 2: {
+ const CaseCluster *CaseA = &CaseClusters[Span.Begin];
+ const CaseCluster *CaseB = &CaseClusters[Span.Begin + 1];
+
+ // Placing a range last may allow register clobbering during the range
+ // test. That means there is no need to clone the register. If it is a
+ // unit range the comparison may have already been done in the binary
+ // search (DoneCmp) and so it should be placed first. If this is a range
+ // of two items and the comparison with the low value has already been
+ // done, comparing with the other element is cheaper than a range test.
+ // If the low end of the range is zero then there is no subtraction and
+ // nothing to be gained.
+ if (!CaseA->isUnitRange() &&
+ !(CaseA->getLow() == 0 || (DoneCmp && CaseA->isPairRange()))) {
+ std::swap(CaseA, CaseB);
+ DoneCmp = false;
+ }
+
+ lowerCaseCluster(*CaseA, Comparison, DoneCmp);
DoneCmp = false;
- lowerCaseCluster(CaseClusters[Span.Begin + 1], Comparison, DoneCmp,
- SearchSpanStack.empty() ? nullptr : DefaultLabel);
- break;
+ lowerCaseCluster(*CaseB, Comparison, DoneCmp,
+ SearchSpanStack.empty() ? nullptr : DefaultTarget);
+ } break;
default:
// Pick the middle item and branch b or ae
SizeT PivotIndex = Span.Begin + (Span.Size / 2);
const CaseCluster &Pivot = CaseClusters[PivotIndex];
Constant *Value = Ctx->getConstantInt32(Pivot.getLow());
- // TODO(ascull): what if this jump is too big?
typename Traits::Insts::Label *Label =
Traits::Insts::Label::create(Func, this);
_cmp(Comparison, Value);
- _br(Traits::Cond::Br_b, Label);
+ // TODO(ascull): does it alway have to be far?
+ _br(Traits::Cond::Br_b, Label, Traits::Insts::Br::Far);
// Lower the left and (pivot+right) sides, falling through to the right
SearchSpanStack.emplace(Span.Begin, Span.Size / 2, Label);
SearchSpanStack.emplace(PivotIndex, Span.Size - (Span.Size / 2), nullptr);
@@ -4746,7 +4778,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
}
}
- _br(DefaultLabel);
+ _br(DefaultTarget);
}
template <class Machine>

Powered by Google App Engine
This is Rietveld 408576698