Avoid issue on 64-bit hosts.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeDAG.cpp
index 0f0ba071c0c3367e6e809cd370975ac12af2de80..e370e4a89719c07535d178b886942776a0b0ee14 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
@@ -550,6 +551,93 @@ SDOperand ExpandFCOPYSIGNToBitwiseOps(SDNode *Node, MVT::ValueType NVT,
   return Result;
 }
 
+/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores.
+static
+SDOperand ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
+                               TargetLowering &TLI) {
+  assert(MVT::isInteger(ST->getStoredVT()) &&
+         "Non integer unaligned stores not implemented.");
+  int SVOffset = ST->getSrcValueOffset();
+  SDOperand Chain = ST->getChain();
+  SDOperand Ptr = ST->getBasePtr();
+  SDOperand Val = ST->getValue();
+  MVT::ValueType VT = Val.getValueType();
+  // Get the half-size VT
+  MVT::ValueType NewStoredVT = ST->getStoredVT() - 1;
+  int NumBits = MVT::getSizeInBits(NewStoredVT);
+  int Alignment = ST->getAlignment();
+  int IncrementSize = NumBits / 8;
+
+  // Divide the stored value in two parts.
+  SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+  SDOperand Lo = Val;
+  SDOperand Hi = DAG.getNode(ISD::SRL, VT, Val, ShiftAmount);
+
+  // Store the two parts
+  SDOperand Store1, Store2;
+  Store1 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Lo:Hi, Ptr,
+                             ST->getSrcValue(), SVOffset, NewStoredVT,
+                             ST->isVolatile(), Alignment);
+  Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                    DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+  Store2 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Hi:Lo, Ptr,
+                             ST->getSrcValue(), SVOffset + IncrementSize,
+                             NewStoredVT, ST->isVolatile(), Alignment);
+
+  return DAG.getNode(ISD::TokenFactor, MVT::Other, Store1, Store2);
+}
+
+/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads.
+static
+SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
+                              TargetLowering &TLI) {
+  assert(MVT::isInteger(LD->getLoadedVT()) &&
+         "Non integer unaligned loads not implemented.");
+  int SVOffset = LD->getSrcValueOffset();
+  SDOperand Chain = LD->getChain();
+  SDOperand Ptr = LD->getBasePtr();
+  MVT::ValueType VT = LD->getValueType(0);
+  MVT::ValueType NewLoadedVT = LD->getLoadedVT() - 1;
+  int NumBits = MVT::getSizeInBits(NewLoadedVT);
+  int Alignment = LD->getAlignment();
+  int IncrementSize = NumBits / 8;
+  ISD::LoadExtType HiExtType = LD->getExtensionType();
+
+  // If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD.
+  if (HiExtType == ISD::NON_EXTLOAD)
+    HiExtType = ISD::ZEXTLOAD;
+
+  // Load the value in two parts
+  SDOperand Lo, Hi;
+  if (TLI.isLittleEndian()) {
+    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+    Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+                        Alignment);
+  } else {
+    Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
+                        NewLoadedVT,LD->isVolatile(), Alignment);
+    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+                      DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+                        SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+                        Alignment);
+  }
+
+  // aggregate the two parts
+  SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+  SDOperand Result = DAG.getNode(ISD::SHL, VT, Hi, ShiftAmount);
+  Result = DAG.getNode(ISD::OR, VT, Result, Lo);
+
+  SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+                             Hi.getValue(1));
+
+  SDOperand Ops[] = { Result, TF };
+  return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other), Ops, 2);
+}
 
 /// LegalizeOp - We know that the specified value has a legal type, and
 /// that its operands are legal.  Now ensure that the operation itself
@@ -878,13 +966,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
-  case ISD::Constant:
+  case ISD::Constant: {
+    ConstantSDNode *CN = cast<ConstantSDNode>(Node);
+    unsigned opAction =
+      TLI.getOperationAction(ISD::Constant, CN->getValueType(0));
+
     // We know we don't need to expand constants here, constants only have one
     // value and we check that it is fine above.
 
-    // FIXME: Maybe we should handle things like targets that don't support full
-    // 32-bit immediates?
+    if (opAction == TargetLowering::Custom) {
+      Tmp1 = TLI.LowerOperation(Result, DAG);
+      if (Tmp1.Val)
+        Result = Tmp1;
+    }
     break;
+  }
   case ISD::ConstantFP: {
     // Spill FP immediates to the constant pool if the target cannot directly
     // codegen them.  Targets often have some immediate values that can be
@@ -957,7 +1053,23 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       AddLegalizedOperand(SDOperand(Node, i), Tmp1);
     }
     return Tmp2;
