* Added lowering hook for external weak global address. It inserts a load
authorEvan Cheng <evan.cheng@apple.com>
Wed, 21 Dec 2005 02:39:21 +0000 (02:39 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 21 Dec 2005 02:39:21 +0000 (02:39 +0000)
  for Darwin.
* Added lowering hook for ISD::RET. It inserts CopyToRegs for the return
  value (or store / fld / copy to ST(0) for floating point value). This
  eliminate the need to write C++ code to handle RET with variable number
  of operands.

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

lib/Target/X86/X86ISelDAGToDAG.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86RegisterInfo.td

index 4484ae50161d4e5546953a84e0b7e1efaa84aeb9..3dcf444d49e39a13044a15f6fa7633e4a3d2062f 100644 (file)
@@ -173,22 +173,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) {
 
   case ISD::GlobalAddress:
     if (AM.GV == 0) {
-      GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
-      // For Darwin, external and weak symbols are indirect, so we want to load
-      // the value at address GV, not the value of GV itself.  This means that
-      // the GlobalAddress must be in the base or index register of the address,
-      // not the GV offset field.
-      if (Subtarget->getIndirectExternAndWeakGlobals() &&
-          (GV->hasWeakLinkage() || GV->isExternal())) {
-        AM.Base.Reg =
-          CurDAG->getTargetNode(X86::MOV32rm, MVT::i32, MVT::Other,
-                                CurDAG->getRegister(0, MVT::i32),
-                                getI8Imm(1), CurDAG->getRegister(0, MVT::i32),
-                                CurDAG->getTargetGlobalAddress(GV, MVT::i32),
-                                CurDAG->getEntryNode());
-      } else {
-        AM.GV = GV;
-      }
+      AM.GV = cast<GlobalAddressSDNode>(N)->getGlobal();
       return false;
     }
     break;
index 496f10548cfc6cfd2ac332569da88b792b74d6dc..ee6e320fc51f45c8bcbb25f497c551ca10596ddb 100644 (file)
@@ -197,6 +197,68 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
   return  LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG);
 }
 
+SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
+                                           SelectionDAG &DAG) {
+  if (!X86DAGIsel)
+    return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
+
+  SDOperand Copy;
+  MVT::ValueType OpVT = Op.getValueType();
+  switch (OpVT) {
+    default: assert(0 && "Unknown type to return!");
+    case MVT::i32:
+      Copy = DAG.getCopyToReg(Chain, X86::EAX, Op, SDOperand());
+      break;
+    case MVT::i64: {
+      SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op, 
+                                 DAG.getConstant(1, MVT::i32));
+      SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
+                                 DAG.getConstant(0, MVT::i32));
+      Copy = DAG.getCopyToReg(Chain, X86::EAX, Hi, SDOperand());
+      Copy = DAG.getCopyToReg(Copy,  X86::EDX, Lo, Copy.getValue(1));
+      break;
+    }
+    case MVT::f32:
+      assert(X86ScalarSSE && "MVT::f32 only legal with scalar sse fp");
+      // Fallthrough intended
+    case MVT::f64:
+      if (!X86ScalarSSE) {
+        std::vector<MVT::ValueType> Tys;
+        Tys.push_back(MVT::Other);
+        Tys.push_back(MVT::Flag);
+        std::vector<SDOperand> Ops;
+        Ops.push_back(Chain);
+        Ops.push_back(Op);
+        Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
+      } else {
+        // Spill the value to memory and reload it into top of stack.
+        unsigned Size = MVT::getSizeInBits(OpVT)/8;
+        MachineFunction &MF = DAG.getMachineFunction();
+        int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size);
+        SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
+        Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Op,
+                            StackSlot, DAG.getSrcValue(NULL));
+        std::vector<MVT::ValueType> Tys;
+        Tys.push_back(MVT::f64);
+        Tys.push_back(MVT::Other);
+        std::vector<SDOperand> Ops;
+        Ops.push_back(Chain);
+        Ops.push_back(StackSlot);
+        Ops.push_back(DAG.getValueType(OpVT));
+        Copy = DAG.getNode(X86ISD::FLD, Tys, Ops);
+        Tys.clear();
+        Tys.push_back(MVT::Other);
+        Tys.push_back(MVT::Flag);
+        Ops.clear();
+        Ops.push_back(Copy.getValue(1));
+        Ops.push_back(Copy);
+        Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
+      }
+      break;
+  }
+  return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
+}
+
 //===----------------------------------------------------------------------===//
 //                    C Calling Convention implementation
 //===----------------------------------------------------------------------===//
@@ -968,6 +1030,20 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
     return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
                        Op.getOperand(0), Op.getOperand(2), CC, Cond);
   }
+  case ISD::GlobalAddress:
+    GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+    // For Darwin, external and weak symbols are indirect, so we want to load
+    // the value at address GV, not the value of GV itself.  This means that
+    // the GlobalAddress must be in the base or index register of the address,
+    // not the GV offset field.
+    if (getTargetMachine().
+        getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals() &&
+        (GV->hasWeakLinkage() || GV->isExternal()))
+      return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Op,
+                         DAG.getSrcValue(NULL));
+    else
+      return Op;
+    break;
   }
 }
 
@@ -978,6 +1054,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM";
   case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM";
   case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM";
+  case X86ISD::FLD:                return "X86ISD::FLD";
+  case X86ISD::FP_SET_RESULT:      return "X86ISD::FP_SET_RESULT";
   case X86ISD::CALL:               return "X86ISD::CALL";
   case X86ISD::TAILCALL:           return "X86ISD::TAILCALL";
   case X86ISD::RDTSC_DAG:          return "X86ISD::RDTSC_DAG";
