[llvm-commits] CVS: llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp SparcV8InstrInfo.td

Chris Lattner lattner at cs.uiuc.edu
Sun Dec 18 07:55:27 PST 2005



Changes in directory llvm/lib/Target/SparcV8:

SparcV8ISelDAGToDAG.cpp updated: 1.19 -> 1.20
SparcV8InstrInfo.td updated: 1.81 -> 1.82
---
Log message:

Implement Calls for V8.  This would be completely autogenerated except for
a small bug in tblgen.  When that is fixed, we can remove the ISD::Call case
in Select.


---
Diffs of the changes:  (+257 -15)

 SparcV8ISelDAGToDAG.cpp |  230 +++++++++++++++++++++++++++++++++++++++++++++++-
 SparcV8InstrInfo.td     |   42 ++++++--
 2 files changed, 257 insertions(+), 15 deletions(-)


Index: llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp
diff -u llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp:1.19 llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp:1.20
--- llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp:1.19	Sun Dec 18 07:33:06 2005
+++ llvm/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp	Sun Dec 18 09:55:15 2005
@@ -50,6 +50,7 @@
 
 namespace {
   class SparcV8TargetLowering : public TargetLowering {
+    int VarArgsFrameOffset;   // Frame offset to start of varargs area.
   public:
     SparcV8TargetLowering(TargetMachine &TM);
     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
@@ -154,7 +155,6 @@
     
     switch (ObjectVT) {
     default: assert(0 && "Unhandled argument type!");
-    // TODO: FP
     case MVT::i1:
     case MVT::i8:
     case MVT::i16:
@@ -278,6 +278,9 @@
   
   // Store remaining ArgRegs to the stack if this is a varargs function.
   if (F.getFunctionType()->isVarArg()) {
+    // Remember the vararg offset for the va_start implementation.
+    VarArgsFrameOffset = ArgOffset;
+    
     for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
       unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
       MF.addLiveIn(*CurArgReg, VReg);
@@ -325,8 +328,208 @@
                                    bool isVarArg, unsigned CC,
                                    bool isTailCall, SDOperand Callee, 
                                    ArgListTy &Args, SelectionDAG &DAG) {
-  assert(0 && "Unimp");
-  abort();
+  MachineFunction &MF = DAG.getMachineFunction();
+  // Count the size of the outgoing arguments.
+  unsigned ArgsSize = 0;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    switch (getValueType(Args[i].second)) {
+    default: assert(0 && "Unknown value type!");
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+    case MVT::i32:
+    case MVT::f32:
+      ArgsSize += 4;
+      break;
+    case MVT::i64:
+    case MVT::f64:
+      ArgsSize += 8;
+      break;
+    }
+  }
+  if (ArgsSize > 4*6)
+    ArgsSize -= 4*6;    // Space for first 6 arguments is prereserved.
+  else
+    ArgsSize = 0;
+
+  Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
+                      DAG.getConstant(ArgsSize, getPointerTy()));
+  
+  SDOperand StackPtr, NullSV;
+  std::vector<SDOperand> Stores;
+  std::vector<SDOperand> RegValuesToPass;
+  unsigned ArgOffset = 68;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    SDOperand Val = Args[i].first;
+    MVT::ValueType ObjectVT = Val.getValueType();
+    SDOperand ValToStore;
+    unsigned ObjSize;
+    switch (ObjectVT) {
+    default: assert(0 && "Unhandled argument type!");
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+      // Promote the integer to 32-bits.  If the input type is signed, use a
+      // sign extend, otherwise use a zero extend.
+      if (Args[i].second->isSigned())
+        Val = DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Val);
+      else
+        Val = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Val);
+      // FALL THROUGH
+    case MVT::i32:
+      ObjSize = 4;
+
+      if (RegValuesToPass.size() >= 6) {
+        ValToStore = Val;
+      } else {
+        RegValuesToPass.push_back(Val);
+      }
+      break;
+    case MVT::f32:
+      ObjSize = 4;
+      if (RegValuesToPass.size() >= 6) {
+        ValToStore = Val;
+      } else {
+        // Convert this to a FP value in an int reg.
+        int FrameIdx = MF.getFrameInfo()->CreateStackObject(4, 4);
+        SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
+        SDOperand SV = DAG.getSrcValue(0);
+        SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                      Val, FIPtr, SV);
+        Val = DAG.getLoad(MVT::i32, Store, FIPtr, SV);
+        RegValuesToPass.push_back(Val);
+      }
+      break;
+    case MVT::f64: {
+      ObjSize = 8;
+      // If we can store this directly into the outgoing slot, do so.  We can
+      // do this when all ArgRegs are used and if the outgoing slot is aligned.
+      if (RegValuesToPass.size() >= 6 && ((ArgOffset-68) & 7) == 0) {
+        ValToStore = Val;
+        break;
+      }
+      
+      // Otherwise, convert this to a FP value in int regs.
+      int FrameIdx = MF.getFrameInfo()->CreateStackObject(8, 8);
+      SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
+      SDOperand SV = DAG.getSrcValue(0);
+      SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                    Val, FIPtr, SV);
+      Val = DAG.getLoad(MVT::i64, Store, FIPtr, SV);
+    }
+      // FALL THROUGH
+    case MVT::i64:
+      ObjSize = 8;
+      if (RegValuesToPass.size() >= 6) {
+        ValToStore = Val;    // Whole thing is passed in memory.
+        break;
+      }
+      
+      // Split the value into top and bottom part.  Top part goes in a reg.
+      SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val, 
+                                 DAG.getConstant(1, MVT::i32));
+      SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val,
+                                 DAG.getConstant(0, MVT::i32));
+      RegValuesToPass.push_back(Hi);
+      
+      if (RegValuesToPass.size() >= 6) {
+        ValToStore = Lo;
+      } else {
+        RegValuesToPass.push_back(Lo);
+      }
+      break;
+    }
+    
+    if (ValToStore.Val) {
+      if (!StackPtr.Val) {
+        StackPtr = DAG.getCopyFromReg(DAG.getEntryNode(), V8::SP, MVT::i32);
+        NullSV = DAG.getSrcValue(NULL);
+      }
+      SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
+      PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
+      Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                   ValToStore, PtrOff, NullSV));
+    }
+    ArgOffset += ObjSize;
+  }
+  
+  // Emit all stores, make sure the occur before any copies into physregs.
+  if (!Stores.empty())
+    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
+  
+  static const unsigned ArgRegs[] = {
+    V8::O0, V8::O1, V8::O2, V8::O3, V8::O4, V8::O5
+  };
+  
+  // Build a sequence of copy-to-reg nodes chained together with token chain
+  // and flag operands which copy the outgoing args into O[0-5].
+  SDOperand InFlag;
+  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
+    Chain = DAG.getCopyToReg(Chain, ArgRegs[i], RegValuesToPass[i], InFlag);
+    InFlag = Chain.getValue(1);
+  }
+
+  std::vector<MVT::ValueType> RetVals;
+  RetVals.push_back(MVT::Other);
+  RetVals.push_back(MVT::Flag);
+
+  // 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.
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+
+  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.
+  Chain = SDOperand(DAG.getCall(NodeTys, Chain, Callee, InFlag), 0);
+  InFlag = Chain.getValue(1);
+  
+  MVT::ValueType RetTyVT = getValueType(RetTy);
+  SDOperand RetVal;
+  if (RetTyVT != MVT::isVoid) {
+    switch (RetTyVT) {
+    default: assert(0 && "Unknown value type to return!");
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+      RetVal = DAG.getCopyFromReg(Chain, V8::O0, MVT::i32, InFlag);
+      Chain = RetVal.getValue(1);
+      
+      // Add a note to keep track of whether it is sign or zero extended.
+      RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext,
+                           MVT::i32, RetVal, DAG.getValueType(RetTyVT));
+      RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal);
+      break;
+    case MVT::i32:
+      RetVal = DAG.getCopyFromReg(Chain, V8::O0, MVT::i32, InFlag);
+      Chain = RetVal.getValue(1);
+      break;
+    case MVT::f32:
+      RetVal = DAG.getCopyFromReg(Chain, V8::F0, MVT::f32, InFlag);
+      Chain = RetVal.getValue(1);
+      break;
+    case MVT::f64:
+      RetVal = DAG.getCopyFromReg(Chain, V8::D0, MVT::f64, InFlag);
+      Chain = RetVal.getValue(1);
+      break;
+    case MVT::i64:
+      SDOperand Lo = DAG.getCopyFromReg(Chain, V8::O0, MVT::i32, InFlag);
+      SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), V8::O0, MVT::i32, 
+                                        Lo.getValue(2));
+      RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
+      Chain = Hi.getValue(1);
+      break;
+    }
+  }
+  
+  Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
+                      DAG.getConstant(ArgsSize, getPointerTy()));
+  
+  MVT::ValueType ActualRetTyVT = RetTyVT;
+  if (RetTyVT >= MVT::i1 && RetTyVT <= MVT::i16)
+    ActualRetTyVT = MVT::i32;   // Promote result to i32.
+  
+  return std::make_pair(RetVal, Chain);
 }
 
 SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
