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))
}
}
break;
+ }
case ISD::FrameIndex:
if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
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);
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_)
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_)
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);
}
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_)
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_)
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";
/// 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)) {
/// 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,
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.
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.
// Complex Pattern Definitions...
//
def lea64addr : ComplexPattern<i64, 4, "SelectLEAAddr",
- [add, mul, shl, or, frameindex, X86Wrapper], []>;
+ [add, mul, shl, or, frameindex, X86WrapperRIP],
+ []>;
//===----------------------------------------------------------------------===//
// Instruction templates...
// 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.