mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
Fix swapped BasePtr and Offset in pre-inc memory addresses.
PPCTargetLowering::getPreIndexedAddressParts currently provides the base part of a memory address in the offset result, and the offset part in the base result. That swap is then undone again when an MI instruction is generated (in PPCDAGToDAGISel::Select for loads, and using .md Pat patterns for stores). This patch reverts this double swap, to make common code and back-end be in sync as to which part of the address is base and which is offset. To avoid performance regressions in certain cases, target code now checks whether the choice of base register would be rejected for pre-inc accesses by common code, and attempts to swap base and offset again in such cases. (Overall, this means that now pre-ice accesses are generated *more* frequently than before.) llvm-svn: 177733
This commit is contained in:
parent
4b7960b48d
commit
c8c3c4dc22
@ -1111,7 +1111,7 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
|
|||||||
|
|
||||||
SDValue Chain = LD->getChain();
|
SDValue Chain = LD->getChain();
|
||||||
SDValue Base = LD->getBasePtr();
|
SDValue Base = LD->getBasePtr();
|
||||||
SDValue Ops[] = { Offset, Base, Chain };
|
SDValue Ops[] = { Base, Offset, Chain };
|
||||||
return CurDAG->getMachineNode(Opcode, dl, LD->getValueType(0),
|
return CurDAG->getMachineNode(Opcode, dl, LD->getValueType(0),
|
||||||
PPCLowering.getPointerTy(),
|
PPCLowering.getPointerTy(),
|
||||||
MVT::Other, Ops, 3);
|
MVT::Other, Ops, 3);
|
||||||
|
@ -1192,6 +1192,7 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
|
|||||||
SelectionDAG &DAG) const {
|
SelectionDAG &DAG) const {
|
||||||
if (DisablePPCPreinc) return false;
|
if (DisablePPCPreinc) return false;
|
||||||
|
|
||||||
|
bool isLoad = true;
|
||||||
SDValue Ptr;
|
SDValue Ptr;
|
||||||
EVT VT;
|
EVT VT;
|
||||||
unsigned Alignment;
|
unsigned Alignment;
|
||||||
@ -1203,6 +1204,7 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
|
|||||||
Ptr = ST->getBasePtr();
|
Ptr = ST->getBasePtr();
|
||||||
VT = ST->getMemoryVT();
|
VT = ST->getMemoryVT();
|
||||||
Alignment = ST->getAlignment();
|
Alignment = ST->getAlignment();
|
||||||
|
isLoad = false;
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1210,7 +1212,25 @@ bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
|
|||||||
if (VT.isVector())
|
if (VT.isVector())
|
||||||
return false;
|
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<FrameIndexSDNode>(Base) || isa<RegisterSDNode>(Base))
|
||||||
|
Swap = true;
|
||||||
|
else if (!isLoad) {
|
||||||
|
SDValue Val = cast<StoreSDNode>(N)->getValue();
|
||||||
|
if (Val == Base || Base.getNode()->isPredecessorOf(Val.getNode()))
|
||||||
|
Swap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Swap)
|
||||||
|
std::swap(Base, Offset);
|
||||||
|
|
||||||
AM = ISD::PRE_INC;
|
AM = ISD::PRE_INC;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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),
|
def : Pat<(aligned4pre_store G8RC:$rS, ptr_rc_nor0:$ptrreg, iaddroff:$ptroff),
|
||||||
(STDU G8RC:$rS, iaddroff:$ptroff, ptr_rc_nor0:$ptrreg)>;
|
(STDU G8RC:$rS, iaddroff:$ptroff, ptr_rc_nor0:$ptrreg)>;
|
||||||
|
|
||||||
def : Pat<(pre_truncsti8 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_truncsti8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STBUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STBUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_truncsti16 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_truncsti16 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STHUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STHUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_truncsti32 G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_truncsti32 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STWUX8 G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STWUX8 G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_store G8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_store G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STDUX G8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STDUX G8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -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
|
// Patterns to match the pre-inc stores. We can't put the patterns on
|
||||||
// the instruction definitions directly as ISel wants the address base
|
// the instruction definitions directly as ISel wants the address base
|
||||||
// and offset to be separate operands, not a single complex operand.
|
// and offset to be separate operands, not a single complex operand.
|
||||||
def : Pat<(pre_truncsti8 GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_truncsti8 GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STBUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STBUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_truncsti16 GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_truncsti16 GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STHUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STHUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_store GPRC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_store GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STWUX GPRC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STWUX GPRC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_store F4RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_store F4RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STFSUX F4RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STFSUX F4RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
def : Pat<(pre_store F8RC:$rS, ptr_rc:$ptrreg, ptr_rc_nor0:$ptroff),
|
def : Pat<(pre_store F8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff),
|
||||||
(STFDUX F8RC:$rS, ptr_rc_nor0:$ptroff, ptr_rc:$ptrreg)>;
|
(STFDUX F8RC:$rS, ptr_rc_nor0:$ptrreg, ptr_rc:$ptroff)>;
|
||||||
|
|
||||||
def SYNC : XForm_24_sync<31, 598, (outs), (ins),
|
def SYNC : XForm_24_sync<31, 598, (outs), (ins),
|
||||||
"sync", LdStSync,
|
"sync", LdStSync,
|
||||||
|
Loading…
Reference in New Issue
Block a user