SelectNodeTo() may return a SDOperand that is different from the input.
[oota-llvm.git] / lib / Target / Sparc / SparcISelDAGToDAG.cpp
index dba02c08cde61e298d54a9c447a8698821b2f9e7..fd224703c69b7b6cf04593e163444119834b9966 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"
@@ -24,6 +25,7 @@
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Support/Debug.h"
 #include <iostream>
+#include <queue>
 #include <set>
 using namespace llvm;
 
@@ -47,7 +49,7 @@ namespace SPISD {
     ITOF,        // Int to FP within a FP register.
 
     CALL,        // A call instruction.
-    RET_FLAG,    // Return with a flag operand.
+    RET_FLAG     // Return with a flag operand.
   };
 }
 
@@ -74,12 +76,18 @@ static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
 static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
   switch (CC) {
   default: assert(0 && "Unknown fp condition code!");
-  case ISD::SETEQ:  return SPCC::FCC_E;
-  case ISD::SETNE:  return SPCC::FCC_NE;
-  case ISD::SETLT:  return SPCC::FCC_L;
-  case ISD::SETGT:  return SPCC::FCC_G;
-  case ISD::SETLE:  return SPCC::FCC_LE;
-  case ISD::SETGE:  return SPCC::FCC_GE;
+  case ISD::SETEQ:
+  case ISD::SETOEQ: return SPCC::FCC_E;
+  case ISD::SETNE:
+  case ISD::SETUNE: return SPCC::FCC_NE;
+  case ISD::SETLT:
+  case ISD::SETOLT: return SPCC::FCC_L;
+  case ISD::SETGT:
+  case ISD::SETOGT: return SPCC::FCC_G;
+  case ISD::SETLE:
+  case ISD::SETOLE: return SPCC::FCC_LE;
+  case ISD::SETGE:
+  case ISD::SETOGE: return SPCC::FCC_GE;
   case ISD::SETULT: return SPCC::FCC_UL;
   case ISD::SETULE: return SPCC::FCC_ULE;
   case ISD::SETUGT: return SPCC::FCC_UG;
@@ -98,11 +106,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);
@@ -163,8 +174,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);
@@ -188,6 +198,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);
@@ -211,7 +223,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);
@@ -246,20 +258,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.
@@ -422,7 +444,8 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
   }
   
   if (!OutChains.empty())
-    DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains));
+    DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other,
+                            &OutChains[0], OutChains.size()));
   
   // Finally, inform the code generator which regs we return values in.
   switch (getValueType(F.getReturnType())) {
@@ -454,7 +477,6 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
                                  bool isVarArg, unsigned CC,
                                  bool isTailCall, SDOperand Callee, 
                                  ArgListTy &Args, SelectionDAG &DAG) {
-  MachineFunction &MF = DAG.getMachineFunction();
   // Count the size of the outgoing arguments.
   unsigned ArgsSize = 0;
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
@@ -544,9 +566,9 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
       }
       
       // Split the value into top and bottom part.  Top part goes in a reg.
-      SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val, 
+      SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, getPointerTy(), Val, 
                                  DAG.getConstant(1, MVT::i32));
-      SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val,
+      SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, getPointerTy(), Val,
                                  DAG.getConstant(0, MVT::i32));
       RegValuesToPass.push_back(Hi);
       
@@ -575,7 +597,7 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
   
   // Emit all stores, make sure the occur before any copies into physregs.
   if (!Stores.empty())
