From 3a3fd0f8d3981691aa2331077a8fae5feee08dd1 Mon Sep 17 00:00:00 2001 From: Roland Levillain Date: Fri, 10 Oct 2014 13:56:31 +0100 Subject: [PATCH] Turn constant conditional jumps into unconditional jumps. If a condition (input of an art::HIf instruction) is constant (an art::HConstant object), evaluate it at compile time and generate an unconditional branch instruction if it is true (in lieu of a conditional jump). Change-Id: I262e43ffe66d5c25dbbfa98092a41c8b3c4c75d6 --- compiler/optimizing/code_generator_arm.cc | 64 ++++++++++++++--------- compiler/optimizing/code_generator_x86.cc | 77 +++++++++++++++++----------- compiler/optimizing/code_generator_x86_64.cc | 75 +++++++++++++++++---------- 3 files changed, 136 insertions(+), 80 deletions(-) diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 9be780216..7a9e9c4ce 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -641,36 +641,51 @@ void LocationsBuilderARM::VisitIf(HIf* if_instr) { void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { HInstruction* cond = if_instr->InputAt(0); - if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) { - // Condition has been materialized, compare the output to 0 - DCHECK(if_instr->GetLocations()->InAt(0).IsRegister()); - __ cmp(if_instr->GetLocations()->InAt(0).As(), - ShifterOperand(0)); - __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), NE); + if (cond->IsIntConstant()) { + // Constant condition, statically compared against 1. + int32_t cond_value = cond->AsIntConstant()->GetValue(); + if (cond_value == 1) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfTrueSuccessor())) { + __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + } + return; + } else { + DCHECK_EQ(cond_value, 0); + } } else { - // Condition has not been materialized, use its inputs as the comparison and its - // condition as the branch condition. - LocationSummary* locations = cond->GetLocations(); - if (locations->InAt(1).IsRegister()) { - __ cmp(locations->InAt(0).As(), - ShifterOperand(locations->InAt(1).As())); + if (!cond->IsCondition() || cond->AsCondition()->NeedsMaterialization()) { + // Condition has been materialized, compare the output to 0 + DCHECK(if_instr->GetLocations()->InAt(0).IsRegister()); + __ cmp(if_instr->GetLocations()->InAt(0).As(), + ShifterOperand(0)); + __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), NE); } else { - DCHECK(locations->InAt(1).IsConstant()); - int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); - ShifterOperand operand; - if (ShifterOperand::CanHoldArm(value, &operand)) { - __ cmp(locations->InAt(0).As(), ShifterOperand(value)); + // Condition has not been materialized, use its inputs as the + // comparison and its condition as the branch condition. + LocationSummary* locations = cond->GetLocations(); + if (locations->InAt(1).IsRegister()) { + __ cmp(locations->InAt(0).As(), + ShifterOperand(locations->InAt(1).As())); } else { - Register temp = IP; - __ LoadImmediate(temp, value); - __ cmp(locations->InAt(0).As(), ShifterOperand(temp)); + DCHECK(locations->InAt(1).IsConstant()); + int32_t value = + locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); + ShifterOperand operand; + if (ShifterOperand::CanHoldArm(value, &operand)) { + __ cmp(locations->InAt(0).As(), ShifterOperand(value)); + } else { + Register temp = IP; + __ LoadImmediate(temp, value); + __ cmp(locations->InAt(0).As(), ShifterOperand(temp)); + } } + __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), + ARMCondition(cond->AsCondition()->GetCondition())); } - __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), - ARMCondition(cond->AsCondition()->GetCondition())); } - - if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfFalseSuccessor())) { __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor())); } } @@ -810,6 +825,7 @@ void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) { } void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) { + // Will be generated at use site. } void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) { diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 34fa46efd..5fc389569 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -577,42 +577,60 @@ void LocationsBuilderX86::VisitIf(HIf* if_instr) { void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) { HInstruction* cond = if_instr->InputAt(0); - bool materialized = !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization(); - // 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. - bool eflags_set = cond->IsCondition() - && cond->AsCondition()->IsBeforeWhenDisregardMoves(if_instr); - if (materialized) { - if (!eflags_set) { - // Materialized condition, compare against 0. - Location lhs = if_instr->GetLocations()->InAt(0); - if (lhs.IsRegister()) { - __ cmpl(lhs.As(), Immediate(0)); - } else { - __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0)); + if (cond->IsIntConstant()) { + // Constant condition, statically compared against 1. + int32_t cond_value = cond->AsIntConstant()->GetValue(); + if (cond_value == 1) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfTrueSuccessor())) { + __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + return; } else { - __ j(X86Condition(cond->AsCondition()->GetCondition()), - codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + DCHECK_EQ(cond_value, 0); } } else { - Location lhs = cond->GetLocations()->InAt(0); - Location rhs = cond->GetLocations()->InAt(1); - // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition). - if (rhs.IsRegister()) { - __ cmpl(lhs.As(), rhs.As()); - } else if (rhs.IsConstant()) { - HIntConstant* instruction = rhs.GetConstant()->AsIntConstant(); - Immediate imm(instruction->AsIntConstant()->GetValue()); - __ cmpl(lhs.As(), imm); + bool materialized = + !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization(); + // 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. + bool eflags_set = cond->IsCondition() + && cond->AsCondition()->IsBeforeWhenDisregardMoves(if_instr); + if (materialized) { + if (!eflags_set) { + // Materialized condition, compare against 0. + Location lhs = if_instr->GetLocations()->InAt(0); + if (lhs.IsRegister()) { + __ cmpl(lhs.As(), Immediate(0)); + } else { + __ cmpl(Address(ESP, lhs.GetStackIndex()), Immediate(0)); + } + __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + } else { + __ j(X86Condition(cond->AsCondition()->GetCondition()), + codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + } } else { - __ cmpl(lhs.As(), Address(ESP, rhs.GetStackIndex())); + Location lhs = cond->GetLocations()->InAt(0); + Location rhs = cond->GetLocations()->InAt(1); + // LHS is guaranteed to be in a register (see + // LocationsBuilderX86::VisitCondition). + if (rhs.IsRegister()) { + __ cmpl(lhs.As(), rhs.As()); + } else if (rhs.IsConstant()) { + HIntConstant* instruction = rhs.GetConstant()->AsIntConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ cmpl(lhs.As(), imm); + } else { + __ cmpl(lhs.As(), Address(ESP, rhs.GetStackIndex())); + } + __ j(X86Condition(cond->AsCondition()->GetCondition()), + codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - __ j(X86Condition(cond->AsCondition()->GetCondition()), - codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfFalseSuccessor())) { __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor())); } } @@ -747,6 +765,7 @@ void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) { } void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) { + // Will be generated at use site. } void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) { diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 059140d9b..5781e7e07 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -479,40 +479,59 @@ void LocationsBuilderX86_64::VisitIf(HIf* if_instr) { void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) { HInstruction* cond = if_instr->InputAt(0); - bool materialized = !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization(); - // 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. - bool eflags_set = cond->IsCondition() - && cond->AsCondition()->IsBeforeWhenDisregardMoves(if_instr); - if (materialized) { - if (!eflags_set) { - // Materialized condition, compare against 0. - Location lhs = if_instr->GetLocations()->InAt(0); - if (lhs.IsRegister()) { - __ cmpl(lhs.As(), Immediate(0)); - } else { - __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()), Immediate(0)); + if (cond->IsIntConstant()) { + // Constant condition, statically compared against 1. + int32_t cond_value = cond->AsIntConstant()->GetValue(); + if (cond_value == 1) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfTrueSuccessor())) { + __ jmp(codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + return; } else { - __ j(X86_64Condition(cond->AsCondition()->GetCondition()), - codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + DCHECK_EQ(cond_value, 0); } } else { - Location lhs = cond->GetLocations()->InAt(0); - Location rhs = cond->GetLocations()->InAt(1); - if (rhs.IsRegister()) { - __ cmpl(lhs.As(), rhs.As()); - } else if (rhs.IsConstant()) { - __ cmpl(lhs.As(), - Immediate(rhs.GetConstant()->AsIntConstant()->GetValue())); + bool materialized = + !cond->IsCondition() || cond->AsCondition()->NeedsMaterialization(); + // 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. + bool eflags_set = cond->IsCondition() + && cond->AsCondition()->IsBeforeWhenDisregardMoves(if_instr); + if (materialized) { + if (!eflags_set) { + // Materialized condition, compare against 0. + Location lhs = if_instr->GetLocations()->InAt(0); + if (lhs.IsRegister()) { + __ cmpl(lhs.As(), Immediate(0)); + } else { + __ cmpl(Address(CpuRegister(RSP), lhs.GetStackIndex()), + Immediate(0)); + } + __ j(kNotEqual, codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + } else { + __ j(X86_64Condition(cond->AsCondition()->GetCondition()), + codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); + } } else { - __ cmpl(lhs.As(), Address(CpuRegister(RSP), rhs.GetStackIndex())); + Location lhs = cond->GetLocations()->InAt(0); + Location rhs = cond->GetLocations()->InAt(1); + if (rhs.IsRegister()) { + __ cmpl(lhs.As(), rhs.As()); + } else if (rhs.IsConstant()) { + __ cmpl(lhs.As(), + Immediate(rhs.GetConstant()->AsIntConstant()->GetValue())); + } else { + __ cmpl(lhs.As(), + Address(CpuRegister(RSP), rhs.GetStackIndex())); + } + __ j(X86_64Condition(cond->AsCondition()->GetCondition()), + codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - __ j(X86_64Condition(cond->AsCondition()->GetCondition()), - codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } - if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) { + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), + if_instr->IfFalseSuccessor())) { __ jmp(codegen_->GetLabelOf(if_instr->IfFalseSuccessor())); } } @@ -679,6 +698,7 @@ void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) { } void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) { + // Will be generated at use site. } void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) { @@ -688,6 +708,7 @@ void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) { } void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) { + // Will be generated at use site. } void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) { -- 2.11.0