diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-09-23 11:25:56 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-09-23 11:25:56 +0000 |
commit | 2e1391b9abdafdbe7e0ef5ef116c49f812394056 (patch) | |
tree | bdac0775c4f9290741f9583c2acbd53655c63fb0 /compiler/optimizing | |
parent | 0f6016557d300a5a07c972465aef1ab2a125f5d1 (diff) | |
parent | 18efde5017369e005f1e8bcd3bbfb04e85053640 (diff) | |
download | art-2e1391b9abdafdbe7e0ef5ef116c49f812394056.zip art-2e1391b9abdafdbe7e0ef5ef116c49f812394056.tar.gz art-2e1391b9abdafdbe7e0ef5ef116c49f812394056.tar.bz2 |
Merge "Fix code generation with materialized conditions."
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 23 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 24 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 12 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 7 |
6 files changed, 57 insertions, 21 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index ad62279..804d352 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -577,7 +577,7 @@ void LocationsBuilderARM::VisitIf(HIf* if_instr) { DCHECK(cond->IsCondition()); HCondition* condition = cond->AsCondition(); if (condition->NeedsMaterialization()) { - locations->SetInAt(0, Location::Any()); + locations->SetInAt(0, Location::RequiresRegister()); } } @@ -590,7 +590,7 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { DCHECK(if_instr->GetLocations()->InAt(0).IsRegister()); __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(0)); - __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), EQ); + __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), NE); } else { // Condition has not been materialized, use its inputs as the comparison and its // condition as the branch condition. diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 3383cb2..f7b8495 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -541,14 +541,18 @@ void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) { DCHECK(cond->IsCondition()); HCondition* condition = cond->AsCondition(); if (condition->NeedsMaterialization()) { - // Materialized condition, compare against 0 - Location lhs = if_instr->GetLocations()->InAt(0); - if (lhs.IsRegister()) { - __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0)); - } else { - __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0)); + // Moves do not affect the eflags register, so if the condition is evaluated + // just before the if, we don't need to evaluate it again. + if (!condition->IsBeforeWhenDisregardMoves(if_instr)) { + // Materialized condition, compare against 0 + Location lhs = if_instr->GetLocations()->InAt(0); + if (lhs.IsRegister()) { + __ cmpl(lhs.AsX86().AsCpuRegister(), Immediate(0)); + } else { + __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0)); + } } - __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } else { Location lhs = condition->GetLocations()->InAt(0); Location rhs = condition->GetLocations()->InAt(1); @@ -625,6 +629,9 @@ void LocationsBuilderX86::VisitCondition(HCondition* comp) { void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) { if (comp->NeedsMaterialization()) { LocationSummary* locations = comp->GetLocations(); + Register reg = locations->Out().AsX86().AsCpuRegister(); + // Clear register: setcc only sets the low byte. + __ xorl(reg, reg); if (locations->InAt(1).IsRegister()) { __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), locations->InAt(1).AsX86().AsCpuRegister()); @@ -636,7 +643,7 @@ void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) { __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), Address(ESP, locations->InAt(1).GetStackIndex())); } - __ setb(X86Condition(comp->GetCondition()), locations->Out().AsX86().AsCpuRegister()); + __ setb(X86Condition(comp->GetCondition()), reg); } } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index ca03af8..283d850 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -424,14 +424,18 @@ void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) { DCHECK(cond->IsCondition()); HCondition* condition = cond->AsCondition(); if (condition->NeedsMaterialization()) { - // Materialized condition, compare against 0. - Location lhs = if_instr->GetLocations()->InAt(0); - if (lhs.IsRegister()) { - __ cmpl(lhs.AsX86_64().AsCpuRegister(), Immediate(0)); - } else { - __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()), Immediate(0)); + // Moves do not affect the eflags register, so if the condition is evaluated + // just before the if, we don't need to evaluate it again. + if (!condition->IsBeforeWhenDisregardMoves(if_instr)) { + // Materialized condition, compare against 0. + Location lhs = if_instr->GetLocations()->InAt(0); + if (lhs.IsRegister()) { + __ cmpl(lhs.AsX86_64().AsCpuRegister(), Immediate(0)); + } else { + __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()), Immediate(0)); + } } - __ j(kEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } else { Location lhs = condition->GetLocations()->InAt(0); Location rhs = condition->GetLocations()->InAt(1); @@ -505,6 +509,9 @@ void LocationsBuilderX86_64::VisitCondition(HCondition* comp) { void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) { if (comp->NeedsMaterialization()) { LocationSummary* locations = comp->GetLocations(); + CpuRegister reg = locations->Out().AsX86_64().AsCpuRegister(); + // Clear register: setcc only sets the low byte. + __ xorq(reg, reg); if (locations->InAt(1).IsRegister()) { __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(), locations->InAt(1).AsX86_64().AsCpuRegister()); @@ -515,8 +522,7 @@ void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) { __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex())); } - __ setcc(X86_64Condition(comp->GetCondition()), - comp->GetLocations()->Out().AsX86_64().AsCpuRegister()); + __ setcc(X86_64Condition(comp->GetCondition()), reg); } } diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 7f64be4..0fb4737 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -82,6 +82,8 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } char GetTypeId(Primitive::Type type) { + // Note that Primitive::Descriptor would not work for us + // because it does not handle reference types (that is kPrimNot). switch (type) { case Primitive::kPrimBoolean: return 'z'; case Primitive::kPrimByte: return 'b'; @@ -127,6 +129,12 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } } else if (location.IsConstant()) { output_ << "constant"; + HConstant* constant = location.GetConstant(); + if (constant->IsIntConstant()) { + output_ << " " << constant->AsIntConstant()->GetValue(); + } else if (constant->IsLongConstant()) { + output_ << " " << constant->AsLongConstant()->GetValue(); + } } else if (location.IsInvalid()) { output_ << "invalid"; } else if (location.IsStackSlot()) { diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 72c5834..09412a9 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -555,14 +555,22 @@ bool HCondition::NeedsMaterialization() const { return true; } - // TODO: should we allow intervening instructions with no side-effect between this condition - // and the If instruction? + // TODO: if there is no intervening instructions with side-effect between this condition + // and the If instruction, we should move the condition just before the If. if (GetNext() != user) { return true; } return false; } +bool HCondition::IsBeforeWhenDisregardMoves(HIf* if_) const { + HInstruction* previous = if_->GetPrevious(); + while (previous != nullptr && previous->IsParallelMove()) { + previous = previous->GetPrevious(); + } + return previous == this; +} + bool HInstruction::Equals(HInstruction* other) const { if (!InstructionTypeEquals(other)) return false; DCHECK_EQ(GetKind(), other->GetKind()); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index fd65338..be6b355 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1095,8 +1095,15 @@ class HCondition : public HBinaryOperation { : HBinaryOperation(Primitive::kPrimBoolean, first, second) {} virtual bool IsCommutative() { return true; } + + // For register allocation purposes, returns whether this instruction needs to be + // materialized (that is, not just be in the processor flags). bool NeedsMaterialization() const; + // For code generation purposes, returns whether this instruction is just before + // `if_`, and disregard moves in between. + bool IsBeforeWhenDisregardMoves(HIf* if_) const; + DECLARE_INSTRUCTION(Condition); virtual IfCondition GetCondition() const = 0; |