diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2016-12-06 20:09:30 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2016-12-06 20:09:30 +0000 |
commit | feb79af8cd7883f723f0714c64b8a325a43dc49f (patch) | |
tree | 331aaeca53bb71abc9f3a3665c91b14a8b71a8c0 | |
parent | 1a8a2edbafcd61110486f5e9e33eab686673ccae (diff) | |
download | llvm-feb79af8cd7883f723f0714c64b8a325a43dc49f.zip llvm-feb79af8cd7883f723f0714c64b8a325a43dc49f.tar.gz llvm-feb79af8cd7883f723f0714c64b8a325a43dc49f.tar.bz2 |
Merging r277755:
------------------------------------------------------------------------
r277755 | tnorthover | 2016-08-04 12:32:28 -0700 (Thu, 04 Aug 2016) | 5 lines
AArch64: don't assume all i128s are BUILD_PAIRs
It leads to a crash when they're not. I'm *sure* I've made this mistake before,
at least once.
------------------------------------------------------------------------
llvm-svn: 288845
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 19 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/cmpxchg-O0.ll | 26 |
2 files changed, 39 insertions, 6 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index ac7de1b..06bfe34 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/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/llvm/test/CodeGen/AArch64/cmpxchg-O0.ll b/llvm/test/CodeGen/AArch64/cmpxchg-O0.ll index c79d82a..bd6c63f 100644 --- a/llvm/test/CodeGen/AArch64/cmpxchg-O0.ll +++ b/llvm/test/CodeGen/AArch64/cmpxchg-O0.ll @@ -73,3 +73,29 @@ define { i128, i1 } @test_cmpxchg_128(i128* %addr, i128 %desired, i128 %new) nou %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: sbcs xzr, [[OLD_HI]], [[DESIRED_HI]] +; CHECK: b.ne [[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 +} |