-        
+   case ISD::EXTRACT_SUBREG: {
+      Tmp1 = LegalizeOp(Node->getOperand(0));
+      ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(1));
+      assert(idx && "Operand must be a constant");
+      Tmp2 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+    }
+    break;
+  case ISD::INSERT_SUBREG: {
+      Tmp1 = LegalizeOp(Node->getOperand(0));
+      Tmp2 = LegalizeOp(Node->getOperand(1));      
+      ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(2));
+      assert(idx && "Operand must be a constant");
+      Tmp3 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+    }
+    break;      
   case ISD::BUILD_VECTOR:
     switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
     default: assert(0 && "This action is not supported yet!");
@@ -1244,6 +1356,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
     return Result.getValue(Op.ResNo);
   case ISD::DYNAMIC_STACKALLOC: {
+    MVT::ValueType VT = Node->getValueType(0);
     Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
     Tmp2 = LegalizeOp(Node->getOperand(1));  // Legalize the size.
     Tmp3 = LegalizeOp(Node->getOperand(2));  // Legalize the alignment.
@@ -1251,8 +1364,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
 
     Tmp1 = Result.getValue(0);
     Tmp2 = Result.getValue(1);
-    switch (TLI.getOperationAction(Node->getOpcode(),
-                                   Node->getValueType(0))) {
+    switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
     default: assert(0 && "This action is not supported yet!");
     case TargetLowering::Expand: {
       unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
@@ -1260,9 +1372,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
              " not tell us which reg is the stack pointer!");
       SDOperand Chain = Tmp1.getOperand(0);
       SDOperand Size  = Tmp2.getOperand(1);
-      SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, Node->getValueType(0));
-      Tmp1 = DAG.getNode(ISD::SUB, Node->getValueType(0), SP, Size);    // Value
-      Tmp2 = DAG.getCopyToReg(SP.getValue(1), SPReg, Tmp1);      // Output chain
+      SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
+      Chain = SP.getValue(1);
+      unsigned Align = cast<ConstantSDNode>(Tmp3)->getValue();
+      unsigned StackAlign =
+        TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
+      if (Align > StackAlign)
+        SP = DAG.getNode(ISD::AND, VT, SP,
+                         DAG.getConstant(-(uint64_t)Align, VT));
+      Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size);       // Value
+      Tmp2 = DAG.getCopyToReg(Chain, SPReg, Tmp1);      // Output chain
       Tmp1 = LegalizeOp(Tmp1);
       Tmp2 = LegalizeOp(Tmp2);
       break;
@@ -1491,7 +1610,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     
       switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
       default: assert(0 && "This action is not supported yet!");
-      case TargetLowering::Legal: break;
+      case TargetLowering::Legal:
+        // If this is an unaligned load and the target doesn't support it,
+        // expand it.
+        if (!TLI.allowsUnalignedMemoryAccesses()) {
+          unsigned ABIAlignment = TLI.getTargetData()->
+            getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+          if (LD->getAlignment() < ABIAlignment){
+            Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+                                         TLI);
+            Tmp3 = Result.getOperand(0);
+            Tmp4 = Result.getOperand(1);
+            LegalizeOp(Tmp3);
+            LegalizeOp(Tmp4);
+          }
+        }
+        break;
       case TargetLowering::Custom:
         Tmp1 = TLI.LowerOperation(Tmp3, DAG);
         if (Tmp1.Val) {
@@ -1545,6 +1679,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
             Tmp1 = LegalizeOp(Tmp3);
             Tmp2 = LegalizeOp(Tmp3.getValue(1));
           }
