Implemented fused branches for long and fp on x86.
Also marked mips fused branches as unimplemented.
Change-Id: I2d845874d73b03dfadcaf5a56d1d315bb1e63763
diff --git a/src/compiler/codegen/x86/FP/X86FP.cc b/src/compiler/codegen/x86/FP/X86FP.cc
index 8cd32b4..4e56e1d 100644
--- a/src/compiler/codegen/x86/FP/X86FP.cc
+++ b/src/compiler/codegen/x86/FP/X86FP.cc
@@ -286,4 +286,74 @@
return false;
}
+void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+ bool gtBias, bool isDouble) {
+ LIR* labelList = cUnit->blockLabelList;
+ LIR* taken = &labelList[bb->taken->id];
+ LIR* notTaken = &labelList[bb->fallThrough->id];
+ LIR* branch = NULL;
+ RegLocation rlSrc1;
+ RegLocation rlSrc2;
+ if (isDouble) {
+ rlSrc1 = oatGetSrcWide(cUnit, mir, 0);
+ rlSrc2 = oatGetSrcWide(cUnit, mir, 2);
+ rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
+ newLIR2(cUnit, kX86UcomisdRR, S2D(rlSrc1.lowReg, rlSrc1.highReg),
+ S2D(rlSrc2.lowReg, rlSrc2.highReg));
+ } else {
+ rlSrc1 = oatGetSrc(cUnit, mir, 0);
+ rlSrc2 = oatGetSrc(cUnit, mir, 1);
+ rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
+ rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
+ newLIR2(cUnit, kX86UcomissRR, rlSrc1.lowReg, rlSrc2.lowReg);
+ }
+ ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
+ switch (ccode) {
+ case kCondEq:
+ if (gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = notTaken;
+ }
+ break;
+ case kCondNe:
+ if (!gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = taken;
+ }
+ break;
+ case kCondLt:
+ if (gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = notTaken;
+ }
+ ccode = kCondCs;
+ break;
+ case kCondLe:
+ if (gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = notTaken;
+ }
+ ccode = kCondLs;
+ break;
+ case kCondGt:
+ if (gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = taken;
+ }
+ ccode = kCondHi;
+ break;
+ case kCondGe:
+ if (gtBias) {
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondPE);
+ branch->target = taken;
+ }
+ ccode = kCondCc;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
+ }
+ opCondBranch(cUnit, ccode, taken);
+}
+
} // namespace art
diff --git a/src/compiler/codegen/x86/X86/Gen.cc b/src/compiler/codegen/x86/X86/Gen.cc
index adad05b..894202e 100644
--- a/src/compiler/codegen/x86/X86/Gen.cc
+++ b/src/compiler/codegen/x86/X86/Gen.cc
@@ -377,4 +377,44 @@
}
}
+void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) {
+ LIR* labelList = cUnit->blockLabelList;
+ LIR* taken = &labelList[bb->taken->id];
+ RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0);
+ RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2);
+ oatFlushAllRegs(cUnit);
+ oatLockCallTemps(cUnit); // Prepare for explicit register usage
+ loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
+ loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
+ ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
+ // Swap operands and condition code to prevent use of zero flag.
+ if (ccode == kCondLe || ccode == kCondGt) {
+ // Compute (r3:r2) = (r3:r2) - (r1:r0)
+ opRegReg(cUnit, kOpSub, r2, r0); // r2 = r2 - r0
+ opRegReg(cUnit, kOpSbc, r3, r1); // r3 = r3 - r1 - CF
+ } else {
+ // Compute (r1:r0) = (r1:r0) - (r3:r2)
+ opRegReg(cUnit, kOpSub, r0, r2); // r0 = r0 - r2
+ opRegReg(cUnit, kOpSbc, r1, r3); // r1 = r1 - r3 - CF
+ }
+ switch (ccode) {
+ case kCondEq:
+ case kCondNe:
+ opRegReg(cUnit, kOpOr, r0, r1); // r0 = r0 | r1
+ break;
+ case kCondLe:
+ ccode = kCondGe;
+ break;
+ case kCondGt:
+ ccode = kCondLt;
+ break;
+ case kCondLt:
+ case kCondGe:
+ break;
+ default:
+ LOG(FATAL) << "Unexpected ccode: " << (int)ccode;
+ }
+ opCondBranch(cUnit, ccode, taken);
+}
+
} // namespace art