initial support for fp compares. Unordered compares not implemented yet
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 10 Oct 2006 12:56:00 +0000 (12:56 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 10 Oct 2006 12:56:00 +0000 (12:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30854 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMInstrInfo.td

index b3d1cfbe7d107603b32610ceeff8e56889b68e85..559873389021dfdca78bc49fba784a14f38ec2a2 100644 (file)
@@ -60,8 +60,13 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::SELECT, MVT::i32, Expand);
 
   setOperationAction(ISD::SETCC, MVT::i32, Expand);
+  setOperationAction(ISD::SETCC, MVT::f32, Expand);
+  setOperationAction(ISD::SETCC, MVT::f64, Expand);
+
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+  setOperationAction(ISD::BR_CC, MVT::f32, Custom);
+  setOperationAction(ISD::BR_CC, MVT::f64, Custom);
 
   setOperationAction(ISD::VASTART,       MVT::Other, Custom);
   setOperationAction(ISD::VAEND,         MVT::Other, Expand);
@@ -100,12 +105,17 @@ namespace llvm {
 
       FMRRD,
 
-      FMDRR
+      FMDRR,
+
+      FMSTAT
     };
   }
 }
 
 /// DAGCCToARMCC - Convert a DAG integer condition code to an ARM CC
+//Note: ARM doesn't have condition codes corresponding to the ordered
+//condition codes of LLVM. We use exception raising instructions so
+//that we can be sure that V == 0 and test only the rest of the expression.
 static ARMCC::CondCodes DAGCCToARMCC(ISD::CondCode CC) {
   switch (CC) {
   default:
@@ -113,12 +123,17 @@ static ARMCC::CondCodes DAGCCToARMCC(ISD::CondCode CC) {
     assert(0 && "Unknown condition code!");
   case ISD::SETUGT: return ARMCC::HI;
   case ISD::SETULE: return ARMCC::LS;
-  case ISD::SETLE:  return ARMCC::LE;
-  case ISD::SETLT:  return ARMCC::LT;
-  case ISD::SETGT:  return ARMCC::GT;
+  case ISD::SETLE:
+  case ISD::SETOLE: return ARMCC::LE;
+  case ISD::SETLT:
+  case ISD::SETOLT: return ARMCC::LT;
+  case ISD::SETGT:
+  case ISD::SETOGT: return ARMCC::GT;
   case ISD::SETNE:  return ARMCC::NE;
-  case ISD::SETEQ:  return ARMCC::EQ;
-  case ISD::SETGE:  return ARMCC::GE;
+  case ISD::SETEQ:
+  case ISD::SETOEQ: return ARMCC::EQ;
+  case ISD::SETGE:
+  case ISD::SETOGE: return ARMCC::GE;
   case ISD::SETUGE: return ARMCC::CS;
   case ISD::SETULT: return ARMCC::CC;
   }
@@ -138,6 +153,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case ARMISD::FUITOD:        return "ARMISD::FUITOD";
   case ARMISD::FMRRD:         return "ARMISD::FMRRD";
   case ARMISD::FMDRR:         return "ARMISD::FMDRR";
+  case ARMISD::FMSTAT:        return "ARMISD::FMSTAT";
   }
 }
 
@@ -520,15 +536,30 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
   return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size());
 }
 
+static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
+                        SelectionDAG &DAG) {
+  MVT::ValueType vt = LHS.getValueType();
+  assert(vt == MVT::i32 || vt == MVT::f32);
+  //Note: unordered floating point compares should use a non throwing
+  //compare.
+  bool isUnorderedFloat = vt == MVT::f32 &&
+    (CC >= ISD::SETUO && CC <= ISD::SETUNE);
+  assert(!isUnorderedFloat && "Unordered float compares are not supported");
+
+  SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
+  if (vt != MVT::i32)
+    Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
+  return Cmp;
+}
+
 static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
   SDOperand LHS = Op.getOperand(0);
   SDOperand RHS = Op.getOperand(1);
   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
   SDOperand TrueVal = Op.getOperand(2);
   SDOperand FalseVal = Op.getOperand(3);
+  SDOperand      Cmp = GetCMP(CC, LHS, RHS, DAG);
   SDOperand    ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
-
-  SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
   return DAG.getNode(ARMISD::SELECT, MVT::i32, TrueVal, FalseVal, ARMCC, Cmp);
 }
 
@@ -538,9 +569,8 @@ static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
   SDOperand    LHS = Op.getOperand(2);
   SDOperand    RHS = Op.getOperand(3);
   SDOperand   Dest = Op.getOperand(4);
+  SDOperand    Cmp = GetCMP(CC, LHS, RHS, DAG);
   SDOperand  ARMCC = DAG.getConstant(DAGCCToARMCC(CC), MVT::i32);
-
-  SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
   return DAG.getNode(ARMISD::BR, MVT::Other, Chain, Dest, ARMCC, Cmp);
 }
 
index 9d4649a558985fadad6f6858ecd6b125bf82b412..3371871a7c4daf5712c3c42971f8a597f8ca6212 100644 (file)
@@ -65,9 +65,11 @@ def retflag        : SDNode<"ARMISD::RET_FLAG", SDTRet,
                           [SDNPHasChain, SDNPOptInFlag]>;
 
 def SDTarmselect   : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0>, SDTCisVT<2, i32>]>;
-
 def armselect      : SDNode<"ARMISD::SELECT", SDTarmselect, [SDNPInFlag, SDNPOutFlag]>;
 
+def SDTarmfmstat   : SDTypeProfile<0, 0, []>;
+def armfmstat      : SDNode<"ARMISD::FMSTAT", SDTarmfmstat, [SDNPInFlag, SDNPOutFlag]>;
+
 def SDTarmbr       : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>;
 def armbr          : SDNode<"ARMISD::BR", SDTarmbr, [SDNPHasChain, SDNPInFlag]>;
 
@@ -171,6 +173,10 @@ def cmp      : InstARM<(ops IntRegs:$a, op_addr_mode1:$b),
                       "cmp $a, $b",
                       [(armcmp IntRegs:$a, addr_mode1:$b)]>;
 
+// Floating Point Compare
+def fcmpes  : InstARM<(ops FPRegs:$a, FPRegs:$b),
+                      "fcmpes $a, $b",
+                      [(armcmp FPRegs:$a, FPRegs:$b)]>;
 
 // Floating Point Conversion
 // We use bitconvert for moving the data between the register classes.
@@ -206,6 +212,8 @@ def FCVTDS  : InstARM<(ops DFPRegs:$dst, FPRegs:$src),
 def FCVTSD  : InstARM<(ops FPRegs:$dst, DFPRegs:$src),
                        "fcvtsd $dst, $src", [(set FPRegs:$dst, (fround DFPRegs:$src))]>;
 
+def FMSTAT  : InstARM<(ops ), "fmstat", [(armfmstat)]>;
+
 // Floating Point Arithmetic
 def FADDS   : InstARM<(ops FPRegs:$dst, FPRegs:$a, FPRegs:$b),
                        "fadds $dst, $a, $b",