1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

PPC32 atomic operations.

llvm-svn: 49947
This commit is contained in:
Evan Cheng 2008-04-19 01:30:48 +00:00
parent b1d240f973
commit 09e77f6b83
3 changed files with 184 additions and 2 deletions

View File

@ -39,7 +39,8 @@ cl::desc("enable preincrement load/store generation on PPC (experimental)"),
cl::Hidden);
PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
: TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) {
: TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()),
PPCAtomicLabelIndex(0) {
setPow2DivIsCheap();
@ -202,6 +203,10 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64 , Custom);
setOperationAction(ISD::ATOMIC_LAS , MVT::i32 , Custom);
setOperationAction(ISD::ATOMIC_LCS , MVT::i32 , Custom);
setOperationAction(ISD::ATOMIC_SWAP , MVT::i32 , Custom);
// We want to custom lower some of our intrinsics.
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
@ -393,6 +398,9 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::VCMPo: return "PPCISD::VCMPo";
case PPCISD::LBRX: return "PPCISD::LBRX";
case PPCISD::STBRX: return "PPCISD::STBRX";
case PPCISD::LWARX: return "PPCISD::LWARX";
case PPCISD::STWCX: return "PPCISD::STWCX";
case PPCISD::CMP_UNRESERVE: return "PPCISD::CMP_UNRESERVE";
case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH";
case PPCISD::MFFS: return "PPCISD::MFFS";
case PPCISD::MTFSB0: return "PPCISD::MTFSB0";
@ -2295,6 +2303,117 @@ SDOperand PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDOperand Op,
return DAG.getNode(PPCISD::DYNALLOC, VTs, Ops, 3);
}
SDOperand PPCTargetLowering::LowerAtomicLAS(SDOperand Op, SelectionDAG &DAG) {
MVT::ValueType VT = Op.getValueType();
SDOperand Chain = Op.getOperand(0);
SDOperand Ptr = Op.getOperand(1);
SDOperand Incr = Op.getOperand(2);
// Issue a "load and reserve".
std::vector<MVT::ValueType> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
};
SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
Chain = Load.getValue(1);
// Compute new value.
SDOperand NewVal = DAG.getNode(ISD::ADD, VT, Load, Incr);
// Issue a "store and check".
SDOperand Ops2[] = {
Chain, // Chain
NewVal, // Value
Ptr, // Ptr
Label, // Label
};
SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops2, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
OutOps, 2);
}
SDOperand PPCTargetLowering::LowerAtomicLCS(SDOperand Op, SelectionDAG &DAG) {
MVT::ValueType VT = Op.getValueType();
SDOperand Chain = Op.getOperand(0);
SDOperand Ptr = Op.getOperand(1);
SDOperand NewVal = Op.getOperand(2);
SDOperand OldVal = Op.getOperand(3);
// Issue a "load and reserve".
std::vector<MVT::ValueType> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
};
SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
Chain = Load.getValue(1);
// Compare and unreserve if not equal.
SDOperand Ops2[] = {
Chain, // Chain
OldVal, // Old value
Load, // Value in memory
Label, // Label
};
Chain = DAG.getNode(PPCISD::CMP_UNRESERVE, MVT::Other, Ops2, 4);
// Issue a "store and check".
SDOperand Ops3[] = {
Chain, // Chain
NewVal, // Value
Ptr, // Ptr
Label, // Label
};
SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops3, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
OutOps, 2);
}
SDOperand PPCTargetLowering::LowerAtomicSWAP(SDOperand Op, SelectionDAG &DAG) {
MVT::ValueType VT = Op.getValueType();
SDOperand Chain = Op.getOperand(0);
SDOperand Ptr = Op.getOperand(1);
SDOperand NewVal = Op.getOperand(2);
// Issue a "load and reserve".
std::vector<MVT::ValueType> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
};
SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
Chain = Load.getValue(1);
// Issue a "store and check".
SDOperand Ops2[] = {
Chain, // Chain
NewVal, // Value
Ptr, // Ptr
Label, // Label
};
SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops2, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
OutOps, 2);
}
/// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when
/// possible.
@ -3404,6 +3523,10 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG, PPCSubTarget);
case ISD::DYNAMIC_STACKALLOC:
return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget);
case ISD::ATOMIC_LAS: return LowerAtomicLAS(Op, DAG);
case ISD::ATOMIC_LCS: return LowerAtomicLCS(Op, DAG);
case ISD::ATOMIC_SWAP: return LowerAtomicSWAP(Op, DAG);
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);

View File

