diff --git a/llvm/lib/Target/R600/SIInstructions.td b/llvm/lib/Target/R600/SIInstructions.td index a00a8ba9471e..f6dc07fbd967 100644 --- a/llvm/lib/Target/R600/SIInstructions.td +++ b/llvm/lib/Target/R600/SIInstructions.td @@ -2222,6 +2222,22 @@ multiclass DSAtomicRetPat { >; } +// Special case of DSAtomicRetPat for add / sub 1 -> inc / dec +multiclass DSAtomicIncRetPat { + def : Pat < + (frag (add i32:$ptr, (i32 IMM16bit:$offset)), (vt 1)), + (inst (i1 0), $ptr, (as_i16imm $offset)) + >; + + def : Pat < + (frag i32:$ptr, (vt 1)), + (inst 0, $ptr, 0) + >; +} + +defm : DSAtomicIncRetPat; +defm : DSAtomicIncRetPat; + defm : DSAtomicRetPat; defm : DSAtomicRetPat; defm : DSAtomicRetPat; diff --git a/llvm/test/CodeGen/R600/local-atomics.ll b/llvm/test/CodeGen/R600/local-atomics.ll index ef440f994fc2..fb70ddf06920 100644 --- a/llvm/test/CodeGen/R600/local-atomics.ll +++ b/llvm/test/CodeGen/R600/local-atomics.ll @@ -47,6 +47,25 @@ define void @lds_atomic_add_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace ret void } +; FUNC-LABEL: @lds_atomic_inc_ret_i32: +; SI: DS_INC_RTN_U32 +; SI: S_ENDPGM +define void @lds_atomic_inc_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind { + %result = atomicrmw add i32 addrspace(3)* %ptr, i32 1 seq_cst + store i32 %result, i32 addrspace(1)* %out, align 4 + ret void +} + +; FUNC-LABEL: @lds_atomic_inc_ret_i32_offset: +; SI: DS_INC_RTN_U32 v{{[0-9]+}}, v{{[0-9]+}}, 0x10 +; SI: S_ENDPGM +define void @lds_atomic_inc_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind { + %gep = getelementptr i32 addrspace(3)* %ptr, i32 4 + %result = atomicrmw add i32 addrspace(3)* %gep, i32 1 seq_cst + store i32 %result, i32 addrspace(1)* %out, align 4 + ret void +} + ; FUNC-LABEL: @lds_atomic_sub_ret_i32: ; SI: DS_SUB_RTN_U32 ; SI: S_ENDPGM @@ -66,6 +85,25 @@ define void @lds_atomic_sub_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace ret void } +; FUNC-LABEL: @lds_atomic_dec_ret_i32: +; SI: DS_DEC_RTN_U32 +; SI: S_ENDPGM +define void @lds_atomic_dec_ret_i32(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind { + %result = atomicrmw sub i32 addrspace(3)* %ptr, i32 1 seq_cst + store i32 %result, i32 addrspace(1)* %out, align 4 + ret void +} + +; FUNC-LABEL: @lds_atomic_dec_ret_i32_offset: +; SI: DS_DEC_RTN_U32 v{{[0-9]+}}, v{{[0-9]+}}, 0x10 +; SI: S_ENDPGM +define void @lds_atomic_dec_ret_i32_offset(i32 addrspace(1)* %out, i32 addrspace(3)* %ptr) nounwind { + %gep = getelementptr i32 addrspace(3)* %ptr, i32 4 + %result = atomicrmw sub i32 addrspace(3)* %gep, i32 1 seq_cst + store i32 %result, i32 addrspace(1)* %out, align 4 + ret void +} + ; FUNC-LABEL: @lds_atomic_and_ret_i32: ; SI: DS_AND_RTN_B32 ; SI: S_ENDPGM