aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-12-10 15:02:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-12-10 15:02:05 +0000
commit6421cca32f69ac849537a3cff78c352195e99f1b (patch)
tree419f8e5570d50a27957e4d3d80abb6639549126f
parent2cf3bd4601bbc6fc1f3ffe845eb57c2da2dff02c (diff)
Notes
-rw-r--r--lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp20
-rw-r--r--lib/Target/AArch64/AArch64ISelLowering.cpp19
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp11
-rw-r--r--test/CodeGen/AArch64/cmpxchg-O0.ll34
-rw-r--r--test/CodeGen/ARM/cmpxchg-O0.ll8
5 files changed, 67 insertions, 25 deletions
diff --git a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 5e477d39e074..a1c98251cec4 100644
--- a/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -718,13 +718,21 @@ bool AArch64ExpandPseudo::expandCMP_SWAP_128(
.addReg(DestLo.getReg(), getKillRegState(DestLo.isDead()))
.addOperand(DesiredLo)
.addImm(0);
- BuildMI(LoadCmpBB, DL, TII->get(AArch64::SBCSXr), AArch64::XZR)
+ BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
+ .addReg(AArch64::WZR)
+ .addReg(AArch64::WZR)
+ .addImm(AArch64CC::EQ);
+ BuildMI(LoadCmpBB, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
.addReg(DestHi.getReg(), getKillRegState(DestHi.isDead()))
- .addOperand(DesiredHi);
- BuildMI(LoadCmpBB, DL, TII->get(AArch64::Bcc))
- .addImm(AArch64CC::NE)
- .addMBB(DoneBB)
- .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
+ .addOperand(DesiredHi)
+ .addImm(0);
+ BuildMI(LoadCmpBB, DL, TII->get(AArch64::CSINCWr), StatusReg)
+ .addReg(StatusReg, RegState::Kill)
+ .addReg(StatusReg, RegState::Kill)
+ .addImm(AArch64CC::EQ);
+ BuildMI(LoadCmpBB, DL, TII->get(AArch64::CBNZW))
+ .addReg(StatusReg, RegState::Kill)
+ .addMBB(DoneBB);
LoadCmpBB->addSuccessor(DoneBB);
LoadCmpBB->addSuccessor(StoreBB);
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp
index ac7de1b422e0..06bfe340e758 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -10083,17 +10083,24 @@ static void ReplaceReductionResults(SDNode *N,
Results.push_back(SplitVal);
}
+static std::pair<SDValue, SDValue> splitInt128(SDValue N, SelectionDAG &DAG) {
+ SDLoc DL(N);
+ SDValue Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::i64, N);
+ SDValue Hi = DAG.getNode(ISD::TRUNCATE, DL, MVT::i64,
+ DAG.getNode(ISD::SRL, DL, MVT::i128, N,
+ DAG.getConstant(64, DL, MVT::i64)));
+ return std::make_pair(Lo, Hi);
+}
+
static void ReplaceCMP_SWAP_128Results(SDNode *N,
SmallVectorImpl<SDValue> & Results,
SelectionDAG &DAG) {
assert(N->getValueType(0) == MVT::i128 &&
"AtomicCmpSwap on types less than 128 should be legal");
- SDValue Ops[] = {N->getOperand(1),
- N->getOperand(2)->getOperand(0),
- N->getOperand(2)->getOperand(1),
- N->getOperand(3)->getOperand(0),
- N->getOperand(3)->getOperand(1),
- N->getOperand(0)};
+ auto Desired = splitInt128(N->getOperand(2), DAG);
+ auto New = splitInt128(N->getOperand(3), DAG);
+ SDValue Ops[] = {N->getOperand(1), Desired.first, Desired.second,
+ New.first, New.second, N->getOperand(0)};
SDNode *CmpSwap = DAG.getMachineNode(
AArch64::CMP_SWAP_128, SDLoc(N),
DAG.getVTList(MVT::i64, MVT::i64, MVT::i32, MVT::Other), Ops);
diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index 56f5728ecfb8..a7b299677c1c 100644
--- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -932,13 +932,10 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
.addReg(DestLo, getKillRegState(Dest.isDead()))
.addReg(DesiredLo, getKillRegState(Desired.isDead())));
- unsigned SBCrr = IsThumb ? ARM::t2SBCrr : ARM::SBCrr;
- MIB = BuildMI(LoadCmpBB, DL, TII->get(SBCrr))
- .addReg(StatusReg, RegState::Define | RegState::Dead)
- .addReg(DestHi, getKillRegState(Dest.isDead()))
- .addReg(DesiredHi, getKillRegState(Desired.isDead()));
- AddDefaultPred(MIB);
- MIB.addReg(ARM::CPSR, RegState::Kill);
+ BuildMI(LoadCmpBB, DL, TII->get(CMPrr))
+ .addReg(DestHi, getKillRegState(Dest.isDead()))
+ .addReg(DesiredHi, getKillRegState(Desired.isDead()))
+ .addImm(ARMCC::EQ).addReg(ARM::CPSR, RegState::Kill);
unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;
BuildMI(LoadCmpBB, DL, TII->get(Bcc))
diff --git a/test/CodeGen/AArch64/cmpxchg-O0.ll b/test/CodeGen/AArch64/cmpxchg-O0.ll
index c79d82a63774..aed1aa493a8f 100644
--- a/test/CodeGen/AArch64/cmpxchg-O0.ll
+++ b/test/CodeGen/AArch64/cmpxchg-O0.ll
@@ -65,11 +65,41 @@ define { i128, i1 } @test_cmpxchg_128(i128* %addr, i128 %desired, i128 %new) nou
; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:
; CHECK: ldaxp [[OLD_LO:x[0-9]+]], [[OLD_HI:x[0-9]+]], [x0]
; CHECK: cmp [[OLD_LO]], x2
-; CHECK: sbcs xzr, [[OLD_HI]], x3
-; CHECK: b.ne [[DONE:.LBB[0-9]+_[0-9]+]]
+; CHECK: cset [[CMP_TMP:w[0-9]+]], ne
+; CHECK: cmp [[OLD_HI]], x3
+; CHECK: cinc [[CMP:w[0-9]+]], [[CMP_TMP]], ne
+; CHECK: cbnz [[CMP]], [[DONE:.LBB[0-9]+_[0-9]+]]
; CHECK: stlxp [[STATUS:w[0-9]+]], x4, x5, [x0]
; CHECK: cbnz [[STATUS]], [[RETRY]]
; CHECK: [[DONE]]:
%res = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst monotonic
ret { i128, i1 } %res
}
+
+; Original implementation assumed the desired & new arguments had already been
+; type-legalized into some kind of BUILD_PAIR operation and crashed when this
+; was false.
+@var128 = global i128 0
+define {i128, i1} @test_cmpxchg_128_unsplit(i128* %addr) {
+; CHECK-LABEL: test_cmpxchg_128_unsplit:
+; CHECK: add x[[VAR128:[0-9]+]], {{x[0-9]+}}, :lo12:var128
+; CHECK: ldr [[DESIRED_HI:x[0-9]+]], [x[[VAR128]], #8]
+; CHECK: ldr [[DESIRED_LO:x[0-9]+]], [x[[VAR128]]]
+; CHECK: ldr [[NEW_HI:x[0-9]+]], [x[[VAR128]], #8]
+; CHECK: ldr [[NEW_LO:x[0-9]+]], [x[[VAR128]]]
+; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:
+; CHECK: ldaxp [[OLD_LO:x[0-9]+]], [[OLD_HI:x[0-9]+]], [x0]
+; CHECK: cmp [[OLD_LO]], [[DESIRED_LO]]
+; CHECK: cset [[CMP_TMP:w[0-9]+]], ne
+; CHECK: cmp [[OLD_HI]], [[DESIRED_HI]]
+; CHECK: cinc [[CMP:w[0-9]+]], [[CMP_TMP]], ne
+; CHECK: cbnz [[CMP]], [[DONE:.LBB[0-9]+_[0-9]+]]
+; CHECK: stlxp [[STATUS:w[0-9]+]], [[NEW_LO]], [[NEW_HI]], [x0]
+; CHECK: cbnz [[STATUS]], [[RETRY]]
+; CHECK: [[DONE]]:
+
+ %desired = load volatile i128, i128* @var128
+ %new = load volatile i128, i128* @var128
+ %val = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst
+ ret { i128, i1 } %val
+}
diff --git a/test/CodeGen/ARM/cmpxchg-O0.ll b/test/CodeGen/ARM/cmpxchg-O0.ll
index ec3005dd8ada..f8ad2bbbbe0e 100644
--- a/test/CodeGen/ARM/cmpxchg-O0.ll
+++ b/test/CodeGen/ARM/cmpxchg-O0.ll
@@ -69,9 +69,9 @@ define { i64, i1 } @test_cmpxchg_64(i64* %addr, i64 %desired, i64 %new) nounwind
; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:
; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0]
; CHECK: cmp [[OLDLO]], r6
-; CHECK: sbcs{{(\.w)?}} [[STATUS:r[0-9]+]], [[OLDHI]], r7
+; CHECK: cmpeq [[OLDHI]], r7
; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]
-; CHECK: strexd [[STATUS]], r4, r5, [r0]
+; CHECK: strexd [[STATUS:r[0-9]+]], r4, r5, [r0]
; CHECK: cmp{{(\.w)?}} [[STATUS]], #0
; CHECK: bne [[RETRY]]
; CHECK: [[DONE]]:
@@ -87,9 +87,9 @@ define { i64, i1 } @test_nontrivial_args(i64* %addr, i64 %desired, i64 %new) {
; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:
; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0]
; CHECK: cmp [[OLDLO]], {{r[0-9]+}}
-; CHECK: sbcs{{(\.w)?}} [[STATUS:r[0-9]+]], [[OLDHI]], {{r[0-9]+}}
+; CHECK: cmpeq [[OLDHI]], {{r[0-9]+}}
; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]
-; CHECK: strexd [[STATUS]], {{r[0-9]+}}, {{r[0-9]+}}, [r0]
+; CHECK: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r0]
; CHECK: cmp{{(\.w)?}} [[STATUS]], #0
; CHECK: bne [[RETRY]]
; CHECK: [[DONE]]: