JumpTable support! What this represents is working asm and jit support for
[oota-llvm.git] / lib / Target / Sparc / SparcISelDAGToDAG.cpp
index a58b2c165400b88737976945b86920193a3b5bd8..a910b3e0473e888bb7571cffb5b19858de99d0bd 100644 (file)
@@ -15,6 +15,7 @@
 #include "SparcTargetMachine.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
+#include "llvm/Intrinsics.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -98,11 +99,14 @@ namespace {
     SparcTargetLowering(TargetMachine &TM);
     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
     
-    /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
-    /// be zero. Op is expected to be a target specific node. Used by DAG
-    /// combiner.
-    virtual bool isMaskedValueZeroForTargetNode(const SDOperand &Op,
-                                                uint64_t Mask) const;
+    /// computeMaskedBitsForTargetNode - Determine which of the bits specified 
+    /// in Mask are known to be either zero or one and return them in the 
+    /// KnownZero/KnownOne bitsets.
+    virtual void computeMaskedBitsForTargetNode(const SDOperand Op,
+                                                uint64_t Mask,
+                                                uint64_t &KnownZero, 
+                                                uint64_t &KnownOne,
+                                                unsigned Depth = 0) const;
     
     virtual std::vector<SDOperand>
       LowerArguments(Function &F, SelectionDAG &DAG);
@@ -111,9 +115,6 @@ namespace {
                   unsigned CC,
                   bool isTailCall, SDOperand Callee, ArgListTy &Args,
                   SelectionDAG &DAG);
-    virtual std::pair<SDOperand, SDOperand>
-      LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
-                              SelectionDAG &DAG);
     virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
                                                        MachineBasicBlock *MBB);
     
@@ -166,8 +167,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
   
   // Sparc doesn't have BRCOND either, it has BR_CC.
   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
-  setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
-  setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
+  setOperationAction(ISD::BRIND, MVT::i32, Expand);
   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
   setOperationAction(ISD::BR_CC, MVT::f32, Custom);
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
@@ -191,6 +191,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::ROTL , MVT::i32, Expand);
   setOperationAction(ISD::ROTR , MVT::i32, Expand);
   setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+  setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
+  setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
 
   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
@@ -214,7 +216,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::VAEND             , MVT::Other, Expand);
   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); 
   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
-  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
+  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom);
 
   setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
   setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
@@ -249,20 +251,30 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
 /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
 /// be zero. Op is expected to be a target specific node. Used by DAG
 /// combiner.
-bool SparcTargetLowering::
-isMaskedValueZeroForTargetNode(const SDOperand &Op, uint64_t Mask) const {
+void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
+                                                         uint64_t Mask,
+                                                         uint64_t &KnownZero, 
+                                                         uint64_t &KnownOne,
+                                                         unsigned Depth) const {
+  uint64_t KnownZero2, KnownOne2;
+  KnownZero = KnownOne = 0;   // Don't know anything.
+  
   switch (Op.getOpcode()) {
-  default: return false; 
+  default: break;
   case SPISD::SELECT_ICC:
   case SPISD::SELECT_FCC:
-    assert(MVT::isInteger(Op.getValueType()) && "Not an integer select!");
-    // These operations are masked zero if both the left and the right are zero.
-    return MaskedValueIsZero(Op.getOperand(0), Mask) &&
-           MaskedValueIsZero(Op.getOperand(1), Mask);
+    ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
+    ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+    assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 
+    assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 
+    
+    // Only known if known in both the LHS and RHS.
+    KnownOne &= KnownOne2;
+    KnownZero &= KnownZero2;
+    break;
   }
 }
 
-
 /// LowerArguments - V8 uses a very simple ABI, where all values are passed in
 /// either one or two GPRs, including FP values.  TODO: we should pass FP values
 /// in FP registers for fastcc functions.
@@ -484,8 +496,7 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
   // Keep stack frames 8-byte aligned.
   ArgsSize = (ArgsSize+7) & ~7;
 
-  Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
-                      DAG.getConstant(ArgsSize, getPointerTy()));
+  Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(ArgsSize, getPointerTy()));
   
   SDOperand StackPtr, NullSV;
   std::vector<SDOperand> Stores;
