1263320SdimPull in r200453 from upstream llvm trunk (by Jakob Stoklund Olesen): 2263320Sdim 3263320Sdim Implement SPARCv9 atomic_swap_64 with a pseudo. 4263320Sdim 5263320Sdim The SWAP instruction only exists in a 32-bit variant, but the 64-bit 6263320Sdim atomic swap can be implemented in terms of CASX, like the other atomic 7263320Sdim rmw primitives. 8263320Sdim 9263320SdimIntroduced here: http://svn.freebsd.org/changeset/base/262264 10263320Sdim 11263320SdimIndex: lib/Target/Sparc/SparcInstr64Bit.td 12263320Sdim=================================================================== 13263320Sdim--- lib/Target/Sparc/SparcInstr64Bit.td 14263320Sdim+++ lib/Target/Sparc/SparcInstr64Bit.td 15263320Sdim@@ -463,6 +463,14 @@ defm ATOMIC_LOAD_MAX : AtomicRMW<atomic_load_max_ 16263320Sdim defm ATOMIC_LOAD_UMIN : AtomicRMW<atomic_load_umin_32, atomic_load_umin_64>; 17263320Sdim defm ATOMIC_LOAD_UMAX : AtomicRMW<atomic_load_umax_32, atomic_load_umax_64>; 18263320Sdim 19263320Sdim+// There is no 64-bit variant of SWAP, so use a pseudo. 20263320Sdim+let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1, 21263320Sdim+ Defs = [ICC], Predicates = [Is64Bit] in 22263320Sdim+def ATOMIC_SWAP_64 : Pseudo<(outs I64Regs:$rd), 23263320Sdim+ (ins ptr_rc:$addr, I64Regs:$rs2), "", 24263320Sdim+ [(set i64:$rd, 25263320Sdim+ (atomic_swap_64 iPTR:$addr, i64:$rs2))]>; 26263320Sdim+ 27263320Sdim // Global addresses, constant pool entries 28263320Sdim let Predicates = [Is64Bit] in { 29263320Sdim 30263320SdimIndex: lib/Target/Sparc/SparcISelLowering.cpp 31263320Sdim=================================================================== 32263320Sdim--- lib/Target/Sparc/SparcISelLowering.cpp 33263320Sdim+++ lib/Target/Sparc/SparcISelLowering.cpp 34263320Sdim@@ -1498,7 +1498,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMac 35263320Sdim 36263320Sdim if (Subtarget->is64Bit()) { 37263320Sdim setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); 38263320Sdim- setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand); 39263320Sdim+ setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal); 40263320Sdim setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); 41263320Sdim setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); 42263320Sdim } 43263320Sdim@@ -2885,6 +2885,9 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M 44263320Sdim case SP::ATOMIC_LOAD_NAND_64: 45263320Sdim return expandAtomicRMW(MI, BB, SP::ANDXrr); 46263320Sdim 47263320Sdim+ case SP::ATOMIC_SWAP_64: 48263320Sdim+ return expandAtomicRMW(MI, BB, 0); 49263320Sdim+ 50263320Sdim case SP::ATOMIC_LOAD_MAX_32: 51263320Sdim return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); 52263320Sdim case SP::ATOMIC_LOAD_MAX_64: 53263320Sdim@@ -3023,7 +3026,8 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr 54263320Sdim 55263320Sdim // Build the loop block. 56263320Sdim unsigned ValReg = MRI.createVirtualRegister(ValueRC); 57263320Sdim- unsigned UpdReg = MRI.createVirtualRegister(ValueRC); 58263320Sdim+ // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP). 59263320Sdim+ unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg); 60263320Sdim 61263320Sdim BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) 62263320Sdim .addReg(Val0Reg).addMBB(MBB) 63263320Sdim@@ -3035,7 +3039,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr 64263320Sdim BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); 65263320Sdim BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) 66263320Sdim .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); 67263320Sdim- } else { 68263320Sdim+ } else if (Opcode) { 69263320Sdim BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) 70263320Sdim .addReg(ValReg).addReg(Rs2Reg); 71263320Sdim } 72263320SdimIndex: test/CodeGen/SPARC/atomics.ll 73263320Sdim=================================================================== 74263320Sdim--- test/CodeGen/SPARC/atomics.ll 75263320Sdim+++ test/CodeGen/SPARC/atomics.ll 76263320Sdim@@ -62,6 +62,15 @@ entry: 77263320Sdim ret i32 %b 78263320Sdim } 79263320Sdim 80263320Sdim+; CHECK-LABEL: test_swap_i64 81263320Sdim+; CHECK: casx [%o1], 82263320Sdim+ 83263320Sdim+define i64 @test_swap_i64(i64 %a, i64* %ptr) { 84263320Sdim+entry: 85263320Sdim+ %b = atomicrmw xchg i64* %ptr, i64 42 monotonic 86263320Sdim+ ret i64 %b 87263320Sdim+} 88263320Sdim+ 89263320Sdim ; CHECK-LABEL: test_load_add_32 90263320Sdim ; CHECK: membar 91263320Sdim ; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]] 92