add isTerminatortto b and bcond
[oota-llvm.git] / lib / Target / ARM / ARMISelDAGToDAG.cpp
index 0423cc8c6ccf4306d800c03e3806beff0253fbd4..283d0f18c796fea04341ba4189eff44cf21066fb 100644 (file)
@@ -70,6 +70,16 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::BR_CC, MVT::f32, Custom);
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
 
+  setOperationAction(ISD::BRCOND,        MVT::Other, Expand);
+
+  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SDIV,      MVT::i32, Expand);
+  setOperationAction(ISD::UDIV,      MVT::i32, Expand);
+  setOperationAction(ISD::SREM,      MVT::i32, Expand);
+  setOperationAction(ISD::UREM,      MVT::i32, Expand);
+
   setOperationAction(ISD::VASTART,       MVT::Other, Custom);
   setOperationAction(ISD::VAEND,         MVT::Other, Expand);
 
@@ -92,7 +102,6 @@ namespace llvm {
       RET_FLAG,
 
       CMP,
-      CMPE,
 
       SELECT,
 
@@ -120,36 +129,42 @@ namespace llvm {
 }
 
 /// DAGFPCCToARMCC - Convert a DAG fp condition code to an ARM CC
+// Unordered = !N & !Z & C & V = V
+// Ordered   =  N | Z | !C | !V = N | Z | !V
 static ARMCC::CondCodes DAGFPCCToARMCC(ISD::CondCode CC) {
   switch (CC) {
   default:
     assert(0 && "Unknown fp condition code!");
-// For the following conditions we use a comparison that throws exceptions,
-// so we may assume that V=0
+// SETOEQ = (N | Z | !V) & Z = Z                               = EQ
+  case ISD::SETEQ:
   case ISD::SETOEQ: return ARMCC::EQ;
+// SETOGT = (N | Z | !V) & !N & !Z = !V &!N &!Z = (N = V) & !Z = GT
+  case ISD::SETGT:
   case ISD::SETOGT: return ARMCC::GT;
+// SETOGE = (N | Z | !V) & !N = (Z | !V) & !N = !V & !N        = GE
+  case ISD::SETGE:
   case ISD::SETOGE: return ARMCC::GE;
-  case ISD::SETOLT: return ARMCC::LT;
-  case ISD::SETOLE: return ARMCC::LE;
+// SETOLT = (N | Z | !V) & N = N                               = MI
+  case ISD::SETLT:
+  case ISD::SETOLT: return ARMCC::MI;
+// SETOLE = (N | Z | !V) & (N | Z) = N | Z = !C | Z            = LS
+  case ISD::SETLE:
+  case ISD::SETOLE: return ARMCC::LS;
+// SETONE = (N | Z | !V) & !Z = (N | !V) & Z = !V & Z = Z      = NE
+  case ISD::SETNE:
   case ISD::SETONE: return ARMCC::NE;
-// For the following conditions the result is undefined in case of a nan,
-// so we may assume that V=0
-  case ISD::SETEQ:  return ARMCC::EQ;
-  case ISD::SETGT:  return ARMCC::GT;
-  case ISD::SETGE:  return ARMCC::GE;
-  case ISD::SETLT:  return ARMCC::LT;
-  case ISD::SETLE:  return ARMCC::LE;
-  case ISD::SETNE:  return ARMCC::NE;
-// For the following we may not assume anything
-//    SETO      =  N | Z | !C | !V              = ???
-//    SETUO     = (!N & !Z & C & V)             = ???
-//    SETUEQ    = (!N & !Z & C & V) | Z         = ???
-//    SETUGT    = (!N & !Z & C & V) | (!Z & !N) = ???
-//    SETUGE    = (!N & !Z & C & V) | !N        = !N  = PL
+// SETO   = N | Z | !V = Z | !V = !V                           = VC
+  case ISD::SETO:   return ARMCC::VC;
+// SETUO  = V                                                  = VS
+  case ISD::SETUO:  return ARMCC::VS;
+// SETUEQ = V | Z                                              = ??
+// SETUGT = V | (!Z & !N) = !Z & !N = !Z & C                   = HI
+  case ISD::SETUGT: return ARMCC::HI;
+// SETUGE = V | !N = !N                                        = PL
   case ISD::SETUGE: return ARMCC::PL;
-//    SETULT    = (!N & !Z & C & V) | N         = ???
-//    SETULE    = (!N & !Z & C & V) | Z | N     = ???
-//    SETUNE    = (!N & !Z & C & V) | !Z        = !Z  = NE
+// SETULT = V | N                                              = ??
+// SETULE = V | Z | N                                          = ??
+// SETUNE = V | !Z = !Z                                        = NE
   case ISD::SETUNE: return ARMCC::NE;
   }
 }
@@ -179,7 +194,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case ARMISD::RET_FLAG:      return "ARMISD::RET_FLAG";
   case ARMISD::SELECT:        return "ARMISD::SELECT";
   case ARMISD::CMP:           return "ARMISD::CMP";
-  case ARMISD::CMPE:          return "ARMISD::CMPE";
   case ARMISD::BR:            return "ARMISD::BR";
   case ARMISD::FSITOS:        return "ARMISD::FSITOS";
   case ARMISD::FTOSIS:        return "ARMISD::FTOSIS";
@@ -280,7 +294,9 @@ public:
 static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Chain    = Op.getOperand(0);
   unsigned CallConv  = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
-  assert(CallConv == CallingConv::C && "unknown calling convention");
+  assert((CallConv == CallingConv::C ||
+          CallConv == CallingConv::Fast)
+         && "unknown calling convention");
   bool isVarArg      = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
   bool isTailCall    = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
   SDOperand Callee   = Op.getOperand(4);
@@ -309,18 +325,20 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
     unsigned ArgOffset = Layout.getOffset(i);
     SDOperand   PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
     PtrOff             = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
-    MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff,
-                                       DAG.getSrcValue(NULL)));
+    MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
   }
   if (!MemOpChains.empty())
     Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
                         &MemOpChains[0], MemOpChains.size());
 
