Skip to content

Commit 92455aa

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277755 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 65a759c commit 92455aa

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9996,17 +9996,24 @@ static void ReplaceReductionResults(SDNode *N,
99969996
Results.push_back(SplitVal);
99979997
}
99989998

9999+
static std::pair<SDValue, SDValue> splitInt128(SDValue N, SelectionDAG &DAG) {
10000+
SDLoc DL(N);
10001+
SDValue Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::i64, N);
10002+
SDValue Hi = DAG.getNode(ISD::TRUNCATE, DL, MVT::i64,
10003+
DAG.getNode(ISD::SRL, DL, MVT::i128, N,
10004+
DAG.getConstant(64, DL, MVT::i64)));
10005+
return std::make_pair(Lo, Hi);
10006+
}
10007+
999910008
static void ReplaceCMP_SWAP_128Results(SDNode *N,
1000010009
SmallVectorImpl<SDValue> & Results,
1000110010
SelectionDAG &DAG) {
1000210011
assert(N->getValueType(0) == MVT::i128 &&
1000310012
"AtomicCmpSwap on types less than 128 should be legal");
10004-
SDValue Ops[] = {N->getOperand(1),
10005-
N->getOperand(2)->getOperand(0),
10006-
N->getOperand(2)->getOperand(1),
10007-
N->getOperand(3)->getOperand(0),
10008-
N->getOperand(3)->getOperand(1),
10009-
N->getOperand(0)};
10013+
auto Desired = splitInt128(N->getOperand(2), DAG);
10014+
auto New = splitInt128(N->getOperand(3), DAG);
10015+
SDValue Ops[] = {N->getOperand(1), Desired.first, Desired.second,
10016+
New.first, New.second, N->getOperand(0)};
1001010017
SDNode *CmpSwap = DAG.getMachineNode(
1001110018
AArch64::CMP_SWAP_128, SDLoc(N),
1001210019
DAG.getVTList(MVT::i64, MVT::i64, MVT::i32, MVT::Other), Ops);

test/CodeGen/AArch64/cmpxchg-O0.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,29 @@ define { i128, i1 } @test_cmpxchg_128(i128* %addr, i128 %desired, i128 %new) nou
7373
%res = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst monotonic
7474
ret { i128, i1 } %res
7575
}
76+
77+
; Original implementation assumed the desired & new arguments had already been
78+
; type-legalized into some kind of BUILD_PAIR operation and crashed when this
79+
; was false.
80+
@var128 = global i128 0
81+
define {i128, i1} @test_cmpxchg_128_unsplit(i128* %addr) {
82+
; CHECK-LABEL: test_cmpxchg_128_unsplit:
83+
; CHECK: add x[[VAR128:[0-9]+]], {{x[0-9]+}}, :lo12:var128
84+
; CHECK: ldr [[DESIRED_HI:x[0-9]+]], [x[[VAR128]], #8]
85+
; CHECK: ldr [[DESIRED_LO:x[0-9]+]], [x[[VAR128]]]
86+
; CHECK: ldr [[NEW_HI:x[0-9]+]], [x[[VAR128]], #8]
87+
; CHECK: ldr [[NEW_LO:x[0-9]+]], [x[[VAR128]]]
88+
; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:
89+
; CHECK: ldaxp [[OLD_LO:x[0-9]+]], [[OLD_HI:x[0-9]+]], [x0]
90+
; CHECK: cmp [[OLD_LO]], [[DESIRED_LO]]
91+
; CHECK: sbcs xzr, [[OLD_HI]], [[DESIRED_HI]]
92+
; CHECK: b.ne [[DONE:.LBB[0-9]+_[0-9]+]]
93+
; CHECK: stlxp [[STATUS:w[0-9]+]], [[NEW_LO]], [[NEW_HI]], [x0]
94+
; CHECK: cbnz [[STATUS]], [[RETRY]]
95+
; CHECK: [[DONE]]:
96+
97+
%desired = load volatile i128, i128* @var128
98+
%new = load volatile i128, i128* @var128
99+
%val = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst
100+
ret { i128, i1 } %val
101+
}

0 commit comments

Comments
 (0)