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