blob: b7ec0104a16231606e6a4d03dcb378bb9d6ff2eb [file] [log] [blame] [edit]
; RUN: opt -S -dxil-resource-access %s | FileCheck %s
target triple = "dxil-pc-shadermodel6.4-compute"
; struct S {
; double d;
; uint4 v;
; };
%struct.S = type <{ double, <4 x i32> }>
; struct T {
; uint x;
; S s[16];
; uint y;
; };
%struct.T = type { i32, [16 x %struct.S], i32 }
declare void @i32_user(i32)
declare void @double_user(double)
declare void @half_user(half)
; CHECK-LABEL: define void @load_offset_i32
define void @load_offset_i32(i32 %idx) {
%buffer = call target("dx.RawBuffer", %struct.S, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
;; StructuredBuffer<S> In;
;; In[0].v[idx];
;
; Here we use a GEP to access the vector, even though that isn't necessarily
; what the clang frontend will codegen.
;
; CHECK: [[MUL:%.*]] = mul i32 %idx, 4
; CHECK: [[ADD:%.*]] = add i32 [[MUL]], 8
; CHECK: [[LOAD:%.*]] = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_s_struct.Ss_0_0t(target("dx.RawBuffer", %struct.S, 0, 0) %buffer, i32 0, i32 [[ADD]])
; CHECK: [[VAL:%.*]] = extractvalue { i32, i1 } [[LOAD]], 0
; CHECK: call void @i32_user(i32 [[VAL]])
%ptr = call ptr @llvm.dx.resource.getpointer(
target("dx.RawBuffer", %struct.S, 0, 0) %buffer, i32 0)
%s.i = getelementptr inbounds nuw i8, ptr %ptr, i32 8
%v.i = getelementptr i32, ptr %s.i, i32 %idx
%elt = load i32, ptr %v.i
call void @i32_user(i32 %elt)
;; StructuredBuffer<S> In;
;; In[0].v[idx];
;
; This matches clang's codegen, using extractelement rather than a gep.
;
; CHECK: [[LOAD:%.*]] = call { <4 x i32>, i1 } @llvm.dx.resource.load.rawbuffer.v4i32.tdx.RawBuffer_s_struct.Ss_0_0t(target("dx.RawBuffer", %struct.S, 0, 0) %buffer, i32 0, i32 8)
; CHECK: [[VEC:%.*]] = extractvalue { <4 x i32>, i1 } [[LOAD]], 0
; CHECK: [[VAL:%.*]] = extractelement <4 x i32> [[VEC]], i32 %idx
; CHECK: call void @i32_user(i32 [[VAL]])
%ptr2 = call ptr @llvm.dx.resource.getpointer(
target("dx.RawBuffer", %struct.S, 0, 0) %buffer, i32 0)
%v2.i = getelementptr inbounds nuw i8, ptr %ptr, i32 8
%v2 = load <4 x i32>, ptr %v2.i
%elt2 = extractelement <4 x i32> %v2, i32 %idx
call void @i32_user(i32 %elt2)
ret void
}
; CHECK-LABEL: define void @load_double
define void @load_double(i32 %idx) {
%buffer = call target("dx.RawBuffer", <4 x double>, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
;; StructuredBuffer<double4> In;
;; In[0][idx];
;
; CHECK: [[MUL:%.*]] = mul i32 %idx, 8
; CHECK: [[LOAD:%.*]] = call { double, i1 } @llvm.dx.resource.load.rawbuffer.f64.tdx.RawBuffer_v4f64_0_0t(target("dx.RawBuffer", <4 x double>, 0, 0) %buffer, i32 0, i32 [[MUL]])
; CHECK: [[VAL:%.*]] = extractvalue { double, i1 } [[LOAD]], 0
; CHECK: call void @double_user(double [[VAL]])
%ptr = call ptr @llvm.dx.resource.getpointer(
target("dx.RawBuffer", <4 x double>, 0, 0) %buffer, i32 0)
%v.i = getelementptr double, ptr %ptr, i32 %idx
%v = load double, ptr %v.i
call void @double_user(double %v)
ret void
}
; CHECK-LABEL: define void @load_half
define void @load_half(i32 %idx) {
%buffer = call target("dx.RawBuffer", <4 x half>, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
;; StructuredBuffer<half4> In;
;; In[0][idx];
;
; CHECK: [[MUL:%.*]] = mul i32 %idx, 2
; CHECK: [[LOAD:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_v4f16_0_0t(target("dx.RawBuffer", <4 x half>, 0, 0) %buffer, i32 0, i32 [[MUL]])
; CHECK: [[VAL:%.*]] = extractvalue { half, i1 } [[LOAD]], 0
; CHECK: call void @half_user(half [[VAL]])
%ptr = call ptr @llvm.dx.resource.getpointer(
target("dx.RawBuffer", <4 x half>, 0, 0) %buffer, i32 0)
%v.i = getelementptr half, ptr %ptr, i32 %idx
%v = load half, ptr %v.i
call void @half_user(half %v)
ret void
}
; CHECK-LABEL: define void @load_nested
define void @load_nested(i32 %idx, i32 %arrayidx, i32 %vecidx) {
%buffer = call target("dx.RawBuffer", %struct.T, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
;; StructuredBuffer<T> In;
;; In[idx].s[arrayidx].v[vecidx];
;
; CHECK: [[MUL:%.*]] = mul i32 %arrayidx, 24
; CHECK: [[ADD:%.*]] = add i32 12, [[MUL]]
; CHECK: [[LOAD:%.*]] = call { <4 x i32>, i1 } @llvm.dx.resource.load.rawbuffer.v4i32.tdx.RawBuffer_s_struct.Ts_0_0t(target("dx.RawBuffer", %struct.T, 0, 0) %buffer, i32 %idx, i32 [[ADD]])
; CHECK: [[VEC:%.*]] = extractvalue { <4 x i32>, i1 } [[LOAD]], 0
; CHECK: [[VAL:%.*]] = extractelement <4 x i32> [[VEC]], i32 %vecidx
; CHECK: call void @i32_user(i32 [[VAL]])
%ptr = call ptr @llvm.dx.resource.getpointer(
target("dx.RawBuffer", %struct.T, 0, 0) %buffer, i32 %idx)
%s.i = getelementptr inbounds nuw %struct.S, ptr %ptr, i32 %arrayidx
%v.i = getelementptr inbounds nuw i8, ptr %s.i, i32 12
%v = load <4 x i32>, ptr %v.i
%elt = extractelement <4 x i32> %v, i32 %vecidx
call void @i32_user(i32 %elt)
ret void
}