[PATCH 4/6] R600: Add zero undef variants of ctlz/cttz tests.

Matt Arsenault Matthew.Arsenault at amd.com
Fri Jun 13 11:07:24 PDT 2014


On 06/13/2014 08:45 AM, Jan Vesely wrote:
> On Fri, 2014-06-13 at 11:24 -0400, Jan Vesely wrote:
>> On Thu, 2014-06-12 at 12:52 -0700, Matt Arsenault wrote:
>>> On Jun 12, 2014, at 12:41 PM, Jan Vesely <jan.vesely at rutgers.edu> wrote:
>>>
>>>> cp + add second argument to function calls
>>>>
>>>> Signed-off-by: Jan Vesely <jan.vesely at rutgers.edu>
>>>> ---
>>>>
>>>> test/CodeGen/R600/ctlz-zero.ll | 254 +++++++++++++++++++++++++++++++++++++++++
>>>> test/CodeGen/R600/cttz-zero.ll | 254 +++++++++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 508 insertions(+)
>>>> create mode 100644 test/CodeGen/R600/ctlz-zero.ll
>>>> create mode 100644 test/CodeGen/R600/cttz-zero.ll
>>>>
>>>> diff --git a/test/CodeGen/R600/ctlz-zero.ll b/test/CodeGen/R600/ctlz-zero.ll
>>>> new file mode 100644
>>>> index 0000000..3ea7b9e
>>>> --- /dev/null
>>>> +++ b/test/CodeGen/R600/ctlz-zero.ll
>>>> @@ -0,0 +1,254 @@
>>>> +; RUN: llc -march=r600 -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
>>>> +; RUN: llc -march=r600 -mcpu=cypress -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
>>>> +
>>>> +declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
>>>> +declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) nounwind readnone
>>>> +declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1) nounwind readnone
>>>> +declare <8 x i32> @llvm.ctlz.v8i32(<8 x i32>, i1) nounwind readnone
>>>> +declare <16 x i32> @llvm.ctlz.v16i32(<16 x i32>, i1) nounwind readnone
>>>> +
>>>> +; FUNC-LABEL: @s_ctlz_i32:
>>>> +; SI: S_LOAD_DWORD [[SVAL:s[0-9]+]],
>>>> +; SI: S_BCNT1_I32_B32 [[SRESULT:s[0-9]+]], [[SVAL]]
>>>> +; SI: V_MOV_B32_e32 [[VRESULT:v[0-9]+]], [[SRESULT]]
>>>> +; SI: BUFFER_STORE_DWORD [[VRESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @s_ctlz_i32(i32 addrspace(1)* noalias %out, i32 %val) nounwind {
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  store i32 %ctlz, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; XXX - Why 0 in register?
>>>> +; FUNC-LABEL: @v_ctlz_i32:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[VZERO:v[0-9]+]], 0
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[VZERO]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  store i32 %ctlz, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_add_chain_i32
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL0:v[0-9]+]],
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL1:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[VZERO:v[0-9]+]], 0
>>>> +; SI: V_BCNT_U32_B32_e32 [[MIDRESULT:v[0-9]+]], [[VAL1]], [[VZERO]]
>>>> +; SI-NOT: ADD
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL0]], [[MIDRESULT]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_add_chain_i32(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in0, i32 addrspace(1)* noalias %in1) nounwind {
>>>> +  %val0 = load i32 addrspace(1)* %in0, align 4
>>>> +  %val1 = load i32 addrspace(1)* %in1, align 4
>>>> +  %ctlz0 = call i32 @llvm.ctlz.i32(i32 %val0, i1 1) nounwind readnone
>>>> +  %ctlz1 = call i32 @llvm.ctlz.i32(i32 %val1, i1 1) nounwind readnone
>>>> +  %add = add i32 %ctlz0, %ctlz1
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_v2i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_v2i32(<2 x i32> addrspace(1)* noalias %out, <2 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <2 x i32> addrspace(1)* %in, align 8
>>>> +  %ctlz = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %val, i1 1) nounwind readnone
>>>> +  store <2 x i32> %ctlz, <2 x i32> addrspace(1)* %out, align 8
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_v4i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_v4i32(<4 x i32> addrspace(1)* noalias %out, <4 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <4 x i32> addrspace(1)* %in, align 16
>>>> +  %ctlz = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %val, i1 1) nounwind readnone
>>>> +  store <4 x i32> %ctlz, <4 x i32> addrspace(1)* %out, align 16
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_v8i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_v8i32(<8 x i32> addrspace(1)* noalias %out, <8 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <8 x i32> addrspace(1)* %in, align 32
>>>> +  %ctlz = call <8 x i32> @llvm.ctlz.v8i32(<8 x i32> %val, i1 1) nounwind readnone
>>>> +  store <8 x i32> %ctlz, <8 x i32> addrspace(1)* %out, align 32
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_v16i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_v16i32(<16 x i32> addrspace(1)* noalias %out, <16 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <16 x i32> addrspace(1)* %in, align 32
>>>> +  %ctlz = call <16 x i32> @llvm.ctlz.v16i32(<16 x i32> %val, i1 1) nounwind readnone
>>>> +  store <16 x i32> %ctlz, <16 x i32> addrspace(1)* %out, align 32
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_inline_constant:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL]], 4
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32_add_inline_constant(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %ctlz, 4
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_inline_constant_inv:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL]], 4
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32_add_inline_constant_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 4, %ctlz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_literal:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[LIT:v[0-9]+]], 0x1869f
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[LIT]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +define void @v_ctlz_i32_add_literal(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %ctlz, 99999
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_var:
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI-DAG: S_LOAD_DWORD [[VAR:s[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32_add_var(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 %const) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %ctlz, %const
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_var_inv:
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI-DAG: S_LOAD_DWORD [[VAR:s[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32_add_var_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 %const) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %const, %ctlz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_ctlz_i32_add_vvar_inv
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]], {{.*}} + 0x0
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAR:v[0-9]+]], {{.*}} + 0x10
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[VAR]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_ctlz_i32_add_vvar_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 addrspace(1)* noalias %constptr) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %ctlz = call i32 @llvm.ctlz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %gep = getelementptr i32 addrspace(1)* %constptr, i32 4
>>>> +  %const = load i32 addrspace(1)* %gep, align 4
>>>> +  %add = add i32 %const, %ctlz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> diff --git a/test/CodeGen/R600/cttz-zero.ll b/test/CodeGen/R600/cttz-zero.ll
>>>> new file mode 100644
>>>> index 0000000..c1f1e23
>>>> --- /dev/null
>>>> +++ b/test/CodeGen/R600/cttz-zero.ll
>>>> @@ -0,0 +1,254 @@
>>>> +; RUN: llc -march=r600 -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
>>>> +; RUN: llc -march=r600 -mcpu=cypress -verify-machineinstrs < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
>>>> +
>>>> +declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
>>>> +declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1) nounwind readnone
>>>> +declare <4 x i32> @llvm.cttz.v4i32(<4 x i32>, i1) nounwind readnone
>>>> +declare <8 x i32> @llvm.cttz.v8i32(<8 x i32>, i1) nounwind readnone
>>>> +declare <16 x i32> @llvm.cttz.v16i32(<16 x i32>, i1) nounwind readnone
>>>> +
>>>> +; FUNC-LABEL: @s_cttz_i32:
>>>> +; SI: S_LOAD_DWORD [[SVAL:s[0-9]+]],
>>>> +; SI: S_BCNT1_I32_B32 [[SRESULT:s[0-9]+]], [[SVAL]]
>>>> +; SI: V_MOV_B32_e32 [[VRESULT:v[0-9]+]], [[SRESULT]]
>>>> +; SI: BUFFER_STORE_DWORD [[VRESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @s_cttz_i32(i32 addrspace(1)* noalias %out, i32 %val) nounwind {
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  store i32 %cttz, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; XXX - Why 0 in register?
>>>> +; FUNC-LABEL: @v_cttz_i32:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[VZERO:v[0-9]+]], 0
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[VZERO]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  store i32 %cttz, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_add_chain_i32
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL0:v[0-9]+]],
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL1:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[VZERO:v[0-9]+]], 0
>>>> +; SI: V_BCNT_U32_B32_e32 [[MIDRESULT:v[0-9]+]], [[VAL1]], [[VZERO]]
>>>> +; SI-NOT: ADD
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL0]], [[MIDRESULT]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_add_chain_i32(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in0, i32 addrspace(1)* noalias %in1) nounwind {
>>>> +  %val0 = load i32 addrspace(1)* %in0, align 4
>>>> +  %val1 = load i32 addrspace(1)* %in1, align 4
>>>> +  %cttz0 = call i32 @llvm.cttz.i32(i32 %val0, i1 1) nounwind readnone
>>>> +  %cttz1 = call i32 @llvm.cttz.i32(i32 %val1, i1 1) nounwind readnone
>>>> +  %add = add i32 %cttz0, %cttz1
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_v2i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_v2i32(<2 x i32> addrspace(1)* noalias %out, <2 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <2 x i32> addrspace(1)* %in, align 8
>>>> +  %cttz = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %val, i1 1) nounwind readnone
>>>> +  store <2 x i32> %cttz, <2 x i32> addrspace(1)* %out, align 8
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_v4i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_v4i32(<4 x i32> addrspace(1)* noalias %out, <4 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <4 x i32> addrspace(1)* %in, align 16
>>>> +  %cttz = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %val, i1 1) nounwind readnone
>>>> +  store <4 x i32> %cttz, <4 x i32> addrspace(1)* %out, align 16
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_v8i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_v8i32(<8 x i32> addrspace(1)* noalias %out, <8 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <8 x i32> addrspace(1)* %in, align 32
>>>> +  %cttz = call <8 x i32> @llvm.cttz.v8i32(<8 x i32> %val, i1 1) nounwind readnone
>>>> +  store <8 x i32> %cttz, <8 x i32> addrspace(1)* %out, align 32
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_v16i32:
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: V_BCNT_U32_B32_e32
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_v16i32(<16 x i32> addrspace(1)* noalias %out, <16 x i32> addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load <16 x i32> addrspace(1)* %in, align 32
>>>> +  %cttz = call <16 x i32> @llvm.cttz.v16i32(<16 x i32> %val, i1 1) nounwind readnone
>>>> +  store <16 x i32> %cttz, <16 x i32> addrspace(1)* %out, align 32
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_inline_constant:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL]], 4
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32_add_inline_constant(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %cttz, 4
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_inline_constant_inv:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL]], 4
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32_add_inline_constant_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 4, %cttz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_literal:
>>>> +; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI: V_MOV_B32_e32 [[LIT:v[0-9]+]], 0x1869f
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[LIT]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +define void @v_cttz_i32_add_literal(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %cttz, 99999
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_var:
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI-DAG: S_LOAD_DWORD [[VAR:s[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32_add_var(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 %const) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %cttz, %const
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_var_inv:
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]],
>>>> +; SI-DAG: S_LOAD_DWORD [[VAR:s[0-9]+]],
>>>> +; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32_add_var_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 %const) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %add = add i32 %const, %cttz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> +
>>>> +; FUNC-LABEL: @v_cttz_i32_add_vvar_inv
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]], {{.*}} + 0x0
>>>> +; SI-DAG: BUFFER_LOAD_DWORD [[VAR:v[0-9]+]], {{.*}} + 0x10
>>>> +; SI: V_BCNT_U32_B32_e32 [[RESULT:v[0-9]+]], [[VAL]], [[VAR]]
>>>> +; SI: BUFFER_STORE_DWORD [[RESULT]],
>>>> +; SI: S_ENDPGM
>>>> +
>>>> +; EG: BCNT_INT
>>>> +define void @v_cttz_i32_add_vvar_inv(i32 addrspace(1)* noalias %out, i32 addrspace(1)* noalias %in, i32 addrspace(1)* noalias %constptr) nounwind {
>>>> +  %val = load i32 addrspace(1)* %in, align 4
>>>> +  %cttz = call i32 @llvm.cttz.i32(i32 %val, i1 1) nounwind readnone
>>>> +  %gep = getelementptr i32 addrspace(1)* %constptr, i32 4
>>>> +  %const = load i32 addrspace(1)* %gep, align 4
>>>> +  %add = add i32 %const, %cttz
>>>> +  store i32 %add, i32 addrspace(1)* %out, align 4
>>>> +  ret void
>>>> +}
>>>> -- 
>>>> 1.9.3
>>>
>>> Is it really correct to use bcnt for this? I was working on matching
>>> the undef versions a while ago and used FFBL / FFBH instructions,
>>> although I haven’t tried running these yet
>> You are right. I didn't check whether there's a better instruction for
>> these.
>>
>> I got ffbh/ffbl running on my TURKS card, but I'm unsure about
>> SI.
> The confusing part is the use of S_ instruction. With your patches I
> see:
>   S_LOAD_DWORD
>   S_FLBIT_I32_B32
>   V_MOV_B32_e32
>   BUFFER_STORE_DWORD
>
> how is it different from:
>   S_LOAD_DWORD s0
>   V_FFBH_U32_e32 v0, s0
>   BUFFER_STORE_DWORD v0, ...
>
> other than executing the computation on every work-item. is there
> power/performance difference?

Theoretically using the SALU instructions is faster and uses less power, 
as well as saves VGPRs. In general it should be better to keep anything 
on the SALU whenever possible, but I don't know the details of how SALU 
instructions are executed or how helpful it is (other than helping with 
register usage)

It would be useful to have tests that actually execute both variants in 
piglit since it's highly likely I got these backwards (I swapped them at 
one point). It's also confusing because the names are different between 
the S and V versions.

As a side note, I have been using a global load from a pointer argument 
as a way to enforce using VALU instructions in tests, but that this 
works is a missing optimization. The pointer needs to be dynamically 
indexed into by a VGPR, because loading a constant offset from a kernel 
argument pointer could be optimized into an s_load

>> Should I keep the +var +imm +inv_var tests, since ffbh/l don't have the
>> extra argument?
>>
>> thanks,
>> Jan
>>

I'm not exactly sure which tests you mean





More information about the llvm-commits mailing list