Switch the PPC backend over to using FORMAL_ARGUMENTS for formal argument
authorChris Lattner <sabre@nondot.org>
Tue, 16 May 2006 18:18:50 +0000 (18:18 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 16 May 2006 18:18:50 +0000 (18:18 +0000)
handling.  This makes the lower argument code significantly simpler (we
only need to handle legal argument types).

Incidentally, this also implements support for vector argument registers,
so long as they are not on the stack.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28331 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h

index c1d4f403e668fbdbcd649ba3624b5d829c333d8a..8e010c39918d0408094ff9dce69cba711c8378a6 100644 (file)
@@ -727,6 +727,161 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
                      Op.getOperand(1), Op.getOperand(2));
 }
 
+static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
+                                       int &VarArgsFrameIndex) {
+  // TODO: add description of PPC stack frame format, or at least some docs.
+  //
+  MachineFunction &MF = DAG.getMachineFunction();
+  MachineFrameInfo *MFI = MF.getFrameInfo();
+  SSARegMap *RegMap = MF.getSSARegMap();
+  std::vector<SDOperand> ArgValues;
+  SDOperand Root = Op.getOperand(0);
+  
+  unsigned ArgOffset = 24;
+  unsigned GPR_remaining = 8;
+  unsigned FPR_remaining = 13;
+  unsigned VR_remaining  = 12;
+  unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0;
+  static const unsigned GPR[] = {
+    PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+    PPC::R7, PPC::R8, PPC::R9, PPC::R10,
+  };
+  static const unsigned FPR[] = {
+    PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
+    PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
+  };
+  static const unsigned VR[] = {
+    PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8,
+    PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13
+  };
+  
+  // Add DAG nodes to load the arguments or copy them out of registers.  On
+  // entry to a function on PPC, the arguments start at offset 24, although the
+  // first ones are often in registers.
+  for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
+    SDOperand ArgVal;
+    bool needsLoad = false;
+    bool ArgLive = !Op.Val->hasNUsesOfValue(0, ArgNo);
+    MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
+    unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
+
+    switch (ObjectVT) {
+    default: assert(0 && "Unhandled argument type!");
+    case MVT::i32:
+      if (!ArgLive) break;
+      if (GPR_remaining > 0) {
+        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+        MF.addLiveIn(GPR[GPR_idx], VReg);
+        ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
+      } else {
+        needsLoad = true;
+      }
+      break;
+    case MVT::f32:
+    case MVT::f64:
+      if (!ArgLive) {
+        if (FPR_remaining > 0) {
+          --FPR_remaining;
+          ++FPR_idx;
+        }        
+        break;
+      }
+      if (FPR_remaining > 0) {
+        unsigned VReg;
+        if (ObjectVT == MVT::f32)
+          VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass);
+        else
+          VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass);
+        MF.addLiveIn(FPR[FPR_idx], VReg);
+        ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
+        --FPR_remaining;
+        ++FPR_idx;
+      } else {
+        needsLoad = true;
+      }
+      break;
+    case MVT::v4f32:
+    case MVT::v4i32:
+    case MVT::v8i16:
+    case MVT::v16i8:
+      if (!ArgLive) {
+        if (VR_remaining > 0) {
+          --VR_remaining;
+          ++VR_idx;
+        }
+        break;
+      }
+      if (VR_remaining > 0) {
+        unsigned VReg = RegMap->createVirtualRegister(&PPC::VRRCRegClass);
+        MF.addLiveIn(VR[VR_idx], VReg);
+        ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT);
+        --VR_remaining;
+        ++VR_idx;
+      } else {
+        // This should be simple, but requires getting 16-byte aligned stack
+        // values.
+        assert(0 && "Loading VR argument not implemented yet!");
+        needsLoad = true;
+      }
+      break;
+    }
+    
+    // We need to load the argument to a virtual register if we determined above
+    // that we ran out of physical registers of the appropriate type
+    if (needsLoad) {
+      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
+      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
+      ArgVal = DAG.getLoad(ObjectVT, Root, FIN,
+                           DAG.getSrcValue(NULL));
+    }
+    
+    // Every 4 bytes of argument space consumes one of the GPRs available for
+    // argument passing.
+    if (GPR_remaining > 0) {
+      unsigned delta = (GPR_remaining > 1 && ObjSize == 8) ? 2 : 1;
+      GPR_remaining -= delta;
+      GPR_idx += delta;
+    }
+    ArgOffset += ObjSize;
+    
+    if (ArgVal.Val == 0)
+      ArgVal = DAG.getNode(ISD::UNDEF, ObjectVT);
+    ArgValues.push_back(ArgVal);
+  }
+  
+  // If the function takes variable number of arguments, make a frame index for
+  // the start of the first vararg value... for expansion of llvm.va_start.
+  bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
+  if (isVarArg) {
+    VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
+    SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
+    // If this function is vararg, store any remaining integer argument regs
+    // to their spots on the stack so that they may be loaded by deferencing the
+    // result of va_next.
+    std::vector<SDOperand> MemOps;
+    for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
+      unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+      MF.addLiveIn(GPR[GPR_idx], VReg);
+      SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
+      SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
+                                    Val, FIN, DAG.getSrcValue(NULL));
+      MemOps.push_back(Store);
+      // Increment the address by four for the next argument to store
+      SDOperand PtrOff = DAG.getConstant(4, MVT::i32);
+      FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff);
+    }
+    if (!MemOps.empty())
+      Root = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps);
+  }
+  
+  ArgValues.push_back(Root);
+  // Return the new list of results.
+  std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
+                                    Op.Val->value_end());
+  return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
+}
+
 static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Copy;
   switch(Op.getNumOperands()) {
@@ -1690,6 +1845,8 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
   case ISD::SETCC:              return LowerSETCC(Op, DAG);
   case ISD::VASTART:            return LowerVASTART(Op, DAG, VarArgsFrameIndex);
+  case ISD::FORMAL_ARGUMENTS:   return LowerFORMAL_ARGUMENTS(Op, DAG,
+                                                             VarArgsFrameIndex);
   case ISD::RET:                return LowerRET(Op, DAG);
     
   case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG);