@@ -595,8 +606,11 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
 
   // 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.
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
 
   std::vector<MVT::ValueType> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
@@ -653,13 +667,6 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
   return std::make_pair(RetVal, Chain);
 }
 
-std::pair<SDOperand, SDOperand> SparcTargetLowering::
-LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
-                        SelectionDAG &DAG) {
-  assert(0 && "Unimp");
-  abort();
-}
-
 // Look at LHS/RHS/CC and see if they are a lowered setcc instruction.  If so
 // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
 static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS,
@@ -815,6 +822,27 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
     }
   }
+  case ISD::DYNAMIC_STACKALLOC: {
+    SDOperand Chain = Op.getOperand(0);  // Legalize the chain.
+    SDOperand Size  = Op.getOperand(1);  // Legalize the size.
+    
+    unsigned SPReg = SP::O6;
+    SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, MVT::i32);
+    SDOperand NewSP = DAG.getNode(ISD::SUB, MVT::i32, SP, Size);    // Value
+    Chain = DAG.getCopyToReg(SP.getValue(1), SPReg, NewSP);      // Output chain
+
+    // The resultant pointer is actually 16 words from the bottom of the stack,
+    // to provide a register spill area.
+    SDOperand NewVal = DAG.getNode(ISD::ADD, MVT::i32, NewSP,
+                                   DAG.getConstant(96, MVT::i32));
+    std::vector<MVT::ValueType> Tys;
+    Tys.push_back(MVT::i32);
+    Tys.push_back(MVT::Other);
+    std::vector<SDOperand> Ops;
+    Ops.push_back(NewVal);
+    Ops.push_back(Chain);
+    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
+  }
   case ISD::RET: {
     SDOperand Copy;
     
@@ -889,7 +917,15 @@ SparcTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
   MachineFunction *F = BB->getParent();
   F->getBasicBlockList().insert(It, copy0MBB);
   F->getBasicBlockList().insert(It, sinkMBB);
-  // Update machine-CFG edges
+  // Update machine-CFG edges by first adding all successors of the current
+  // block to the new block which will contain the Phi node for the select.
+  for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), 
+      e = BB->succ_end(); i != e; ++i)
+    sinkMBB->addSuccessor(*i);
+  // Next, remove all successors of the current block, and add the true
+  // and fallthrough blocks as its successors.
+  while(!BB->succ_empty())
+    BB->removeSuccessor(BB->succ_begin());
   BB->addSuccessor(copy0MBB);
   BB->addSuccessor(sinkMBB);
   
@@ -974,6 +1010,9 @@ bool SparcDAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
     Offset = CurDAG->getTargetConstant(0, MVT::i32);
     return true;
   }
