reimplement support for GS and FS relative address space matching

by having X86DAGToDAGISel::SelectAddr get passed in the parent node
of the operand match (the load/store/atomic op) and having it get
the address space from that, instead of having special FS/GS addr
mode operations that require duplicating the entire instruction set
to support.

This makes FS and GS relative accesses *far* more predictable and
work much better.  It also simplifies the X86 backend a bit, more
to come.

There is still a pending issue with nodes like ISD::PREFETCH and
X86ISD::FLD, which really should be MemSDNode's but aren't.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114491 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-09-21 22:07:31 +00:00
parent 67aff164c0
commit b86faa17a4
3 changed files with 44 additions and 57 deletions

View File

@ -197,7 +197,7 @@ namespace {
bool MatchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
unsigned Depth);
bool MatchAddressBase(SDValue N, X86ISelAddressMode &AM);
bool SelectAddr(SDValue N, SDValue &Base,
bool SelectAddr(SDNode *Parent, SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index, SDValue &Disp,
SDValue &Segment);
bool SelectLEAAddr(SDValue N, SDValue &Base,
@ -1147,7 +1147,11 @@ bool X86DAGToDAGISel::MatchAddressBase(SDValue N, X86ISelAddressMode &AM) {
/// SelectAddr - returns true if it is able pattern match an addressing mode.
/// It returns the operands which make up the maximal addressing mode it can
/// match by reference.
bool X86DAGToDAGISel::SelectAddr(SDValue N, SDValue &Base,
///
/// Parent is the parent node of the addr operand that is being matched. It
/// is always a load, store, atomic node, or null. It is only null when
/// checking memory operands for inline asm nodes.
bool X86DAGToDAGISel::SelectAddr(SDNode *Parent, SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index,
SDValue &Disp, SDValue &Segment) {
X86ISelAddressMode AM;
@ -1163,6 +1167,31 @@ bool X86DAGToDAGISel::SelectAddr(SDValue N, SDValue &Base,
if (!AM.IndexReg.getNode())
AM.IndexReg = CurDAG->getRegister(0, VT);
if (Parent &&
// This list of opcodes are all the nodes that have an "addr:$ptr" operand
// that are not a MemSDNode, and thus don't have proper addrspace info.
Parent->getOpcode() != ISD::PREFETCH &&
Parent->getOpcode() != ISD::INTRINSIC_W_CHAIN && // unaligned loads, fixme
Parent->getOpcode() != ISD::INTRINSIC_VOID && // nontemporal stores.
Parent->getOpcode() != X86ISD::VZEXT_LOAD &&
Parent->getOpcode() != X86ISD::FLD &&
Parent->getOpcode() != X86ISD::FILD &&
Parent->getOpcode() != X86ISD::FILD_FLAG &&
Parent->getOpcode() != X86ISD::FP_TO_INT16_IN_MEM &&
Parent->getOpcode() != X86ISD::FP_TO_INT32_IN_MEM &&
Parent->getOpcode() != X86ISD::FP_TO_INT64_IN_MEM &&
Parent->getOpcode() != X86ISD::LCMPXCHG_DAG &&
Parent->getOpcode() != X86ISD::FST) {
unsigned AddrSpace =
cast<MemSDNode>(Parent)->getPointerInfo().getAddrSpace();
// AddrSpace 256 -> GS, 257 -> FS.
if (AddrSpace == 256)
AM.Segment = CurDAG->getRegister(X86::GS, VT);
if (AddrSpace == 257)
AM.Segment = CurDAG->getRegister(X86::FS, VT);
}
getAddressOperands(AM, Base, Scale, Index, Disp, Segment);
return true;
}
@ -1186,7 +1215,7 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Root,
IsProfitableToFold(N.getOperand(0), N.getNode(), Root) &&
IsLegalToFold(N.getOperand(0), N.getNode(), Root, OptLevel)) {
LoadSDNode *LD = cast<LoadSDNode>(PatternNodeWithChain);
if (!SelectAddr(LD->getBasePtr(), Base, Scale, Index, Disp,Segment))
if (!SelectAddr(LD, LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
return false;
return true;
}
@ -1204,7 +1233,7 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Root,
IsLegalToFold(N.getOperand(0), N.getNode(), Root, OptLevel)) {
// Okay, this is a zero extending load. Fold it.
LoadSDNode *LD = cast<LoadSDNode>(N.getOperand(0).getOperand(0));
if (!SelectAddr(LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
if (!SelectAddr(LD, LD->getBasePtr(), Base, Scale, Index, Disp, Segment))
return false;
PatternNodeWithChain = SDValue(LD, 0);
return true;
@ -1310,7 +1339,8 @@ bool X86DAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N,
!IsLegalToFold(N, P, P, OptLevel))
return false;
return SelectAddr(N.getOperand(1), Base, Scale, Index, Disp, Segment);
return SelectAddr(N.getNode(),
N.getOperand(1), Base, Scale, Index, Disp, Segment);
}
/// getGlobalBaseReg - Return an SDNode that returns the value of
@ -1328,7 +1358,7 @@ SDNode *X86DAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
SDValue In2L = Node->getOperand(2);
SDValue In2H = Node->getOperand(3);
SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
if (!SelectAddr(In1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
if (!SelectAddr(Node, In1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
return NULL;
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
@ -1354,7 +1384,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) {
SDValue Ptr = Node->getOperand(1);
SDValue Val = Node->getOperand(2);
SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
if (!SelectAddr(Ptr, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
if (!SelectAddr(Node, Ptr, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
return 0;
bool isInc = false, isDec = false, isSub = false, isCN = false;
@ -1970,7 +2000,7 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
case 'v': // not offsetable ??
default: return true;
case 'm': // memory
if (!SelectAddr(Op, Op0, Op1, Op2, Op3, Op4))
if (!SelectAddr(0, Op, Op0, Op1, Op2, Op3, Op4))
return true;
break;
}

View File

@ -1611,16 +1611,6 @@ def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
[(X86TLSCall addr:$sym)]>,
Requires<[In64BitMode]>;
let AddedComplexity = 5, isCodeGenOnly = 1 in
def MOV64GSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
"movq\t%gs:$src, $dst",
[(set GR64:$dst, (gsload addr:$src))]>, SegGS;
let AddedComplexity = 5, isCodeGenOnly = 1 in
def MOV64FSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
"movq\t%fs:$src, $dst",
[(set GR64:$dst, (fsload addr:$src))]>, SegFS;
//===----------------------------------------------------------------------===//
// Atomic Instructions
//===----------------------------------------------------------------------===//

View File

@ -337,7 +337,7 @@ def i32i8imm : Operand<i32> {
//
// Define X86 specific addressing mode.
def addr : ComplexPattern<iPTR, 5, "SelectAddr", [], []>;
def addr : ComplexPattern<iPTR, 5, "SelectAddr", [], [SDNPWantParent]>;
def lea32addr : ComplexPattern<i32, 5, "SelectLEAAddr",
[add, sub, mul, X86mul_imm, shl, or, frameindex],
[]>;
@ -419,30 +419,11 @@ def immSext8 : PatLeaf<(imm), [{ return immSext8(N); }]>;
def i16immSExt8 : PatLeaf<(i16 immSext8)>;
def i32immSExt8 : PatLeaf<(i32 immSext8)>;
/// Load patterns: these constraint the match to the right address space.
def dsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{
if (cast<LoadSDNode>(N)->getPointerInfo().getAddrSpace() > 255)
return false;
return true;
}]>;
def gsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{
return cast<LoadSDNode>(N)->getPointerInfo().getAddrSpace() == 256;
}]>;
def fsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{
return cast<LoadSDNode>(N)->getPointerInfo().getAddrSpace() == 257;
}]>;
// Helper fragments for loads.
// It's always safe to treat a anyext i16 load as a i32 load if the i16 is
// known to be 32-bit aligned or better. Ditto for i8 to i16.
def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{
LoadSDNode *LD = cast<LoadSDNode>(N);
if (LD->getPointerInfo().getAddrSpace() > 255)
return false;
ISD::LoadExtType ExtType = LD->getExtensionType();
if (ExtType == ISD::NON_EXTLOAD)
return true;
@ -453,8 +434,6 @@ def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{
def loadi16_anyext : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)),[{
LoadSDNode *LD = cast<LoadSDNode>(N);
if (LD->getPointerInfo().getAddrSpace() > 255)
return false;
ISD::LoadExtType ExtType = LD->getExtensionType();
if (ExtType == ISD::EXTLOAD)
return LD->getAlignment() >= 2 && !LD->isVolatile();
@ -463,8 +442,6 @@ def loadi16_anyext : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)),[{
def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{
LoadSDNode *LD = cast<LoadSDNode>(N);
if (LD->getPointerInfo().getAddrSpace() > 255)
return false;
ISD::LoadExtType ExtType = LD->getExtensionType();
if (ExtType == ISD::NON_EXTLOAD)
return true;
@ -473,11 +450,11 @@ def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{
return false;
}]>;
def loadi8 : PatFrag<(ops node:$ptr), (i8 (dsload node:$ptr))>;
def loadi64 : PatFrag<(ops node:$ptr), (i64 (dsload node:$ptr))>;
def loadf32 : PatFrag<(ops node:$ptr), (f32 (dsload node:$ptr))>;
def loadf64 : PatFrag<(ops node:$ptr), (f64 (dsload node:$ptr))>;
def loadf80 : PatFrag<(ops node:$ptr), (f80 (dsload node:$ptr))>;
def loadi8 : PatFrag<(ops node:$ptr), (i8 (load node:$ptr))>;
def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr))>;
def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr))>;
def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr))>;
def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr))>;
def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>;
def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>;
@ -3909,16 +3886,6 @@ def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
[(X86TLSCall addr:$sym)]>,
Requires<[In32BitMode]>;
let AddedComplexity = 5, isCodeGenOnly = 1 in
def GS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
"movl\t%gs:$src, $dst",
[(set GR32:$dst, (gsload addr:$src))]>, SegGS;
let AddedComplexity = 5, isCodeGenOnly = 1 in
def FS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
"movl\t%fs:$src, $dst",
[(set GR32:$dst, (fsload addr:$src))]>, SegFS;
//===----------------------------------------------------------------------===//
// EH Pseudo Instructions
//