-    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
+    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0],Stores.size());
   
   static const unsigned ArgRegs[] = {
     SP::O0, SP::O1, SP::O2, SP::O3, SP::O4, SP::O5
@@ -600,12 +622,8 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
   std::vector<MVT::ValueType> NodeTys;
   NodeTys.push_back(MVT::Other);   // Returns a chain
   NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
-  std::vector<SDOperand> Ops;
-  Ops.push_back(Chain);
-  Ops.push_back(Callee);
-  if (InFlag.Val)
-    Ops.push_back(InFlag);
-  Chain = DAG.getNode(SPISD::CALL, NodeTys, Ops);
+  SDOperand Ops[] = { Chain, Callee, InFlag };
+  Chain = DAG.getNode(SPISD::CALL, NodeTys, Ops, InFlag.Val ? 3 : 2);
   InFlag = Chain.getValue(1);
   
   MVT::ValueType RetTyVT = getValueType(RetTy);
@@ -722,10 +740,8 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       std::vector<MVT::ValueType> VTs;
       VTs.push_back(MVT::i32);
       VTs.push_back(MVT::Flag);
-      std::vector<SDOperand> Ops;
-      Ops.push_back(LHS);
-      Ops.push_back(RHS);
-      CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops).getValue(1);
+      SDOperand Ops[2] = { LHS, RHS };
+      CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops, 2).getValue(1);
       if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
       Opc = SPISD::BRICC;
     } else {
@@ -753,10 +769,8 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       std::vector<MVT::ValueType> VTs;
       VTs.push_back(LHS.getValueType());   // subcc returns a value
       VTs.push_back(MVT::Flag);
-      std::vector<SDOperand> Ops;
-      Ops.push_back(LHS);
-      Ops.push_back(RHS);
-      CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops).getValue(1);
+      SDOperand Ops[2] = { LHS, RHS };
+      CompareFlag = DAG.getNode(SPISD::CMPICC, VTs, Ops, 2).getValue(1);
       Opc = SPISD::SELECT_ICC;
       if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
     } else {
@@ -800,13 +814,31 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       std::vector<MVT::ValueType> Tys;
       Tys.push_back(MVT::f64);
       Tys.push_back(MVT::Other);
-      std::vector<SDOperand> Ops;
       // Bit-Convert the value to f64.
-      Ops.push_back(DAG.getNode(ISD::BIT_CONVERT, MVT::f64, V));
-      Ops.push_back(V.getValue(1));
-      return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
+      SDOperand Ops[2] = { DAG.getNode(ISD::BIT_CONVERT, MVT::f64, V),
+                           V.getValue(1) };
+      return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2);
     }
   }
+  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);
+    SDOperand Ops[2] = { NewVal, Chain };
+    return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops, 2);
+  }
   case ISD::RET: {
     SDOperand Copy;
     
@@ -816,7 +848,7 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
       abort();
     case 1: 
       return SDOperand(); // ret void is legal
-    case 2: {
+    case 3: {
       unsigned ArgReg;
       switch(Op.getOperand(1).getValueType()) {
       default: assert(0 && "Unknown type to return!");
@@ -828,8 +860,8 @@ LowerOperation(SDOperand Op, SelectionDAG &DAG) {
                               SDOperand());
       break;
     }
-    case 3:
-      Copy = DAG.getCopyToReg(Op.getOperand(0), SP::I0, Op.getOperand(2), 
+    case 5:
+      Copy = DAG.getCopyToReg(Op.getOperand(0), SP::I0, Op.getOperand(3), 
                               SDOperand());
       Copy = DAG.getCopyToReg(Copy, SP::I1, Op.getOperand(1), Copy.getValue(1));
       break;
@@ -881,7 +913,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);
   
@@ -926,7 +966,7 @@ public:
       Subtarget(TM.getSubtarget<SparcSubtarget>()) {
   }
 
-  void Select(SDOperand &Result, SDOperand Op);
+  SDNode *Select(SDOperand &Result, SDOperand Op);
 
   // Complex Pattern Selectors.
   bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
@@ -952,7 +992,6 @@ void SparcDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
   
   // Select target instructions for the DAG.
   DAG.setRoot(SelectRoot(DAG.getRoot()));
-  CodeGenMap.clear();
   DAG.RemoveDeadNodes();
   
   // Emit machine code to BB. 
@@ -1024,64 +1063,22 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1,
   return true;
 }
 
-void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
+SDNode *SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
   SDNode *N = Op.Val;
   if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
       N->getOpcode() < SPISD::FIRST_NUMBER) {
     Result = Op;
-    return;   // Already selected.
+    return NULL;   // Already selected.
   }
 
-                 // If this has already been converted, use it.
-  std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
-  if (CGMI != CodeGenMap.end()) {
-    Result = CGMI->second;
-    return;
-  }
-  
   switch (N->getOpcode()) {
   default: break;
-  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.
     SDOperand DivLHS, DivRHS;
-    Select(DivLHS, N->getOperand(0));
-    Select(DivRHS, N->getOperand(1));
+    AddToQueue(DivLHS, N->getOperand(0));
+    AddToQueue(DivRHS, N->getOperand(1));
     
     // Set the Y register to the high-part.
     SDOperand TopPart;
@@ -1096,25 +1093,25 @@ void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
 
     // FIXME: Handle div by immediate.
     unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
-    Result = CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
-    return;
+    return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS,
+                                TopPart).Val;
   }    
   case ISD::MULHU:
   case ISD::MULHS: {
     // FIXME: Handle mul by immediate.
     SDOperand MulLHS, MulRHS;
-    Select(MulLHS, N->getOperand(0));
-    Select(MulRHS, N->getOperand(1));
+    AddToQueue(MulLHS, N->getOperand(0));
+    AddToQueue(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);
     // The high part is in the Y register.
-    Result = CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1));
-    return;
+    return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1)).Val;
+    return NULL;
   }
   }
   
-  SelectCode(Result, Op);
+  return SelectCode(Result, Op);
 }