Files
clang-p2996/llvm/test/CodeGen/NVPTX/vector-loads.ll
Alex MacLean 76c9bfefa4 [NVPTX] Remove Float register classes (#140487)
These classes are redundant, as the untyped "Int" classes can be used
for all float operations. This change is intended to be as minimal as
possible and leaves the many potential simplifications and refactors
this exposes as future work.
2025-05-21 11:33:57 -07:00

210 lines
6.4 KiB
LLVM

; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_20 | FileCheck %s
; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64 -mcpu=sm_20 | %ptxas-verify %}
; Even though general vector types are not supported in PTX, we can still
; optimize loads/stores with pseudo-vector instructions of the form:
;
; ld.v2.f32 {%r0, %r1}, [%r0]
;
; which will load two floats at once into scalar registers.
; CHECK-LABEL: foo
define void @foo(ptr %a) {
; CHECK: ld.v2.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <2 x float>, ptr %a
%t2 = fmul <2 x float> %t1, %t1
store <2 x float> %t2, ptr %a
ret void
}
; CHECK-LABEL: foo2
define void @foo2(ptr %a) {
; CHECK: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <4 x float>, ptr %a
%t2 = fmul <4 x float> %t1, %t1
store <4 x float> %t2, ptr %a
ret void
}
; CHECK-LABEL: foo3
define void @foo3(ptr %a) {
; CHECK: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
; CHECK-NEXT: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <8 x float>, ptr %a
%t2 = fmul <8 x float> %t1, %t1
store <8 x float> %t2, ptr %a
ret void
}
; CHECK-LABEL: foo4
define void @foo4(ptr %a) {
; CHECK: ld.v2.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <2 x i32>, ptr %a
%t2 = mul <2 x i32> %t1, %t1
store <2 x i32> %t2, ptr %a
ret void
}
; CHECK-LABEL: foo5
define void @foo5(ptr %a) {
; CHECK: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <4 x i32>, ptr %a
%t2 = mul <4 x i32> %t1, %t1
store <4 x i32> %t2, ptr %a
ret void
}
; CHECK-LABEL: foo6
define void @foo6(ptr %a) {
; CHECK: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
; CHECK-NEXT: ld.v4.b32 {%r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}}
%t1 = load <8 x i32>, ptr %a
%t2 = mul <8 x i32> %t1, %t1
store <8 x i32> %t2, ptr %a
ret void
}
; The following test wasn't passing previously as the address
; computation was still too complex when LSV was called.
declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() #0
declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() #0
; CHECK-LABEL: foo_complex
define void @foo_complex(ptr nocapture readonly align 16 dereferenceable(134217728) %alloc0) {
%t0 = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x(), !range !1
%t1 = tail call i32 @llvm.nvvm.read.ptx.sreg.ctaid.x()
%t2 = lshr i32 %t1, 8
%t3 = shl nuw nsw i32 %t1, 9
%ttile_origin.2 = and i32 %t3, 130560
%tstart_offset_x_mul = shl nuw nsw i32 %t0, 1
%t4 = or disjoint i32 %ttile_origin.2, %tstart_offset_x_mul
%t6 = or disjoint i32 %t4, 1
%t8 = or disjoint i32 %t4, 128
%t9 = zext i32 %t8 to i64
%t10 = or disjoint i32 %t4, 129
%t11 = zext i32 %t10 to i64
%t20 = zext i32 %t2 to i64
%t27 = getelementptr inbounds [1024 x [131072 x i8]], ptr %alloc0, i64 0, i64 %t20, i64 %t9
; CHECK: ld.v2.b8
%t28 = load i8, ptr %t27, align 2
%t31 = getelementptr inbounds [1024 x [131072 x i8]], ptr %alloc0, i64 0, i64 %t20, i64 %t11
%t32 = load i8, ptr %t31, align 1
%t33 = icmp ult i8 %t28, %t32
%t34 = select i1 %t33, i8 %t32, i8 %t28
store i8 %t34, ptr %t31
; CHECK: ret
ret void
}
; CHECK-LABEL: extv8f16_global_a16(
define void @extv8f16_global_a16(ptr addrspace(1) noalias readonly align 16 %dst, ptr addrspace(1) noalias readonly align 16 %src) #0 {
; CHECK: ld.global.v4.b32 {%r
%v = load <8 x half>, ptr addrspace(1) %src, align 16
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
%ext = fpext <8 x half> %v to <8 x float>
; CHECK: st.global.v4.b32
; CHECK: st.global.v4.b32
store <8 x float> %ext, ptr addrspace(1) %dst, align 16
ret void
}
; CHECK-LABEL: extv8f16_global_a4(
define void @extv8f16_global_a4(ptr addrspace(1) noalias readonly align 16 %dst, ptr addrspace(1) noalias readonly align 16 %src) #0 {
; CHECK: ld.global.b32 %r
; CHECK: ld.global.b32 %r
; CHECK: ld.global.b32 %r
; CHECK: ld.global.b32 %r
%v = load <8 x half>, ptr addrspace(1) %src, align 4
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
%ext = fpext <8 x half> %v to <8 x float>
; CHECK: st.global.v4.b32
; CHECK: st.global.v4.b32
store <8 x float> %ext, ptr addrspace(1) %dst, align 16
ret void
}
; CHECK-LABEL: extv8f16_generic_a16(
define void @extv8f16_generic_a16(ptr noalias readonly align 16 %dst, ptr noalias readonly align 16 %src) #0 {
; CHECK: ld.v4.b32 {%r
%v = load <8 x half>, ptr %src, align 16
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
%ext = fpext <8 x half> %v to <8 x float>
; CHECK: st.v4.b32
; CHECK: st.v4.b32
store <8 x float> %ext, ptr %dst, align 16
ret void
}
; CHECK-LABEL: extv8f16_generic_a4(
define void @extv8f16_generic_a4(ptr noalias readonly align 16 %dst, ptr noalias readonly align 16 %src) #0 {
; CHECK: ld.b32 %r
; CHECK: ld.b32 %r
; CHECK: ld.b32 %r
; CHECK: ld.b32 %r
%v = load <8 x half>, ptr %src, align 4
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: mov.b32 {%rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
; CHECK: cvt.f32.f16 %r{{.*}}, %rs
%ext = fpext <8 x half> %v to <8 x float>
; CHECK: st.v4.b32
; CHECK: st.v4.b32
store <8 x float> %ext, ptr %dst, align 16
ret void
}
!1 = !{i32 0, i32 64}
; CHECK-LABEL: bf16_v4_align_load_store
define dso_local void @bf16_v4_align_load_store(ptr noundef %0, ptr noundef %1) #0 {
; CHECK: ld.v4.b16
; CHECK: st.v4.b16
%3 = load <4 x bfloat>, ptr %1, align 8
store <4 x bfloat> %3, ptr %0, align 8
ret void
}