@@ -1715,174 +1872,6 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
 //  Other Lowering Code
 //===----------------------------------------------------------------------===//
 
-std::vector<SDOperand>
-PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
-  //
-  // add beautiful description of PPC stack frame format, or at least some docs
-  //
-  MachineFunction &MF = DAG.getMachineFunction();
-  MachineFrameInfo *MFI = MF.getFrameInfo();
-  SSARegMap *RegMap = MF.getSSARegMap();
-  std::vector<SDOperand> ArgValues;
-  
-  unsigned ArgOffset = 24;
-  unsigned GPR_remaining = 8;
-  unsigned FPR_remaining = 13;
-  unsigned GPR_idx = 0, FPR_idx = 0;
-  static const unsigned GPR[] = {
-    PPC::R3, PPC::R4, PPC::R5, PPC::R6,
-    PPC::R7, PPC::R8, PPC::R9, PPC::R10,
-  };
-  static const unsigned FPR[] = {
-    PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
-    PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
-  };
-  
-  // Add DAG nodes to load the arguments...  On entry to a function on PPC,
-  // the arguments start at offset 24, although they are likely to be passed
-  // in registers.
-  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
-    SDOperand newroot, argt;
-    unsigned ObjSize;
-    bool needsLoad = false;
-    bool ArgLive = !I->use_empty();
-    MVT::ValueType ObjectVT = getValueType(I->getType());
-    
-    switch (ObjectVT) {
-    default: assert(0 && "Unhandled argument type!");
-    case MVT::i1:
-    case MVT::i8:
-    case MVT::i16:
-    case MVT::i32:
-      ObjSize = 4;
-      if (!ArgLive) break;
-      if (GPR_remaining > 0) {
-        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
-        MF.addLiveIn(GPR[GPR_idx], VReg);
-        argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
-        if (ObjectVT != MVT::i32) {
-          unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext 
-                                                       : ISD::AssertZext;
-          argt = DAG.getNode(AssertOp, MVT::i32, argt, 
-                             DAG.getValueType(ObjectVT));
-          argt = DAG.getNode(ISD::TRUNCATE, ObjectVT, argt);
-        }
-      } else {
-        needsLoad = true;
-      }
-      break;
-    case MVT::i64:
-      ObjSize = 8;
-      if (!ArgLive) break;
-      if (GPR_remaining > 0) {
-        SDOperand argHi, argLo;
-        unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
-        MF.addLiveIn(GPR[GPR_idx], VReg);
-        argHi = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
-        // If we have two or more remaining argument registers, then both halves
-        // of the i64 can be sourced from there.  Otherwise, the lower half will
-        // have to come off the stack.  This can happen when an i64 is preceded
-        // by 28 bytes of arguments.
-        if (GPR_remaining > 1) {
-          unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
-          MF.addLiveIn(GPR[GPR_idx+1], VReg);
-          argLo = DAG.getCopyFromReg(argHi, VReg, MVT::i32);
-        } else {
-          int FI = MFI->CreateFixedObject(4, ArgOffset+4);
-          SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-          argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN,
-                              DAG.getSrcValue(NULL));
-        }
-        // Build the outgoing arg thingy
-        argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi);
-        newroot = argLo;
-      } else {
-        needsLoad = true;
-      }
-      break;
-    case MVT::f32:
-    case MVT::f64:
-      ObjSize = (ObjectVT == MVT::f64) ? 8 : 4;
-      if (!ArgLive) {
-        if (FPR_remaining > 0) {
-          --FPR_remaining;
-          ++FPR_idx;
-        }        
-        break;
-      }
-      if (FPR_remaining > 0) {
-        unsigned VReg;
-        if (ObjectVT == MVT::f32)
-          VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass);
-        else
-          VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass);
-        MF.addLiveIn(FPR[FPR_idx], VReg);
-        argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, ObjectVT);
-        --FPR_remaining;
-        ++FPR_idx;
-      } else {
-        needsLoad = true;
-      }
-      break;
-    }
-    
-    // We need to load the argument to a virtual register if we determined above
-    // that we ran out of physical registers of the appropriate type
-    if (needsLoad) {
-      unsigned SubregOffset = 0;
-      if (ObjectVT == MVT::i8 || ObjectVT == MVT::i1) SubregOffset = 3;
-      if (ObjectVT == MVT::i16) SubregOffset = 2;
-      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
-      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
-      FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN,
-                        DAG.getConstant(SubregOffset, MVT::i32));
-      argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN,
-                                   DAG.getSrcValue(NULL));
-    }
-    
-    // Every 4 bytes of argument space consumes one of the GPRs available for
-    // argument passing.
-    if (GPR_remaining > 0) {
-      unsigned delta = (GPR_remaining > 1 && ObjSize == 8) ? 2 : 1;
-      GPR_remaining -= delta;
-      GPR_idx += delta;
-    }
-    ArgOffset += ObjSize;
-    if (newroot.Val)
-      DAG.setRoot(newroot.getValue(1));
-    
-    ArgValues.push_back(argt);
-  }
-  
-  // If the function takes variable number of arguments, make a frame index for
-  // the start of the first vararg value... for expansion of llvm.va_start.
-  if (F.isVarArg()) {
-    VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
-    SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32);
-    // If this function is vararg, store any remaining integer argument regs
-    // to their spots on the stack so that they may be loaded by deferencing the
-    // result of va_next.
-    std::vector<SDOperand> MemOps;
-    for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
-      unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
-      MF.addLiveIn(GPR[GPR_idx], VReg);
-      SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
-      SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
-                                    Val, FIN, DAG.getSrcValue(NULL));
-      MemOps.push_back(Store);
-      // Increment the address by four for the next argument to store
-      SDOperand PtrOff = DAG.getConstant(4, getPointerTy());
-      FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff);
-    }
-    if (!MemOps.empty()) {
-      MemOps.push_back(DAG.getRoot());
-      DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps));
-    }
-  }
-  
-  return ArgValues;
-}
-
 std::pair<SDOperand, SDOperand>
 PPCTargetLowering::LowerCallTo(SDOperand Chain,
                                const Type *RetTy, bool isVarArg,
index bcd7268b934e3cbe6b9b205dae62837a65dc6ae1..f5bfff559bc0a48497a748b05b6e6bcb9483c7d2 100644 (file)
@@ -166,10 +166,6 @@ namespace llvm {
                                                 uint64_t &KnownZero, 
                                                 uint64_t &KnownOne,
                                                 unsigned Depth = 0) const;
-    /// LowerArguments - This hook must be implemented to indicate how we should
-    /// lower the arguments for the specified function, into the specified DAG.
-    virtual std::vector<SDOperand>
-      LowerArguments(Function &F, SelectionDAG &DAG);
     
     /// LowerCallTo - This hook lowers an abstract call to a function into an
     /// actual call.