-  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
-  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
-  // node so that legalize doesn't hack it.
+  // If the callee is a GlobalAddress node (quite common, every direct call is)
+  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+  // Likewise ExternalSymbol -> TargetExternalSymbol.
+  assert(Callee.getValueType() == MVT::i32);
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
 
   // If this is a direct call, pass the chain and the callee.
   assert (Callee.Val);
@@ -490,7 +508,9 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
   // memory location argument.
   MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
   SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
-  return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), Op.getOperand(2));
+  SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
+  return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
+                      SV->getOffset());
 }
 
 static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
@@ -566,8 +586,7 @@ static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
       MF.addLiveIn(REGS[RegNo], VReg);
 
       SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
-      SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN,
-                                     DAG.getSrcValue(NULL));
+      SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
       MemOps.push_back(Store);
     }
     Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
@@ -586,15 +605,7 @@ static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
   MVT::ValueType vt = LHS.getValueType();
   assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
 
-  bool isOrderedFloat = (vt == MVT::f32 || vt == MVT::f64) &&
-    (CC >= ISD::SETOEQ && CC <= ISD::SETONE);
-
-  SDOperand Cmp;
-  if (isOrderedFloat) {
-    Cmp = DAG.getNode(ARMISD::CMPE, MVT::Flag, LHS, RHS);
-  } else {
-    Cmp = DAG.getNode(ARMISD::CMP,  MVT::Flag, LHS, RHS);
-  }
+  SDOperand Cmp = DAG.getNode(ARMISD::CMP,  MVT::Flag, LHS, RHS);
 
   if (vt != MVT::i32)
     Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
@@ -732,6 +743,7 @@ public:
   bool SelectAddrRegImm(SDOperand N, SDOperand &Offset, SDOperand &Base);
   bool SelectAddrMode1(SDOperand N, SDOperand &Arg, SDOperand &Shift,
                       SDOperand &ShiftType);
+  bool SelectAddrMode5(SDOperand N, SDOperand &Arg, SDOperand &Offset);
 
   // Include the pieces autogenerated from the target description.
 #include "ARMGenDAGISel.inc"
@@ -830,6 +842,14 @@ bool ARMDAGToDAGISel::SelectAddrMode1(SDOperand N,
   return true;
 }
 
+bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand N, SDOperand &Arg,
+                                      SDOperand &Offset) {
+  //TODO: detect offset
+  Offset = CurDAG->getTargetConstant(0, MVT::i32);
+  Arg    = N;
+  return true;
+}
+
 //register plus/minus 12 bit offset
 bool ARMDAGToDAGISel::SelectAddrRegImm(SDOperand N, SDOperand &Offset,
                                    SDOperand &Base) {