diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2017-09-28 16:22:54 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2017-09-28 16:22:54 +0000 |
commit | e7870d75ef7b9b6c844b38f37ecf931ca39e394c (patch) | |
tree | a9f038bf4ebbf60d4895f2dddad96d8b439f152f /lib/Target/SystemZ | |
parent | 6bae1b9b2b8ac34fb81415e1fd8824574acf3765 (diff) |
[SystemZ] Custom-expand ATOMIC_CMP_AND_SWAP_WITH_SUCCESS
The SystemZ compare-and-swap instructions already provide the "success"
indication via a condition-code value, so the default expansion of those
operations generates an unnecessary extra comparsion.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314428 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ')
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.cpp | 62 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZISelLowering.h | 6 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZInstrInfo.td | 4 | ||||
-rw-r--r-- | lib/Target/SystemZ/SystemZOperators.td | 17 |
4 files changed, 67 insertions, 22 deletions
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 9e24a3b9548..be7c5e430fc 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -221,13 +221,17 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Custom); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom); // Even though i128 is not a legal type, we still need to custom lower // the atomic operations in order to exploit SystemZ instructions. setOperationAction(ISD::ATOMIC_LOAD, MVT::i128, Custom); setOperationAction(ISD::ATOMIC_STORE, MVT::i128, Custom); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i128, Custom); + + // We can use the CC result of compare-and-swap to implement + // the "success" result of ATOMIC_CMP_SWAP_WITH_SUCCESS. + setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i128, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); @@ -3483,25 +3487,38 @@ SDValue SystemZTargetLowering::lowerATOMIC_LOAD_SUB(SDValue Op, return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_SUB); } -// Node is an 8- or 16-bit ATOMIC_CMP_SWAP operation. Lower the first two -// into a fullword ATOMIC_CMP_SWAPW operation. +// Lower 8/16/32/64-bit ATOMIC_CMP_SWAP_WITH_SUCCESS node. SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const { auto *Node = cast<AtomicSDNode>(Op.getNode()); - - // We have native support for 32-bit compare and swap. - EVT NarrowVT = Node->getMemoryVT(); - EVT WideVT = MVT::i32; - if (NarrowVT == WideVT) - return Op; - - int64_t BitSize = NarrowVT.getSizeInBits(); SDValue ChainIn = Node->getOperand(0); SDValue Addr = Node->getOperand(1); SDValue CmpVal = Node->getOperand(2); SDValue SwapVal = Node->getOperand(3); MachineMemOperand *MMO = Node->getMemOperand(); SDLoc DL(Node); + + // We have native support for 32-bit and 64-bit compare and swap, but we + // still need to expand extracting the "success" result from the CC. + EVT NarrowVT = Node->getMemoryVT(); + EVT WideVT = NarrowVT == MVT::i64 ? MVT::i64 : MVT::i32; + if (NarrowVT == WideVT) { + SDVTList Tys = DAG.getVTList(WideVT, MVT::Other, MVT::Glue); + SDValue Ops[] = { ChainIn, Addr, CmpVal, SwapVal }; + SDValue AtomicOp = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAP, + DL, Tys, Ops, NarrowVT, MMO); + SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(2), + SystemZ::CCMASK_CS, SystemZ::CCMASK_CS_EQ); + + DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), AtomicOp.getValue(0)); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), Success); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(1)); + return SDValue(); + } + + // Convert 8-bit and 16-bit compare and swap to a loop, implemented + // via a fullword ATOMIC_CMP_SWAPW operation. + int64_t BitSize = NarrowVT.getSizeInBits(); EVT PtrVT = Addr.getValueType(); // Get the address of the containing word. @@ -3520,12 +3537,18 @@ SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, DAG.getConstant(0, DL, WideVT), BitShift); // Construct the ATOMIC_CMP_SWAPW node. - SDVTList VTList = DAG.getVTList(WideVT, MVT::Other); + SDVTList VTList = DAG.getVTList(WideVT, MVT::Other, MVT::Glue); SDValue Ops[] = { ChainIn, AlignedAddr, CmpVal, SwapVal, BitShift, NegBitShift, DAG.getConstant(BitSize, DL, WideVT) }; SDValue AtomicOp = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAPW, DL, VTList, Ops, NarrowVT, MMO); - return AtomicOp; + SDValue Success = emitSETCC(DAG, DL, AtomicOp.getValue(2), + SystemZ::CCMASK_ICMP, SystemZ::CCMASK_CMP_EQ); + + DAG.ReplaceAllUsesOfValueWith(Op.getValue(0), AtomicOp.getValue(0)); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), Success); + DAG.ReplaceAllUsesOfValueWith(Op.getValue(2), AtomicOp.getValue(1)); + return SDValue(); } SDValue SystemZTargetLowering::lowerSTACKSAVE(SDValue Op, @@ -4753,7 +4776,7 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_UMIN); case ISD::ATOMIC_LOAD_UMAX: return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_UMAX); - case ISD::ATOMIC_CMP_SWAP: + case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: return lowerATOMIC_CMP_SWAP(Op, DAG); case ISD::STACKSAVE: return lowerSTACKSAVE(Op, DAG); @@ -4847,16 +4870,20 @@ SystemZTargetLowering::LowerOperationWrapper(SDNode *N, Results.push_back(Res); break; } - case ISD::ATOMIC_CMP_SWAP: { + case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: { SDLoc DL(N); - SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other); + SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other, MVT::Glue); SDValue Ops[] = { N->getOperand(0), N->getOperand(1), lowerI128ToGR128(DAG, N->getOperand(2)), lowerI128ToGR128(DAG, N->getOperand(3)) }; MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand(); SDValue Res = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_CMP_SWAP_128, DL, Tys, Ops, MVT::i128, MMO); + SDValue Success = emitSETCC(DAG, DL, Res.getValue(2), + SystemZ::CCMASK_CS, SystemZ::CCMASK_CS_EQ); + Success = DAG.getZExtOrTrunc(Success, DL, N->getValueType(1)); Results.push_back(lowerGR128ToI128(DAG, Res)); + Results.push_back(Success); Results.push_back(Res.getValue(1)); break; } @@ -4972,6 +4999,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(ATOMIC_LOADW_UMIN); OPCODE(ATOMIC_LOADW_UMAX); OPCODE(ATOMIC_CMP_SWAPW); + OPCODE(ATOMIC_CMP_SWAP); OPCODE(ATOMIC_LOAD_128); OPCODE(ATOMIC_STORE_128); OPCODE(ATOMIC_CMP_SWAP_128); diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index 92e03c3b8b0..e2e27d9598d 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -308,6 +308,10 @@ enum NodeType : unsigned { // Operand 5: the width of the field in bits (8 or 16) ATOMIC_CMP_SWAPW, + // Atomic compare-and-swap returning glue (condition code). + // Val, OUTCHAIN, glue = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + ATOMIC_CMP_SWAP, + // 128-bit atomic load. // Val, OUTCHAIN = ATOMIC_LOAD_128(INCHAIN, ptr) ATOMIC_LOAD_128, @@ -317,7 +321,7 @@ enum NodeType : unsigned { ATOMIC_STORE_128, // 128-bit atomic compare-and-swap. - // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + // Val, OUTCHAIN, glue = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) ATOMIC_CMP_SWAP_128, // Byte swapping load. diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 766d07e8d89..55a796cddf4 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1717,8 +1717,8 @@ let mayLoad = 1, Defs = [CC] in // Compare and swap. let Defs = [CC] in { - defm CS : CmpSwapRSPair<"cs", 0xBA, 0xEB14, atomic_cmp_swap_32, GR32>; - def CSG : CmpSwapRSY<"csg", 0xEB30, atomic_cmp_swap_64, GR64>; + defm CS : CmpSwapRSPair<"cs", 0xBA, 0xEB14, z_atomic_cmp_swap, GR32>; + def CSG : CmpSwapRSY<"csg", 0xEB30, z_atomic_cmp_swap, GR64>; } // Compare double and swap. diff --git a/lib/Target/SystemZ/SystemZOperators.td b/lib/Target/SystemZ/SystemZOperators.td index 570218254f8..d067f331f67 100644 --- a/lib/Target/SystemZ/SystemZOperators.td +++ b/lib/Target/SystemZ/SystemZOperators.td @@ -55,6 +55,11 @@ def SDT_ZAtomicCmpSwapW : SDTypeProfile<1, 6, SDTCisVT<4, i32>, SDTCisVT<5, i32>, SDTCisVT<6, i32>]>; +def SDT_ZAtomicCmpSwap : SDTypeProfile<1, 3, + [SDTCisInt<0>, + SDTCisPtrTy<1>, + SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>]>; def SDT_ZAtomicLoad128 : SDTypeProfile<1, 1, [SDTCisVT<0, untyped>, SDTCisPtrTy<1>]>; @@ -296,7 +301,15 @@ def z_atomic_loadw_min : AtomicWOp<"ATOMIC_LOADW_MIN">; def z_atomic_loadw_max : AtomicWOp<"ATOMIC_LOADW_MAX">; def z_atomic_loadw_umin : AtomicWOp<"ATOMIC_LOADW_UMIN">; def z_atomic_loadw_umax : AtomicWOp<"ATOMIC_LOADW_UMAX">; -def z_atomic_cmp_swapw : AtomicWOp<"ATOMIC_CMP_SWAPW", SDT_ZAtomicCmpSwapW>; + +def z_atomic_cmp_swap : SDNode<"SystemZISD::ATOMIC_CMP_SWAP", + SDT_ZAtomicCmpSwap, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPOutGlue, SDNPMemOperand]>; +def z_atomic_cmp_swapw : SDNode<"SystemZISD::ATOMIC_CMP_SWAPW", + SDT_ZAtomicCmpSwapW, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, + SDNPOutGlue, SDNPMemOperand]>; def z_atomic_load_128 : SDNode<"SystemZISD::ATOMIC_LOAD_128", SDT_ZAtomicLoad128, @@ -307,7 +320,7 @@ def z_atomic_store_128 : SDNode<"SystemZISD::ATOMIC_STORE_128", def z_atomic_cmp_swap_128 : SDNode<"SystemZISD::ATOMIC_CMP_SWAP_128", SDT_ZAtomicCmpSwap128, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, - SDNPMemOperand]>; + SDNPOutGlue, SDNPMemOperand]>; def z_mvc : SDNode<"SystemZISD::MVC", SDT_ZMemMemLength, [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>; |