Optimized FCMP_OEQ and FCMP_UNE for x86.
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index 05db7cb886b7cc0f929a26674ef545a3b8c8e916..ebf9eecf208e7e40d0d1f5e01057057baa4dddcf 100644 (file)
@@ -5100,6 +5100,71 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
       Cond = Cmp;
       addTest = false;
     }
+  // Also, recognize the pattern generated by an FCMP_UNE. We can emit
+  // two branches instead of an explicit OR instruction with a
+  // separate test.
+  } else if (Cond.getOpcode() == ISD::OR &&
+             Cond.hasOneUse() &&
+             Cond.getOperand(0).getOpcode() == X86ISD::SETCC &&
+             Cond.getOperand(0).hasOneUse() &&
+             Cond.getOperand(1).getOpcode() == X86ISD::SETCC &&
+             Cond.getOperand(1).hasOneUse()) {
+    SDValue Cmp = Cond.getOperand(0).getOperand(1);
+    unsigned Opc = Cmp.getOpcode();
+    if (Cmp == Cond.getOperand(1).getOperand(1) &&
+        (Opc == X86ISD::CMP ||
+         Opc == X86ISD::COMI ||
+         Opc == X86ISD::UCOMI)) {
+      CC = Cond.getOperand(0).getOperand(0);
+      Chain = DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
+                          Chain, Dest, CC, Cmp);
+      CC = Cond.getOperand(1).getOperand(0);
+      Cond = Cmp;
+      addTest = false;
+    }
+  // Also, recognize the pattern generated by an FCMP_OEQ. We can emit
+  // two branches instead of an explicit AND instruction with a
+  // separate test. However, we only do this if this block doesn't
+  // have a fall-through edge, because this requires an explicit
+  // jmp when the condition is false.
+  } else if (Cond.getOpcode() == ISD::AND &&
+             Cond.hasOneUse() &&
+             Cond.getOperand(0).getOpcode() == X86ISD::SETCC &&
+             Cond.getOperand(0).hasOneUse() &&
+             Cond.getOperand(1).getOpcode() == X86ISD::SETCC &&
+             Cond.getOperand(1).hasOneUse()) {
+    SDValue Cmp = Cond.getOperand(0).getOperand(1);
+    unsigned Opc = Cmp.getOpcode();
+    if (Cmp == Cond.getOperand(1).getOperand(1) &&
+        (Opc == X86ISD::CMP ||
+         Opc == X86ISD::COMI ||
+         Opc == X86ISD::UCOMI) &&
+        Op.getNode()->hasOneUse()) {
+      X86::CondCode CCode =
+        (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0);
+      CCode = X86::GetOppositeBranchCondition(CCode);
+      CC = DAG.getConstant(CCode, MVT::i8);
+      SDValue User = SDValue(*Op.getNode()->use_begin(), 0);
+      // Look for an unconditional branch following this conditional branch.
+      // We need this because we need to reverse the successors in order
+      // to implement FCMP_OEQ.
+      if (User.getOpcode() == ISD::BR) {
+        SDValue FalseBB = User.getOperand(1);
+        SDValue NewBR =
+          DAG.UpdateNodeOperands(User, User.getOperand(0), Dest);
+        assert(NewBR == User);
+        Dest = FalseBB;
+
+        Chain = DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
+                            Chain, Dest, CC, Cmp);
+        X86::CondCode CCode =
+          (X86::CondCode)Cond.getOperand(1).getConstantOperandVal(0);
+        CCode = X86::GetOppositeBranchCondition(CCode);
+        CC = DAG.getConstant(CCode, MVT::i8);
+        Cond = Cmp;
+        addTest = false;
+      }
+    }
   }
 
   if (addTest) {
@@ -5107,7 +5172,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) {
     Cond= DAG.getNode(X86ISD::CMP, MVT::i32, Cond, DAG.getConstant(0, MVT::i8));
   }
   return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
-                     Chain, Op.getOperand(2), CC, Cond);
+                     Chain, Dest, CC, Cond);
 }