- Use a different wrapper node for RIP-relative GV, etc.
authorEvan Cheng <evan.cheng@apple.com>
Thu, 30 Nov 2006 21:55:46 +0000 (21:55 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 30 Nov 2006 21:55:46 +0000 (21:55 +0000)
- Proper support for both small static and PIC modes under X86-64
- Some (non-optimal) support for medium modes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32046 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/X86InstrX86-64.td

index 09f07d01caa539852a0e386528556f0c4fe015c4..19df6e9671d8c8e16887de5b28e4cdaf2df3982d 100644 (file)
@@ -590,63 +590,19 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
     break;
   }
 
-  case ISD::TargetConstantPool:
-    if (AM.BaseType == X86ISelAddressMode::RegBase &&
-        AM.Base.Reg.Val == 0 &&
-        AM.CP == 0) {
-      ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
-      AM.CP = CP->getConstVal();
-      AM.Align = CP->getAlignment();
-      AM.Disp += CP->getOffset();
-      return false;
-    }
-    break;
-
-  case ISD::TargetGlobalAddress:
-    if (AM.BaseType == X86ISelAddressMode::RegBase &&
-        AM.Base.Reg.Val == 0 &&
-        AM.GV == 0) {
-      GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(N);
-      AM.GV = G->getGlobal();
-      AM.Disp += G->getOffset();
-      return false;
-    }
-    break;
-
-  case ISD::TargetExternalSymbol:
-    if (isRoot &&
-        AM.BaseType == X86ISelAddressMode::RegBase &&
-        AM.Base.Reg.Val == 0) {
-      ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(N.getOperand(0));
-      AM.ES = S->getSymbol();
-      return false;
-    }
-    break;
-
-  case ISD::TargetJumpTable:
-    if (isRoot &&
-        AM.BaseType == X86ISelAddressMode::RegBase &&
-        AM.Base.Reg.Val == 0) {
-      JumpTableSDNode *J = cast<JumpTableSDNode>(N.getOperand(0));
-      AM.JT = J->getIndex();
-      return false;
-    }
-    break;
-
   case X86ISD::Wrapper:
+  case X86ISD::WrapperRIP: {
+    bool isRIP = N.getOpcode() == X86ISD::WrapperRIP;
+    // Under X86-64 non-small code model, GV (and friends) are 64-bits.
+    if (!isRIP && Subtarget->is64Bit() && TM.getCodeModel() != CodeModel::Small)
+      break;
+
     // If value is available in a register both base and index components have
     // been picked, we can't fit the result available in the register in the
     // addressing mode. Duplicate GlobalAddress or ConstantPool as displacement.
-
-    // Can't fit GV or CP in addressing mode for X86-64 medium or large code
-    // model since the displacement field is 32-bit. Ok for small code model.
-
-    // For X86-64 PIC code, only allow GV / CP + displacement so we can use RIP
-    // relative addressing mode.
-    if (Subtarget->is64Bit() && TM.getCodeModel() != CodeModel::Small)
-      break;
     if (!Available || (AM.Base.Reg.Val && AM.IndexReg.Val)) {
-      bool isRIP = Subtarget->is64Bit();
+      // For X86-64 PIC code, only allow GV / CP + displacement so we can use
+      // RIP relative addressing mode.
       if (isRIP &&
           (AM.Base.Reg.Val || AM.Scale > 1 || AM.IndexReg.Val ||
            AM.BaseType == X86ISelAddressMode::FrameIndexBase))
@@ -683,6 +639,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
       }
     }
     break;
+  }
 
   case ISD::FrameIndex:
     if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
