[llvm] [LSV][AMDGPU] Vectorize unordered and monotonic atomic loads (PR #190152)

Harrison Hao via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 04:36:09 PDT 2026


================
@@ -0,0 +1,351 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -passes=load-store-vectorizer -S < %s | FileCheck %s
+
+define amdgpu_cs void @atomic_two_load_monotonic_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_monotonic_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <2 x float>, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <2 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_monotonic_merge2(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_monotonic_merge2(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <2 x float>, ptr addrspace(1) [[P1]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <2 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %a0 = load atomic float, ptr addrspace(1) %p1  syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p2 syncscope("agent") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_unordered_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_unordered_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <2 x float>, ptr addrspace(1) [[P]] syncscope("agent") unordered, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <2 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") unordered, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") unordered, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_unordered_workgroup_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_unordered_workgroup_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <2 x float>, ptr addrspace(1) [[P]] syncscope("workgroup") unordered, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <2 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("workgroup") unordered, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("workgroup") unordered, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_monotonic_workgroup_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_monotonic_workgroup_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <2 x float>, ptr addrspace(1) [[P]] syncscope("workgroup") monotonic, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <2 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("workgroup") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("workgroup") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_volatile_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_volatile_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A0:%.*]] = load atomic volatile float, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A1:%.*]] = load atomic volatile float, ptr addrspace(1) [[P1]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A0]], [[A1]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic volatile float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load atomic volatile float, ptr addrspace(1) %p1 syncscope("agent") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_mixed_atomic_noatomic_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_mixed_atomic_noatomic_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A01:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A12:%.*]] = load float, ptr addrspace(1) [[P1]], align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load float, ptr addrspace(1) %p1, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_gap_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_gap_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8
+; CHECK-NEXT:    [[A0:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A1:%.*]] = load atomic float, ptr addrspace(1) [[P1]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A0]], [[A1]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_acquire_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_acquire_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A0:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") acquire, align 4
+; CHECK-NEXT:    [[A1:%.*]] = load atomic float, ptr addrspace(1) [[P1]] syncscope("agent") acquire, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A0]], [[A1]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") acquire, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") acquire, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_seq_cst_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_seq_cst_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A0:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") seq_cst, align 4
+; CHECK-NEXT:    [[A1:%.*]] = load atomic float, ptr addrspace(1) [[P1]] syncscope("agent") seq_cst, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A0]], [[A1]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") seq_cst, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") seq_cst, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_same_offset_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_same_offset_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[NUM1:%.*]] = fadd float [[TMP1]], 1.000000e+00
+; CHECK-NEXT:    [[NUM2:%.*]] = fadd float [[TMP1]], 2.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[NUM1]], [[NUM2]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %num1 = fadd float %a0, 1.0
+  %num2 = fadd float %a1, 2.0
+  %res = fadd float %num1, %num2
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_mixed_order_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_mixed_order_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A01:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") unordered, align 4
+; CHECK-NEXT:    [[A12:%.*]] = load atomic float, ptr addrspace(1) [[P1]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") unordered, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_two_load_mixed_scope_no_merge(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_two_load_mixed_scope_no_merge(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 4
+; CHECK-NEXT:    [[A01:%.*]] = load atomic float, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A12:%.*]] = load atomic float, ptr addrspace(1) [[P1]] syncscope("workgroup") monotonic, align 4
+; CHECK-NEXT:    [[RES:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    store float [[RES]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %a0 = load atomic float, ptr addrspace(1) %p syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("workgroup") monotonic, align 4
+  %res = fadd float %a0, %a1
+  store float %res, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_four_load_monotonic_merge_b128(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_four_load_monotonic_merge_b128(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <4 x float>, ptr addrspace(1) [[P]] syncscope("agent") monotonic, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[A34:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[S01:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    [[S23:%.*]] = fadd float [[A23]], [[A34]]
+; CHECK-NEXT:    [[SUM:%.*]] = fadd float [[S01]], [[S23]]
+; CHECK-NEXT:    store float [[SUM]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %p3 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 12
+  %a0 = load atomic float, ptr addrspace(1) %p  syncscope("agent") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") monotonic, align 4
+  %a2 = load atomic float, ptr addrspace(1) %p2 syncscope("agent") monotonic, align 4
+  %a3 = load atomic float, ptr addrspace(1) %p3 syncscope("agent") monotonic, align 4
+  %s01 = fadd float %a0, %a1
+  %s23 = fadd float %a2, %a3
+  %sum = fadd float %s01, %s23
+  store float %sum, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_four_load_monotonic_workgroup_merge_b128(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_four_load_monotonic_workgroup_merge_b128(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <4 x float>, ptr addrspace(1) [[P]] syncscope("workgroup") monotonic, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[A34:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[S01:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    [[S23:%.*]] = fadd float [[A23]], [[A34]]
+; CHECK-NEXT:    [[SUM:%.*]] = fadd float [[S01]], [[S23]]
+; CHECK-NEXT:    store float [[SUM]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %p3 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 12
+  %a0 = load atomic float, ptr addrspace(1) %p  syncscope("workgroup") monotonic, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("workgroup") monotonic, align 4
+  %a2 = load atomic float, ptr addrspace(1) %p2 syncscope("workgroup") monotonic, align 4
+  %a3 = load atomic float, ptr addrspace(1) %p3 syncscope("workgroup") monotonic, align 4
+  %s01 = fadd float %a0, %a1
+  %s23 = fadd float %a2, %a3
+  %sum = fadd float %s01, %s23
+  store float %sum, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_four_load_unordered_merge_b128(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_four_load_unordered_merge_b128(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <4 x float>, ptr addrspace(1) [[P]] syncscope("agent") unordered, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[A34:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[S01:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    [[S23:%.*]] = fadd float [[A23]], [[A34]]
+; CHECK-NEXT:    [[SUM:%.*]] = fadd float [[S01]], [[S23]]
+; CHECK-NEXT:    store float [[SUM]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %p3 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 12
+  %a0 = load atomic float, ptr addrspace(1) %p  syncscope("agent") unordered, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("agent") unordered, align 4
+  %a2 = load atomic float, ptr addrspace(1) %p2 syncscope("agent") unordered, align 4
+  %a3 = load atomic float, ptr addrspace(1) %p3 syncscope("agent") unordered, align 4
+  %s01 = fadd float %a0, %a1
+  %s23 = fadd float %a2, %a3
+  %sum = fadd float %s01, %s23
+  store float %sum, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define amdgpu_cs void @atomic_four_load_unordered_workgroup_merge_b128(ptr addrspace(1) align 16 %p, ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_cs void @atomic_four_load_unordered_workgroup_merge_b128(
+; CHECK-SAME: ptr addrspace(1) align 16 [[P:%.*]], ptr addrspace(1) [[OUT:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic <4 x float>, ptr addrspace(1) [[P]] syncscope("workgroup") unordered, align 4
+; CHECK-NEXT:    [[A01:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[A12:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[A23:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[A34:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[S01:%.*]] = fadd float [[A01]], [[A12]]
+; CHECK-NEXT:    [[S23:%.*]] = fadd float [[A23]], [[A34]]
+; CHECK-NEXT:    [[SUM:%.*]] = fadd float [[S01]], [[S23]]
+; CHECK-NEXT:    store float [[SUM]], ptr addrspace(1) [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 4
+  %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8
+  %p3 = getelementptr inbounds i8, ptr addrspace(1) %p, i64 12
+  %a0 = load atomic float, ptr addrspace(1) %p  syncscope("workgroup") unordered, align 4
+  %a1 = load atomic float, ptr addrspace(1) %p1 syncscope("workgroup") unordered, align 4
+  %a2 = load atomic float, ptr addrspace(1) %p2 syncscope("workgroup") unordered, align 4
+  %a3 = load atomic float, ptr addrspace(1) %p3 syncscope("workgroup") unordered, align 4
+  %s01 = fadd float %a0, %a1
+  %s23 = fadd float %a2, %a3
+  %sum = fadd float %s01, %s23
+  store float %sum, ptr addrspace(1) %out, align 4
+  ret void
+}
----------------
harrisonGPU wrote:

I have already added : `atomic_two_load_mixed_order_no_merge`, `atomic_two_load_mixed_scope_no_merge`, and `atomic_two_load_mixed_atomic_noatomic_no_merge` these three tests.

https://github.com/llvm/llvm-project/pull/190152


More information about the llvm-commits mailing list