@@ -734,6 +937,7 @@
   }
     
   case ISD::RET: {
+    // FIXME: change this to use flag operands to allow autogen of ret.
     if (N->getNumOperands() == 2) {
       SDOperand Chain = Select(N->getOperand(0));     // Token chain.
       SDOperand Val = Select(N->getOperand(1));
@@ -757,6 +961,26 @@
     }
     break;  // Generated code handles the void case.
   }
+  case ISD::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) goto P47Fail;
+    SDOperand N2 = N->getOperand(2);
+    SDOperand InFlag = SDOperand(0,0);
+    SDOperand Chain = N->getOperand(0);
+    SDOperand Tmp0 = N1;
+    Chain = Select(Chain);
+    InFlag = Select(N2);
+    SDOperand Result = CurDAG->getTargetNode(V8::CALL, MVT::Other, MVT::Flag, Tmp0, Chain, InFlag);
+    Chain = CodeGenMap[SDOperand(N, 0)] = Result.getValue(0);
+     CodeGenMap[SDOperand(N, 1)] = Result.getValue(1);
+    return Result.getValue(Op.ResNo);
+  }
+    P47Fail:;
+    
   }
   
   return SelectCode(Op);


Index: llvm/lib/Target/SparcV8/SparcV8InstrInfo.td
diff -u llvm/lib/Target/SparcV8/SparcV8InstrInfo.td:1.81 llvm/lib/Target/SparcV8/SparcV8InstrInfo.td:1.82
--- llvm/lib/Target/SparcV8/SparcV8InstrInfo.td:1.81	Sun Dec 18 02:21:00 2005
+++ llvm/lib/Target/SparcV8/SparcV8InstrInfo.td	Sun Dec 18 09:55:15 2005
@@ -57,6 +57,7 @@
 
 // Branch targets have OtherVT type.
 def brtarget : Operand<OtherVT>;
