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
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 9be7802..7a9e9c4 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -641,36 +641,51 @@
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<Register>(),
- ShifterOperand(0));
- __ 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.
- LocationSummary* locations = cond->GetLocations();
- if (locations->InAt(1).IsRegister()) {
- __ cmp(locations->InAt(0).As<Register>(),
- ShifterOperand(locations->InAt(1).As<Register>()));
- } 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<Register>(), ShifterOperand(value));
- } else {
- Register temp = IP;
- __ LoadImmediate(temp, value);
- __ cmp(locations->InAt(0).As<Register>(), ShifterOperand(temp));
+ 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);
}
- __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()),
- ARMCondition(cond->AsCondition()->GetCondition()));
+ } else {
+ 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<Register>(),
+ ShifterOperand(0));
+ __ 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.
+ LocationSummary* locations = cond->GetLocations();
+ if (locations->InAt(1).IsRegister()) {
+ __ cmp(locations->InAt(0).As<Register>(),
+ ShifterOperand(locations->InAt(1).As<Register>()));
+ } 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<Register>(), ShifterOperand(value));
+ } else {
+ Register temp = IP;
+ __ LoadImmediate(temp, value);
+ __ cmp(locations->InAt(0).As<Register>(), ShifterOperand(temp));
+ }
+ }
+ __ 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 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 34fa46e..5fc3895 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -577,42 +577,60 @@
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<Register>(), 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 {
+ DCHECK_EQ(cond_value, 0);
+ }
+ } else {
+ 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<Register>(), 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 {
+ 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<Register>(), rhs.As<Register>());
+ } else if (rhs.IsConstant()) {
+ HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
+ Immediate imm(instruction->AsIntConstant()->GetValue());
+ __ cmpl(lhs.As<Register>(), imm);
+ } else {
+ __ cmpl(lhs.As<Register>(), Address(ESP, rhs.GetStackIndex()));
+ }
__ j(X86Condition(cond->AsCondition()->GetCondition()),
codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
}
- } 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<Register>(), rhs.As<Register>());
- } else if (rhs.IsConstant()) {
- HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
- Immediate imm(instruction->AsIntConstant()->GetValue());
- __ cmpl(lhs.As<Register>(), imm);
- } else {
- __ cmpl(lhs.As<Register>(), Address(ESP, rhs.GetStackIndex()));
- }
- __ 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 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 059140d..5781e7e 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -479,40 +479,59 @@
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<CpuRegister>(), 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 {
+ DCHECK_EQ(cond_value, 0);
+ }
+ } else {
+ 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<CpuRegister>(), 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 {
+ Location lhs = cond->GetLocations()->InAt(0);
+ Location rhs = cond->GetLocations()->InAt(1);
+ if (rhs.IsRegister()) {
+ __ cmpl(lhs.As<CpuRegister>(), rhs.As<CpuRegister>());
+ } else if (rhs.IsConstant()) {
+ __ cmpl(lhs.As<CpuRegister>(),
+ Immediate(rhs.GetConstant()->AsIntConstant()->GetValue()));
+ } else {
+ __ cmpl(lhs.As<CpuRegister>(),
+ Address(CpuRegister(RSP), rhs.GetStackIndex()));
+ }
__ j(X86_64Condition(cond->AsCondition()->GetCondition()),
codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
}
- } else {
- Location lhs = cond->GetLocations()->InAt(0);
- Location rhs = cond->GetLocations()->InAt(1);
- if (rhs.IsRegister()) {
- __ cmpl(lhs.As<CpuRegister>(), rhs.As<CpuRegister>());
- } else if (rhs.IsConstant()) {
- __ cmpl(lhs.As<CpuRegister>(),
- Immediate(rhs.GetConstant()->AsIntConstant()->GetValue()));
- } else {
- __ cmpl(lhs.As<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
- }
- __ 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 InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
+ // Will be generated at use site.
}
void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
@@ -688,6 +708,7 @@
}
void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
+ // Will be generated at use site.
}
void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) {