diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1236,6 +1236,12 @@ XLenVT, Expand); } + if (Subtarget.hasStdExtA()) { + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Custom); + if (Subtarget.is64Bit()) + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom); + } + if (Subtarget.hasVendorXTHeadMemIdx()) { for (unsigned im = (unsigned)ISD::PRE_INC; im != (unsigned)ISD::POST_DEC; ++im) { @@ -2902,6 +2908,18 @@ return DAG.getNode(RISCVISD::VSLIDEUP_VL, DL, VT, Ops); } +static SDValue lowerATOMIC_LOAD_SUB(SDValue Op, SelectionDAG &DAG) { + SDLoc DL(Op); + MVT VT = Op.getSimpleValueType(); + SDValue RHS = Op.getOperand(2); + AtomicSDNode *AN = cast(Op.getNode()); + SDValue NewRHS = + DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), RHS); + return DAG.getAtomic(ISD::ATOMIC_LOAD_ADD, DL, AN->getMemoryVT(), + Op.getOperand(0), Op.getOperand(1), NewRHS, + AN->getMemOperand()); +} + struct VIDSequence { int64_t StepNumerator; unsigned StepDenominator; @@ -6093,6 +6111,8 @@ !Subtarget.hasVInstructionsF16())) return SplitVPOp(Op, DAG); return lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget); + case ISD::ATOMIC_LOAD_SUB: + return lowerATOMIC_LOAD_SUB(Op, DAG); } } @@ -10809,6 +10829,15 @@ Results.push_back(Res.getValue(1)); break; } + case ISD::ATOMIC_LOAD_SUB: { + MVT VT = N->getSimpleValueType(0); + assert(VT == MVT::i32 && Subtarget.is64Bit() && + "Unexpected custom legalization"); + SDValue Res = lowerATOMIC_LOAD_SUB(SDValue(N, 0), DAG); + Results.push_back(Res); + Results.push_back(Res.getValue(1)); + break; + } } } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -174,17 +174,6 @@ defm : AMOPat<"atomic_load_umax_32", "AMOMAXU_W">; defm : AMOPat<"atomic_load_umin_32", "AMOMINU_W">; -def : Pat<(XLenVT (atomic_load_sub_32_monotonic GPR:$addr, GPR:$incr)), - (AMOADD_W GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(XLenVT (atomic_load_sub_32_acquire GPR:$addr, GPR:$incr)), - (AMOADD_W_AQ GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(XLenVT (atomic_load_sub_32_release GPR:$addr, GPR:$incr)), - (AMOADD_W_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(XLenVT (atomic_load_sub_32_acq_rel GPR:$addr, GPR:$incr)), - (AMOADD_W_AQ_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(XLenVT (atomic_load_sub_32_seq_cst GPR:$addr, GPR:$incr)), - (AMOADD_W_AQ_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; - /// Pseudo AMOs class PseudoAMO : Pseudo<(outs GPR:$res, GPR:$scratch), @@ -346,17 +335,6 @@ /// 64-bit AMOs -def : Pat<(i64 (atomic_load_sub_64_monotonic GPR:$addr, GPR:$incr)), - (AMOADD_D GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(i64 (atomic_load_sub_64_acquire GPR:$addr, GPR:$incr)), - (AMOADD_D_AQ GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(i64 (atomic_load_sub_64_release GPR:$addr, GPR:$incr)), - (AMOADD_D_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(i64 (atomic_load_sub_64_acq_rel GPR:$addr, GPR:$incr)), - (AMOADD_D_AQ_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; -def : Pat<(i64 (atomic_load_sub_64_seq_cst GPR:$addr, GPR:$incr)), - (AMOADD_D_AQ_RL GPR:$addr, (SUB (XLenVT X0), GPR:$incr))>; - /// 64-bit pseudo AMOs let Size = 20 in diff --git a/llvm/test/CodeGen/RISCV/atomic-rmw-sub-constant.ll b/llvm/test/CodeGen/RISCV/atomic-rmw-sub-constant.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/atomic-rmw-sub-constant.ll @@ -0,0 +1,92 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s +; RUN: llc -mtriple=riscv32 -mattr=+a -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefixes=RV32IA %s +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64I %s +; RUN: llc -mtriple=riscv64 -mattr=+a -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefixes=RV64IA %s + +define i32 @atomicrmw_sub_i32_constant(ptr %a) nounwind { +; RV32I-LABEL: atomicrmw_sub_i32_constant: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: li a1, 1 +; RV32I-NEXT: li a2, 5 +; RV32I-NEXT: call __atomic_fetch_sub_4@plt +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV32IA-LABEL: atomicrmw_sub_i32_constant: +; RV32IA: # %bb.0: +; RV32IA-NEXT: li a1, -1 +; RV32IA-NEXT: amoadd.w.aqrl a0, a1, (a0) +; RV32IA-NEXT: ret +; +; RV64I-LABEL: atomicrmw_sub_i32_constant: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: li a1, 1 +; RV64I-NEXT: li a2, 5 +; RV64I-NEXT: call __atomic_fetch_sub_4@plt +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64IA-LABEL: atomicrmw_sub_i32_constant: +; RV64IA: # %bb.0: +; RV64IA-NEXT: li a1, -1 +; RV64IA-NEXT: amoadd.w.aqrl a0, a1, (a0) +; RV64IA-NEXT: ret + %1 = atomicrmw sub ptr %a, i32 1 seq_cst + ret i32 %1 +} + +define i64 @atomicrmw_sub_i64_constant(ptr %a) nounwind { +; RV32I-LABEL: atomicrmw_sub_i64_constant: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: li a1, 1 +; RV32I-NEXT: li a3, 5 +; RV32I-NEXT: li a2, 0 +; RV32I-NEXT: call __atomic_fetch_sub_8@plt +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV32IA-LABEL: atomicrmw_sub_i64_constant: +; RV32IA: # %bb.0: +; RV32IA-NEXT: addi sp, sp, -16 +; RV32IA-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IA-NEXT: li a1, 1 +; RV32IA-NEXT: li a3, 5 +; RV32IA-NEXT: li a2, 0 +; RV32IA-NEXT: call __atomic_fetch_sub_8@plt +; RV32IA-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IA-NEXT: addi sp, sp, 16 +; RV32IA-NEXT: ret +; +; RV64I-LABEL: atomicrmw_sub_i64_constant: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: li a1, 1 +; RV64I-NEXT: li a2, 5 +; RV64I-NEXT: call __atomic_fetch_sub_8@plt +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64IA-LABEL: atomicrmw_sub_i64_constant: +; RV64IA: # %bb.0: +; RV64IA-NEXT: li a1, -1 +; RV64IA-NEXT: amoadd.d.aqrl a0, a1, (a0) +; RV64IA-NEXT: ret + %1 = atomicrmw sub ptr %a, i64 1 seq_cst + ret i64 %1 +} diff --git a/llvm/test/CodeGen/RISCV/atomic-rmw.ll b/llvm/test/CodeGen/RISCV/atomic-rmw.ll --- a/llvm/test/CodeGen/RISCV/atomic-rmw.ll +++ b/llvm/test/CodeGen/RISCV/atomic-rmw.ll @@ -13411,7 +13411,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_monotonic: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b monotonic @@ -13447,7 +13447,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_acquire: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w.aq a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b acquire @@ -13483,7 +13483,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_release: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w.rl a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b release @@ -13519,7 +13519,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_acq_rel: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w.aqrl a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b acq_rel @@ -13555,7 +13555,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_seq_cst: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w.aqrl a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b seq_cst diff --git a/llvm/test/CodeGen/RISCV/atomic-signext.ll b/llvm/test/CodeGen/RISCV/atomic-signext.ll --- a/llvm/test/CodeGen/RISCV/atomic-signext.ll +++ b/llvm/test/CodeGen/RISCV/atomic-signext.ll @@ -2330,7 +2330,7 @@ ; ; RV64IA-LABEL: atomicrmw_sub_i32_monotonic: ; RV64IA: # %bb.0: -; RV64IA-NEXT: neg a1, a1 +; RV64IA-NEXT: negw a1, a1 ; RV64IA-NEXT: amoadd.w a0, a1, (a0) ; RV64IA-NEXT: ret %1 = atomicrmw sub ptr %a, i32 %b monotonic