From: James Y Knight Date: Tue, 29 Mar 2016 19:09:54 +0000 (+0000) Subject: [SPARC] Use AtomicExpandPass to expand AtomicRMW instructions. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7306cd47d433ee1a7e765a0077ffed457e202507;p=platform%2Fupstream%2Fllvm.git [SPARC] Use AtomicExpandPass to expand AtomicRMW instructions. They were previously expanded to CAS loops in a custom isel expansion, but AtomicExpandPass knows how to do that generically. Testing is covered by the existing sparc atomics.ll testcases. llvm-svn: 264771 --- diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index d08d30a..ebb7792 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1394,6 +1394,14 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // TargetLowering Implementation //===----------------------------------------------------------------------===// +TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { + if (AI->getOperation() == AtomicRMWInst::Xchg && + AI->getType()->getPrimitiveSizeInBits() == 32) + return AtomicExpansionKind::None; // Uses xchg instruction + + return AtomicExpansionKind::CmpXChg; +} + /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC /// condition. static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { @@ -3005,51 +3013,6 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case SP::SELECT_CC_DFP_FCC: case SP::SELECT_CC_QFP_FCC: return expandSelectCC(MI, BB, SP::FBCOND); - - case SP::ATOMIC_LOAD_ADD_32: - return expandAtomicRMW(MI, BB, SP::ADDrr); - case SP::ATOMIC_LOAD_ADD_64: - return expandAtomicRMW(MI, BB, SP::ADDXrr); - case SP::ATOMIC_LOAD_SUB_32: - return expandAtomicRMW(MI, BB, SP::SUBrr); - case SP::ATOMIC_LOAD_SUB_64: - return expandAtomicRMW(MI, BB, SP::SUBXrr); - case SP::ATOMIC_LOAD_AND_32: - return expandAtomicRMW(MI, BB, SP::ANDrr); - case SP::ATOMIC_LOAD_AND_64: - return expandAtomicRMW(MI, BB, SP::ANDXrr); - case SP::ATOMIC_LOAD_OR_32: - return expandAtomicRMW(MI, BB, SP::ORrr); - case SP::ATOMIC_LOAD_OR_64: - return expandAtomicRMW(MI, BB, SP::ORXrr); - case SP::ATOMIC_LOAD_XOR_32: - return expandAtomicRMW(MI, BB, SP::XORrr); - case SP::ATOMIC_LOAD_XOR_64: - return expandAtomicRMW(MI, BB, SP::XORXrr); - case SP::ATOMIC_LOAD_NAND_32: - return expandAtomicRMW(MI, BB, SP::ANDrr); - case SP::ATOMIC_LOAD_NAND_64: - return expandAtomicRMW(MI, BB, SP::ANDXrr); - - case SP::ATOMIC_SWAP_64: - return expandAtomicRMW(MI, BB, 0); - - case SP::ATOMIC_LOAD_MAX_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); - case SP::ATOMIC_LOAD_MAX_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G); - case SP::ATOMIC_LOAD_MIN_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE); - case SP::ATOMIC_LOAD_MIN_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE); - case SP::ATOMIC_LOAD_UMAX_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU); - case SP::ATOMIC_LOAD_UMAX_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU); - case SP::ATOMIC_LOAD_UMIN_32: - return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU); - case SP::ATOMIC_LOAD_UMIN_64: - return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU); } } @@ -3112,101 +3075,6 @@ SparcTargetLowering::expandSelectCC(MachineInstr *MI, return BB; } -MachineBasicBlock* -SparcTargetLowering::expandAtomicRMW(MachineInstr *MI, - MachineBasicBlock *MBB, - unsigned Opcode, - unsigned CondCode) const { - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - - // MI is an atomic read-modify-write instruction of the form: - // - // rd = atomicrmw addr, rs2 - // - // All three operands are registers. - unsigned DestReg = MI->getOperand(0).getReg(); - unsigned AddrReg = MI->getOperand(1).getReg(); - unsigned Rs2Reg = MI->getOperand(2).getReg(); - - // SelectionDAG has already inserted memory barriers before and after MI, so - // we simply have to implement the operatiuon in terms of compare-and-swap. - // - // %val0 = load %addr - // loop: - // %val = phi %val0, %dest - // %upd = op %val, %rs2 - // %dest = cas %addr, %val, %upd - // cmp %val, %dest - // bne loop - // done: - // - bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg)); - const TargetRegisterClass *ValueRC = - is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; - unsigned Val0Reg = MRI.createVirtualRegister(ValueRC); - - BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg) - .addReg(AddrReg).addImm(0); - - // Split the basic block MBB before MI and insert the loop block in the hole. - MachineFunction::iterator MFI = MBB->getIterator(); - const BasicBlock *LLVM_BB = MBB->getBasicBlock(); - MachineFunction *MF = MBB->getParent(); - MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB); - ++MFI; - MF->insert(MFI, LoopMBB); - MF->insert(MFI, DoneMBB); - - // Move MI and following instructions to DoneMBB. - DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end()); - DoneMBB->transferSuccessorsAndUpdatePHIs(MBB); - - // Connect the CFG again. - MBB->addSuccessor(LoopMBB); - LoopMBB->addSuccessor(LoopMBB); - LoopMBB->addSuccessor(DoneMBB); - - // Build the loop block. - unsigned ValReg = MRI.createVirtualRegister(ValueRC); - // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP). - unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg); - - BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) - .addReg(Val0Reg).addMBB(MBB) - .addReg(DestReg).addMBB(LoopMBB); - - if (CondCode) { - // This is one of the min/max operations. We need a CMPrr followed by a - // MOVXCC/MOVICC. - BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); - BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) - .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); - } else if (Opcode) { - BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) - .addReg(ValReg).addReg(Rs2Reg); - } - - if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 || - MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) { - unsigned TmpReg = UpdReg; - UpdReg = MRI.createVirtualRegister(ValueRC); - BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1); - } - - BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg) - .addReg(AddrReg).addReg(ValReg).addReg(UpdReg) - .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); - BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg); - BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND)) - .addMBB(LoopMBB).addImm(SPCC::ICC_NE); - - MI->eraseFromParent(); - return DoneMBB; -} - //===----------------------------------------------------------------------===// // Sparc Inline Assembly Support //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index c470fa8..5ee0256 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -187,6 +187,8 @@ namespace llvm { return true; } + AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; + void ReplaceNodeResults(SDNode *N, SmallVectorImpl& Results, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index 419e8cc..299f00e 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -510,39 +510,6 @@ def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>; } // Predicates = [Is64Bit] -let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1, - Defs = [ICC] in -multiclass AtomicRMW { - - def _32 : Pseudo<(outs IntRegs:$rd), - (ins ptr_rc:$addr, IntRegs:$rs2), "", - [(set i32:$rd, (op32 iPTR:$addr, i32:$rs2))]>; - - let Predicates = [Is64Bit] in - def _64 : Pseudo<(outs I64Regs:$rd), - (ins ptr_rc:$addr, I64Regs:$rs2), "", - [(set i64:$rd, (op64 iPTR:$addr, i64:$rs2))]>; -} - -defm ATOMIC_LOAD_ADD : AtomicRMW; -defm ATOMIC_LOAD_SUB : AtomicRMW; -defm ATOMIC_LOAD_AND : AtomicRMW; -defm ATOMIC_LOAD_OR : AtomicRMW; -defm ATOMIC_LOAD_XOR : AtomicRMW; -defm ATOMIC_LOAD_NAND : AtomicRMW; -defm ATOMIC_LOAD_MIN : AtomicRMW; -defm ATOMIC_LOAD_MAX : AtomicRMW; -defm ATOMIC_LOAD_UMIN : AtomicRMW; -defm ATOMIC_LOAD_UMAX : AtomicRMW; - -// There is no 64-bit variant of SWAP, so use a pseudo. -let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1, - Defs = [ICC], Predicates = [Is64Bit] in -def ATOMIC_SWAP_64 : Pseudo<(outs I64Regs:$rd), - (ins ptr_rc:$addr, I64Regs:$rs2), "", - [(set i64:$rd, - (atomic_swap_64 iPTR:$addr, i64:$rs2))]>; - let Predicates = [Is64Bit], hasSideEffects = 1, Uses = [ICC], cc = 0b10 in defm TXCC : TRAP<"%xcc">;