diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 926859a6a3de..8b307971f203 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -1111,7 +1111,7 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { SDValue Chain = LD->getChain(); SDValue Base = LD->getBasePtr(); - SDValue Ops[] = { Offset, Base, Chain }; + SDValue Ops[] = { Base, Offset, Chain }; return CurDAG->getMachineNode(Opcode, dl, LD->getValueType(0), PPCLowering.getPointerTy(), MVT::Other, Ops, 3); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index c7d454692ecd..218a20db5794 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1192,6 +1192,7 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, SelectionDAG &DAG) const { if (DisablePPCPreinc) return false; + bool isLoad = true; SDValue Ptr; EVT VT; unsigned Alignment; @@ -1203,6 +1204,7 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, Ptr = ST->getBasePtr(); VT = ST->getMemoryVT(); Alignment = ST->getAlignment(); + isLoad = false; } else return false; @@ -1210,7 +1212,25 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, if (VT.isVector()) return false; - if (SelectAddressRegReg(Ptr, Offset, Base, DAG)) { + if (SelectAddressRegReg(Ptr, Base, Offset, DAG)) { + + // Common code will reject creating a pre-inc form if the base pointer + // is a frame index, or if N is a store and the base pointer is either + // the same as or a predecessor of the value being stored. Check for + // those situations here, and try with swapped Base/Offset instead. + bool Swap = false; + + if (isa(Base) || isa(Base)) + Swap = true; + else if (!isLoad) { + SDValue Val = cast(N)->getValue(); + if (Val == Base || Base.getNode()->isPredecessorOf(Val.getNode())) + Swap = true; + } + + if (Swap) + std::swap(Base, Offset); + AM = ISD::PRE_INC; return true; } diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 70e2881e797f..ac7bcfb41228 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -875,14 +875,14 @@ def : Pat<(pre_truncsti32 G8RC:$rS, ptr_rc_nor0:$ptrreg, iaddroff:$ptroff), def : Pat<(aligned4pre_store G8RC:$rS, ptr_rc_nor0:$ptrreg, iaddroff:$ptroff), (STDU G8RC:$rS, iaddroff:$ptroff, ptr_rc_nor0:$ptrreg)>; -def : Pat<(pre_truncsti8 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STBUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_truncsti16 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STHUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_truncsti32 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STWUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_store G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STDUX G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; +def : Pat<(pre_truncsti8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STBUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_truncsti16 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STHUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_truncsti32 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STWUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_store G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STDUX G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 0e37449128c3..be4a7eefccaf 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -1004,16 +1004,16 @@ def STFDUX: XForm_8<31, 759, (outs ptr_rc_nor0:$ea_res), (ins F8RC:$rS, memrr:$d // Patterns to match the pre-inc stores. We can't put the patterns on // the instruction definitions directly as ISel wants the address base // and offset to be separate operands, not a single complex operand. -def : Pat<(pre_truncsti8 GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STBUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_truncsti16 GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STHUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_store GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STWUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_store F4RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STFSUX F4RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; -def : Pat<(pre_store F8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff), - (STFDUX F8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>; +def : Pat<(pre_truncsti8 GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STBUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_truncsti16 GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STHUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_store GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STWUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_store F4RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STFSUX F4RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; +def : Pat<(pre_store F8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff), + (STFDUX F8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>; def SYNC : XForm_24_sync<31, 598, (outs), (ins), "sync", LdStSync,