break;
case ISD::ConstantPool:
- case ISD::TargetConstantPool:
if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N)) {
AM.BaseType = X86ISelAddressMode::ConstantPoolBase;
break;
case ISD::GlobalAddress:
- case ISD::TargetGlobalAddress:
if (AM.GV == 0) {
AM.GV = cast<GlobalAddressSDNode>(N)->getGlobal();
return false;
}
break;
- case X86ISD::TGAWrapper:
- if (AM.GV == 0) {
- AM.GV = cast<GlobalAddressSDNode>(N.getOperand(0))->getGlobal();
- return false;
+ case X86ISD::Wrapper:
+ if (ConstantPoolSDNode *CP =
+ dyn_cast<ConstantPoolSDNode>(N.getOperand(0))) {
+ if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
+ AM.BaseType = X86ISelAddressMode::ConstantPoolBase;
+ AM.Base.Reg = CurDAG->getTargetConstantPool(CP->get(), MVT::i32,
+ CP->getAlignment());
+ return false;
+ }
+ } else if (GlobalAddressSDNode *G =
+ dyn_cast<GlobalAddressSDNode>(N.getOperand(0))) {
+ if (AM.GV == 0) {
+ AM.GV = cast<GlobalAddressSDNode>(N.getOperand(0))->getGlobal();
+ return false;
+ }
}
break;
Complexity++;
if (SelectIndex)
Complexity++;
- if (AM.GV)
+ if (AM.GV) {
Complexity++;
- else if (AM.Disp > 1)
+ if (AM.Disp)
+ Complexity++;
+ } else if (AM.Disp > 1)
Complexity++;
// Suppose base == %eax and it has multiple uses, then instead of
// movl %eax, %ecx
switch (Opcode) {
default: break;
- case X86ISD::TGAWrapper: {
- GlobalValue *GV = cast<GlobalAddressSDNode>(N.getOperand(0))->getGlobal();
- SDOperand TGA = CurDAG->getTargetGlobalAddress(GV, MVT::i32);
- Result = CodeGenMap[N] =
- SDOperand(CurDAG->getTargetNode(X86::MOV32ri, MVT::i32, TGA), 0);
+ case X86ISD::GlobalBaseReg:
+ Result = getGlobalBaseReg();
+ return;
+
+ case X86ISD::Wrapper: {
+ // It's beneficial to manully select the wrapper nodes here rather
+ // then using tablgen'd code to match this. We do not want to mutate the
+ // node to MOV32ri and we do not want to record this in CodeGenMap.
+ // We want to allow the wrapped leaf nodes be duplicated so they can
+ // be used in addressing modes.
+ // e.g.
+ // 0xa59e4a0: i32 = TargetGlobalAddress <xxx> 0
+ // 0xa59e740: i32 = X86ISD::Wrapper 0xa59e4a0
+ // ...
+ // 0xa59e880: i32 = add 0xa59e740, 0xa59e800
+ // ...
+ // 0xa59e880: <multiple use>
+ // 0xa59e970: i32 = add 0xa59e880, 0xa59e910
+ // ...
+ // 0xa59ea60: i32,ch = load 0xa589780, 0xa59e970, 0xa59ea00
+ // ...
+ // 0xa59e880: <multiple use>
+ // 0xa59eb60: ch = CopyToReg 0xa59ea60:1, 0xa59eaf0, 0xa59e880
+ // By allowing the TargetGlobalAddress to be duplicated, it can appear
+ // in the load address as well as an operand of the add.
+ Result = SDOperand(CurDAG->getTargetNode(X86::MOV32ri, MVT::i32,
+ N.getOperand(0)), 0);
+#ifndef NDEBUG
+ DEBUG(std::cerr << std::string(Indent-2, ' '));
+ DEBUG(std::cerr << "== ");
+ DEBUG(Result.Val->dump(CurDAG));
+ DEBUG(std::cerr << "\n");
+ Indent -= 2;
+#endif
return;
}
+
case ISD::MULHU:
case ISD::MULHS: {
if (Opcode == ISD::MULHU)
return;
}
- case X86ISD::GlobalBaseReg:
- Result = getGlobalBaseReg();
- return;
-
case ISD::SDIV:
case ISD::UDIV:
case ISD::SREM:
// Darwin ABI issue.
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
+ setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
// 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom);
setOperationAction(ISD::SRA_PARTS , MVT::i32 , Custom);
}
case ISD::ConstantPool: {
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
- SDOperand Result =
- DAG.getTargetConstantPool(CP->get(), getPointerTy(), CP->getAlignment());
- // Only lower ConstantPool on Darwin.
+ SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
+ DAG.getTargetConstantPool(CP->get(), getPointerTy(),
+ CP->getAlignment()));
if (getTargetMachine().getSubtarget<X86Subtarget>().isTargetDarwin()) {
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC)
return Result;
}
case ISD::GlobalAddress: {
- SDOperand Result;
- // Only lower GlobalAddress on Darwin.
+ GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+ SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
+ DAG.getTargetGlobalAddress(GV, getPointerTy()));
if (getTargetMachine().
getSubtarget<X86Subtarget>().isTargetDarwin()) {
- GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
- Result = DAG.getNode(X86ISD::TGAWrapper, getPointerTy(),
- DAG.getTargetGlobalAddress(GV, getPointerTy()));
// With PIC, the address is actually $g + Offset.
if (getTargetMachine().getRelocationModel() == Reloc::PIC)
Result = DAG.getNode(ISD::ADD, getPointerTy(),
return Result;
}
+ case ISD::ExternalSymbol: {
+ const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
+ SDOperand Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(),
+ DAG.getTargetExternalSymbol(Sym, getPointerTy()));
+ if (getTargetMachine().
+ getSubtarget<X86Subtarget>().isTargetDarwin()) {
+ // With PIC, the address is actually $g + Offset.
+ if (getTargetMachine().getRelocationModel() == Reloc::PIC)
+ Result = DAG.getNode(ISD::ADD, getPointerTy(),
+ DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
+ }
+
+ return Result;
+ }
case ISD::VASTART: {
// vastart just stores the address of the VarArgsFrameIndex slot into the
// memory location argument.
case X86ISD::REP_MOVS: return "X86ISD::RET_MOVS";
case X86ISD::LOAD_PACK: return "X86ISD::LOAD_PACK";
case X86ISD::GlobalBaseReg: return "X86ISD::GlobalBaseReg";
- case X86ISD::TGAWrapper: return "X86ISD::TGAWrapper";
+ case X86ISD::Wrapper: return "X86ISD::Wrapper";
}
}
/// at function entry, used for PIC code.
GlobalBaseReg,
- /// TGAWrapper - A wrapper node for TargetGlobalAddress, only used on
- /// Darwin.
- TGAWrapper,
+ /// TCPWrapper - A wrapper node for TargetConstantPool,
+ /// TargetExternalSymbol, and TargetGlobalAddress.
+ Wrapper,
};
// X86 specific condition code. These correspond to X86_*_COND in
def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
[SDNPHasChain, SDNPOutFlag]>;
-def X86loadp : SDNode<"X86ISD::LOAD_PACK", SDTLoad,
+def X86loadp : SDNode<"X86ISD::LOAD_PACK", SDTLoad,
[SDNPHasChain]>;
-def X86TGAWrapper : SDNode<"X86ISD::TGAWrapper", SDTIntUnaryOp>;
-
//===----------------------------------------------------------------------===//
// X86 Operand Definitions.
//
// Define X86 specific addressing mode.
def addr : ComplexPattern<i32, 4, "SelectAddr", []>;
def leaaddr : ComplexPattern<i32, 4, "SelectLEAAddr",
- [add, frameindex, constpool]>;
+ [add, frameindex]>;
//===----------------------------------------------------------------------===//
// X86 Instruction Format Definitions.
// Non-Instruction Patterns
//===----------------------------------------------------------------------===//
-// GlobalAddress and ExternalSymbol
-def : Pat<(i32 globaladdr:$dst), (MOV32ri tglobaladdr:$dst)>;
-def : Pat<(i32 externalsym:$dst), (MOV32ri texternalsym:$dst)>;
-
// Calls
def : Pat<(X86call tglobaladdr:$dst),
(CALLpcrel32 tglobaladdr:$dst)>;