@@ -1040,7 +997,8 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
       SDOperand N0 = N.getOperand(0);
       SDOperand N1 = N.getOperand(1);
       if (N.Val->getValueType(0) == PtrVT &&
-          N0.getOpcode() == X86ISD::Wrapper &&
+          (N0.getOpcode() == X86ISD::Wrapper
+           || N0.getOpcode() == X86ISD::WrapperRIP) &&
           N1.getOpcode() == ISD::Constant) {
         unsigned Offset = (unsigned)cast<ConstantSDNode>(N1)->getValue();
         SDOperand C(0, 0);
index 1e3530f21f61ad11ccdc9506854856b8185e5cb2..375777a3290da1c05ae8637f67aad10a66c73548 100644 (file)
@@ -3832,8 +3832,15 @@ X86TargetLowering::LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
   SDOperand Result = DAG.getTargetConstantPool(CP->getConstVal(),
                                                getPointerTy(),
                                                CP->getAlignment());
+  // Use X86ISD::WrapperRIP if we are in X86-64 small / medium PIC mode.
+  TargetMachine &tm = getTargetMachine();
+  unsigned WrapperOpcode = (Subtarget->is64Bit() &&
+                            (tm.getCodeModel() == CodeModel::Small ||
+                             tm.getCodeModel() == CodeModel::Medium) &&
+                            tm.getRelocationModel() == Reloc::PIC_)
+    ? X86ISD::WrapperRIP : X86ISD::Wrapper;
+  Result = DAG.getNode(WrapperOpcode, getPointerTy(), Result);
   if (Subtarget->isTargetDarwin()) {
-    Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
     // With PIC, the address is actually $g + Offset.
     if (!Subtarget->is64Bit() &&
         getTargetMachine().getRelocationModel() == Reloc::PIC_)
@@ -3848,8 +3855,15 @@ SDOperand
 X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   SDOperand Result = DAG.getTargetGlobalAddress(GV, getPointerTy());
+  // Use X86ISD::WrapperRIP if we are in X86-64 small / medium PIC mode.
+  TargetMachine &tm = getTargetMachine();
+  unsigned WrapperOpcode = (Subtarget->is64Bit() &&
+                            (tm.getCodeModel() == CodeModel::Small ||
+                             tm.getCodeModel() == CodeModel::Medium) &&
+                            tm.getRelocationModel() == Reloc::PIC_)
+    ? X86ISD::WrapperRIP : X86ISD::Wrapper;
+  Result = DAG.getNode(WrapperOpcode, getPointerTy(), Result);
   if (Subtarget->isTargetDarwin()) {
-    Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
     // With PIC, the address is actually $g + Offset.
     if (!Subtarget->is64Bit() &&
         getTargetMachine().getRelocationModel() == Reloc::PIC_)
@@ -3865,7 +3879,6 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
         Subtarget->GVRequiresExtraLoad(GV, false))
       Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), Result, NULL, 0);
   } else if (Subtarget->GVRequiresExtraLoad(GV, false)) {
-    Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
     Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), Result, NULL, 0);
   }
 
@@ -3876,8 +3889,15 @@ SDOperand
 X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
   const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
   SDOperand Result = DAG.getTargetExternalSymbol(Sym, getPointerTy());
