Instead of trying to precalculate GEP offsets ahead of time and then process resource accesses based off of these offsets, traverse the GEP chain inline for each access. This makes it easier to get the types correct when translating GEPs for cbuffer and structured buffer accesses, which in turn lets us access individual elements of those structures directly. Fixes #160208, #164517, and #169430
96 lines
3.5 KiB
LLVM
96 lines
3.5 KiB
LLVM
; 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 }
|
|
|
|
; CHECK-LABEL: define void @store_offset_i32
|
|
define void @store_offset_i32(i32 %idx, i32 %data) {
|
|
%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] = data;
|
|
;
|
|
; CHECK: [[MUL:%.*]] = mul i32 %idx, 4
|
|
; CHECK: [[ADD:%.*]] = add i32 [[MUL]], 8
|
|
; CHECK: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_s_struct.Ss_0_0t.i32(target("dx.RawBuffer", %struct.S, 0, 0) %buffer, i32 0, i32 [[ADD]], i32 %data)
|
|
%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
|
|
store i32 %data, ptr %v.i
|
|
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @store_double
|
|
define void @store_double(i32 %idx, double %data) {
|
|
%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] = data;
|
|
;
|
|
; CHECK: [[MUL:%.*]] = mul i32 %idx, 8
|
|
; CHECK: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f64_0_0t.f64(target("dx.RawBuffer", <4 x double>, 0, 0) %buffer, i32 0, i32 [[MUL]], double %data)
|
|
%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
|
|
store double %data, ptr %v.i
|
|
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @store_half
|
|
define void @store_half(i32 %idx, half %data) {
|
|
%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] = data;
|
|
;
|
|
; CHECK: [[MUL:%.*]] = mul i32 %idx, 2
|
|
; CHECK: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_v4f16_0_0t.f16(target("dx.RawBuffer", <4 x half>, 0, 0) %buffer, i32 0, i32 [[MUL]], half %data)
|
|
%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
|
|
store half %data, ptr %v.i
|
|
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: define void @store_nested
|
|
define void @store_nested(i32 %idx, i32 %arrayidx, i32 %vecidx, i32 %data) {
|
|
%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: [[MUL0:%.*]] = mul i32 %vecidx, 4
|
|
; CHECK: [[ADD0:%.*]] = add i32 [[MUL0]], 1
|
|
; CHECK: [[MUL1:%.*]] = mul i32 %arrayidx, 24
|
|
; CHECK: [[ADD1:%.*]] = add i32 [[ADD0]], [[MUL1]]
|
|
; CHECK: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_s_struct.Ts_0_0t.i32(target("dx.RawBuffer", %struct.T, 0, 0) %buffer, i32 %idx, i32 [[ADD1]], i32 %data)
|
|
%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
|
|
%i = getelementptr i32, ptr %v.i, i32 %vecidx
|
|
store i32 %data, ptr %i
|
|
|
|
ret void
|
|
}
|