llvm.org GIT mirror llvm / 8608f2e
64-bit atomic operations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49949 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 12 years ago
6 changed file(s) with 129 addition(s) and 57 deletion(s). Raw diff Collapse all Expand all
205205 setOperationAction(ISD::ATOMIC_LAS , MVT::i32 , Custom);
206206 setOperationAction(ISD::ATOMIC_LCS , MVT::i32 , Custom);
207207 setOperationAction(ISD::ATOMIC_SWAP , MVT::i32 , Custom);
208 if (TM.getSubtarget().has64BitSupport()) {
209 setOperationAction(ISD::ATOMIC_LAS , MVT::i64 , Custom);
210 setOperationAction(ISD::ATOMIC_LCS , MVT::i64 , Custom);
211 setOperationAction(ISD::ATOMIC_SWAP , MVT::i64 , Custom);
212 }
208213
209214 // We want to custom lower some of our intrinsics.
210215 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
397402 case PPCISD::VCMPo: return "PPCISD::VCMPo";
398403 case PPCISD::LBRX: return "PPCISD::LBRX";
399404 case PPCISD::STBRX: return "PPCISD::STBRX";
400 case PPCISD::LWARX: return "PPCISD::LWARX";
401 case PPCISD::STWCX: return "PPCISD::STWCX";
405 case PPCISD::LARX: return "PPCISD::LARX";
406 case PPCISD::STCX: return "PPCISD::STCX";
402407 case PPCISD::CMP_UNRESERVE: return "PPCISD::CMP_UNRESERVE";
403408 case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH";
404409 case PPCISD::MFFS: return "PPCISD::MFFS";
23032308 }
23042309
23052310 SDOperand PPCTargetLowering::LowerAtomicLAS(SDOperand Op, SelectionDAG &DAG) {
2306 MVT::ValueType VT = Op.getValueType();
2311 MVT::ValueType VT = Op.Val->getValueType(0);
23072312 SDOperand Chain = Op.getOperand(0);
23082313 SDOperand Ptr = Op.getOperand(1);
23092314 SDOperand Incr = Op.getOperand(2);
23152320
23162321 SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
23172322 SDOperand Ops[] = {
2318 Chain, // Chain
2319 Ptr, // Ptr
2320 Label, // Label
2323 Chain, // Chain
2324 Ptr, // Ptr
2325 Label, // Label
23212326 };
2322 SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
2327 SDOperand Load = DAG.getNode(PPCISD::LARX, VTs, Ops, 3);
23232328 Chain = Load.getValue(1);
23242329
23252330 // Compute new value.
23272332
23282333 // Issue a "store and check".
23292334 SDOperand Ops2[] = {
2330 Chain, // Chain
2331 NewVal, // Value
2332 Ptr, // Ptr
2333 Label, // Label
2335 Chain, // Chain
2336 NewVal, // Value
2337 Ptr, // Ptr
2338 Label, // Label
23342339 };
2335 SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops2, 4);
2340 SDOperand Store = DAG.getNode(PPCISD::STCX, MVT::Other, Ops2, 4);
23362341 SDOperand OutOps[] = { Load, Store };
23372342 return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
23382343 OutOps, 2);
23392344 }
23402345
23412346 SDOperand PPCTargetLowering::LowerAtomicLCS(SDOperand Op, SelectionDAG &DAG) {
2342 MVT::ValueType VT = Op.getValueType();
2347 MVT::ValueType VT = Op.Val->getValueType(0);
23432348 SDOperand Chain = Op.getOperand(0);
23442349 SDOperand Ptr = Op.getOperand(1);
23452350 SDOperand NewVal = Op.getOperand(2);
23522357
23532358 SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
23542359 SDOperand Ops[] = {
2355 Chain, // Chain
2356 Ptr, // Ptr
2357 Label, // Label
2360 Chain, // Chain
2361 Ptr, // Ptr
2362 Label, // Label
23582363 };
2359 SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
2364 SDOperand Load = DAG.getNode(PPCISD::LARX, VTs, Ops, 3);
23602365 Chain = Load.getValue(1);
23612366
23622367 // Compare and unreserve if not equal.
23632368 SDOperand Ops2[] = {
2364 Chain, // Chain
2365 OldVal, // Old value
2366 Load, // Value in memory
2367 Label, // Label
2369 Chain, // Chain
2370 OldVal, // Old value
2371 Load, // Value in memory
2372 Label, // Label
23682373 };
23692374 Chain = DAG.getNode(PPCISD::CMP_UNRESERVE, MVT::Other, Ops2, 4);
23702375
23712376 // Issue a "store and check".
23722377 SDOperand Ops3[] = {
2373 Chain, // Chain
2374 NewVal, // Value
2375 Ptr, // Ptr
2376 Label, // Label
2378 Chain, // Chain
2379 NewVal, // Value
2380 Ptr, // Ptr
2381 Label, // Label
23772382 };
2378 SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops3, 4);
2383 SDOperand Store = DAG.getNode(PPCISD::STCX, MVT::Other, Ops3, 4);
23792384 SDOperand OutOps[] = { Load, Store };
23802385 return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
23812386 OutOps, 2);
23822387 }
23832388
23842389 SDOperand PPCTargetLowering::LowerAtomicSWAP(SDOperand Op, SelectionDAG &DAG) {
2385 MVT::ValueType VT = Op.getValueType();
2390 MVT::ValueType VT = Op.Val->getValueType(0);
23862391 SDOperand Chain = Op.getOperand(0);
23872392 SDOperand Ptr = Op.getOperand(1);
23882393 SDOperand NewVal = Op.getOperand(2);
23942399
23952400 SDOperand Label = DAG.getConstant(PPCAtomicLabelIndex++, MVT::i32);
23962401 SDOperand Ops[] = {
2397 Chain, // Chain
2398 Ptr, // Ptr
2399 Label, // Label
2402 Chain, // Chain
2403 Ptr, // Ptr
2404 Label, // Label
24002405 };
2401 SDOperand Load = DAG.getNode(PPCISD::LWARX, VTs, Ops, 3);
2406 SDOperand Load = DAG.getNode(PPCISD::LARX, VTs, Ops, 3);
24022407 Chain = Load.getValue(1);
24032408
24042409 // Issue a "store and check".
24052410 SDOperand Ops2[] = {
2406 Chain, // Chain
2407 NewVal, // Value
2408 Ptr, // Ptr
2409 Label, // Label
2411 Chain, // Chain
2412 NewVal, // Value
2413 Ptr, // Ptr
2414 Label, // Label
24102415 };
2411 SDOperand Store = DAG.getNode(PPCISD::STWCX, MVT::Other, Ops2, 4);
2416 SDOperand Store = DAG.getNode(PPCISD::STCX, MVT::Other, Ops2, 4);
24122417 SDOperand OutOps[] = { Load, Store };
24132418 return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
24142419 OutOps, 2);
151151 /// MTFSF = F8RC, INFLAG - This moves the register into the FPSCR.
152152 MTFSF,
153153
154 /// LWARX = This corresponds to PPC lwarx instrcution: load word and
154 /// LARX = This corresponds to PPC l{w|d}arx instrcution: load and
155155 /// reserve indexed. This is used to implement atomic operations.
156 LWARX,
157
158 /// STWCX = This corresponds to PPC stwcx. instrcution: store word
159 /// conditional indexed. This is used to implement atomic operations.
160 STWCX,
156 LARX,
157
158 /// STCX = This corresponds to PPC stcx. instrcution: store conditional
159 /// indexed. This is used to implement atomic operations.
160 STCX,
161161
162162 /// CMP_UNRESERVE = Test for equality and "unreserve" if not true. This
163163 /// is used to implement atomic operations.
114114 (BL8_ELF tglobaladdr:$dst)>;
115115 def : Pat<(PPCcall_ELF (i64 texternalsym:$dst)),
116116 (BL8_ELF texternalsym:$dst)>;
117
118
119 // Atomic operations.
120 def LDARX : Pseudo<(outs G8RC:$rD), (ins memrr:$ptr, i32imm:$label),
121 "\nLa${label}_entry:\n\tldarx $rD, $ptr",
122 [(set G8RC:$rD, (PPClarx xoaddr:$ptr, imm:$label))]>;
123
124 let Defs = [CR0] in {
125 def STDCX : Pseudo<(outs), (ins G8RC:$rS, memrr:$dst, i32imm:$label),
126 "stdcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
127 [(PPCstcx G8RC:$rS, xoaddr:$dst, imm:$label)]>;
128
129 def CMP_UNRESd : Pseudo<(outs), (ins G8RC:$rA, G8RC:$rB, i32imm:$label),
130 "cmpd $rA, $rB\n\tbne- La${label}_exit",
131 [(PPCcmp_unres G8RC:$rA, G8RC:$rB, imm:$label)]>;
132 def CMP_UNRESdi : Pseudo<(outs), (ins G8RC:$rA, s16imm64:$imm, i32imm:$label),
133 "cmpdi $rA, $imm\n\tbne- La${label}_exit",
134 [(PPCcmp_unres G8RC:$rA, immSExt16:$imm, imm:$label)]>;
135 }
117136
118137 //===----------------------------------------------------------------------===//
119138 // 64-bit SPR manipulation instrs.
4141 SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
4242 ]>;
4343
44 def SDT_PPClwarx : SDTypeProfile<1, 2, [
45 SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
44 def SDT_PPClarx : SDTypeProfile<1, 2, [
45 SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
4646 ]>;
47 def SDT_PPCstwcx : SDTypeProfile<0, 3, [
48 SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
47 def SDT_PPCstcx : SDTypeProfile<0, 3, [
48 SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>
4949 ]>;
5050 def SDT_PPCcmp_unres : SDTypeProfile<0, 3, [
51 SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>
51 SDTCisSameAs<0, 1>, SDTCisInt<1>, SDTCisVT<2, i32>
5252 ]>;
5353
5454 //===----------------------------------------------------------------------===//
131131 def PPCstbrx : SDNode<"PPCISD::STBRX", SDT_PPCstbrx,
132132 [SDNPHasChain, SDNPMayStore]>;
133133
134 def PPClwarx : SDNode<"PPCISD::LWARX", SDT_PPClwarx,
135 [SDNPHasChain, SDNPMayLoad]>;
136 def PPCstwcx : SDNode<"PPCISD::STWCX", SDT_PPCstwcx,
137 [SDNPHasChain, SDNPMayStore]>;
134 def PPClarx : SDNode<"PPCISD::LARX", SDT_PPClarx,
135 [SDNPHasChain, SDNPMayLoad]>;
136 def PPCstcx : SDNode<"PPCISD::STCX", SDT_PPCstcx,
137 [SDNPHasChain, SDNPMayStore]>;
138138 def PPCcmp_unres : SDNode<"PPCISD::CMP_UNRESERVE", SDT_PPCcmp_unres,
139139 [SDNPHasChain]>;
140140
481481 // Atomic operations.
482482 def LWARX : Pseudo<(outs GPRC:$rD), (ins memrr:$ptr, i32imm:$label),
483483 "\nLa${label}_entry:\n\tlwarx $rD, $ptr",
484 [(set GPRC:$rD, (PPClwarx xoaddr:$ptr, imm:$label))]>;
484 [(set GPRC:$rD, (PPClarx xoaddr:$ptr, imm:$label))]>;
485485
486486 let Defs = [CR0] in {
487487 def STWCX : Pseudo<(outs), (ins GPRC:$rS, memrr:$dst, i32imm:$label),
488 "stwcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
489 [(PPCstwcx GPRC:$rS, xoaddr:$dst, imm:$label)]>;
488 "stwcx. $rS, $dst\n\tbne- La${label}_entry\nLa${label}_exit:",
489 [(PPCstcx GPRC:$rS, xoaddr:$dst, imm:$label)]>;
490490
491491 def CMP_UNRESw : Pseudo<(outs), (ins GPRC:$rA, GPRC:$rB, i32imm:$label),
492492 "cmpw $rA, $rB\n\tbne- La${label}_exit",
493493 [(PPCcmp_unres GPRC:$rA, GPRC:$rB, imm:$label)]>;
494494 def CMP_UNRESwi : Pseudo<(outs), (ins GPRC:$rA, s16imm:$imm, i32imm:$label),
495495 "cmpwi $rA, $imm\n\tbne- La${label}_exit",
496 [(PPCcmp_unres GPRC:$rA, imm:$imm, imm:$label)]>;
496 [(PPCcmp_unres GPRC:$rA, immSExt16:$imm, imm:$label)]>;
497497 }
498498
499499 //===----------------------------------------------------------------------===//
12641264 (FMRSD (LFSX xaddr:$src))>;
12651265
12661266 // Atomic operations
1267 def : Pat<(PPCcmp_unres imm:$imm, GPRC:$rA, imm:$label),
1268 (CMP_UNRESwi GPRC:$rA, imm:$imm, imm:$label)>;
1267 def : Pat<(PPCcmp_unres immSExt16:$imm, GPRC:$rA, imm:$label),
1268 (CMP_UNRESwi GPRC:$rA, immSExt16:$imm, imm:$label)>;
12691269
12701270 include "PPCInstrAltivec.td"
12711271 include "PPCInstr64Bit.td"
0 ; RUN: llvm-as < %s | llc -march=ppc32 | grep lwarx | count 4
1 ; RUN: llvm-as < %s | llc -march=ppc32 | grep stwcx. | count 4
2
3 define i32 @exchange_and_add(i32* %mem, i32 %val) nounwind {
4 %tmp = call i32 @llvm.atomic.las.i32( i32* %mem, i32 %val )
5 ret i32 %tmp
6 }
7
8 define i32 @exchange_and_cmp(i32* %mem) nounwind {
9 %tmp = call i32 @llvm.atomic.lcs.i32( i32* %mem, i32 0, i32 1 )
10 ret i32 %tmp
11 }
12
13 define i16 @exchange_and_cmp16(i16* %mem) nounwind {
14 %tmp = call i16 @llvm.atomic.lcs.i16( i16* %mem, i16 0, i16 1 )
15 ret i16 %tmp
16 }
17
18 define i32 @exchange(i32* %mem, i32 %val) nounwind {
19 %tmp = call i32 @llvm.atomic.swap.i32( i32* %mem, i32 1 )
20 ret i32 %tmp
21 }
22
23 declare i32 @llvm.atomic.las.i32(i32*, i32) nounwind
24 declare i32 @llvm.atomic.lcs.i32(i32*, i32, i32) nounwind
25 declare i16 @llvm.atomic.lcs.i16(i16*, i16, i16) nounwind
26 declare i32 @llvm.atomic.swap.i32(i32*, i32) nounwind
0 ; RUN: llvm-as < %s | llc -march=ppc64 | grep ldarx | count 3
1 ; RUN: llvm-as < %s | llc -march=ppc64 | grep stdcx. | count 3
2
3 define i64 @exchange_and_add(i64* %mem, i64 %val) nounwind {
4 %tmp = call i64 @llvm.atomic.las.i64( i64* %mem, i64 %val )
5 ret i64 %tmp
6 }
7
8 define i64 @exchange_and_cmp(i64* %mem) nounwind {
9 %tmp = call i64 @llvm.atomic.lcs.i64( i64* %mem, i64 0, i64 1 )
10 ret i64 %tmp
11 }
12
13 define i64 @exchange(i64* %mem, i64 %val) nounwind {
14 %tmp = call i64 @llvm.atomic.swap.i64( i64* %mem, i64 1 )
15 ret i64 %tmp
16 }
17
18 declare i64 @llvm.atomic.las.i64(i64*, i64) nounwind
19 declare i64 @llvm.atomic.lcs.i64(i64*, i64, i64) nounwind
20 declare i64 @llvm.atomic.swap.i64(i64*, i64) nounwind