From b86faa17a4e574580ad029a8082a27ead2fa6013 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 21 Sep 2010 22:07:31 +0000 Subject: [PATCH] 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 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 46 +++++++++++++++++++++++++++++++------- lib/Target/X86/X86Instr64bit.td | 10 --------- lib/Target/X86/X86InstrInfo.td | 45 +++++-------------------------------- 3 files changed, 44 insertions(+), 57 deletions(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 06aa9d3fbc6..a5d0aaa1b1a 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -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(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(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(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(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; } diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 307d4312a3b..cbdd1ffbd62 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -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 //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index ac661dc7bd4..5ac89d65e31 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -337,7 +337,7 @@ def i32i8imm : Operand { // // Define X86 specific addressing mode. -def addr : ComplexPattern; +def addr : ComplexPattern; def lea32addr : ComplexPattern; @@ -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(N)->getPointerInfo().getAddrSpace() > 255) - return false; - return true; -}]>; - -def gsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - return cast(N)->getPointerInfo().getAddrSpace() == 256; -}]>; - -def fsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - return cast(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(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(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(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 // -- 2.11.0