@@ -985,5 +1063,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::TEST:               return "X86ISD::TEST";
   case X86ISD::CMOV:               return "X86ISD::CMOV";
   case X86ISD::BRCOND:             return "X86ISD::BRCOND";
+  case X86ISD::RET_FLAG:           return "X86ISD::RET_FLAG";
   }
 }
index b1ce8e22b0e367c70b7f4bf278b3fd9edc63140a..a1c09136dcaf6ac466a76201943d4a426e8ecc75 100644 (file)
@@ -40,6 +40,17 @@ namespace llvm {
       FP_TO_INT32_IN_MEM,
       FP_TO_INT64_IN_MEM,
 
+      /// FLD - This instruction implements an extending load to FP stack slots.
+      /// This corresponds to the X86::FLD32m / X86::FLD64m. It takes a chain
+      /// operand, ptr to load from, and a VALUETYPE node indicating the type
+      /// to load.
+      FLD,
+
+      /// FP_SET_RESULT - This corresponds to FpSETRESULT pseudo instrcuction
+      /// which copies the source operand to ST(0). It takes a chain and writes
+      /// a chain and a flag.
+      FP_SET_RESULT,
+
       /// CALL/TAILCALL - These operations represent an abstract X86 call
       /// instruction, which includes a bunch of information.  In particular the
       /// operands of these node are:
@@ -75,6 +86,9 @@ namespace llvm {
 
       /// X86 conditional branches.
       BRCOND,
+
+      // Return with a flag operand.
+      RET_FLAG,
     };
   }
 
@@ -113,6 +127,9 @@ namespace llvm {
                 bool isTailCall, SDOperand Callee, ArgListTy &Args,
                 SelectionDAG &DAG);
 
+    virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
+                                    SelectionDAG &DAG);
+    
     virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
                                    Value *VAListV, SelectionDAG &DAG);
     virtual std::pair<SDOperand,SDOperand>
index dffc0e6724ca84b55fc46f6df51bb7a4d64ea221..3598d0c7c0cc3ef24ed0b119171e80a1dd924cae 100644 (file)
@@ -28,11 +28,25 @@ def SDTX86BrCond  : SDTypeProfile<0, 3,
                                   [SDTCisVT<0, OtherVT>,
                                    SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
 
-def X86cmp    : SDNode<"X86ISD::CMP" ,   SDTX86CmpTest, []>;
-def X86test   : SDNode<"X86ISD::TEST",   SDTX86CmpTest, []>;
+def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, FlagVT>]>;
 
-def X86cmov   : SDNode<"X86ISD::CMOV",   SDTX86Cmov,    []>;
-def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond,  [SDNPHasChain]>;
+def SDTX86Fld     : SDTypeProfile<1, 2, [SDTCisFP<0>,
+                                         SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
+
+def SDTX86FpSet   : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
+
+def X86cmp    : SDNode<"X86ISD::CMP" ,     SDTX86CmpTest, []>;
+def X86test   : SDNode<"X86ISD::TEST",     SDTX86CmpTest, []>;
+
+def X86cmov   : SDNode<"X86ISD::CMOV",     SDTX86Cmov,    []>;
+def X86Brcond : SDNode<"X86ISD::BRCOND",   SDTX86BrCond,  [SDNPHasChain]>;
+
+def X86retflag: SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>;
+
+def X86fld    : SDNode<"X86ISD::FLD",      SDTX86Fld,     [SDNPHasChain]>;
+
+def X86fpset  : SDNode<"X86ISD::FP_SET_RESULT",
+                                           SDTX86FpSet,   [SDNPHasChain]>;
 
 //===----------------------------------------------------------------------===//
 // X86 Operand Definitions.
@@ -274,6 +288,8 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in
 let isTerminator = 1, isReturn = 1, isBarrier = 1 in
   def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>;
 
+def : Pat<(X86retflag FLAG), (RET)>;
+
 // All branches are RawFrm, Void, Branch, and Terminators
 let isBranch = 1, isTerminator = 1 in
   class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
@@ -2188,10 +2204,21 @@ def FpDIV : FPI<0, Pseudo, TwoArgFP ,
                 (ops RFP:$dst, RFP:$src1, RFP:$src2), "",
                 []>;    // f1 = fdiv f2, f3
 
+def FpLD32m  : FPI<0xD9, MRM0m, ZeroArgFP,
+                   (ops RFP:$dst, f32mem:$src),
+                   "fld{s} $src",
+                   [(set RFP:$dst, (X86fld addr:$src, f32))]>;
+
+def FpLD64m  : FPI<0xDD, MRM0m, ZeroArgFP,
+                   (ops RFP:$dst, f64mem:$src),
+                   "fld{l} $src",
+                   [(set RFP:$dst, (X86fld addr:$src, f64))]>;
+
 def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>,
                   Imp<[ST0], []>;  // FPR = ST(0)
 
-def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "", []>,
+def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "",
+                      [(X86fpset RFP:$src)]>,
                   Imp<[], [ST0]>;  // ST(0) = FPR
 
 // FADD reg, mem: Before stackification, these are represented by:
index 06b9543e4951ca1fbe7197a5f7265d2d2389bdd5..0e43d2b87487217a5c5c19f54d956df308d7e247 100644 (file)
@@ -142,6 +142,11 @@ def RST : RegisterClass<"X86", [f64], 32,
   }];
 }
 
-def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS]> {
+// FIXME:
+// HACKTROCITY: define a flags reg class for things that need to take a flag.
+// this should really be handled by tablgen.
+let Namespace = "X86" in
+  def FLAG : Register<"FLAG">;
+def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS, FLAG]> {
     let Size = 32;
 }