X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSystemZ%2FSystemZISelDAGToDAG.cpp;h=7febed25cb84cc09328d35f21365ee76fcd691a7;hb=68ad65c25d66d34098dfa00ae78eaf38b0ab4ecf;hp=d7174087cd57276506d320c08ec9a56c1cc90582;hpb=3e84ad28d4d3ceee25771b1e30315c20b7608c39;p=oota-llvm.git diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index d7174087cd5..7febed25cb8 100644 --- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -107,7 +107,8 @@ static uint64_t allOnes(unsigned int Count) { // // (and (rotl Input, Rotate), Mask) // -// otherwise. The value has BitSize bits. +// otherwise. The output value has BitSize bits, although Input may be +// narrower (in which case the upper bits are don't care). struct RxSBGOperands { RxSBGOperands(unsigned Op, SDValue N) : Opcode(Op), BitSize(N.getValueType().getSizeInBits()), @@ -128,7 +129,7 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { const SystemZSubtarget &Subtarget; // Used by SystemZOperands.td to create integer constants. - inline SDValue getImm(const SDNode *Node, uint64_t Imm) { + inline SDValue getImm(const SDNode *Node, uint64_t Imm) const { return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); } @@ -142,39 +143,39 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { // Try to fold more of the base or index of AM into AM, where IsBase // selects between the base and index. - bool expandAddress(SystemZAddressingMode &AM, bool IsBase); + bool expandAddress(SystemZAddressingMode &AM, bool IsBase) const; // Try to describe N in AM, returning true on success. - bool selectAddress(SDValue N, SystemZAddressingMode &AM); + bool selectAddress(SDValue N, SystemZAddressingMode &AM) const; // Extract individual target operands from matched address AM. void getAddressOperands(const SystemZAddressingMode &AM, EVT VT, - SDValue &Base, SDValue &Disp); + SDValue &Base, SDValue &Disp) const; void getAddressOperands(const SystemZAddressingMode &AM, EVT VT, - SDValue &Base, SDValue &Disp, SDValue &Index); + SDValue &Base, SDValue &Disp, SDValue &Index) const; // Try to match Addr as a FormBD address with displacement type DR. // Return true on success, storing the base and displacement in // Base and Disp respectively. bool selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr, - SDValue &Base, SDValue &Disp); + SDValue &Base, SDValue &Disp) const; // Try to match Addr as a FormBDX address with displacement type DR. // Return true on success and if the result had no index. Store the // base and displacement in Base and Disp respectively. bool selectMVIAddr(SystemZAddressingMode::DispRange DR, SDValue Addr, - SDValue &Base, SDValue &Disp); + SDValue &Base, SDValue &Disp) const; // Try to match Addr as a FormBDX* address of form Form with // displacement type DR. Return true on success, storing the base, // displacement and index in Base, Disp and Index respectively. bool selectBDXAddr(SystemZAddressingMode::AddrForm Form, SystemZAddressingMode::DispRange DR, SDValue Addr, - SDValue &Base, SDValue &Disp, SDValue &Index); + SDValue &Base, SDValue &Disp, SDValue &Index) const; // PC-relative address matching routines used by SystemZOperands.td. - bool selectPCRelAddress(SDValue Addr, SDValue &Target) { - if (Addr.getOpcode() == SystemZISD::PCREL_WRAPPER) { + bool selectPCRelAddress(SDValue Addr, SDValue &Target) const { + if (SystemZISD::isPCREL(Addr.getOpcode())) { Target = Addr.getOperand(0); return true; } @@ -182,72 +183,72 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { } // BD matching routines used by SystemZOperands.td. - bool selectBDAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectBDAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr, Base, Disp); } - bool selectBDAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectBDAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp); } - bool selectBDAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectBDAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr, Base, Disp); } - bool selectBDAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectBDAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp); } // MVI matching routines used by SystemZOperands.td. - bool selectMVIAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectMVIAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp); } - bool selectMVIAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { + bool selectMVIAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const { return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp); } // BDX matching routines used by SystemZOperands.td. bool selectBDXAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, SystemZAddressingMode::Disp12Only, Addr, Base, Disp, Index); } bool selectBDXAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, SystemZAddressingMode::Disp12Pair, Addr, Base, Disp, Index); } bool selectDynAlloc12Only(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc, SystemZAddressingMode::Disp12Only, Addr, Base, Disp, Index); } bool selectBDXAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, SystemZAddressingMode::Disp20Only, Addr, Base, Disp, Index); } bool selectBDXAddr20Only128(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, SystemZAddressingMode::Disp20Only128, Addr, Base, Disp, Index); } bool selectBDXAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, SystemZAddressingMode::Disp20Pair, Addr, Base, Disp, Index); } bool selectLAAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXLA, SystemZAddressingMode::Disp12Pair, Addr, Base, Disp, Index); } bool selectLAAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp, - SDValue &Index) { + SDValue &Index) const { return selectBDXAddr(SystemZAddressingMode::FormBDXLA, SystemZAddressingMode::Disp20Pair, Addr, Base, Disp, Index); @@ -256,21 +257,21 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { // Check whether (or Op (and X InsertMask)) is effectively an insertion // of X into bits InsertMask of some Y != Op. Return true if so and // set Op to that Y. - bool detectOrAndInsertion(SDValue &Op, uint64_t InsertMask); + bool detectOrAndInsertion(SDValue &Op, uint64_t InsertMask) const; // Try to update RxSBG so that only the bits of RxSBG.Input in Mask are used. // Return true on success. - bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask); + bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) const; // Try to fold some of RxSBG.Input into other fields of RxSBG. // Return true on success. - bool expandRxSBG(RxSBGOperands &RxSBG); + bool expandRxSBG(RxSBGOperands &RxSBG) const; - // Return an undefined i64 value. - SDValue getUNDEF64(SDLoc DL); + // Return an undefined value of type VT. + SDValue getUNDEF(SDLoc DL, EVT VT) const; // Convert N to VT, if it isn't already. - SDValue convertTo(SDLoc DL, EVT VT, SDValue N); + SDValue convertTo(SDLoc DL, EVT VT, SDValue N) const; // Try to implement AND or shift node N using RISBG with the zero flag set. // Return the selected node on success, otherwise return null. @@ -290,6 +291,17 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { SDNode *splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0, uint64_t UpperVal, uint64_t LowerVal); + // Return true if Load and Store are loads and stores of the same size + // and are guaranteed not to overlap. Such operations can be implemented + // using block (SS-format) instructions. + // + // Partial overlap would lead to incorrect code, since the block operations + // are logically bytewise, even though they have a fast path for the + // non-overlapping case. We also need to avoid full overlap (i.e. two + // addresses that might be equal at run time) because although that case + // would be handled correctly, it might be implemented by millicode. + bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load) const; + // N is a (store (load Y), X) pattern. Return true if it can use an MVC // from Y to X. bool storeLoadCanUseMVC(SDNode *N) const; @@ -384,9 +396,9 @@ static bool expandIndex(SystemZAddressingMode &AM, SDValue Base, // The base or index of AM is equivalent to Op0 + Op1, where IsBase selects // between the base and index. Try to fold Op1 into AM's displacement. static bool expandDisp(SystemZAddressingMode &AM, bool IsBase, - SDValue Op0, ConstantSDNode *Op1) { + SDValue Op0, uint64_t Op1) { // First try adjusting the displacement. - int64_t TestDisp = AM.Disp + Op1->getSExtValue(); + int64_t TestDisp = AM.Disp + Op1; if (selectDisp(AM.DR, TestDisp)) { changeComponent(AM, IsBase, Op0); AM.Disp = TestDisp; @@ -399,7 +411,7 @@ static bool expandDisp(SystemZAddressingMode &AM, bool IsBase, } bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM, - bool IsBase) { + bool IsBase) const { SDValue N = IsBase ? AM.Base : AM.Index; unsigned Opcode = N.getOpcode(); if (Opcode == ISD::TRUNCATE) { @@ -419,13 +431,23 @@ bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM, return expandAdjDynAlloc(AM, IsBase, Op0); if (Op0Code == ISD::Constant) - return expandDisp(AM, IsBase, Op1, cast(Op0)); + return expandDisp(AM, IsBase, Op1, + cast(Op0)->getSExtValue()); if (Op1Code == ISD::Constant) - return expandDisp(AM, IsBase, Op0, cast(Op1)); + return expandDisp(AM, IsBase, Op0, + cast(Op1)->getSExtValue()); if (IsBase && expandIndex(AM, Op0, Op1)) return true; } + if (Opcode == SystemZISD::PCREL_OFFSET) { + SDValue Full = N.getOperand(0); + SDValue Base = N.getOperand(1); + SDValue Anchor = Base.getOperand(0); + uint64_t Offset = (cast(Full)->getOffset() - + cast(Anchor)->getOffset()); + return expandDisp(AM, IsBase, Base, Offset); + } return false; } @@ -504,14 +526,15 @@ static bool shouldUseLA(SDNode *Base, int64_t Disp, SDNode *Index) { // Return true if Addr is suitable for AM, updating AM if so. bool SystemZDAGToDAGISel::selectAddress(SDValue Addr, - SystemZAddressingMode &AM) { + SystemZAddressingMode &AM) const { // Start out assuming that the address will need to be loaded separately, // then try to extend it as much as we can. AM.Base = Addr; // First try treating the address as a constant. if (Addr.getOpcode() == ISD::Constant && - expandDisp(AM, true, SDValue(), cast(Addr))) + expandDisp(AM, true, SDValue(), + cast(Addr)->getSExtValue())) ; else // Otherwise try expanding each component. @@ -551,7 +574,7 @@ static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N) { void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, EVT VT, SDValue &Base, - SDValue &Disp) { + SDValue &Disp) const { Base = AM.Base; if (!Base.getNode()) // Register 0 means "no base". This is mostly useful for shifts. @@ -576,7 +599,8 @@ void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, EVT VT, SDValue &Base, - SDValue &Disp, SDValue &Index) { + SDValue &Disp, + SDValue &Index) const { getAddressOperands(AM, VT, Base, Disp); Index = AM.Index; @@ -587,7 +611,7 @@ void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr, SDValue &Base, - SDValue &Disp) { + SDValue &Disp) const { SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR); if (!selectAddress(Addr, AM)) return false; @@ -598,7 +622,7 @@ bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR, bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR, SDValue Addr, SDValue &Base, - SDValue &Disp) { + SDValue &Disp) const { SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR); if (!selectAddress(Addr, AM) || AM.Index.getNode()) return false; @@ -610,7 +634,7 @@ bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR, bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form, SystemZAddressingMode::DispRange DR, SDValue Addr, SDValue &Base, - SDValue &Disp, SDValue &Index) { + SDValue &Disp, SDValue &Index) const { SystemZAddressingMode AM(Form, DR); if (!selectAddress(Addr, AM)) return false; @@ -620,7 +644,7 @@ bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form, } bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op, - uint64_t InsertMask) { + uint64_t InsertMask) const { // We're only interested in cases where the insertion is into some operand // of Op, rather than into Op itself. The only useful case is an AND. if (Op.getOpcode() != ISD::AND) @@ -651,7 +675,8 @@ bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op, return true; } -bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) { +bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG, + uint64_t Mask) const { const SystemZInstrInfo *TII = getInstrInfo(); if (RxSBG.Rotate != 0) Mask = (Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)); @@ -682,7 +707,7 @@ static bool shiftedInBitsMatter(RxSBGOperands &RxSBG, uint64_t Count, return (ShiftedIn & RxSBG.Mask) != 0; } -bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { +bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { SDValue N = RxSBG.Input; unsigned Opcode = N.getOpcode(); switch (Opcode) { @@ -738,7 +763,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { case ISD::ROTL: { // Any 64-bit rotate left can be merged into the RxSBG. - if (RxSBG.BitSize != 64) + if (RxSBG.BitSize != 64 || N.getValueType() != MVT::i64) return false; ConstantSDNode *CountNode = dyn_cast(N.getOperand(1).getNode()); @@ -750,6 +775,19 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { return true; } + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: { + // Check that the extension bits are don't-care (i.e. are masked out + // by the final mask). + unsigned InnerBitSize = N.getOperand(0).getValueType().getSizeInBits(); + if (shiftedInBitsMatter(RxSBG, RxSBG.BitSize - InnerBitSize, false)) + return false; + + RxSBG.Input = N.getOperand(0); + return true; + } + case ISD::SHL: { ConstantSDNode *CountNode = dyn_cast(N.getOperand(1).getNode()); @@ -757,7 +795,8 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { return false; uint64_t Count = CountNode->getZExtValue(); - if (Count < 1 || Count >= RxSBG.BitSize) + unsigned BitSize = N.getValueType().getSizeInBits(); + if (Count < 1 || Count >= BitSize) return false; if (RxSBG.Opcode == SystemZ::RNSBG) { @@ -767,7 +806,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { return false; } else { // Treat (shl X, count) as (and (rotl X, count), ~0<getZExtValue(); - if (Count < 1 || Count >= RxSBG.BitSize) + unsigned BitSize = N.getValueType().getSizeInBits(); + if (Count < 1 || Count >= BitSize) return false; if (RxSBG.Opcode == SystemZ::RNSBG || Opcode == ISD::SRA) { @@ -795,7 +835,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { } else { // Treat (srl X, count), mask) as (and (rotl X, size-count), ~0>>count), // which is similar to SLL above. - if (!refineRxSBGMask(RxSBG, allOnes(RxSBG.BitSize - Count))) + if (!refineRxSBGMask(RxSBG, allOnes(BitSize - Count))) return false; } @@ -808,17 +848,17 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) { } } -SDValue SystemZDAGToDAGISel::getUNDEF64(SDLoc DL) { - SDNode *N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64); +SDValue SystemZDAGToDAGISel::getUNDEF(SDLoc DL, EVT VT) const { + SDNode *N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT); return SDValue(N, 0); } -SDValue SystemZDAGToDAGISel::convertTo(SDLoc DL, EVT VT, SDValue N) { +SDValue SystemZDAGToDAGISel::convertTo(SDLoc DL, EVT VT, SDValue N) const { if (N.getValueType() == MVT::i32 && VT == MVT::i64) - return CurDAG->getTargetInsertSubreg(SystemZ::subreg_32bit, - DL, VT, getUNDEF64(DL), N); + return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32, + DL, VT, getUNDEF(DL, MVT::i64), N); if (N.getValueType() == MVT::i64 && VT == MVT::i32) - return CurDAG->getTargetExtractSubreg(SystemZ::subreg_32bit, DL, VT, N); + return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32, DL, VT, N); assert(N.getValueType() == VT && "Unexpected value types"); return N; } @@ -828,7 +868,8 @@ SDNode *SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) { RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0)); unsigned Count = 0; while (expandRxSBG(RISBG)) - Count += 1; + if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND) + Count += 1; if (Count == 0) return 0; if (Count == 1) { @@ -856,14 +897,22 @@ SDNode *SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) { } } + unsigned Opcode = SystemZ::RISBG; + EVT OpcodeVT = MVT::i64; + if (VT == MVT::i32 && Subtarget.hasHighWord()) { + Opcode = SystemZ::RISBMux; + OpcodeVT = MVT::i32; + RISBG.Start &= 31; + RISBG.End &= 31; + } SDValue Ops[5] = { - getUNDEF64(SDLoc(N)), - convertTo(SDLoc(N), MVT::i64, RISBG.Input), + getUNDEF(SDLoc(N), OpcodeVT), + convertTo(SDLoc(N), OpcodeVT, RISBG.Input), CurDAG->getTargetConstant(RISBG.Start, MVT::i32), CurDAG->getTargetConstant(RISBG.End | 128, MVT::i32), CurDAG->getTargetConstant(RISBG.Rotate, MVT::i32) }; - N = CurDAG->getMachineNode(SystemZ::RISBG, SDLoc(N), MVT::i64, Ops); + N = CurDAG->getMachineNode(Opcode, SDLoc(N), OpcodeVT, Ops); return convertTo(SDLoc(N), VT, SDValue(N, 0)).getNode(); } @@ -877,7 +926,8 @@ SDNode *SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) { unsigned Count[] = { 0, 0 }; for (unsigned I = 0; I < 2; ++I) while (expandRxSBG(RxSBG[I])) - Count[I] += 1; + if (RxSBG[I].Input.getOpcode() != ISD::ANY_EXTEND) + Count[I] += 1; // Do nothing if neither operand is suitable. if (Count[0] == 0 && Count[1] == 0) @@ -925,13 +975,8 @@ SDNode *SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node, return Or.getNode(); } -// Return true if Load and Store: -// - are loads and stores of the same size; -// - do not partially overlap; and -// - can be decomposed into what are logically individual character accesses -// without changing the semantics. -static bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load, - AliasAnalysis *AA) { +bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store, + LoadSDNode *Load) const { // Check that the two memory operands have the same size. if (Load->getMemoryVT() != Store->getMemoryVT()) return false; @@ -944,19 +989,19 @@ static bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load, if (Load->isInvariant()) return true; - // If both operands are aligned, they must be equal or not overlap. - uint64_t Size = Load->getMemoryVT().getStoreSize(); - if (Load->getAlignment() >= Size && Store->getAlignment() >= Size) - return true; - // Otherwise we need to check whether there's an alias. const Value *V1 = Load->getSrcValue(); const Value *V2 = Store->getSrcValue(); if (!V1 || !V2) return false; + // Reject equality. + uint64_t Size = Load->getMemoryVT().getStoreSize(); int64_t End1 = Load->getSrcValueOffset() + Size; int64_t End2 = Store->getSrcValueOffset() + Size; + if (V1 == V2 && End1 == End2) + return false; + return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getTBAAInfo()), AliasAnalysis::Location(V2, End2, Store->getTBAAInfo())); } @@ -970,14 +1015,14 @@ bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const { uint64_t Size = Load->getMemoryVT().getStoreSize(); if (Size > 1 && Size <= 8) { // Prefer LHRL, LRL and LGRL. - if (Load->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER) + if (SystemZISD::isPCREL(Load->getBasePtr().getOpcode())) return false; // Prefer STHRL, STRL and STGRL. - if (Store->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER) + if (SystemZISD::isPCREL(Store->getBasePtr().getOpcode())) return false; } - return canUseBlockOperation(Store, Load, AA); + return canUseBlockOperation(Store, Load); } bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N, @@ -985,11 +1030,7 @@ bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N, StoreSDNode *StoreA = cast(N); LoadSDNode *LoadA = cast(StoreA->getValue().getOperand(1 - I)); LoadSDNode *LoadB = cast(StoreA->getValue().getOperand(I)); - if (LoadA->isVolatile() || - LoadA->getMemoryVT() != StoreA->getMemoryVT() || - LoadA->getBasePtr() != StoreA->getBasePtr()) - return false; - return canUseBlockOperation(StoreA, LoadB, AA); + return !LoadA->isVolatile() && canUseBlockOperation(StoreA, LoadB); } SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) {