@ -150,7 +150,19 @@ namespace llvm {
FADDRTZ,
/// MTFSF = F8RC, INFLAG - This moves the register into the FPSCR.
MTFSF
MTFSF,
/// LWARX = This corresponds to PPC lwarx instrcution: load word and
/// reserve indexed. This is used to implement atomic operations.
LWARX,
/// STWCX = This corresponds to PPC stwcx. instrcution: store word
/// conditional indexed. This is used to implement atomic operations.
STWCX,
/// CMP_UNRESERVE = Test for equality and "unreserve" if not true. This
/// is used to implement atomic operations.
CMP_UNRESERVE
};
}
@ -296,6 +308,11 @@ namespace llvm {
/// the offset of the target addressing mode.
virtual bool isLegalAddressImmediate(GlobalValue *GV) const;
private:
/// PPCAtomicLabelIndex - Keep track the number of PPC atomic labels.
///
unsigned PPCAtomicLabelIndex;
SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG);
@ -324,6 +341,9 @@ namespace llvm {
SDOperand LowerDYNAMIC_STACKALLOC(SDOperand Op, SelectionDAG &DAG,
const PPCSubtarget &Subtarget);
SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerAtomicLAS(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerAtomicLCS(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerAtomicSWAP(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFP_ROUND_INREG(SDOperand Op, SelectionDAG &DAG);

View File

@ -42,6 +42,16 @@ def SDT_PPCstbrx : SDTypeProfile<0, 4, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
]>;
def SDT_PPClwarx : SDTypeProfile<1, 2, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
]>;
def SDT_PPCstwcx : SDTypeProfile<0, 3, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
]>;
def SDT_PPCcmp_unres : SDTypeProfile<0, 3, [
SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>
]>;
//===----------------------------------------------------------------------===//
// PowerPC specific DAG Nodes.
//
@ -122,6 +132,13 @@ def PPClbrx : SDNode<"PPCISD::LBRX", SDT_PPClbrx,
def PPCstbrx : SDNode<"PPCISD::STBRX", SDT_PPCstbrx,
[SDNPHasChain, SDNPMayStore]>;
def PPClwarx : SDNode<"PPCISD::LWARX", SDT_PPClwarx,
[SDNPHasChain, SDNPMayLoad]>;
def PPCstwcx : SDNode<"PPCISD::STWCX", SDT_PPCstwcx,
[SDNPHasChain, SDNPMayStore]>;
def PPCcmp_unres : SDNode<"PPCISD::CMP_UNRESERVE", SDT_PPCcmp_unres,
[SDNPHasChain]>;
// Instructions to support dynamic alloca.
def SDTDynOp : SDTypeProfile<1, 2, []>;
def PPCdynalloc : SDNode<"PPCISD::DYNALLOC", SDTDynOp, [SDNPHasChain]>;
@ -462,6 +479,24 @@ def DCBZL : DCB_Form<1014, 1, (outs), (ins memrr:$dst),
"dcbzl $dst", LdStDCBF, [(int_ppc_dcbzl xoaddr:$dst)]>,
PPC970_DGroup_Single;
// Atomic operations.
def LWARX : Pseudo<(outs GPRC:$rD), (ins memrr:$ptr, i32imm:$label),
"\nLa${label}_entry:\n\tlwarx $rD, $ptr",
[(set GPRC:$rD, (PPClwarx xoaddr:$ptr, imm:$label))]>;
let Defs = [CR0] in {
def STWCX : Pseudo<(outs), (ins GPRC:$rS, memrr:$dst, i32imm:$label),
"stwcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
[(PPCstwcx GPRC:$rS, xoaddr:$dst, imm:$label)]>;
def CMP_UNRESw : Pseudo<(outs), (ins GPRC:$rA, GPRC:$rB, i32imm:$label),
"cmpw $rA, $rB\n\tbne- La${label}_exit",
[(PPCcmp_unres GPRC:$rA, GPRC:$rB, imm:$label)]>;
def CMP_UNRESwi : Pseudo<(outs), (ins GPRC:$rA, s16imm:$imm, i32imm:$label),
"cmpwi $rA, $imm\n\tbne- La${label}_exit",
[(PPCcmp_unres GPRC:$rA, imm:$imm, imm:$label)]>;
}
//===----------------------------------------------------------------------===//
// PPC32 Load Instructions.
//
@ -1229,5 +1264,9 @@ def : Pat<(extloadf32 iaddr:$src),
def : Pat<(extloadf32 xaddr:$src),
(FMRSD (LFSX xaddr:$src))>;
// Atomic operations
def : Pat<(PPCcmp_unres imm:$imm, GPRC:$rA, imm:$label),
(CMP_UNRESwi GPRC:$rA, imm:$imm, imm:$label)>;
include "PPCInstrAltivec.td"
include "PPCInstr64Bit.td"