-
Notifications
You must be signed in to change notification settings - Fork 15.4k
AMDGPU: Fix creating illegally typed readfirstlane in atomic optimizer #128388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AMDGPU: Fix creating illegally typed readfirstlane in atomic optimizer #128388
Conversation
We need to promote 8/16-bit cases to 32-bit. Unfortunately we are missing demanded bits optimizations on readfirstlane, so we end up emitting an and instruction on the input.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@llvm/pr-subscribers-backend-amdgpu Author: Matt Arsenault (arsenm) ChangesWe need to promote 8/16-bit cases to 32-bit. Unfortunately we are Patch is 196.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128388.diff 3 Files Affected:
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
index 02f5ce2d18ff6..e46d0587e7943 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp
@@ -898,8 +898,15 @@ void AMDGPUAtomicOptimizerImpl::optimizeAtomic(Instruction &I,
// We need to broadcast the value who was the lowest active lane (the first
// lane) to all other lanes in the wavefront.
- Value *BroadcastI = nullptr;
- BroadcastI = B.CreateIntrinsic(Ty, Intrinsic::amdgcn_readfirstlane, PHI);
+
+ Value *ReadlaneVal = PHI;
+ if (TyBitWidth < 32)
+ ReadlaneVal = B.CreateZExt(PHI, B.getInt32Ty());
+
+ Value *BroadcastI = B.CreateIntrinsic(
+ ReadlaneVal->getType(), Intrinsic::amdgcn_readfirstlane, ReadlaneVal);
+ if (TyBitWidth < 32)
+ BroadcastI = B.CreateTrunc(BroadcastI, Ty);
// Now that we have the result of our single atomic operation, we need to
// get our individual lane's slice into the result. We use the lane offset
diff --git a/llvm/test/CodeGen/AMDGPU/atomic-optimizer-promote-i8.ll b/llvm/test/CodeGen/AMDGPU/atomic-optimizer-promote-i8.ll
new file mode 100644
index 0000000000000..d3e591634503f
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/atomic-optimizer-promote-i8.ll
@@ -0,0 +1,176 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -passes=amdgpu-atomic-optimizer %s | FileCheck %s
+
+define amdgpu_kernel void @uniform_or_i8(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i8 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_or_i8(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i8 [[VAL:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true)
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP1]], 32
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP2]], i32 0)
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP4]], i32 [[TMP5]])
+; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT: br i1 [[TMP7]], label %[[BB8:.*]], label %[[BB10:.*]]
+; CHECK: [[BB8]]:
+; CHECK-NEXT: [[TMP9:%.*]] = atomicrmw or ptr addrspace(1) [[UNIFORM_PTR]], i8 [[VAL]] monotonic, align 1
+; CHECK-NEXT: br label %[[BB10]]
+; CHECK: [[BB10]]:
+; CHECK-NEXT: [[TMP11:%.*]] = phi i8 [ poison, [[TMP0:%.*]] ], [ [[TMP9]], %[[BB8]] ]
+; CHECK-NEXT: [[TMP16:%.*]] = zext i8 [[TMP11]] to i32
+; CHECK-NEXT: [[TMP17:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[TMP16]])
+; CHECK-NEXT: [[TMP12:%.*]] = trunc i32 [[TMP17]] to i8
+; CHECK-NEXT: [[TMP13:%.*]] = trunc i32 [[TMP6]] to i8
+; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP7]], i8 0, i8 [[VAL]]
+; CHECK-NEXT: [[TMP15:%.*]] = or i8 [[TMP12]], [[TMP14]]
+; CHECK-NEXT: store i8 [[TMP15]], ptr addrspace(1) [[RESULT]], align 1
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw or ptr addrspace(1) %uniform.ptr, i8 %val monotonic, align 1
+ store i8 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_add_i8(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i8 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_add_i8(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i8 [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true)
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP1]], 32
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP2]], i32 0)
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP4]], i32 [[TMP5]])
+; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]])
+; CHECK-NEXT: [[TMP8:%.*]] = trunc i64 [[TMP7]] to i8
+; CHECK-NEXT: [[TMP9:%.*]] = mul i8 [[VAL]], [[TMP8]]
+; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT: br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB13:.*]]
+; CHECK: [[BB11]]:
+; CHECK-NEXT: [[TMP12:%.*]] = atomicrmw add ptr addrspace(1) [[UNIFORM_PTR]], i8 [[TMP9]] monotonic, align 1
+; CHECK-NEXT: br label %[[BB13]]
+; CHECK: [[BB13]]:
+; CHECK-NEXT: [[TMP14:%.*]] = phi i8 [ poison, [[TMP0:%.*]] ], [ [[TMP12]], %[[BB11]] ]
+; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP14]] to i32
+; CHECK-NEXT: [[TMP20:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[TMP19]])
+; CHECK-NEXT: [[TMP15:%.*]] = trunc i32 [[TMP20]] to i8
+; CHECK-NEXT: [[TMP16:%.*]] = trunc i32 [[TMP6]] to i8
+; CHECK-NEXT: [[TMP17:%.*]] = mul i8 [[VAL]], [[TMP16]]
+; CHECK-NEXT: [[TMP18:%.*]] = add i8 [[TMP15]], [[TMP17]]
+; CHECK-NEXT: store i8 [[TMP18]], ptr addrspace(1) [[RESULT]], align 1
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw add ptr addrspace(1) %uniform.ptr, i8 %val monotonic, align 1
+ store i8 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i8 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_xchg_i8(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i8 [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[RMW:%.*]] = atomicrmw xchg ptr addrspace(1) [[UNIFORM_PTR]], i8 [[VAL]] monotonic, align 1
+; CHECK-NEXT: store i8 [[RMW]], ptr addrspace(1) [[RESULT]], align 1
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw xchg ptr addrspace(1) %uniform.ptr, i8 %val monotonic, align 1
+ store i8 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_or_i16(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i16 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_or_i16(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i16 [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true)
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP1]], 32
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP2]], i32 0)
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP4]], i32 [[TMP5]])
+; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT: br i1 [[TMP7]], label %[[BB8:.*]], label %[[BB10:.*]]
+; CHECK: [[BB8]]:
+; CHECK-NEXT: [[TMP9:%.*]] = atomicrmw or ptr addrspace(1) [[UNIFORM_PTR]], i16 [[VAL]] monotonic, align 2
+; CHECK-NEXT: br label %[[BB10]]
+; CHECK: [[BB10]]:
+; CHECK-NEXT: [[TMP11:%.*]] = phi i16 [ poison, [[TMP0:%.*]] ], [ [[TMP9]], %[[BB8]] ]
+; CHECK-NEXT: [[TMP16:%.*]] = zext i16 [[TMP11]] to i32
+; CHECK-NEXT: [[TMP17:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[TMP16]])
+; CHECK-NEXT: [[TMP12:%.*]] = trunc i32 [[TMP17]] to i16
+; CHECK-NEXT: [[TMP13:%.*]] = trunc i32 [[TMP6]] to i16
+; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP7]], i16 0, i16 [[VAL]]
+; CHECK-NEXT: [[TMP15:%.*]] = or i16 [[TMP12]], [[TMP14]]
+; CHECK-NEXT: store i16 [[TMP15]], ptr addrspace(1) [[RESULT]], align 2
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw or ptr addrspace(1) %uniform.ptr, i16 %val monotonic, align 2
+ store i16 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_add_i16(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i16 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_add_i16(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i16 [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true)
+; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP1]], 32
+; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP2]], i32 0)
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP4]], i32 [[TMP5]])
+; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]])
+; CHECK-NEXT: [[TMP8:%.*]] = trunc i64 [[TMP7]] to i16
+; CHECK-NEXT: [[TMP9:%.*]] = mul i16 [[VAL]], [[TMP8]]
+; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT: br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB13:.*]]
+; CHECK: [[BB11]]:
+; CHECK-NEXT: [[TMP12:%.*]] = atomicrmw add ptr addrspace(1) [[UNIFORM_PTR]], i16 [[TMP9]] monotonic, align 2
+; CHECK-NEXT: br label %[[BB13]]
+; CHECK: [[BB13]]:
+; CHECK-NEXT: [[TMP14:%.*]] = phi i16 [ poison, [[TMP0:%.*]] ], [ [[TMP12]], %[[BB11]] ]
+; CHECK-NEXT: [[TMP19:%.*]] = zext i16 [[TMP14]] to i32
+; CHECK-NEXT: [[TMP20:%.*]] = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[TMP19]])
+; CHECK-NEXT: [[TMP15:%.*]] = trunc i32 [[TMP20]] to i16
+; CHECK-NEXT: [[TMP16:%.*]] = trunc i32 [[TMP6]] to i16
+; CHECK-NEXT: [[TMP17:%.*]] = mul i16 [[VAL]], [[TMP16]]
+; CHECK-NEXT: [[TMP18:%.*]] = add i16 [[TMP15]], [[TMP17]]
+; CHECK-NEXT: store i16 [[TMP18]], ptr addrspace(1) [[RESULT]], align 2
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw add ptr addrspace(1) %uniform.ptr, i16 %val monotonic, align 2
+ store i16 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i16 %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_xchg_i16(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], i16 [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[RMW:%.*]] = atomicrmw xchg ptr addrspace(1) [[UNIFORM_PTR]], i16 [[VAL]] monotonic, align 2
+; CHECK-NEXT: store i16 [[RMW]], ptr addrspace(1) [[RESULT]], align 2
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw xchg ptr addrspace(1) %uniform.ptr, i16 %val monotonic, align 2
+ store i16 %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_fadd_f16(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, half %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_fadd_f16(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], half [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[RMW:%.*]] = atomicrmw fadd ptr addrspace(1) [[UNIFORM_PTR]], half [[VAL]] monotonic, align 2
+; CHECK-NEXT: store half [[RMW]], ptr addrspace(1) [[RESULT]], align 2
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw fadd ptr addrspace(1) %uniform.ptr, half %val monotonic, align 2
+ store half %rmw, ptr addrspace(1) %result
+ ret void
+}
+
+define amdgpu_kernel void @uniform_fadd_bf16(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, bfloat %val) {
+; CHECK-LABEL: define amdgpu_kernel void @uniform_fadd_bf16(
+; CHECK-SAME: ptr addrspace(1) [[RESULT:%.*]], ptr addrspace(1) [[UNIFORM_PTR:%.*]], bfloat [[VAL:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[RMW:%.*]] = atomicrmw fadd ptr addrspace(1) [[UNIFORM_PTR]], bfloat [[VAL]] monotonic, align 2
+; CHECK-NEXT: store bfloat [[RMW]], ptr addrspace(1) [[RESULT]], align 2
+; CHECK-NEXT: ret void
+;
+ %rmw = atomicrmw fadd ptr addrspace(1) %uniform.ptr, bfloat %val monotonic, align 2
+ store bfloat %rmw, ptr addrspace(1) %result
+ ret void
+}
diff --git a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
index bc89a186db010..3737cc414c58f 100644
--- a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
+++ b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
@@ -7149,3 +7149,4244 @@ entry:
store i64 %old, ptr addrspace(1) %out
ret void
}
+
+define amdgpu_kernel void @uniform_or_i8(ptr addrspace(1) %result, ptr addrspace(1) %uniform.ptr, i8 %val) {
+; GFX7LESS-LABEL: uniform_or_i8:
+; GFX7LESS: ; %bb.0:
+; GFX7LESS-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x9
+; GFX7LESS-NEXT: s_load_dword s6, s[4:5], 0xd
+; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0
+; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0
+; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0
+; GFX7LESS-NEXT: ; implicit-def: $vgpr0
+; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc
+; GFX7LESS-NEXT: s_cbranch_execz .LBB12_2
+; GFX7LESS-NEXT: ; %bb.1:
+; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0)
+; GFX7LESS-NEXT: s_and_b32 s8, s2, -4
+; GFX7LESS-NEXT: s_mov_b32 s11, 0xf000
+; GFX7LESS-NEXT: s_and_b32 s2, s2, 3
+; GFX7LESS-NEXT: s_lshl_b32 s2, s2, 3
+; GFX7LESS-NEXT: s_and_b32 s7, s6, 0xff
+; GFX7LESS-NEXT: s_lshl_b32 s7, s7, s2
+; GFX7LESS-NEXT: s_mov_b32 s10, -1
+; GFX7LESS-NEXT: s_mov_b32 s9, s3
+; GFX7LESS-NEXT: v_mov_b32_e32 v0, s7
+; GFX7LESS-NEXT: buffer_atomic_or v0, off, s[8:11], 0 glc
+; GFX7LESS-NEXT: s_waitcnt vmcnt(0) expcnt(0)
+; GFX7LESS-NEXT: v_lshrrev_b32_e32 v0, s2, v0
+; GFX7LESS-NEXT: .LBB12_2:
+; GFX7LESS-NEXT: s_or_b64 exec, exec, s[4:5]
+; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0)
+; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000
+; GFX7LESS-NEXT: s_mov_b32 s2, -1
+; GFX7LESS-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX7LESS-NEXT: v_mov_b32_e32 v1, s6
+; GFX7LESS-NEXT: v_readfirstlane_b32 s4, v0
+; GFX7LESS-NEXT: v_cndmask_b32_e64 v0, v1, 0, vcc
+; GFX7LESS-NEXT: v_or_b32_e32 v0, s4, v0
+; GFX7LESS-NEXT: buffer_store_byte v0, off, s[0:3], 0
+; GFX7LESS-NEXT: s_endpgm
+;
+; GFX8-LABEL: uniform_or_i8:
+; GFX8: ; %bb.0:
+; GFX8-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
+; GFX8-NEXT: s_load_dword s6, s[4:5], 0x34
+; GFX8-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0
+; GFX8-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0
+; GFX8-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0
+; GFX8-NEXT: ; implicit-def: $vgpr0
+; GFX8-NEXT: s_and_saveexec_b64 s[4:5], vcc
+; GFX8-NEXT: s_cbranch_execz .LBB12_2
+; GFX8-NEXT: ; %bb.1:
+; GFX8-NEXT: s_waitcnt lgkmcnt(0)
+; GFX8-NEXT: s_and_b32 s8, s2, -4
+; GFX8-NEXT: s_and_b32 s2, s2, 3
+; GFX8-NEXT: s_mov_b32 s9, s3
+; GFX8-NEXT: s_lshl_b32 s2, s2, 3
+; GFX8-NEXT: s_and_b32 s3, s6, 0xff
+; GFX8-NEXT: s_lshl_b32 s3, s3, s2
+; GFX8-NEXT: s_mov_b32 s11, 0xf000
+; GFX8-NEXT: s_mov_b32 s10, -1
+; GFX8-NEXT: v_mov_b32_e32 v0, s3
+; GFX8-NEXT: buffer_atomic_or v0, off, s[8:11], 0 glc
+; GFX8-NEXT: s_waitcnt vmcnt(0)
+; GFX8-NEXT: v_lshrrev_b32_e32 v0, s2, v0
+; GFX8-NEXT: .LBB12_2:
+; GFX8-NEXT: s_or_b64 exec, exec, s[4:5]
+; GFX8-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX8-NEXT: v_readfirstlane_b32 s4, v0
+; GFX8-NEXT: s_waitcnt lgkmcnt(0)
+; GFX8-NEXT: v_mov_b32_e32 v0, s6
+; GFX8-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; GFX8-NEXT: s_mov_b32 s3, 0xf000
+; GFX8-NEXT: s_mov_b32 s2, -1
+; GFX8-NEXT: v_or_b32_e32 v0, s4, v0
+; GFX8-NEXT: buffer_store_byte v0, off, s[0:3], 0
+; GFX8-NEXT: s_endpgm
+;
+; GFX9-LABEL: uniform_or_i8:
+; GFX9: ; %bb.0:
+; GFX9-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
+; GFX9-NEXT: s_load_dword s6, s[4:5], 0x34
+; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0
+; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0
+; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0
+; GFX9-NEXT: ; implicit-def: $vgpr0
+; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc
+; GFX9-NEXT: s_cbranch_execz .LBB12_2
+; GFX9-NEXT: ; %bb.1:
+; GFX9-NEXT: s_waitcnt lgkmcnt(0)
+; GFX9-NEXT: s_and_b32 s8, s2, -4
+; GFX9-NEXT: s_and_b32 s2, s2, 3
+; GFX9-NEXT: s_mov_b32 s9, s3
+; GFX9-NEXT: s_lshl_b32 s2, s2, 3
+; GFX9-NEXT: s_and_b32 s3, s6, 0xff
+; GFX9-NEXT: s_lshl_b32 s3, s3, s2
+; GFX9-NEXT: s_mov_b32 s11, 0xf000
+; GFX9-NEXT: s_mov_b32 s10, -1
+; GFX9-NEXT: v_mov_b32_e32 v0, s3
+; GFX9-NEXT: buffer_atomic_or v0, off, s[8:11], 0 glc
+; GFX9-NEXT: s_waitcnt vmcnt(0)
+; GFX9-NEXT: v_lshrrev_b32_e32 v0, s2, v0
+; GFX9-NEXT: .LBB12_2:
+; GFX9-NEXT: s_or_b64 exec, exec, s[4:5]
+; GFX9-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX9-NEXT: v_readfirstlane_b32 s4, v0
+; GFX9-NEXT: s_waitcnt lgkmcnt(0)
+; GFX9-NEXT: v_mov_b32_e32 v0, s6
+; GFX9-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; GFX9-NEXT: s_mov_b32 s3, 0xf000
+; GFX9-NEXT: s_mov_b32 s2, -1
+; GFX9-NEXT: v_or_b32_e32 v0, s4, v0
+; GFX9-NEXT: buffer_store_byte v0, off, s[0:3], 0
+; GFX9-NEXT: s_endpgm
+;
+; GFX1064-LABEL: uniform_or_i8:
+; GFX1064: ; %bb.0:
+; GFX1064-NEXT: s_clause 0x1
+; GFX1064-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
+; GFX1064-NEXT: s_load_dword s6, s[4:5], 0x34
+; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0
+; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0
+; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0
+; GFX1064-NEXT: ; implicit-def: $vgpr0
+; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc
+; GFX1064-NEXT: s_cbranch_execz .LBB12_2
+; GFX1064-NEXT: ; %bb.1:
+; GFX1064-NEXT: s_waitcnt lgkmcnt(0)
+; GFX1064-NEXT: s_and_b32 s7, s2, 3
+; GFX1064-NEXT: s_and_b32 s8, s6, 0xff
+; GFX1064-NEXT: s_lshl_b32 s7, s7, 3
+; GFX1064-NEXT: s_mov_b32 s11, 0x31016000
+; GFX1064-NEXT: s_lshl_b32 s9, s8, s7
+; GFX1064-NEXT: s_and_b32 s8, s2, -4
+; GFX1064-NEXT: v_mov_b32_e32 v0, s9
+; GFX1064-NEXT: s_mov_b32 s10, -1
+; GFX1064-NEXT: s_mov_b32 s9, s3
+; GFX1064-NEXT: buffer_atomic_or v0, off, s[8:11], 0 glc
+; GFX1064-NEXT: s_waitcnt vmcnt(0)
+; GFX1064-NEXT: v_lshrrev_b32_e32 v0, s7, v0
+; GFX1064-NEXT: .LBB12_2:
+; GFX1064-NEXT: s_or_b64 exec, exec, s[4:5]
+; GFX1064-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX1064-NEXT: s_waitcnt lgkmcnt(0)
+; GFX1064-NEXT: s_mov_b32 s3, 0x31016000
+; GFX1064-NEXT: v_readfirstlane_b32 s2, v0
+; GFX1064-NEXT: v_cndmask_b32_e64 v0, s6, 0, vcc
+; GFX1064-NEXT: v_or_b32_e32 v0, s2, v0
+; GFX1064-NEXT: s_mov_b32 s2, -1
+; GFX1064-NEXT: buffer_store_byte v0, off, s[0:3], 0
+; GFX1064-NEXT: s_endpgm
+;
+; GFX1032-LABEL: uniform_or_i8:
+; GFX1032: ; %bb.0:
+; GFX1032-NEXT: s_clause 0x1
+; GFX1032-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x24
+; GFX1032-NEXT: s_load_dword s6, s[4:5], 0x34
+; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0
+; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0
+; GFX1032-NEXT: ; implicit-def: $vgpr0
+; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo
+; GFX1032-NEXT: s_cbranch_execz .LBB12_2
+; GFX1032-NEXT: ; %bb.1:
+; GFX1032-NEXT: s_waitcnt lgkmcnt(0)
+; GFX1032-NEXT: s_and_b32 s5, s2, 3
+; GFX1032-NEXT: s_and_b32 s7, s6, 0xff
+; GFX1032-NEXT: s_lshl_b32 s5, s5, 3
+; GFX1032-NEXT: s_and_b32 s8, s2, -4
+; GFX1032-NEXT: s_lshl_b32 s7, s7, s5
+; GFX1032-NEXT: s_mov_b32 s11, 0x31016000
+; GFX1032-NEXT: v_mov_b32_e32 v0, s7
+; GFX1032-NEXT: s_mov_b32 s10, -1
+; GFX1032-NEXT: s_mov_b32 s9, s3
+; GFX1032-NEXT: buffer_atomic_or v0, off, s[8:11], 0 glc
+; GFX1032-NEXT: s_waitcnt vmcnt(0)
+; GFX1032-NEXT: v_lshrrev_b32_e32 v0, s5, v0
+; GFX1032-NEXT: .LBB12_2:
+; GFX1032-NEXT: s_or_b32 exec_lo, exec_lo, s4
+; GFX1032-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX1032-NEXT: s_waitcnt lgkmcnt(0)
+; GFX1032-NEXT: s_mov_b32 s3, 0x31016000
+; GFX1032-NEXT: v_readfirstlane_b32 s2, v0
+; GFX1032-NEXT: v_cndmask_b32_e64 v0, s6, 0, vcc_lo
+; GFX1032-NEXT: v_or_b32_e32 v0, s2, v0
+; GFX1032-NEXT: s_mov_b32 s2, -1
+; GFX1032-NEXT: buffer_store_byte v0, off, s[0:3], 0
+; GFX1032-NEXT: s_endpgm
+;
+; GFX1164-LABEL: uniform_or_i8:
+; GFX1164: ; %bb.0:
+; GFX1164-NEXT: s_clause 0x1
+; GFX1164-NEXT: s_load_b128 s[0:3], s[4:5], 0x24
+; GFX1164-NEXT: s_load_b32 s6, s[4:5], 0x34
+; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0
+; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0
+; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0
+; GFX1164-NEXT: ; implicit-def: $vgpr0
+; GFX1164-NEXT: s_and_saveexec_b64 s[4:5], vcc
+; GFX1164-NEXT: s_cbranch_execz .LBB12_2
+; GFX1164-NEXT: ; %bb.1:
+; GFX1164-NEXT: s_waitcnt lgkmcnt(0)
+; GFX1164-NEXT: s_and_b32 s7, s2, 3
...
[truncated]
|
jhuber6
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
|
Since 5feb32b this shouldn't be necessary, but it's not working |
Right, after 5feb32b i8/i16 are no longer illegal for the readfirstlane. What exactly is the problem? Can you please share the reproducer if its handy? |
The reproducer is most of the tests in the commit. The i8 intrinsics are not legalized. setOperationAction is probably missing for i8 or Other |
pravinjagtap
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Per the change description, i8 is not legal here. It is only handling legal types. This makes sense to me, although I could adjust the patch here to only use i16. However that's just adding extra steps for legalization |

We need to promote 8/16-bit cases to 32-bit. Unfortunately we are
missing demanded bits optimizations on readfirstlane, so we end up emitting
an and instruction on the input. I'm also surprised this pass isn't handling
half or bfloat yet.