summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2016-08-28 16:17:58 +0000
committerHal Finkel <hfinkel@anl.gov>2016-08-28 16:17:58 +0000
commit5728200f3367461d4a173880498f51490e163d94 (patch)
treeda688e5e7eca96d32319cc931136df84150138d4 /llvm/lib/Target/PowerPC/PPCISelLowering.cpp
parentc0d14ecea36703b1c035f69c7080699938fb8821 (diff)
downloadbcm5719-llvm-5728200f3367461d4a173880498f51490e163d94.tar.gz
bcm5719-llvm-5728200f3367461d4a173880498f51490e163d94.zip
[PowerPC] Implement lowering for atomicrmw min/max/umin/umax
Implement lowering for atomicrmw min/max/umin/umax. Fixes PR28818. llvm-svn: 279933
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp101
1 files changed, 98 insertions, 3 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index bbbc51ab198..e89b6caa527 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -8387,7 +8387,9 @@ Instruction* PPCTargetLowering::emitTrailingFence(IRBuilder<> &Builder,
MachineBasicBlock *
PPCTargetLowering::EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB,
unsigned AtomicSize,
- unsigned BinOpcode) const {
+ unsigned BinOpcode,
+ unsigned CmpOpcode,
+ unsigned CmpPred) const {
// This also handles ATOMIC_SWAP, indicated by BinOpcode==0.
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
@@ -8427,8 +8429,12 @@ PPCTargetLowering::EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB,
DebugLoc dl = MI.getDebugLoc();
MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *loop2MBB =
+ CmpOpcode ? F->CreateMachineBasicBlock(LLVM_BB) : nullptr;
MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, loopMBB);
+ if (CmpOpcode)
+ F->insert(It, loop2MBB);
F->insert(It, exitMBB);
exitMBB->splice(exitMBB->begin(), BB,
std::next(MachineBasicBlock::iterator(MI)), BB->end());
@@ -8450,11 +8456,31 @@ PPCTargetLowering::EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB,
// st[wd]cx. r0, ptr
// bne- loopMBB
// fallthrough --> exitMBB
+
+ // For max/min...
+ // loopMBB:
+ // l[wd]arx dest, ptr
+ // cmpl?[wd] incr, dest
+ // bgt exitMBB
+ // loop2MBB:
+ // st[wd]cx. dest, ptr
+ // bne- loopMBB
+ // fallthrough --> exitMBB
+
BB = loopMBB;
BuildMI(BB, dl, TII->get(LoadMnemonic), dest)
.addReg(ptrA).addReg(ptrB);
if (BinOpcode)
BuildMI(BB, dl, TII->get(BinOpcode), TmpReg).addReg(incr).addReg(dest);
+ if (CmpOpcode) {
+ BuildMI(BB, dl, TII->get(CmpOpcode), PPC::CR0)
+ .addReg(incr).addReg(dest);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(CmpPred).addReg(PPC::CR0).addMBB(exitMBB);
+ BB->addSuccessor(loop2MBB);
+ BB->addSuccessor(exitMBB);
+ BB = loop2MBB;
+ }
BuildMI(BB, dl, TII->get(StoreMnemonic))
.addReg(TmpReg).addReg(ptrA).addReg(ptrB);
BuildMI(BB, dl, TII->get(PPC::BCC))
@@ -8472,10 +8498,13 @@ MachineBasicBlock *
PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI,
MachineBasicBlock *BB,
bool is8bit, // operation
- unsigned BinOpcode) const {
+ unsigned BinOpcode,
+ unsigned CmpOpcode,
+ unsigned CmpPred) const {
// If we support part-word atomic mnemonics, just use them
if (Subtarget.hasPartwordAtomics())
- return EmitAtomicBinary(MI, BB, is8bit ? 1 : 2, BinOpcode);
+ return EmitAtomicBinary(MI, BB, is8bit ? 1 : 2, BinOpcode,
+ CmpOpcode, CmpPred);
// This also handles ATOMIC_SWAP, indicated by BinOpcode==0.
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
@@ -8497,8 +8526,12 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI,
DebugLoc dl = MI.getDebugLoc();
MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *loop2MBB =
+ CmpOpcode ? F->CreateMachineBasicBlock(LLVM_BB) : nullptr;
MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, loopMBB);
+ if (CmpOpcode)
+ F->insert(It, loop2MBB);
F->insert(It, exitMBB);
exitMBB->splice(exitMBB->begin(), BB,
std::next(MachineBasicBlock::iterator(MI)), BB->end());
@@ -8583,6 +8616,32 @@ PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI,
.addReg(TmpDestReg).addReg(MaskReg);
BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), Tmp3Reg)
.addReg(TmpReg).addReg(MaskReg);
+ if (CmpOpcode) {
+ // For unsigned comparisons, we can directly compare the shifted values.
+ // For signed comparisons we shift and sign extend.
+ unsigned SReg = RegInfo.createVirtualRegister(RC);
+ BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), SReg)
+ .addReg(TmpDestReg).addReg(MaskReg);
+ unsigned ValueReg = SReg;
+ unsigned CmpReg = Incr2Reg;
+ if (CmpOpcode == PPC::CMPW) {
+ ValueReg = RegInfo.createVirtualRegister(RC);
+ BuildMI(BB, dl, TII->get(PPC::SRW), ValueReg)
+ .addReg(SReg).addReg(ShiftReg);
+ unsigned ValueSReg = RegInfo.createVirtualRegister(RC);
+ BuildMI(BB, dl, TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
+ .addReg(ValueReg);
+ ValueReg = ValueSReg;
+ CmpReg = incr;
+ }
+ BuildMI(BB, dl, TII->get(CmpOpcode), PPC::CR0)
+ .addReg(CmpReg).addReg(ValueReg);
+ BuildMI(BB, dl, TII->get(PPC::BCC))
+ .addImm(CmpPred).addReg(PPC::CR0).addMBB(exitMBB);
+ BB->addSuccessor(loop2MBB);
+ BB->addSuccessor(exitMBB);
+ BB = loop2MBB;
+ }
BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg)
.addReg(Tmp3Reg).addReg(Tmp2Reg);
BuildMI(BB, dl, TII->get(PPC::STWCX))
@@ -9089,6 +9148,42 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
else if (MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I64)
BB = EmitAtomicBinary(MI, BB, 8, PPC::SUBF8);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I8)
+ BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I16)
+ BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I32)
+ BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I64)
+ BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPD, PPC::PRED_GE);
+
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I8)
+ BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I16)
+ BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I32)
+ BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I64)
+ BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPD, PPC::PRED_LE);
+
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I8)
+ BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPLW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I16)
+ BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPLW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I32)
+ BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPLW, PPC::PRED_GE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I64)
+ BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPLD, PPC::PRED_GE);
+
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I8)
+ BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPLW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I16)
+ BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPLW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I32)
+ BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPLW, PPC::PRED_LE);
+ else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I64)
+ BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPLD, PPC::PRED_LE);
+
else if (MI.getOpcode() == PPC::ATOMIC_SWAP_I8)
BB = EmitPartwordAtomicBinary(MI, BB, true, 0);
else if (MI.getOpcode() == PPC::ATOMIC_SWAP_I16)
OpenPOWER on IntegriCloud