+  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+      Addr.getOpcode() == ISD::TargetGlobalAddress)
+    return false;  // direct calls.
   
   if (Addr.getOpcode() == ISD::ADD) {
     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
@@ -1007,7 +1046,11 @@ bool SparcDAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
 
 bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1, 
                                      SDOperand &R2) {
-  if (Addr.getOpcode() == ISD::FrameIndex) return false; 
+  if (Addr.getOpcode() == ISD::FrameIndex) return false;
+  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+      Addr.getOpcode() == ISD::TargetGlobalAddress)
+    return false;  // direct calls.
+  
   if (Addr.getOpcode() == ISD::ADD) {
     if (isa<ConstantSDNode>(Addr.getOperand(1)) &&
         Predicate_simm13(Addr.getOperand(1).Val))
@@ -1042,56 +1085,6 @@ void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
   
   switch (N->getOpcode()) {
   default: break;
-  case ISD::FrameIndex: {
-    int FI = cast<FrameIndexSDNode>(N)->getIndex();
-    if (N->hasOneUse()) {
-      Result = CurDAG->SelectNodeTo(N, SP::ADDri, MVT::i32,
-                                    CurDAG->getTargetFrameIndex(FI, MVT::i32),
-                                    CurDAG->getTargetConstant(0, MVT::i32));
-      return;
-    }
-
-    Result = CodeGenMap[Op] = 
-      SDOperand(CurDAG->getTargetNode(SP::ADDri, MVT::i32,
-                                      CurDAG->getTargetFrameIndex(FI, MVT::i32),
-                                    CurDAG->getTargetConstant(0, MVT::i32)), 0);
-    return;
-  }
-  case ISD::ADD_PARTS: {
-    SDOperand LHSL, LHSH, RHSL, RHSH;
-    Select(LHSL, N->getOperand(0));
-    Select(LHSH, N->getOperand(1));
-    Select(RHSL, N->getOperand(2));
-    Select(RHSH, N->getOperand(3));
-    // FIXME, handle immediate RHS.
-    SDOperand Low =
-      SDOperand(CurDAG->getTargetNode(SP::ADDCCrr, MVT::i32, MVT::Flag,
-                                      LHSL, RHSL), 0);
-    SDOperand Hi =
-      SDOperand(CurDAG->getTargetNode(SP::ADDXrr, MVT::i32, LHSH, RHSH, 
-                                      Low.getValue(1)), 0);
-    CodeGenMap[SDOperand(N, 0)] = Low;
-    CodeGenMap[SDOperand(N, 1)] = Hi;
-    Result = Op.ResNo ? Hi : Low;
-    return;
-  }
-  case ISD::SUB_PARTS: {
-    SDOperand LHSL, LHSH, RHSL, RHSH;
-    Select(LHSL, N->getOperand(0));
-    Select(LHSH, N->getOperand(1));
-    Select(RHSL, N->getOperand(2));
-    Select(RHSH, N->getOperand(3));
-    SDOperand Low =
-      SDOperand(CurDAG->getTargetNode(SP::SUBCCrr, MVT::i32, MVT::Flag,
-                                      LHSL, RHSL), 0);
-    SDOperand Hi =
-      SDOperand(CurDAG->getTargetNode(SP::SUBXrr, MVT::i32, LHSH, RHSH, 
-                                      Low.getValue(1)), 0);
-    CodeGenMap[SDOperand(N, 0)] = Low;
-    CodeGenMap[SDOperand(N, 1)] = Hi;
-    Result = Op.ResNo ? Hi : Low;
-    return;
-  }
   case ISD::SDIV:
   case ISD::UDIV: {
     // FIXME: should use a custom expander to expose the SRA to the dag.
@@ -1123,39 +1116,11 @@ void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
     Select(MulRHS, N->getOperand(1));
     unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
     SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag,
-                                          MulLHS, MulRHS);
+                                        MulLHS, MulRHS);
     // The high part is in the Y register.
     Result = CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1));
     return;
   }
-  case SPISD::CALL:
-    // FIXME: This is a workaround for a bug in tblgen.
-  { // Pattern #47: (call:Flag (tglobaladdr:i32):$dst, ICC:Flag)
-    // Emits: (CALL:void (tglobaladdr:i32):$dst)
-    // Pattern complexity = 2  cost = 1
-    SDOperand N1 = N->getOperand(1);
-    if (N1.getOpcode() != ISD::TargetGlobalAddress &&
-        N1.getOpcode() != ISD::ExternalSymbol) goto P47Fail;
-    SDOperand InFlag = SDOperand(0, 0);
-    SDOperand Chain = N->getOperand(0);
-    SDOperand Tmp0 = N1;
-    Select(Chain, Chain);
-    SDNode *ResNode;
-    if (N->getNumOperands() == 3) {
-      Select(InFlag, N->getOperand(2));
-      ResNode = CurDAG->getTargetNode(SP::CALL, MVT::Other, MVT::Flag, Tmp0, 
-                                      Chain, InFlag);
-    } else {
-      ResNode = CurDAG->getTargetNode(SP::CALL, MVT::Other, MVT::Flag, Tmp0, 
-                                      Chain);
-    }
-    Chain = CodeGenMap[SDOperand(N, 0)] = SDOperand(ResNode, 0);
-     CodeGenMap[SDOperand(N, 1)] = SDOperand(ResNode, 1);
-    Result = SDOperand(ResNode, Op.ResNo);
-    return;
-  }
-    P47Fail:;
-    
   }
   
   SelectCode(Result, Op);