Implemented fused branches for long and fp on x86.

Also marked mips fused branches as unimplemented.

Change-Id: I2d845874d73b03dfadcaf5a56d1d315bb1e63763
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index ca9d865..33ef0ad 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -1843,7 +1843,6 @@
           squashDupRangeChecks(cUnit, &tbb, mir, arrSreg, idxSreg);
         }
         break;
-#if defined(TARGET_ARM)
       case Instruction::CMPL_FLOAT:
       case Instruction::CMPL_DOUBLE:
       case Instruction::CMPG_FLOAT:
@@ -1913,7 +1912,6 @@
           }
         }
         break;
-#endif
       default:
         break;
     }
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index d49b329..e56e627 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -852,7 +852,6 @@
       storeValue(cUnit, rlDest, rlSrc);
       break;
     }
-#if defined(TARGET_ARM)
     case kMirOpFusedCmplFloat:
       genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
       break;
@@ -868,7 +867,6 @@
     case kMirOpFusedCmpLong:
       genFusedLongCmpBranch(cUnit, bb, mir);
       break;
-#endif
     default:
       break;
   }
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index a57d34a..2bf26e4 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -210,4 +210,10 @@
   return false;
 }
 
+void genFusedFPCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+                                bool gtBias, bool isDouble)
+{
+  UNIMPLEMENTED(FATAL) << "Need codegen for fused fp cmp branch";
+}
+
 } //  namespace art
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index 7712985..c304836 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -517,4 +517,9 @@
 #endif
 }
 
+void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
+{
+  UNIMPLEMENTED(FATAL) << "Need codegen for fused long cmp branch";
+}
+
 }  // namespace art
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