Skip to content

Commit ff6d333

Browse files
committed
[RISCV] Prevent tryToFoldBNEOnCmpXchgResult from deleting AND if it has others users.
This disables the transform if the branch does not have the kill flag set for the AND we want to delete. Ideally we'd be able to share the AND with the AND we create in the expansion, but that's a more complex transform. So this starts with the simple approach to fix miscompile. This should be backported to LLVM 17. Fixes PR65025.ll Reviewed By: asb Differential Revision: https://reviews.llvm.org/D158962
1 parent 538b90c commit ff6d333

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,15 @@ bool tryToFoldBNEOnCmpXchgResult(MachineBasicBlock &MBB,
601601
if (!(BNEOp0 == DestReg && BNEOp1 == CmpValReg) &&
602602
!(BNEOp0 == CmpValReg && BNEOp1 == DestReg))
603603
return false;
604+
605+
// Make sure the branch is the only user of the AND.
606+
if (MaskReg.isValid()) {
607+
if (BNEOp0 == DestReg && !MBBI->getOperand(0).isKill())
608+
return false;
609+
if (BNEOp1 == DestReg && !MBBI->getOperand(1).isKill())
610+
return false;
611+
}
612+
604613
ToErase.push_back(&*MBBI);
605614
LoopHeadBNETarget = MBBI->getOperand(2).getMBB();
606615
MBBI = skipDebugInstructionsForward(std::next(MBBI), E);

llvm/test/CodeGen/RISCV/pr65025.ll

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2+
; RUN: llc < %s -mtriple=riscv64 -mattr=+a | FileCheck %s
3+
4+
define ptr @cmpxchg_masked_and_branch1(ptr %ptr, i8 signext %cmp, i8 signext %val) nounwind {
5+
; CHECK-LABEL: cmpxchg_masked_and_branch1:
6+
; CHECK: # %bb.0: # %do_cmpxchg
7+
; CHECK-NEXT: andi a3, a0, -4
8+
; CHECK-NEXT: slli a4, a0, 3
9+
; CHECK-NEXT: li a5, 255
10+
; CHECK-NEXT: sllw a5, a5, a4
11+
; CHECK-NEXT: andi a1, a1, 255
12+
; CHECK-NEXT: sllw a1, a1, a4
13+
; CHECK-NEXT: andi a2, a2, 255
14+
; CHECK-NEXT: sllw a2, a2, a4
15+
; CHECK-NEXT: .LBB0_3: # %do_cmpxchg
16+
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
17+
; CHECK-NEXT: lr.w.aqrl a4, (a3)
18+
; CHECK-NEXT: and a6, a4, a5
19+
; CHECK-NEXT: bne a6, a1, .LBB0_5
20+
; CHECK-NEXT: # %bb.4: # %do_cmpxchg
21+
; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1
22+
; CHECK-NEXT: xor a6, a4, a2
23+
; CHECK-NEXT: and a6, a6, a5
24+
; CHECK-NEXT: xor a6, a4, a6
25+
; CHECK-NEXT: sc.w.rl a6, a6, (a3)
26+
; CHECK-NEXT: bnez a6, .LBB0_3
27+
; CHECK-NEXT: .LBB0_5: # %do_cmpxchg
28+
; CHECK-NEXT: and a2, a4, a5
29+
; CHECK-NEXT: bne a1, a2, .LBB0_2
30+
; CHECK-NEXT: # %bb.1: # %returnptr
31+
; CHECK-NEXT: xor a1, a1, a2
32+
; CHECK-NEXT: snez a1, a1
33+
; CHECK-NEXT: addi a1, a1, -1
34+
; CHECK-NEXT: and a0, a1, a0
35+
; CHECK-NEXT: ret
36+
; CHECK-NEXT: .LBB0_2: # %exit
37+
; CHECK-NEXT: li a0, 0
38+
; CHECK-NEXT: ret
39+
do_cmpxchg:
40+
%0 = cmpxchg ptr %ptr, i8 %cmp, i8 %val seq_cst seq_cst
41+
%1 = extractvalue { i8, i1 } %0, 1
42+
%2 = select i1 %1, ptr %ptr, ptr null
43+
br i1 %1, label %returnptr, label %exit
44+
returnptr:
45+
ret ptr %2
46+
exit:
47+
ret ptr null
48+
}

0 commit comments

Comments
 (0)