+def calltarget : Operand<i32>;
 
 def SDTV8cmpicc : 
 SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisInt<1>, SDTCisSameAs<1, 2>]>;
@@ -83,6 +84,15 @@
 def V8selecticc : SDNode<"V8ISD::SELECT_ICC", SDTV8selectcc>;
 def V8selectfcc : SDNode<"V8ISD::SELECT_FCC", SDTV8selectcc>;
 
+// These are target-independent nodes, but have target-specific formats.
+def SDT_V8CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>;
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_V8CallSeq, [SDNPHasChain]>;
+def callseq_end   : SDNode<"ISD::CALLSEQ_END",   SDT_V8CallSeq, [SDNPHasChain]>;
+
+def SDT_V8Call    : SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisVT<1, i32>,
+                                         SDTCisVT<2, FlagVT>]>;
+def call          : SDNode<"ISD::CALL", SDT_V8Call, [SDNPHasChain]>;
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -92,8 +102,12 @@
    : InstV8<ops, asmstr, pattern>;
 
 def PHI : Pseudo<(ops variable_ops), "PHI", []>;
-def ADJCALLSTACKDOWN : Pseudo<(ops i32imm:$amt), "!ADJCALLSTACKDOWN $amt",[]>;
-def ADJCALLSTACKUP : Pseudo<(ops i32imm:$amt), "!ADJCALLSTACKUP $amt", []>;
+def ADJCALLSTACKDOWN : Pseudo<(ops i32imm:$amt),
+                               "!ADJCALLSTACKDOWN $amt",
+                               [(callseq_start imm:$amt)]>;
+def ADJCALLSTACKUP : Pseudo<(ops i32imm:$amt),
+                            "!ADJCALLSTACKUP $amt",
+                            [(callseq_end imm:$amt)]>;
 def IMPLICIT_DEF : Pseudo<(ops IntRegs:$dst), "!IMPLICIT_DEF $dst", []>;
 def FpMOVD : Pseudo<(ops DFPRegs:$dst, DFPRegs:$src),
                     "!FpMOVD", []>;      // pseudo 64-bit double move
@@ -523,23 +537,27 @@
 
 // Section B.24 - Call and Link Instruction, p. 125
 // This is the only Format 1 instruction
-let Uses = [O0, O1, O2, O3, O4, O5], hasDelaySlot = 1, isCall = 1 in { 
+let Uses = [O0, O1, O2, O3, O4, O5], hasDelaySlot = 1, isCall = 1,
+    Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7,
+    D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in { 
   // pc-relative call:
-  let Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7,
-    D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in
-  def CALL : InstV8<(ops IntRegs:$dst), "call $dst", []> {
+  def CALL : InstV8<(ops calltarget:$dst),
+                    "call $dst",
+                  [(set ICC/*bogus*/, (call tglobaladdr:$dst, ICC/*bogus*/))]> {
     bits<30> disp;
     let op = 1;
     let Inst{29-0} = disp;
   }
 
-  // indirect call (O7 is an EXPLICIT def in indirect calls, so it cannot also
-  // be an implicit def):
-  let Defs = [O0, O1, O2, O3, O4, O5, G1, G2, G3, G4, G5, G6, G7,
-    D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in
+  // indirect calls
   def JMPLrr : F3_1<2, 0b111000,
-                    (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c),
-                    "jmpl $b+$c, $dst", []>;
+                    (ops MEMrr:$ptr),
+                    "jmpl $ptr",
+                    [(set ICC/*bogus*/, (call  ADDRrr:$ptr, ICC/*bogus*/))]>;
+  def JMPLri : F3_2<2, 0b111000,
+                    (ops MEMri:$ptr),
+                    "jmpl $ptr",
+                    [(set ICC/*bogus*/, (call  ADDRri:$ptr, ICC/*bogus*/))]>;
 }
 
 // Section B.28 - Read State Register Instructions






More information about the llvm-commits mailing list