+  // Use X86ISD::WrapperRIP if we are in X86-64 small / medium PIC mode.
+  TargetMachine &tm = getTargetMachine();
+  unsigned WrapperOpcode = (Subtarget->is64Bit() &&
+                            (tm.getCodeModel() == CodeModel::Small ||
+                             tm.getCodeModel() == CodeModel::Medium) &&
+                            tm.getRelocationModel() == Reloc::PIC_)
+    ? X86ISD::WrapperRIP : X86ISD::Wrapper;
+  Result = DAG.getNode(WrapperOpcode, getPointerTy(), Result);
   if (Subtarget->isTargetDarwin()) {
-    Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
     // With PIC, the address is actually $g + Offset.
     if (!Subtarget->is64Bit() &&
         getTargetMachine().getRelocationModel() == Reloc::PIC_)
@@ -4244,8 +4264,15 @@ SDOperand X86TargetLowering::LowerBRCOND(SDOperand Op, SelectionDAG &DAG) {
 SDOperand X86TargetLowering::LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
   JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
   SDOperand Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy());
+  // Use X86ISD::WrapperRIP if we are in X86-64 small / medium PIC mode.
+  TargetMachine &tm = getTargetMachine();
+  unsigned WrapperOpcode = (Subtarget->is64Bit() &&
+                            (tm.getCodeModel() == CodeModel::Small ||
+                             tm.getCodeModel() == CodeModel::Medium) &&
+                            tm.getRelocationModel() == Reloc::PIC_)
+    ? X86ISD::WrapperRIP : X86ISD::Wrapper;
+  Result = DAG.getNode(WrapperOpcode, getPointerTy(), Result);
   if (Subtarget->isTargetDarwin()) {
-    Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result);
     // With PIC, the address is actually $g + Offset.
     if (!Subtarget->is64Bit() &&
         getTargetMachine().getRelocationModel() == Reloc::PIC_)
@@ -4978,6 +5005,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case X86ISD::LOAD_UA:            return "X86ISD::LOAD_UA";
   case X86ISD::GlobalBaseReg:      return "X86ISD::GlobalBaseReg";
   case X86ISD::Wrapper:            return "X86ISD::Wrapper";
+  case X86ISD::WrapperRIP:         return "X86ISD::WrapperRIP";
   case X86ISD::S2VEC:              return "X86ISD::S2VEC";
   case X86ISD::PEXTRW:             return "X86ISD::PEXTRW";
   case X86ISD::PINSRW:             return "X86ISD::PINSRW";
@@ -5220,12 +5248,13 @@ static SDOperand getShuffleScalarElt(SDNode *N, unsigned i, SelectionDAG &DAG) {
 /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the
 /// node is a GlobalAddress + an offset.
 static bool isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) {
-  if (N->getOpcode() == X86ISD::Wrapper) {
+  unsigned Opc = N->getOpcode();
+  if (Opc == X86ISD::Wrapper || Opc == X86ISD::WrapperRIP) {
     if (dyn_cast<GlobalAddressSDNode>(N->getOperand(0))) {
       GA = cast<GlobalAddressSDNode>(N->getOperand(0))->getGlobal();
       return true;
     }
-  } else if (N->getOpcode() == ISD::ADD) {
+  } else if (Opc == ISD::ADD) {
     SDOperand N1 = N->getOperand(0);
     SDOperand N2 = N->getOperand(1);
     if (isGAPlusOffset(N1.Val, GA, Offset)) {
index f28b95127d2f8de4ba3421f3f3d818eda0d783c1..26c8f336acf4ab0f2b5eb8a4e4dffeae4cb60205 100644 (file)
@@ -150,6 +150,10 @@ namespace llvm {
       /// TargetExternalSymbol, and TargetGlobalAddress.
       Wrapper,
 
+      /// WrapperRIP - Special wrapper used under X86-64 PIC mode for RIP
+      /// relative displacements.
+      WrapperRIP,
+
       /// S2VEC - X86 version of SCALAR_TO_VECTOR. The destination base does not
       /// have to match the operand type.
       S2VEC,
index f50553c077af5ca3a40a2944fd39946e534a1d6d..cb07abe3655ec2c90838fe1d6139abe838c0f07f 100644 (file)
@@ -84,7 +84,8 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr,
 def X86rdtsc   : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
                         [SDNPHasChain, SDNPOutFlag]>;
 
-def X86Wrapper : SDNode<"X86ISD::Wrapper",  SDTX86Wrapper>;
+def X86Wrapper    : SDNode<"X86ISD::Wrapper",     SDTX86Wrapper>;
+def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP",  SDTX86Wrapper>;
 
 //===----------------------------------------------------------------------===//
 // X86 Operand Definitions.
@@ -169,6 +170,8 @@ def HasSSE3  : Predicate<"Subtarget->hasSSE3()">;
 def FPStack  : Predicate<"!Subtarget->hasSSE2()">;
 def In32BitMode : Predicate<"!Subtarget->is64Bit()">;
 def In64BitMode : Predicate<"Subtarget->is64Bit()">;
+def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
+def NotSmallCode :Predicate<"TM.getCodeModel() != CodeModel::Small">;
 
 //===----------------------------------------------------------------------===//
 // X86 specific pattern fragments.
index 0e024d1931e5e786e640f2a897d2d7001407cf8c..0c49e94c0b9698ba302c89239b5c8b4274f763dc 100644 (file)
@@ -36,7 +36,8 @@ def lea64_32mem : Operand<i32> {
 // Complex Pattern Definitions...
 //
 def lea64addr : ComplexPattern<i64, 4, "SelectLEAAddr",
-                               [add, mul, shl, or, frameindex, X86Wrapper], []>;
+                               [add, mul, shl, or, frameindex, X86WrapperRIP],
+                               []>;
 
 //===----------------------------------------------------------------------===//
 // Instruction templates...
@@ -1020,6 +1021,30 @@ def MOV64ri64i32 : Ii32<0xB8, AddRegFrm, (ops GR64:$dst, i64i32imm:$src),
 // Non-Instruction Patterns
 //===----------------------------------------------------------------------===//
 
+// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable
+def : Pat<(i64 (X86Wrapper tconstpool  :$dst)),
+          (MOV64ri32 tconstpool  :$dst)>, Requires<[SmallCode]>;
+def : Pat<(i64 (X86Wrapper tjumptable  :$dst)),
+          (MOV64ri32 tjumptable  :$dst)>, Requires<[SmallCode]>;
+def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
+          (MOV64ri32 tglobaladdr :$dst)>, Requires<[SmallCode]>;
+def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
+          (MOV64ri32 texternalsym:$dst)>, Requires<[SmallCode]>;
+
+def : Pat<(i64 (X86Wrapper tconstpool  :$dst)),
+          (MOV64ri tconstpool  :$dst)>, Requires<[NotSmallCode]>;
+def : Pat<(i64 (X86Wrapper tjumptable  :$dst)),
+          (MOV64ri tjumptable  :$dst)>, Requires<[NotSmallCode]>;
+def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)),
+          (MOV64ri tglobaladdr :$dst)>, Requires<[NotSmallCode]>;
+def : Pat<(i64 (X86Wrapper texternalsym:$dst)),
+          (MOV64ri texternalsym:$dst)>, Requires<[NotSmallCode]>;
+
+def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst),
+          (MOV64mi32 addr:$dst, tglobaladdr:$src)>, Requires<[SmallCode]>;
+def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst),
+          (MOV64mi32 addr:$dst, texternalsym:$src)>, Requires<[SmallCode]>;
+
 // Calls
 // Direct PC relative function call for small code model. 32-bit displacement
 // sign extended to 64-bit.