Implement llvm.atomic.cmp.swap.i32 on PPC. Patch by Gary Benson!

llvm-svn: 53505
This commit is contained in:
Evan Cheng 2008-07-12 02:23:19 +00:00
parent 7457283357
commit c69b53dff9
4 changed files with 329 additions and 220 deletions

View File

@ -40,8 +40,7 @@ cl::desc("enable preincrement load/store generation on PPC (experimental)"),
cl::Hidden);
PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
: TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()),
PPCAtomicLabelIndex(0) {
: TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) {
setPow2DivIsCheap();
@ -378,45 +377,47 @@ unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const {
const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
default: return 0;
case PPCISD::FSEL: return "PPCISD::FSEL";
case PPCISD::FCFID: return "PPCISD::FCFID";
case PPCISD::FCTIDZ: return "PPCISD::FCTIDZ";
case PPCISD::FCTIWZ: return "PPCISD::FCTIWZ";
case PPCISD::STFIWX: return "PPCISD::STFIWX";
case PPCISD::VMADDFP: return "PPCISD::VMADDFP";
case PPCISD::VNMSUBFP: return "PPCISD::VNMSUBFP";
case PPCISD::VPERM: return "PPCISD::VPERM";
case PPCISD::Hi: return "PPCISD::Hi";
case PPCISD::Lo: return "PPCISD::Lo";
case PPCISD::DYNALLOC: return "PPCISD::DYNALLOC";
case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg";
case PPCISD::SRL: return "PPCISD::SRL";
case PPCISD::SRA: return "PPCISD::SRA";
case PPCISD::SHL: return "PPCISD::SHL";
case PPCISD::EXTSW_32: return "PPCISD::EXTSW_32";
case PPCISD::STD_32: return "PPCISD::STD_32";
case PPCISD::CALL_ELF: return "PPCISD::CALL_ELF";
case PPCISD::CALL_Macho: return "PPCISD::CALL_Macho";
case PPCISD::MTCTR: return "PPCISD::MTCTR";
case PPCISD::BCTRL_Macho: return "PPCISD::BCTRL_Macho";
case PPCISD::BCTRL_ELF: return "PPCISD::BCTRL_ELF";
case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG";
case PPCISD::MFCR: return "PPCISD::MFCR";
case PPCISD::VCMP: return "PPCISD::VCMP";
case PPCISD::VCMPo: return "PPCISD::VCMPo";
case PPCISD::LBRX: return "PPCISD::LBRX";
case PPCISD::STBRX: return "PPCISD::STBRX";
case PPCISD::LARX: return "PPCISD::LARX";
case PPCISD::STCX: return "PPCISD::STCX";
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";
case PPCISD::MTFSB1: return "PPCISD::MTFSB1";
case PPCISD::FADDRTZ: return "PPCISD::FADDRTZ";
case PPCISD::MTFSF: return "PPCISD::MTFSF";
case PPCISD::TAILCALL: return "PPCISD::TAILCALL";
case PPCISD::TC_RETURN: return "PPCISD::TC_RETURN";
case PPCISD::FSEL: return "PPCISD::FSEL";
case PPCISD::FCFID: return "PPCISD::FCFID";
case PPCISD::FCTIDZ: return "PPCISD::FCTIDZ";
case PPCISD::FCTIWZ: return "PPCISD::FCTIWZ";
case PPCISD::STFIWX: return "PPCISD::STFIWX";
case PPCISD::VMADDFP: return "PPCISD::VMADDFP";
case PPCISD::VNMSUBFP: return "PPCISD::VNMSUBFP";
case PPCISD::VPERM: return "PPCISD::VPERM";
case PPCISD::Hi: return "PPCISD::Hi";
case PPCISD::Lo: return "PPCISD::Lo";
case PPCISD::DYNALLOC: return "PPCISD::DYNALLOC";
case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg";
case PPCISD::SRL: return "PPCISD::SRL";
case PPCISD::SRA: return "PPCISD::SRA";
case PPCISD::SHL: return "PPCISD::SHL";
case PPCISD::EXTSW_32: return "PPCISD::EXTSW_32";
case PPCISD::STD_32: return "PPCISD::STD_32";
case PPCISD::CALL_ELF: return "PPCISD::CALL_ELF";
case PPCISD::CALL_Macho: return "PPCISD::CALL_Macho";
case PPCISD::MTCTR: return "PPCISD::MTCTR";
case PPCISD::BCTRL_Macho: return "PPCISD::BCTRL_Macho";
case PPCISD::BCTRL_ELF: return "PPCISD::BCTRL_ELF";
case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG";
case PPCISD::MFCR: return "PPCISD::MFCR";
case PPCISD::VCMP: return "PPCISD::VCMP";
case PPCISD::VCMPo: return "PPCISD::VCMPo";
case PPCISD::LBRX: return "PPCISD::LBRX";
case PPCISD::STBRX: return "PPCISD::STBRX";
case PPCISD::ATOMIC_LOAD_ADD: return "PPCISD::ATOMIC_LOAD_ADD";
case PPCISD::ATOMIC_CMP_SWAP: return "PPCISD::ATOMIC_CMP_SWAP";
case PPCISD::ATOMIC_SWAP: return "PPCISD::ATOMIC_SWAP";
case PPCISD::LARX: return "PPCISD::LARX";
case PPCISD::STCX: return "PPCISD::STCX";
case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH";
case PPCISD::MFFS: return "PPCISD::MFFS";
case PPCISD::MTFSB0: return "PPCISD::MTFSB0";
case PPCISD::MTFSB1: return "PPCISD::MTFSB1";
case PPCISD::FADDRTZ: return "PPCISD::FADDRTZ";
case PPCISD::MTFSF: return "PPCISD::MTFSF";
case PPCISD::TAILCALL: return "PPCISD::TAILCALL";
case PPCISD::TC_RETURN: return "PPCISD::TC_RETURN";
}
}
@ -2726,33 +2727,13 @@ SDOperand PPCTargetLowering::LowerAtomicLOAD_ADD(SDOperand Op, SelectionDAG &DAG
SDOperand Ptr = Op.getOperand(1);
SDOperand Incr = Op.getOperand(2);
// Issue a "load and reserve".
std::vector<MVT> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDVTList VTs = DAG.getVTList(VT, MVT::Other);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
Chain,
Ptr,
Incr,
};
SDOperand Load = DAG.getNode(PPCISD::LARX, 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::STCX, MVT::Other, Ops2, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getMergeValues(OutOps, 2);
return DAG.getNode(PPCISD::ATOMIC_LOAD_ADD, VTs, Ops, 3);
}
SDOperand PPCTargetLowering::LowerAtomicCMP_SWAP(SDOperand Op, SelectionDAG &DAG) {
@ -2762,39 +2743,14 @@ SDOperand PPCTargetLowering::LowerAtomicCMP_SWAP(SDOperand Op, SelectionDAG &DAG
SDOperand NewVal = Op.getOperand(2);
SDOperand OldVal = Op.getOperand(3);
// Issue a "load and reserve".
std::vector<MVT> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDVTList VTs = DAG.getVTList(VT, MVT::Other);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
Chain,
Ptr,
OldVal,
NewVal,
};
SDOperand Load = DAG.getNode(PPCISD::LARX, 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::STCX, MVT::Other, Ops3, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getMergeValues(OutOps, 2);
return DAG.getNode(PPCISD::ATOMIC_CMP_SWAP, VTs, Ops, 4);
}
SDOperand PPCTargetLowering::LowerAtomicSWAP(SDOperand Op, SelectionDAG &DAG) {
@ -2803,30 +2759,13 @@ SDOperand PPCTargetLowering::LowerAtomicSWAP(SDOperand Op, SelectionDAG &DAG) {
SDOperand Ptr = Op.getOperand(1);
SDOperand NewVal = Op.getOperand(2);
// Issue a "load and reserve".
std::vector<MVT> VTs;
VTs.push_back(VT);
VTs.push_back(MVT::Other);
SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
SDVTList VTs = DAG.getVTList(VT, MVT::Other);
SDOperand Ops[] = {
Chain, // Chain
Ptr, // Ptr
Label, // Label
Chain,
Ptr,
NewVal,
};
SDOperand Load = DAG.getNode(PPCISD::LARX, 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::STCX, MVT::Other, Ops2, 4);
SDOperand OutOps[] = { Load, Store };
return DAG.getMergeValues(OutOps, 2);
return DAG.getNode(PPCISD::ATOMIC_SWAP, VTs, Ops, 3);
}
/// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when
@ -3981,58 +3920,197 @@ MachineBasicBlock *
PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) {
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
assert((MI->getOpcode() == PPC::SELECT_CC_I4 ||
MI->getOpcode() == PPC::SELECT_CC_I8 ||
MI->getOpcode() == PPC::SELECT_CC_F4 ||
MI->getOpcode() == PPC::SELECT_CC_F8 ||
MI->getOpcode() == PPC::SELECT_CC_VRRC) &&
"Unexpected instr type to insert");
// To "insert" a SELECT_CC instruction, we actually have to insert the diamond
// control-flow pattern. The incoming instruction knows the destination vreg
// to set, the condition code register to branch on, the true/false values to
// select between, and a branch opcode to use.
// To "insert" these instructions we actually have to insert their
// control-flow patterns.
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineFunction::iterator It = BB;
++It;
// thisMBB:
// ...
// TrueVal = ...
// cmpTY ccX, r1, r2
// bCC copy1MBB
// fallthrough --> copy0MBB
MachineBasicBlock *thisMBB = BB;
MachineFunction *F = BB->getParent();
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
unsigned SelectPred = MI->getOperand(4).getImm();
BuildMI(BB, TII->get(PPC::BCC))
.addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB);
F->insert(It, copy0MBB);
F->insert(It, sinkMBB);
// Update machine-CFG edges by transferring all successors of the current
// block to the new block which will contain the Phi node for the select.
sinkMBB->transferSuccessors(BB);
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
// copy0MBB:
// %FalseValue = ...
// # fallthrough to sinkMBB
BB = copy0MBB;
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
// sinkMBB:
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
// ...
BB = sinkMBB;
BuildMI(BB, TII->get(PPC::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB)
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
if (MI->getOpcode() == PPC::SELECT_CC_I4 ||
MI->getOpcode() == PPC::SELECT_CC_I8 ||
MI->getOpcode() == PPC::SELECT_CC_F4 ||
MI->getOpcode() == PPC::SELECT_CC_F8 ||
MI->getOpcode() == PPC::SELECT_CC_VRRC) {
// The incoming instruction knows the destination vreg to set, the
// condition code register to branch on, the true/false values to
// select between, and a branch opcode to use.
// thisMBB:
// ...
// TrueVal = ...
// cmpTY ccX, r1, r2
// bCC copy1MBB
// fallthrough --> copy0MBB
MachineBasicBlock *thisMBB = BB;
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
unsigned SelectPred = MI->getOperand(4).getImm();
BuildMI(BB, TII->get(PPC::BCC))
.addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB);
F->insert(It, copy0MBB);
F->insert(It, sinkMBB);
// Update machine-CFG edges by transferring all successors of the current
// block to the new block which will contain the Phi node for the select.
sinkMBB->transferSuccessors(BB);
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
// copy0MBB:
// %FalseValue = ...
// # fallthrough to sinkMBB
BB = copy0MBB;
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
// sinkMBB:
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
// ...
BB = sinkMBB;
BuildMI(BB, TII->get(PPC::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB)
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
}
else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I32 ||
MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I64) {
bool is64bit = MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I64;
unsigned dest = MI->getOperand(0).getReg();
unsigned ptrA = MI->getOperand(1).getReg();
unsigned ptrB = MI->getOperand(2).getReg();
unsigned incr = MI->getOperand(3).getReg();
MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, loopMBB);
F->insert(It, exitMBB);
exitMBB->transferSuccessors(BB);
MachineRegisterInfo &RegInfo = F->getRegInfo();
unsigned TmpReg = RegInfo.createVirtualRegister(
is64bit ? (const TargetRegisterClass *) &PPC::GPRCRegClass :
(const TargetRegisterClass *) &PPC::G8RCRegClass);
// thisMBB:
// ...
// fallthrough --> loopMBB
BB->addSuccessor(loopMBB);
// loopMBB:
// l[wd]arx dest, ptr
// add r0, dest, incr
// st[wd]cx. r0, ptr
// bne- loopMBB
// fallthrough --> exitMBB
BB = loopMBB;
BuildMI(BB, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest)
.addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(is64bit ? PPC::ADD4 : PPC::ADD8), TmpReg)
.addReg(incr).addReg(dest);
BuildMI(BB, TII->get(is64bit ? PPC::STDCX : PPC::STWCX))
.addReg(TmpReg).addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(PPC::BCC))
.addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB);
BB->addSuccessor(loopMBB);
BB->addSuccessor(exitMBB);
// exitMBB:
// ...
BB = exitMBB;
}
else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 ||
MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64) {
bool is64bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64;
unsigned dest = MI->getOperand(0).getReg();
unsigned ptrA = MI->getOperand(1).getReg();
unsigned ptrB = MI->getOperand(2).getReg();
unsigned oldval = MI->getOperand(3).getReg();
unsigned newval = MI->getOperand(4).getReg();
MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, loopMBB);
F->insert(It, exitMBB);
exitMBB->transferSuccessors(BB);
// thisMBB:
// ...
// fallthrough --> loopMBB
BB->addSuccessor(loopMBB);
// loopMBB:
// l[wd]arx dest, ptr
// cmp[wd] dest, oldval
// bne- exitMBB
// st[wd]cx. newval, ptr
// bne- loopMBB
// fallthrough --> exitMBB
BB = loopMBB;
BuildMI(BB, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest)
.addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(is64bit ? PPC::CMPD : PPC::CMPW), PPC::CR0)
.addReg(oldval).addReg(dest);
BuildMI(BB, TII->get(PPC::BCC))
.addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(exitMBB);
BuildMI(BB, TII->get(is64bit ? PPC::STDCX : PPC::STWCX))
.addReg(newval).addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(PPC::BCC))
.addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB);
BB->addSuccessor(loopMBB);
BB->addSuccessor(exitMBB);
// exitMBB:
// ...
BB = exitMBB;
}
else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I32 ||
MI->getOpcode() == PPC::ATOMIC_SWAP_I64) {
bool is64bit = MI->getOpcode() == PPC::ATOMIC_SWAP_I64;
unsigned dest = MI->getOperand(0).getReg();
unsigned ptrA = MI->getOperand(1).getReg();
unsigned ptrB = MI->getOperand(2).getReg();
unsigned newval = MI->getOperand(3).getReg();
MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, loopMBB);
F->insert(It, exitMBB);
exitMBB->transferSuccessors(BB);
// thisMBB:
// ...
// fallthrough --> loopMBB
BB->addSuccessor(loopMBB);
// loopMBB:
// l[wd]arx dest, ptr
// st[wd]cx. newval, ptr
// bne- loopMBB
// fallthrough --> exitMBB
BB = loopMBB;
BuildMI(BB, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest)
.addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(is64bit ? PPC::STDCX : PPC::STWCX))
.addReg(newval).addReg(ptrA).addReg(ptrB);
BuildMI(BB, TII->get(PPC::BCC))
.addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB);
BB->addSuccessor(loopMBB);
BB->addSuccessor(exitMBB);
// exitMBB:
// ...
BB = exitMBB;
}
else {
assert(0 && "Unexpected instr type to insert");
}
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
return BB;

