Fuse long and FP compare & condition on ARM in Optimizing.
Also:
- Stylistic changes in corresponding parts on the x86 and
x86-64 code generators.
- Update and improve the documentation of
art::arm::Condition.
Bug: 21120453
Change-Id: If144772046e7d21362c3c2086246cb7d011d49ce
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index ddaa60d..ae7bcc8 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -363,7 +363,7 @@
#undef __
#define __ down_cast<X86_64Assembler*>(GetAssembler())->
-inline Condition X86_64Condition(IfCondition cond) {
+inline Condition X86_64IntegerCondition(IfCondition cond) {
switch (cond) {
case kCondEQ: return kEqual;
case kCondNE: return kNotEqual;
@@ -371,10 +371,22 @@
case kCondLE: return kLessEqual;
case kCondGT: return kGreater;
case kCondGE: return kGreaterEqual;
- default:
- LOG(FATAL) << "Unknown if condition";
}
- return kEqual;
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
+}
+
+inline Condition X86_64FPCondition(IfCondition cond) {
+ switch (cond) {
+ case kCondEQ: return kEqual;
+ case kCondNE: return kNotEqual;
+ case kCondLT: return kBelow;
+ case kCondLE: return kBelowEqual;
+ case kCondGT: return kAbove;
+ case kCondGE: return kAboveEqual;
+ };
+ LOG(FATAL) << "Unreachable";
+ UNREACHABLE();
}
void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
@@ -836,46 +848,12 @@
void InstructionCodeGeneratorX86_64::GenerateFPJumps(HCondition* cond,
Label* true_label,
Label* false_label) {
- bool gt_bias = cond->IsGtBias();
- IfCondition if_cond = cond->GetCondition();
- Condition ccode = X86_64Condition(if_cond);
- switch (if_cond) {
- case kCondEQ:
- if (!gt_bias) {
- __ j(kParityEven, false_label);
- }
- break;
- case kCondNE:
- if (!gt_bias) {
- __ j(kParityEven, true_label);
- }
- break;
- case kCondLT:
- if (gt_bias) {
- __ j(kParityEven, false_label);
- }
- ccode = kBelow;
- break;
- case kCondLE:
- if (gt_bias) {
- __ j(kParityEven, false_label);
- }
- ccode = kBelowEqual;
- break;
- case kCondGT:
- if (gt_bias) {
- __ j(kParityEven, true_label);
- }
- ccode = kAbove;
- break;
- case kCondGE:
- if (gt_bias) {
- __ j(kParityEven, true_label);
- }
- ccode = kAboveEqual;
- break;
+ if (cond->IsFPConditionTrueIfNaN()) {
+ __ j(kUnordered, true_label);
+ } else if (cond->IsFPConditionFalseIfNaN()) {
+ __ j(kUnordered, false_label);
}
- __ j(ccode, true_label);
+ __ j(X86_64FPCondition(cond->GetCondition()), true_label);
}
void InstructionCodeGeneratorX86_64::GenerateCompareTestAndBranch(HIf* if_instr,
@@ -911,7 +889,7 @@
__ cmpq(left_reg, Immediate(static_cast<int32_t>(value)));
}
} else {
- // Value won't fit in an 32-bit integer.
+ // Value won't fit in a 32-bit integer.
__ cmpq(left_reg, codegen_->LiteralInt64Address(value));
}
} else if (right.IsDoubleStackSlot()) {
@@ -919,7 +897,7 @@
} else {
__ cmpq(left_reg, right.AsRegister<CpuRegister>());
}
- __ j(X86_64Condition(condition->GetCondition()), true_target);
+ __ j(X86_64IntegerCondition(condition->GetCondition()), true_target);
break;
}
case Primitive::kPrimFloat: {
@@ -978,7 +956,7 @@
DCHECK_EQ(cond_value, 0);
}
} else {
- bool materialized =
+ bool is_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
@@ -989,7 +967,7 @@
&& cond->AsCondition()->IsBeforeWhenDisregardMoves(instruction)
&& !Primitive::IsFloatingPointType(type);
- if (materialized) {
+ if (is_materialized) {
if (!eflags_set) {
// Materialized condition, compare against 0.
Location lhs = instruction->GetLocations()->InAt(0);
@@ -1001,16 +979,20 @@
}
__ j(kNotEqual, true_target);
} else {
- __ j(X86_64Condition(cond->AsCondition()->GetCondition()), true_target);
+ __ j(X86_64IntegerCondition(cond->AsCondition()->GetCondition()), true_target);
}
} else {
+ // Condition has not been materialized, use its inputs as the
+ // comparison and its condition as the branch condition.
+
// Is this a long or FP comparison that has been folded into the HCondition?
if (type == Primitive::kPrimLong || Primitive::IsFloatingPointType(type)) {
- // Generate the comparison directly
+ // Generate the comparison directly.
GenerateCompareTestAndBranch(instruction->AsIf(), cond->AsCondition(),
true_target, false_target, always_true_target);
return;
}
+
Location lhs = cond->GetLocations()->InAt(0);
Location rhs = cond->GetLocations()->InAt(1);
if (rhs.IsRegister()) {
@@ -1026,7 +1008,7 @@
__ cmpl(lhs.AsRegister<CpuRegister>(),
Address(CpuRegister(RSP), rhs.GetStackIndex()));
}
- __ j(X86_64Condition(cond->AsCondition()->GetCondition()), true_target);
+ __ j(X86_64IntegerCondition(cond->AsCondition()->GetCondition()), true_target);
}
}
if (false_target != nullptr) {
@@ -1175,7 +1157,7 @@
} else {
__ cmpl(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
}
- __ setcc(X86_64Condition(cond->GetCondition()), reg);
+ __ setcc(X86_64IntegerCondition(cond->GetCondition()), reg);
return;
case Primitive::kPrimLong:
// Clear output register: setcc only sets the low byte.
@@ -1198,7 +1180,7 @@
} else {
__ cmpq(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
}
- __ setcc(X86_64Condition(cond->GetCondition()), reg);
+ __ setcc(X86_64IntegerCondition(cond->GetCondition()), reg);
return;
case Primitive::kPrimFloat: {
XmmRegister lhs_reg = lhs.AsFpuRegister<XmmRegister>();
@@ -1231,12 +1213,12 @@
// Convert the jumps into the result.
Label done_label;
- // false case: result = 0;
+ // False case: result = 0.
__ Bind(&false_label);
__ xorl(reg, reg);
__ jmp(&done_label);
- // True case: result = 1
+ // True case: result = 1.
__ Bind(&true_label);
__ movl(reg, Immediate(1));
__ Bind(&done_label);