[llvm] [VectorCombine][AMDGPU] Shrink demanded vector loads (PR #202501)

Krzysztof Drewniak via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 23:08:34 PDT 2026


================
@@ -0,0 +1,206 @@
+; RUN: opt < %s -passes=vector-combine -S -mtriple=amdgcn-amd-amdpal -mcpu=gfx1201 | FileCheck %s
+
+target triple = "amdgcn-amd-amdpal"
+
+define void @shrink_i32_load_prefix(ptr addrspace(1) %out,
+                                    ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_i32_load_prefix(
+; CHECK-NOT: load <4 x i32>
+; CHECK: load <3 x i32>, ptr addrspace(4) %p, align 8
+entry:
+  %v = load <4 x i32>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <4 x i32> %v, i32 0
+  %e1 = extractelement <4 x i32> %v, i32 1
+  %e2 = extractelement <4 x i32> %v, i32 2
+  store volatile i32 %e0, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %e1, ptr addrspace(1) %out1, align 4
+  %out2 = getelementptr i32, ptr addrspace(1) %out, i32 2
+  store volatile i32 %e2, ptr addrspace(1) %out2, align 4
+  ret void
+}
+
+define void @shrink_i16_load_prefix(ptr addrspace(1) %out,
+                                    ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_i16_load_prefix(
+; CHECK-NOT: load <4 x i16>
+; CHECK: load <2 x i16>, ptr addrspace(4) %p, align 4
+entry:
+  %v = load <4 x i16>, ptr addrspace(4) %p, align 4
+  %e0 = extractelement <4 x i16> %v, i32 0
+  %e1 = extractelement <4 x i16> %v, i32 1
+  store volatile i16 %e0, ptr addrspace(1) %out, align 2
+  %out1 = getelementptr i16, ptr addrspace(1) %out, i32 1
+  store volatile i16 %e1, ptr addrspace(1) %out1, align 2
+  ret void
+}
+
+define void @shrink_i64_load_to_i32_chunks(ptr addrspace(1) %out,
+                                           ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_i64_load_to_i32_chunks(
+; CHECK-NOT: load <6 x i64>
+; CHECK: [[L0:%.*]] = load <3 x i32>, ptr addrspace(4) %p, align 8{{$}}
+; CHECK: [[P1:%.*]] = getelementptr i8, ptr addrspace(4) %p, i64 16
+; CHECK: [[L1:%.*]] = load <3 x i32>, ptr addrspace(4) [[P1]], align 8{{$}}
+; CHECK: [[P2:%.*]] = getelementptr i8, ptr addrspace(4) %p, i64 32
+; CHECK: [[L2:%.*]] = load <3 x i32>, ptr addrspace(4) [[P2]], align 8{{$}}
+; CHECK: extractelement <3 x i32> [[L0]], i32 0
+; CHECK: extractelement <3 x i32> [[L0]], i32 1
+; CHECK: extractelement <3 x i32> [[L0]], i32 2
+; CHECK: extractelement <3 x i32> [[L1]], i32 0
+; CHECK: extractelement <3 x i32> [[L1]], i32 1
+; CHECK: extractelement <3 x i32> [[L1]], i32 2
+; CHECK: extractelement <3 x i32> [[L2]], i32 0
+; CHECK: extractelement <3 x i32> [[L2]], i32 1
+; CHECK: extractelement <3 x i32> [[L2]], i32 2
+entry:
+  %v = load <6 x i64>, ptr addrspace(4) %p, align 8, !range !0
+  %e0 = extractelement <6 x i64> %v, i32 0
+  %e1 = extractelement <6 x i64> %v, i32 1
+  %e2 = extractelement <6 x i64> %v, i32 2
+  %e3 = extractelement <6 x i64> %v, i32 3
+  %e4 = extractelement <6 x i64> %v, i32 4
+  %e5 = extractelement <6 x i64> %v, i32 5
+
+  %d0 = trunc i64 %e0 to i32
+  %e0hi = lshr i64 %e0, 32
+  %d1 = trunc i64 %e0hi to i32
+  %d2 = trunc i64 %e1 to i32
+
+  %d4 = trunc i64 %e2 to i32
+  %e2hi = lshr i64 %e2, 32
+  %d5 = trunc i64 %e2hi to i32
+  %d6 = trunc i64 %e3 to i32
+
+  %d8 = trunc i64 %e4 to i32
+  %e4hi = lshr i64 %e4, 32
+  %d9 = trunc i64 %e4hi to i32
+  %d10 = trunc i64 %e5 to i32
+
+  %out0 = getelementptr i32, ptr addrspace(1) %out, i32 0
+  store volatile i32 %d0, ptr addrspace(1) %out0, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %d1, ptr addrspace(1) %out1, align 4
+  %out2 = getelementptr i32, ptr addrspace(1) %out, i32 2
+  store volatile i32 %d2, ptr addrspace(1) %out2, align 4
+  %out4 = getelementptr i32, ptr addrspace(1) %out, i32 4
+  store volatile i32 %d4, ptr addrspace(1) %out4, align 4
+  %out5 = getelementptr i32, ptr addrspace(1) %out, i32 5
+  store volatile i32 %d5, ptr addrspace(1) %out5, align 4
+  %out6 = getelementptr i32, ptr addrspace(1) %out, i32 6
+  store volatile i32 %d6, ptr addrspace(1) %out6, align 4
+  %out8 = getelementptr i32, ptr addrspace(1) %out, i32 8
+  store volatile i32 %d8, ptr addrspace(1) %out8, align 4
+  %out9 = getelementptr i32, ptr addrspace(1) %out, i32 9
+  store volatile i32 %d9, ptr addrspace(1) %out9, align 4
+  %out10 = getelementptr i32, ptr addrspace(1) %out, i32 10
+  store volatile i32 %d10, ptr addrspace(1) %out10, align 4
+  ret void
+}
+
+define void @shrink_float_load_prefix(ptr addrspace(1) %out,
+                                      ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_float_load_prefix(
+; CHECK-NOT: load <4 x float>
+; CHECK: load <3 x float>, ptr addrspace(4) %p, align 8
+entry:
+  %v = load <4 x float>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <4 x float> %v, i32 0
+  %e1 = extractelement <4 x float> %v, i32 1
+  %e2 = extractelement <4 x float> %v, i32 2
+  store volatile float %e0, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr float, ptr addrspace(1) %out, i32 1
+  store volatile float %e1, ptr addrspace(1) %out1, align 4
+  %out2 = getelementptr float, ptr addrspace(1) %out, i32 2
+  store volatile float %e2, ptr addrspace(1) %out2, align 4
+  ret void
+}
+
+define void @do_not_shrink_when_all_bits_are_demanded(ptr addrspace(1) %out,
+                                                      ptr addrspace(4) %p) {
+; CHECK-LABEL: @do_not_shrink_when_all_bits_are_demanded(
+; CHECK: load <2 x i64>, ptr addrspace(4) %p, align 8
+; CHECK-NOT: load <{{[0-9]+}} x i32>
+entry:
+  %v = load <2 x i64>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <2 x i64> %v, i32 0
+  %e1 = extractelement <2 x i64> %v, i32 1
+  %e0lo = trunc i64 %e0 to i32
+  %e0hi64 = lshr i64 %e0, 32
+  %e0hi = trunc i64 %e0hi64 to i32
+  %e1lo = trunc i64 %e1 to i32
+  %e1hi64 = lshr i64 %e1, 32
+  %e1hi = trunc i64 %e1hi64 to i32
+  store volatile i32 %e0lo, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %e0hi, ptr addrspace(1) %out1, align 4
+  %out2 = getelementptr i32, ptr addrspace(1) %out, i32 2
+  store volatile i32 %e1lo, ptr addrspace(1) %out2, align 4
+  %out3 = getelementptr i32, ptr addrspace(1) %out, i32 3
+  store volatile i32 %e1hi, ptr addrspace(1) %out3, align 4
+  ret void
+}
+
+define void @do_not_shrink_to_non_b96_chunks(ptr addrspace(1) %out,
+                                             ptr addrspace(4) %p) {
+; CHECK-LABEL: @do_not_shrink_to_non_b96_chunks(
+; CHECK: load <2 x i64>, ptr addrspace(4) %p, align 8
+; CHECK-NOT: load <{{[0-9]+}} x i32>
+entry:
+  %v = load <2 x i64>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <2 x i64> %v, i32 0
+  %e1 = extractelement <2 x i64> %v, i32 1
+  %e0lo = trunc i64 %e0 to i32
+  %e1lo = trunc i64 %e1 to i32
+  store volatile i32 %e0lo, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %e1lo, ptr addrspace(1) %out1, align 4
+  ret void
+}
+
+define void @shrink_to_single_b64(ptr addrspace(1) %out, ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_to_single_b64(
+; CHECK-NOT: load <2 x i64>
+; CHECK: load <1 x i64>, ptr addrspace(4) %p, align 8
+entry:
+  %v = load <2 x i64>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <2 x i64> %v, i32 0
+  %e0lo = trunc i64 %e0 to i32
+  %e0hi64 = lshr i64 %e0, 32
+  %e0hi = trunc i64 %e0hi64 to i32
+  store volatile i32 %e0lo, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %e0hi, ptr addrspace(1) %out1, align 4
+  ret void
+}
+
+define void @do_not_shrink_volatile_load(ptr addrspace(1) %out,
+                                         ptr addrspace(4) %p) {
+; CHECK-LABEL: @do_not_shrink_volatile_load(
+; CHECK: load volatile <2 x i64>, ptr addrspace(4) %p, align 8
+; CHECK-NOT: load <{{[0-9]+}} x i32>
+entry:
+  %v = load volatile <2 x i64>, ptr addrspace(4) %p, align 8
+  %e0 = extractelement <2 x i64> %v, i32 0
+  %d0 = trunc i64 %e0 to i32
+  store volatile i32 %d0, ptr addrspace(1) %out, align 4
+  ret void
+}
+
+define void @shrink_drops_range_metadata_for_shorter_vector(
+    ptr addrspace(1) %out, ptr addrspace(4) %p) {
+; CHECK-LABEL: @shrink_drops_range_metadata_for_shorter_vector(
+; CHECK: load <1 x i64>, ptr addrspace(4) %p, align 8{{$}}
+entry:
+  %v = load <2 x i64>, ptr addrspace(4) %p, align 8, !range !0
+  %e0 = extractelement <2 x i64> %v, i32 0
+  %e0lo = trunc i64 %e0 to i32
+  %e0hi64 = lshr i64 %e0, 32
+  %e0hi = trunc i64 %e0hi64 to i32
+  store volatile i32 %e0lo, ptr addrspace(1) %out, align 4
+  %out1 = getelementptr i32, ptr addrspace(1) %out, i32 1
+  store volatile i32 %e0hi, ptr addrspace(1) %out1, align 4
----------------
krzysz00 wrote:

Do these stores need to be volatile?

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


More information about the llvm-commits mailing list