Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -1248,9 +1248,10 @@ return nullptr; } - /// Returns true if the platform's atomic operations are sign extended. - virtual bool hasSignExtendedAtomicOps() const { - return false; + /// Returns how the platform's atomic operations are extended (ZERO_EXTEND, + /// SIGN_EXTEND, or ANY_EXTEND). + virtual ISD::NodeType getExtendForAtomicOps() const { + return ISD::ZERO_EXTEND; } /// @} Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2837,25 +2837,38 @@ cast(Node)->getFailureOrdering(), cast(Node)->getSynchScope()); + SDValue ExtRes = Res; SDValue LHS = Res; SDValue RHS = Node->getOperand(1); EVT AtomicType = cast(Node)->getMemoryVT(); EVT OuterType = Node->getValueType(0); - if (TLI.hasSignExtendedAtomicOps()) { + switch (TLI.getExtendForAtomicOps()) { + case ISD::SIGN_EXTEND: LHS = DAG.getNode(ISD::AssertSext, dl, OuterType, Res, DAG.getValueType(AtomicType)); RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, OuterType, Node->getOperand(2), DAG.getValueType(AtomicType)); - } else { - LHS = DAG.getNode(ISD::AssertZext, dl, OuterType, Res, DAG.getValueType(AtomicType)); + ExtRes = LHS; + break; + case ISD::ZERO_EXTEND: + LHS = DAG.getNode(ISD::AssertZext, dl, OuterType, Res, + DAG.getValueType(AtomicType)); RHS = DAG.getNode(ISD::ZERO_EXTEND, dl, OuterType, Node->getOperand(2)); + ExtRes = LHS; + break; + case ISD::ANY_EXTEND: + LHS = DAG.getZeroExtendInReg(Res, dl, AtomicType); + RHS = DAG.getNode(ISD::ZERO_EXTEND, dl, OuterType, Node->getOperand(2)); + break; + default: + llvm_unreachable("Invalid atomic op extension"); } SDValue Success = DAG.getSetCC(dl, Node->getValueType(1), LHS, RHS, ISD::SETEQ); - Results.push_back(LHS.getValue(0)); + Results.push_back(ExtRes.getValue(0)); Results.push_back(Success); Results.push_back(Res.getValue(1)); break; Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -238,8 +238,8 @@ bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; - bool hasSignExtendedAtomicOps() const override { - return true; + ISD::NodeType getExtendForAtomicOps() const override { + return ISD::SIGN_EXTEND; } void LowerOperationWrapper(SDNode *N, Index: lib/Target/SystemZ/SystemZISelLowering.h =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.h +++ lib/Target/SystemZ/SystemZISelLowering.h @@ -459,6 +459,10 @@ SelectionDAG &DAG) const override; SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; + ISD::NodeType getExtendForAtomicOps() const override { + return ISD::ANY_EXTEND; + } + bool supportSwiftError() const override { return true; } Index: test/CodeGen/SystemZ/cmpxchg-05.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/cmpxchg-05.ll @@ -0,0 +1,35 @@ +; Test proper extension of 8-bit/16-bit cmpxchg. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; CHECK-LABEL: f1 +; CHECK: llgcr %r2, [[RES:%r[0-9]+]] +define zeroext i8 @f1(i8* nocapture, i8 zeroext, i8 zeroext) { + %cx = cmpxchg i8* %0, i8 %1, i8 %2 seq_cst seq_cst + %res = extractvalue { i8, i1 } %cx, 0 + ret i8 %res +} + +; CHECK-LABEL: f2 +; CHECK: llghr %r2, [[RES:%r[0-9]+]] +define zeroext i16 @f2(i16* nocapture, i16 zeroext, i16 zeroext) { + %cx = cmpxchg i16* %0, i16 %1, i16 %2 seq_cst seq_cst + %res = extractvalue { i16, i1 } %cx, 0 + ret i16 %res +} + +; CHECK-LABEL: f3 +; CHECK: lgbr %r2, [[RES:%r[0-9]+]] +define signext i8 @f3(i8* nocapture, i8 signext, i8 signext) { + %cx = cmpxchg i8* %0, i8 %1, i8 %2 seq_cst seq_cst + %res = extractvalue { i8, i1 } %cx, 0 + ret i8 %res +} + +; CHECK-LABEL: f4 +; CHECK: lghr %r2, [[RES:%r[0-9]+]] +define signext i16 @f4(i16* nocapture, i16 signext, i16 signext) { + %cx = cmpxchg i16* %0, i16 %1, i16 %2 seq_cst seq_cst + %res = extractvalue { i16, i1 } %cx, 0 + ret i16 %res +}