diff --git a/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp --- a/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp @@ -601,6 +601,15 @@ if (!(BNEOp0 == DestReg && BNEOp1 == CmpValReg) && !(BNEOp0 == CmpValReg && BNEOp1 == DestReg)) return false; + + // Make sure the branch is the only user of the AND. + if (MaskReg.isValid()) { + if (BNEOp0 == DestReg && !MBBI->getOperand(0).isKill()) + return false; + if (BNEOp1 == DestReg && !MBBI->getOperand(1).isKill()) + return false; + } + ToErase.push_back(&*MBBI); LoopHeadBNETarget = MBBI->getOperand(2).getMBB(); MBBI = skipDebugInstructionsForward(std::next(MBBI), E); diff --git a/llvm/test/CodeGen/RISCV/pr65025.ll b/llvm/test/CodeGen/RISCV/pr65025.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr65025.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -mtriple=riscv64 -mattr=+a | FileCheck %s + +define ptr @cmpxchg_masked_and_branch1(ptr %ptr, i8 signext %cmp, i8 signext %val) nounwind { +; CHECK-LABEL: cmpxchg_masked_and_branch1: +; CHECK: # %bb.0: # %do_cmpxchg +; CHECK-NEXT: andi a3, a0, -4 +; CHECK-NEXT: slli a4, a0, 3 +; CHECK-NEXT: li a5, 255 +; CHECK-NEXT: sllw a5, a5, a4 +; CHECK-NEXT: andi a1, a1, 255 +; CHECK-NEXT: sllw a1, a1, a4 +; CHECK-NEXT: andi a2, a2, 255 +; CHECK-NEXT: sllw a2, a2, a4 +; CHECK-NEXT: .LBB0_3: # %do_cmpxchg +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: lr.w.aqrl a4, (a3) +; CHECK-NEXT: and a6, a4, a5 +; CHECK-NEXT: bne a6, a1, .LBB0_5 +; CHECK-NEXT: # %bb.4: # %do_cmpxchg +; CHECK-NEXT: # in Loop: Header=BB0_3 Depth=1 +; CHECK-NEXT: xor a6, a4, a2 +; CHECK-NEXT: and a6, a6, a5 +; CHECK-NEXT: xor a6, a4, a6 +; CHECK-NEXT: sc.w.rl a6, a6, (a3) +; CHECK-NEXT: bnez a6, .LBB0_3 +; CHECK-NEXT: .LBB0_5: # %do_cmpxchg +; CHECK-NEXT: and a2, a4, a5 +; CHECK-NEXT: bne a1, a2, .LBB0_2 +; CHECK-NEXT: # %bb.1: # %returnptr +; CHECK-NEXT: xor a1, a1, a2 +; CHECK-NEXT: snez a1, a1 +; CHECK-NEXT: addi a1, a1, -1 +; CHECK-NEXT: and a0, a1, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_2: # %exit +; CHECK-NEXT: li a0, 0 +; CHECK-NEXT: ret +do_cmpxchg: + %0 = cmpxchg ptr %ptr, i8 %cmp, i8 %val seq_cst seq_cst + %1 = extractvalue { i8, i1 } %0, 1 + %2 = select i1 %1, ptr %ptr, ptr null + br i1 %1, label %returnptr, label %exit +returnptr: + ret ptr %2 +exit: + ret ptr null +}