+        } else {
+          // If this is an unaligned load and the target doesn't support it,
+          // expand it.
+          if (!TLI.allowsUnalignedMemoryAccesses()) {
+            unsigned ABIAlignment = TLI.getTargetData()->
+              getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+            if (LD->getAlignment() < ABIAlignment){
+              Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+                                           TLI);
+              Tmp1 = Result.getOperand(0);
+              Tmp2 = Result.getOperand(1);
+              LegalizeOp(Tmp1);
+              LegalizeOp(Tmp2);
+            }
+          }
         }
         break;
       case TargetLowering::Expand:
@@ -1794,7 +1943,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
         MVT::ValueType VT = Tmp3.getValueType();
         switch (TLI.getOperationAction(ISD::STORE, VT)) {
         default: assert(0 && "This action is not supported yet!");
-        case TargetLowering::Legal:  break;
+        case TargetLowering::Legal:
+          // If this is an unaligned store and the target doesn't support it,
+          // expand it.
+          if (!TLI.allowsUnalignedMemoryAccesses()) {
+            unsigned ABIAlignment = TLI.getTargetData()->
+              getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+            if (ST->getAlignment() < ABIAlignment)
+              Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+                                            TLI);
+          }
+          break;
         case TargetLowering::Custom:
           Tmp1 = TLI.LowerOperation(Result, DAG);
           if (Tmp1.Val) Result = Tmp1;
@@ -1907,7 +2066,17 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       MVT::ValueType StVT = cast<StoreSDNode>(Result.Val)->getStoredVT();
       switch (TLI.getStoreXAction(StVT)) {
       default: assert(0 && "This action is not supported yet!");
-      case TargetLowering::Legal: break;
+      case TargetLowering::Legal:
+        // If this is an unaligned store and the target doesn't support it,
+        // expand it.
+        if (!TLI.allowsUnalignedMemoryAccesses()) {
+          unsigned ABIAlignment = TLI.getTargetData()->
+            getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+          if (ST->getAlignment() < ABIAlignment)
+            Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+                                          TLI);
+        }
+        break;
       case TargetLowering::Custom:
         Tmp1 = TLI.LowerOperation(Result, DAG);
         if (Tmp1.Val) Result = Tmp1;
@@ -2722,9 +2891,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
   case ISD::CTLZ:
     Tmp1 = LegalizeOp(Node->getOperand(0));   // Op
     switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
-    case TargetLowering::Custom: assert(0 && "Cannot custom handle this yet!");
+    case TargetLowering::Custom:
     case TargetLowering::Legal:
       Result = DAG.UpdateNodeOperands(Result, Tmp1);
+      if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+          TargetLowering::Custom) {
+        Tmp1 = TLI.LowerOperation(Result, DAG);
+        if (Tmp1.Val) {
+          Result = Tmp1;
+        }
+      }
       break;
     case TargetLowering::Promote: {
       MVT::ValueType OVT = Tmp1.getValueType();
@@ -2744,7 +2920,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
                             DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
                             ISD::SETEQ);
         Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
-                           DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
+                             DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
         break;
       case ISD::CTLZ:
         // Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
@@ -2846,7 +3022,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
       // type.  If so, convert to the vector type.
       MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
       if (TLI.isTypeLegal(TVT)) {
-        // Turn this into a bit convert of the packed input.
+        // Turn this into a bit convert of the vector input.
         Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0), 
                              LegalizeOp(Node->getOperand(0)));
         break;