View File

@ -152,6 +152,11 @@ namespace llvm {
/// MTFSF = F8RC, INFLAG - This moves the register into the FPSCR.
MTFSF,
/// ATOMIC_LOAD_ADD, ATOMIC_CMP_SWAP, ATOMIC_SWAP - These
/// correspond to the llvm.atomic.load.add, llvm.atomic.cmp.swap
/// and llvm.atomic.swap intrinsics.
ATOMIC_LOAD_ADD, ATOMIC_CMP_SWAP, ATOMIC_SWAP,
/// LARX = This corresponds to PPC l{w|d}arx instrcution: load and
/// reserve indexed. This is used to implement atomic operations.
LARX,
@ -160,10 +165,6 @@ namespace llvm {
/// indexed. This is used to implement atomic operations.
STCX,
/// CMP_UNRESERVE = Test for equality and "unreserve" if not true. This
/// is used to implement atomic operations.
CMP_UNRESERVE,
/// TAILCALL - Indicates a tail call should be taken.
TAILCALL,
/// TC_RETURN - A tail call return.
@ -325,10 +326,6 @@ namespace llvm {
SelectionDAG &DAG) const;
private:
/// PPCAtomicLabelIndex - Keep track the number of PPC atomic labels.
///
unsigned PPCAtomicLabelIndex;
SDOperand getFramePointerFrameIndex(SelectionDAG & DAG) const;
SDOperand getReturnAddrFrameIndex(SelectionDAG & DAG) const;

View File

@ -116,24 +116,35 @@ def : Pat<(PPCcall_ELF (i64 tglobaladdr:$dst)),
def : Pat<(PPCcall_ELF (i64 texternalsym:$dst)),
(BL8_ELF texternalsym:$dst)>;
// Atomic operations.
def LDARX : Pseudo<(outs G8RC:$rD), (ins memrr:$ptr, i32imm:$label),
"\nLa${label}_entry:\n\tldarx $rD, $ptr",
[(set G8RC:$rD, (PPClarx xoaddr:$ptr, imm:$label))]>;
let Defs = [CR0] in {
def STDCX : Pseudo<(outs), (ins G8RC:$rS, memrr:$dst, i32imm:$label),
"stdcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
[(PPCstcx G8RC:$rS, xoaddr:$dst, imm:$label)]>;
def CMP_UNRESd : Pseudo<(outs), (ins G8RC:$rA, G8RC:$rB, i32imm:$label),
"cmpd $rA, $rB\n\tbne- La${label}_exit",
[(PPCcmp_unres G8RC:$rA, G8RC:$rB, imm:$label)]>;
def CMP_UNRESdi : Pseudo<(outs), (ins G8RC:$rA, s16imm64:$imm, i32imm:$label),
"cmpdi $rA, $imm\n\tbne- La${label}_exit",
[(PPCcmp_unres G8RC:$rA, immSExt16:$imm, imm:$label)]>;
// Atomic operations
let usesCustomDAGSchedInserter = 1 in {
let Uses = [CR0] in {
def ATOMIC_LOAD_ADD_I64 : Pseudo<
(outs G8RC:$dst), (ins memrr:$ptr, G8RC:$incr),
"${:comment} ATOMIC_LOAD_ADD_I64 PSEUDO!",
[(set G8RC:$dst, (PPCatomic_load_add xoaddr:$ptr, G8RC:$incr))]>;
def ATOMIC_CMP_SWAP_I64 : Pseudo<
(outs G8RC:$dst), (ins memrr:$ptr, G8RC:$old, G8RC:$new),
"${:comment} ATOMIC_CMP_SWAP_I64 PSEUDO!",
[(set G8RC:$dst, (PPCatomic_cmp_swap xoaddr:$ptr, G8RC:$old, G8RC:$new))]>;
def ATOMIC_SWAP_I64 : Pseudo<
(outs G8RC:$dst), (ins memrr:$ptr, G8RC:$new),
"${:comment} ATOMIC_SWAP_I64 PSEUDO!",
[(set G8RC:$dst, (PPCatomic_swap xoaddr:$ptr, G8RC:$new))]>;
}
}
// Instructions to support atomic operations
def LDARX : XForm_1<31, 84, (outs G8RC:$rD), (ins memrr:$ptr),
"ldarx $rD, $ptr", LdStLDARX,
[(set G8RC:$rD, (PPClarx xoaddr:$ptr))]>;
let Defs = [CR0] in
def STDCX : XForm_1<31, 214, (outs), (ins G8RC:$rS, memrr:$dst),
"stdcx. $rS, $dst", LdStSTDCX,
[(PPCstcx G8RC:$rS, xoaddr:$dst)]>,
isDOT;
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in
def TCRETURNdi8 :Pseudo< (outs),
(ins calltarget:$dst, i32imm:$offset, variable_ops),

View File

@ -42,15 +42,21 @@ def SDT_PPCstbrx : SDTypeProfile<0, 4, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
]>;
def SDT_PPCatomic_load_add : SDTypeProfile<1, 2, [
SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>
]>;
def SDT_PPCatomic_cmp_swap : SDTypeProfile<1, 3, [
SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>, SDTCisInt<3>
]>;
def SDT_PPCatomic_swap : SDTypeProfile<1, 2, [
SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisInt<2>
]>;
def SDT_PPClarx : SDTypeProfile<1, 2, [
SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
def SDT_PPClarx : SDTypeProfile<1, 1, [
SDTCisInt<0>, SDTCisPtrTy<1>
]>;
def SDT_PPCstcx : SDTypeProfile<0, 3, [
SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
]>;
def SDT_PPCcmp_unres : SDTypeProfile<0, 3, [
SDTCisSameAs<0, 1>, SDTCisInt<1>, SDTCisVT<2, i32>
def SDT_PPCstcx : SDTypeProfile<0, 2, [
SDTCisInt<0>, SDTCisPtrTy<1>
]>;
def SDT_PPCTC_ret : SDTypeProfile<0, 2, [
@ -143,12 +149,22 @@ def PPClbrx : SDNode<"PPCISD::LBRX", SDT_PPClbrx,
def PPCstbrx : SDNode<"PPCISD::STBRX", SDT_PPCstbrx,
[SDNPHasChain, SDNPMayStore]>;
// Atomic operations
def PPCatomic_load_add : SDNode<"PPCISD::ATOMIC_LOAD_ADD",
SDT_PPCatomic_load_add,
[SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
def PPCatomic_cmp_swap : SDNode<"PPCISD::ATOMIC_CMP_SWAP",
SDT_PPCatomic_cmp_swap,
[SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
def PPCatomic_swap : SDNode<"PPCISD::ATOMIC_SWAP",
SDT_PPCatomic_swap,
[SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
// Instructions to support atomic operations
def PPClarx : SDNode<"PPCISD::LARX", SDT_PPClarx,
[SDNPHasChain, SDNPMayLoad]>;
def PPCstcx : SDNode<"PPCISD::STCX", SDT_PPCstcx,
[SDNPHasChain, SDNPMayStore]>;
def PPCcmp_unres : SDNode<"PPCISD::CMP_UNRESERVE", SDT_PPCcmp_unres,
[SDNPHasChain]>;
// Instructions to support dynamic alloca.
def SDTDynOp : SDTypeProfile<1, 2, []>;
@ -530,24 +546,35 @@ 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 : XForm_1<31, 20, (outs GPRC:$rD), (ins memrr:$ptr, i32imm:$label),
"\nLa${label}_entry:\n\tlwarx $rD, $ptr", LdStLWARX,
[(set GPRC:$rD, (PPClarx 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:",
[(PPCstcx 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, immSExt16:$imm, imm:$label)]>;
// Atomic operations
let usesCustomDAGSchedInserter = 1 in {
let Uses = [CR0] in {
def ATOMIC_LOAD_ADD_I32 : Pseudo<
(outs GPRC:$dst), (ins memrr:$ptr, GPRC:$incr),
"${:comment} ATOMIC_LOAD_ADD_I32 PSEUDO!",
[(set GPRC:$dst, (PPCatomic_load_add xoaddr:$ptr, GPRC:$incr))]>;
def ATOMIC_CMP_SWAP_I32 : Pseudo<
(outs GPRC:$dst), (ins memrr:$ptr, GPRC:$old, GPRC:$new),
"${:comment} ATOMIC_CMP_SWAP_I32 PSEUDO!",
[(set GPRC:$dst, (PPCatomic_cmp_swap xoaddr:$ptr, GPRC:$old, GPRC:$new))]>;
def ATOMIC_SWAP_I32 : Pseudo<
(outs GPRC:$dst), (ins memrr:$ptr, GPRC:$new),
"${:comment} ATOMIC_SWAP_I32 PSEUDO!",
[(set GPRC:$dst, (PPCatomic_swap xoaddr:$ptr, GPRC:$new))]>;
}
}
// Instructions to support atomic operations
def LWARX : XForm_1<31, 20, (outs GPRC:$rD), (ins memrr:$src),
"lwarx $rD, $src", LdStLWARX,
[(set GPRC:$rD, (PPClarx xoaddr:$src))]>;
let Defs = [CR0] in
def STWCX : XForm_1<31, 150, (outs), (ins GPRC:$rS, memrr:$dst),
"stwcx. $rS, $dst", LdStSTWCX,
[(PPCstcx GPRC:$rS, xoaddr:$dst)]>,
isDOT;
//===----------------------------------------------------------------------===//
// PPC32 Load Instructions.
//
@ -1327,9 +1354,5 @@ def : Pat<(extloadf32 iaddr:$src),
def : Pat<(extloadf32 xaddr:$src),
(FMRSD (LFSX xaddr:$src))>;
// Atomic operations
def : Pat<(PPCcmp_unres immSExt16:$imm, GPRC:$rA, imm:$label),
(CMP_UNRESwi GPRC:$rA, immSExt16:$imm, imm:$label)>;
include "PPCInstrAltivec.td"
include "PPCInstr64Bit.td"