[llvm] r310094 - [SystemZ] Add support for 128-bit atomic load/store/cmpxchg
Ulrich Weigand via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 4 11:57:58 PDT 2017
Author: uweigand
Date: Fri Aug 4 11:57:58 2017
New Revision: 310094
URL: http://llvm.org/viewvc/llvm-project?rev=310094&view=rev
Log:
[SystemZ] Add support for 128-bit atomic load/store/cmpxchg
This adds support for the main 128-bit atomic operations,
using the SystemZ instructions LPQ, STPQ, and CDSG.
Generating these instructions is a bit more complex than usual
since the i128 type is not legal for the back-end. Therefore,
we have to hook the LowerOperationWrapper and ReplaceNodeResults
TargetLowering callbacks.
Added:
llvm/trunk/test/CodeGen/SystemZ/atomic-load-05.ll
llvm/trunk/test/CodeGen/SystemZ/atomic-store-05.ll
llvm/trunk/test/CodeGen/SystemZ/cmpxchg-06.ll
Modified:
llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=310094&r1=310093&r2=310094&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Fri Aug 4 11:57:58 2017
@@ -222,6 +222,12 @@ SystemZTargetLowering::SystemZTargetLowe
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);
+
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
// Traps are legal, as we will convert them to "j .+2".
@@ -4789,6 +4795,88 @@ SDValue SystemZTargetLowering::LowerOper
}
}
+// Lower operations with invalid operand or result types (currently used
+// only for 128-bit integer types).
+
+static SDValue lowerI128ToGR128(SelectionDAG &DAG, SDValue In) {
+ SDLoc DL(In);
+ SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In,
+ DAG.getIntPtrConstant(0, DL));
+ SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, In,
+ DAG.getIntPtrConstant(1, DL));
+ SDNode *Pair = DAG.getMachineNode(SystemZ::PAIR128, DL,
+ MVT::Untyped, Hi, Lo);
+ return SDValue(Pair, 0);
+}
+
+static SDValue lowerGR128ToI128(SelectionDAG &DAG, SDValue In) {
+ SDLoc DL(In);
+ SDValue Hi = DAG.getTargetExtractSubreg(SystemZ::subreg_h64,
+ DL, MVT::i64, In);
+ SDValue Lo = DAG.getTargetExtractSubreg(SystemZ::subreg_l64,
+ DL, MVT::i64, In);
+ return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i128, Lo, Hi);
+}
+
+void
+SystemZTargetLowering::LowerOperationWrapper(SDNode *N,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const {
+ switch (N->getOpcode()) {
+ case ISD::ATOMIC_LOAD: {
+ SDLoc DL(N);
+ SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other);
+ SDValue Ops[] = { N->getOperand(0), N->getOperand(1) };
+ MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand();
+ SDValue Res = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_LOAD_128,
+ DL, Tys, Ops, MVT::i128, MMO);
+ Results.push_back(lowerGR128ToI128(DAG, Res));
+ Results.push_back(Res.getValue(1));
+ break;
+ }
+ case ISD::ATOMIC_STORE: {
+ SDLoc DL(N);
+ SDVTList Tys = DAG.getVTList(MVT::Other);
+ SDValue Ops[] = { N->getOperand(0),
+ lowerI128ToGR128(DAG, N->getOperand(2)),
+ N->getOperand(1) };
+ MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand();
+ SDValue Res = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_STORE_128,
+ DL, Tys, Ops, MVT::i128, MMO);
+ // We have to enforce sequential consistency by performing a
+ // serialization operation after the store.
+ if (cast<AtomicSDNode>(N)->getOrdering() ==
+ AtomicOrdering::SequentiallyConsistent)
+ Res = SDValue(DAG.getMachineNode(SystemZ::Serialize, DL,
+ MVT::Other, Res), 0);
+ Results.push_back(Res);
+ break;
+ }
+ case ISD::ATOMIC_CMP_SWAP: {
+ SDLoc DL(N);
+ SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other);
+ 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);
+ Results.push_back(lowerGR128ToI128(DAG, Res));
+ Results.push_back(Res.getValue(1));
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected node to lower");
+ }
+}
+
+void
+SystemZTargetLowering::ReplaceNodeResults(SDNode *N,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const {
+ return LowerOperationWrapper(N, Results, DAG);
+}
+
const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
#define OPCODE(NAME) case SystemZISD::NAME: return "SystemZISD::" #NAME
switch ((SystemZISD::NodeType)Opcode) {
@@ -4889,6 +4977,9 @@ const char *SystemZTargetLowering::getTa
OPCODE(ATOMIC_LOADW_UMIN);
OPCODE(ATOMIC_LOADW_UMAX);
OPCODE(ATOMIC_CMP_SWAPW);
+ OPCODE(ATOMIC_LOAD_128);
+ OPCODE(ATOMIC_STORE_128);
+ OPCODE(ATOMIC_CMP_SWAP_128);
OPCODE(LRV);
OPCODE(STRV);
OPCODE(PREFETCH);
@@ -5916,6 +6007,32 @@ SystemZTargetLowering::emitAtomicCmpSwap
return DoneMBB;
}
+// Emit a move from two GR64s to a GR128.
+MachineBasicBlock *
+SystemZTargetLowering::emitPair128(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+ MachineFunction &MF = *MBB->getParent();
+ const SystemZInstrInfo *TII =
+ static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ DebugLoc DL = MI.getDebugLoc();
+
+ unsigned Dest = MI.getOperand(0).getReg();
+ unsigned Hi = MI.getOperand(1).getReg();
+ unsigned Lo = MI.getOperand(2).getReg();
+ unsigned Tmp1 = MRI.createVirtualRegister(&SystemZ::GR128BitRegClass);
+ unsigned Tmp2 = MRI.createVirtualRegister(&SystemZ::GR128BitRegClass);
+
+ BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::IMPLICIT_DEF), Tmp1);
+ BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), Tmp2)
+ .addReg(Tmp1).addReg(Hi).addImm(SystemZ::subreg_h64);
+ BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::INSERT_SUBREG), Dest)
+ .addReg(Tmp2).addReg(Lo).addImm(SystemZ::subreg_l64);
+
+ MI.eraseFromParent();
+ return MBB;
+}
+
// Emit an extension from a GR64 to a GR128. ClearEven is true
// if the high register of the GR128 value must be cleared or false if
// it's "don't care".
@@ -6309,6 +6426,8 @@ MachineBasicBlock *SystemZTargetLowering
case SystemZ::CondStoreF64Inv:
return emitCondStore(MI, MBB, SystemZ::STD, 0, true);
+ case SystemZ::PAIR128:
+ return emitPair128(MI, MBB);
case SystemZ::AEXT128:
return emitExt128(MI, MBB, false);
case SystemZ::ZEXT128:
Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h?rev=310094&r1=310093&r2=310094&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h Fri Aug 4 11:57:58 2017
@@ -308,6 +308,18 @@ enum NodeType : unsigned {
// Operand 5: the width of the field in bits (8 or 16)
ATOMIC_CMP_SWAPW,
+ // 128-bit atomic load.
+ // Val, OUTCHAIN = ATOMIC_LOAD_128(INCHAIN, ptr)
+ ATOMIC_LOAD_128,
+
+ // 128-bit atomic store.
+ // OUTCHAIN = ATOMIC_STORE_128(INCHAIN, val, ptr)
+ ATOMIC_STORE_128,
+
+ // 128-bit atomic compare-and-swap.
+ // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap)
+ ATOMIC_CMP_SWAP_128,
+
// Byte swapping load.
//
// Operand 0: the address to load from
@@ -449,6 +461,10 @@ public:
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const override;
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
+ void LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const override;
+ void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
+ SelectionDAG &DAG) const override;
bool allowTruncateForTailCall(Type *, Type *) const override;
bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
@@ -566,6 +582,8 @@ private:
MachineBasicBlock *emitCondStore(MachineInstr &MI, MachineBasicBlock *BB,
unsigned StoreOpcode, unsigned STOCOpcode,
bool Invert) const;
+ MachineBasicBlock *emitPair128(MachineInstr &MI,
+ MachineBasicBlock *MBB) const;
MachineBasicBlock *emitExt128(MachineInstr &MI, MachineBasicBlock *MBB,
bool ClearEven) const;
MachineBasicBlock *emitAtomicLoadBinary(MachineInstr &MI,
Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td?rev=310094&r1=310093&r2=310094&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td Fri Aug 4 11:57:58 2017
@@ -372,6 +372,9 @@ let Defs = [CC], CCValues = 0xE, Compare
def LTGR : UnaryRRE<"ltgr", 0xB902, null_frag, GR64, GR64>;
}
+let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in
+ def PAIR128 : Pseudo<(outs GR128:$dst), (ins GR64:$hi, GR64:$lo), []>;
+
// Immediate moves.
let hasSideEffects = 0, isAsCheapAsAMove = 1, isMoveImm = 1,
isReMaterializable = 1 in {
@@ -1721,7 +1724,7 @@ let Defs = [CC] in {
// Compare double and swap.
let Defs = [CC] in {
defm CDS : CmpSwapRSPair<"cds", 0xBB, 0xEB31, null_frag, GR128>;
- def CDSG : CmpSwapRSY<"cdsg", 0xEB3E, null_frag, GR128>;
+ def CDSG : CmpSwapRSY<"cdsg", 0xEB3E, z_atomic_cmp_swap_128, GR128>;
}
// Compare and swap and store.
@@ -1733,8 +1736,8 @@ let Uses = [R0L, R1D], Defs = [CC], mayS
def PLO : SideEffectQuaternarySSe<"plo", 0xEE, GR64>;
// Load/store pair from/to quadword.
-def LPQ : UnaryRXY<"lpq", 0xE38F, null_frag, GR128, 16>;
-def STPQ : StoreRXY<"stpq", 0xE38E, null_frag, GR128, 16>;
+def LPQ : UnaryRXY<"lpq", 0xE38F, z_atomic_load_128, GR128, 16>;
+def STPQ : StoreRXY<"stpq", 0xE38E, z_atomic_store_128, GR128, 16>;
// Load pair disjoint.
let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in {
Modified: llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZOperators.td?rev=310094&r1=310093&r2=310094&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZOperators.td (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZOperators.td Fri Aug 4 11:57:58 2017
@@ -55,6 +55,17 @@ def SDT_ZAtomicCmpSwapW : SDTypeProf
SDTCisVT<4, i32>,
SDTCisVT<5, i32>,
SDTCisVT<6, i32>]>;
+def SDT_ZAtomicLoad128 : SDTypeProfile<1, 1,
+ [SDTCisVT<0, untyped>,
+ SDTCisPtrTy<1>]>;
+def SDT_ZAtomicStore128 : SDTypeProfile<0, 2,
+ [SDTCisVT<0, untyped>,
+ SDTCisPtrTy<1>]>;
+def SDT_ZAtomicCmpSwap128 : SDTypeProfile<1, 3,
+ [SDTCisVT<0, untyped>,
+ SDTCisPtrTy<1>,
+ SDTCisVT<2, untyped>,
+ SDTCisVT<3, untyped>]>;
def SDT_ZMemMemLength : SDTypeProfile<0, 3,
[SDTCisPtrTy<0>,
SDTCisPtrTy<1>,
@@ -287,6 +298,17 @@ def z_atomic_loadw_umin : AtomicWOp<"ATO
def z_atomic_loadw_umax : AtomicWOp<"ATOMIC_LOADW_UMAX">;
def z_atomic_cmp_swapw : AtomicWOp<"ATOMIC_CMP_SWAPW", SDT_ZAtomicCmpSwapW>;
+def z_atomic_load_128 : SDNode<"SystemZISD::ATOMIC_LOAD_128",
+ SDT_ZAtomicLoad128,
+ [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+def z_atomic_store_128 : SDNode<"SystemZISD::ATOMIC_STORE_128",
+ SDT_ZAtomicStore128,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def z_atomic_cmp_swap_128 : SDNode<"SystemZISD::ATOMIC_CMP_SWAP_128",
+ SDT_ZAtomicCmpSwap128,
+ [SDNPHasChain, SDNPMayStore, SDNPMayLoad,
+ SDNPMemOperand]>;
+
def z_mvc : SDNode<"SystemZISD::MVC", SDT_ZMemMemLength,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
def z_mvc_loop : SDNode<"SystemZISD::MVC_LOOP", SDT_ZMemMemLoop,
Added: llvm/trunk/test/CodeGen/SystemZ/atomic-load-05.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/atomic-load-05.ll?rev=310094&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/atomic-load-05.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/atomic-load-05.ll Fri Aug 4 11:57:58 2017
@@ -0,0 +1,13 @@
+; Test 128-bit atomic loads.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+define i128 @f1(i128 *%src) {
+; CHECK-LABEL: f1:
+; CHECK: lpq %r0, 0(%r3)
+; CHECK-DAG: stg %r1, 8(%r2)
+; CHECK-DAG: stg %r0, 0(%r2)
+; CHECK: br %r14
+ %val = load atomic i128, i128 *%src seq_cst, align 16
+ ret i128 %val
+}
Added: llvm/trunk/test/CodeGen/SystemZ/atomic-store-05.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/atomic-store-05.ll?rev=310094&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/atomic-store-05.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/atomic-store-05.ll Fri Aug 4 11:57:58 2017
@@ -0,0 +1,25 @@
+; Test 128-bit atomic stores.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+define void @f1(i128 %val, i128 *%src) {
+; CHECK-LABEL: f1:
+; CHECK-DAG: lg %r1, 8(%r2)
+; CHECK-DAG: lg %r0, 0(%r2)
+; CHECK: stpq %r0, 0(%r3)
+; CHECK: bcr 1{{[45]}}, %r0
+; CHECK: br %r14
+ store atomic i128 %val, i128 *%src seq_cst, align 16
+ ret void
+}
+
+define void @f2(i128 %val, i128 *%src) {
+; CHECK-LABEL: f2:
+; CHECK-DAG: lg %r1, 8(%r2)
+; CHECK-DAG: lg %r0, 0(%r2)
+; CHECK: stpq %r0, 0(%r3)
+; CHECK-NOT: bcr 1{{[45]}}, %r0
+; CHECK: br %r14
+ store atomic i128 %val, i128 *%src monotonic, align 16
+ ret void
+}
Added: llvm/trunk/test/CodeGen/SystemZ/cmpxchg-06.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/cmpxchg-06.ll?rev=310094&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/cmpxchg-06.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/cmpxchg-06.ll Fri Aug 4 11:57:58 2017
@@ -0,0 +1,113 @@
+; Test 64-bit compare and swap.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; Check CDSG without a displacement.
+define i128 @f1(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f1:
+; CHECK-DAG: lg %r1, 8(%r4)
+; CHECK-DAG: lg %r0, 0(%r4)
+; CHECK-DAG: lg %r13, 8(%r3)
+; CHECK-DAG: lg %r12, 0(%r3)
+; CHECK: cdsg %r12, %r0, 0(%r5)
+; CHECK-DAG: stg %r13, 8(%r2)
+; CHECK-DAG: stg %r12, 0(%r2)
+; CHECK: br %r14
+ %pairval = cmpxchg i128 *%src, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check the high end of the aligned CDSG range.
+define i128 @f2(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f2:
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 524272(%r5)
+; CHECK: br %r14
+ %ptr = getelementptr i128, i128 *%src, i128 32767
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check the next doubleword up, which needs separate address logic.
+; Other sequences besides this one would be OK.
+define i128 @f3(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f3:
+; CHECK: agfi %r5, 524288
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
+; CHECK: br %r14
+ %ptr = getelementptr i128, i128 *%src, i128 32768
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check the high end of the negative aligned CDSG range.
+define i128 @f4(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f4:
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -16(%r5)
+; CHECK: br %r14
+ %ptr = getelementptr i128, i128 *%src, i128 -1
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check the low end of the CDSG range.
+define i128 @f5(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f5:
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, -524288(%r5)
+; CHECK: br %r14
+ %ptr = getelementptr i128, i128 *%src, i128 -32768
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check the next doubleword down, which needs separate address logic.
+; Other sequences besides this one would be OK.
+define i128 @f6(i128 %cmp, i128 %swap, i128 *%src) {
+; CHECK-LABEL: f6:
+; CHECK: agfi %r5, -524304
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
+; CHECK: br %r14
+ %ptr = getelementptr i128, i128 *%src, i128 -32769
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check that CDSG does not allow an index.
+define i128 @f7(i128 %cmp, i128 %swap, i64 %src, i64 %index) {
+; CHECK-LABEL: f7:
+; CHECK: agr %r5, %r6
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r5)
+; CHECK: br %r14
+ %add1 = add i64 %src, %index
+ %ptr = inttoptr i64 %add1 to i128 *
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check that a constant %cmp value is loaded into a register first.
+define i128 @f8(i128 %swap, i128 *%ptr) {
+; CHECK-LABEL: f8:
+; CHECK: lghi {{%r[0-9]+}}, 1001
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
+; CHECK: br %r14
+ %pairval = cmpxchg i128 *%ptr, i128 1001, i128 %swap seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
+
+; Check that a constant %swap value is loaded into a register first.
+define i128 @f9(i128 %cmp, i128 *%ptr) {
+; CHECK-LABEL: f9:
+; CHECK: lghi {{%r[0-9]+}}, 1002
+; CHECK: cdsg {{%r[0-9]+}}, {{%r[0-9]+}}, 0(%r4)
+; CHECK: br %r14
+ %pairval = cmpxchg i128 *%ptr, i128 %cmp, i128 1002 seq_cst seq_cst
+ %val = extractvalue { i128, i1 } %pairval, 0
+ ret i128 %val
+}
More information about the llvm-commits
mailing list