@@ -3026,33 +3202,43 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
-  case ISD::FP_ROUND:
-    if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) == 
-        TargetLowering::Expand) {
-      // The only way we can lower this is to turn it into a TRUNCSTORE,
-      // EXTLOAD pair, targetting a temporary location (a stack slot).
-
-      // NOTE: there is a choice here between constantly creating new stack
-      // slots and always reusing the same one.  We currently always create
-      // new ones, as reuse may inhibit scheduling.
-      MVT::ValueType VT = Op.getValueType();    // 32
-      const Type *Ty = MVT::getTypeForValueType(VT);
-      uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
-      unsigned Align  = TLI.getTargetData()->getPrefTypeAlignment(Ty);
-      MachineFunction &MF = DAG.getMachineFunction();
-      int SSFI =
-        MF.getFrameInfo()->CreateStackObject(TySize, Align);
-      SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
-      Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
-                                 StackSlot, NULL, 0, VT);
-      Result = DAG.getLoad(VT, Result, StackSlot, NULL, 0, VT);
-      break;
+  case ISD::FP_EXTEND: 
+  case ISD::FP_ROUND: {
+      MVT::ValueType newVT = Op.getValueType();
+      MVT::ValueType oldVT = Op.getOperand(0).getValueType();
+      if (TLI.getConvertAction(oldVT, newVT) == TargetLowering::Expand) {
+        // The only way we can lower this is to turn it into a STORE,
+        // LOAD pair, targetting a temporary location (a stack slot).
+
+        // NOTE: there is a choice here between constantly creating new stack
+        // slots and always reusing the same one.  We currently always create
+        // new ones, as reuse may inhibit scheduling.
+        MVT::ValueType slotVT = 
+                (Node->getOpcode() == ISD::FP_EXTEND) ? oldVT : newVT;
+        const Type *Ty = MVT::getTypeForValueType(slotVT);
+        uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+        unsigned Align  = TLI.getTargetData()->getPrefTypeAlignment(Ty);
+        MachineFunction &MF = DAG.getMachineFunction();
+        int SSFI =
+          MF.getFrameInfo()->CreateStackObject(TySize, Align);
+        SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+        if (Node->getOpcode() == ISD::FP_EXTEND) {
+          Result = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0),
+                                     StackSlot, NULL, 0);
+          Result = DAG.getExtLoad(ISD::EXTLOAD, newVT,
+                                     Result, StackSlot, NULL, 0, oldVT);
+        } else {
+          Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
+                                     StackSlot, NULL, 0, newVT);
+          Result = DAG.getLoad(newVT, Result, StackSlot, NULL, 0, newVT);
+        }
+        break;
+      }
     }
     // FALL THROUGH
   case ISD::ANY_EXTEND:
   case ISD::ZERO_EXTEND:
   case ISD::SIGN_EXTEND:
-  case ISD::FP_EXTEND:
     switch (getTypeAction(Node->getOperand(0).getValueType())) {
     case Expand: assert(0 && "Shouldn't need to expand other operators here!");
     case Legal:
@@ -3140,6 +3326,31 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
   }
+  case ISD::ADJUST_TRAMP: {
+    Tmp1 = LegalizeOp(Node->getOperand(0));
+    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+    default: assert(0 && "This action is not supported yet!");
+    case TargetLowering::Custom:
+      Result = DAG.UpdateNodeOperands(Result, Tmp1);
+      Result = TLI.LowerOperation(Result, DAG);
+      if (Result.Val) break;
+      // FALL THROUGH
+    case TargetLowering::Expand:
+      Result = Tmp1;
+      break;
+    }
+    break;
+  }
+  case ISD::TRAMPOLINE: {
+    SDOperand Ops[6];
+    for (unsigned i = 0; i != 6; ++i)
+      Ops[i] = LegalizeOp(Node->getOperand(i));
+    Result = DAG.UpdateNodeOperands(Result, Ops, 6);
+    // The only option for this node is to custom lower it.
+    Result = TLI.LowerOperation(Result, DAG);
+    assert(Result.Val && "Should always custom lower!");
+    break;
+  }
   }
   
   assert(Result.getValueType() == Op.getValueType() &&
@@ -3605,7 +3816,7 @@ SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
     if (isTypeLegal(TVT)) {
       Vec = LegalizeOp(Vec);
       Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
-      Op = LegalizeOp(Op);
+      return Op;
     }
     break;
   case TargetLowering::Expand:
@@ -3935,7 +4146,7 @@ SDOperand SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) {
 
 
 /// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
-/// support the operation, but do support the resultant packed vector type.
+/// support the operation, but do support the resultant vector type.
 SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
   
   // If the only non-undef value is the low element, turn this into a 
@@ -5401,6 +5612,11 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
   case ISD::FP_ROUND:
     Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPROUND_F64_F32),Node,true,Hi);
     break;
+  case ISD::FPOWI:
+    Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
+                                          ? RTLIB::POWI_F32 : RTLIB::POWI_F64),
+                       Node, false, Hi);
+    break;
   case ISD::FSQRT:
   case ISD::FSIN:
   case ISD::FCOS: {