Skip to content

Commit 8d00442

Browse files
authored
opt: allow aggressive DCE to optimize untyped_pointers (KhronosGroup#6602)
This will be required to allow DXC generating descriptor heaps code which uses untyped pointers/descriptor_heap
1 parent e4bceac commit 8d00442

5 files changed

Lines changed: 210 additions & 4 deletions

File tree

source/opt/aggressive_dead_code_elim_pass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ void AggressiveDCEPass::AddStores(Function* func, uint32_t ptrId) {
128128
switch (user->opcode()) {
129129
case spv::Op::OpAccessChain:
130130
case spv::Op::OpInBoundsAccessChain:
131+
case spv::Op::OpUntypedAccessChainKHR:
131132
case spv::Op::OpCopyObject:
132133
this->AddStores(func, user->result_id());
133134
break;
@@ -1123,6 +1124,7 @@ void AggressiveDCEPass::InitExtensions() {
11231124
"SPV_EXT_demote_to_helper_invocation",
11241125
"SPV_EXT_descriptor_indexing",
11251126
"SPV_EXT_descriptor_heap",
1127+
"SPV_KHR_untyped_pointers",
11261128
"SPV_NV_fragment_shader_barycentric",
11271129
"SPV_NV_compute_shader_derivatives",
11281130
"SPV_NV_shader_image_footprint",

source/opt/instruction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ Instruction* Instruction::GetBaseAddress() const {
252252
switch (base_inst->opcode()) {
253253
case spv::Op::OpAccessChain:
254254
case spv::Op::OpInBoundsAccessChain:
255+
case spv::Op::OpUntypedAccessChainKHR:
255256
case spv::Op::OpPtrAccessChain:
256257
case spv::Op::OpInBoundsPtrAccessChain:
257258
case spv::Op::OpImageTexelPointer:

source/opt/ir_context.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ void IRContext::AddCombinatorsForCapability(uint32_t capability) {
580580
(uint32_t)spv::Op::OpTypeStruct,
581581
(uint32_t)spv::Op::OpTypeOpaque,
582582
(uint32_t)spv::Op::OpTypePointer,
583+
(uint32_t)spv::Op::OpTypeUntypedPointerKHR,
583584
(uint32_t)spv::Op::OpTypeFunction,
584585
(uint32_t)spv::Op::OpTypeEvent,
585586
(uint32_t)spv::Op::OpTypeDeviceEvent,
@@ -588,10 +589,12 @@ void IRContext::AddCombinatorsForCapability(uint32_t capability) {
588589
(uint32_t)spv::Op::OpTypePipe,
589590
(uint32_t)spv::Op::OpTypeForwardPointer,
590591
(uint32_t)spv::Op::OpVariable,
592+
(uint32_t)spv::Op::OpUntypedVariableKHR,
591593
(uint32_t)spv::Op::OpImageTexelPointer,
592594
(uint32_t)spv::Op::OpLoad,
593595
(uint32_t)spv::Op::OpAccessChain,
594596
(uint32_t)spv::Op::OpInBoundsAccessChain,
597+
(uint32_t)spv::Op::OpUntypedAccessChainKHR,
595598
(uint32_t)spv::Op::OpArrayLength,
596599
(uint32_t)spv::Op::OpVectorExtractDynamic,
597600
(uint32_t)spv::Op::OpVectorInsertDynamic,

source/opt/mem_pass.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ bool MemPass::IsTargetType(const Instruction* typeInst) const {
7272

7373
bool MemPass::IsNonPtrAccessChain(const spv::Op opcode) const {
7474
return opcode == spv::Op::OpAccessChain ||
75-
opcode == spv::Op::OpInBoundsAccessChain;
75+
opcode == spv::Op::OpInBoundsAccessChain ||
76+
opcode == spv::Op::OpUntypedAccessChainKHR;
7677
}
7778

7879
bool MemPass::IsPtr(uint32_t ptrId) {
@@ -88,11 +89,14 @@ bool MemPass::IsPtr(uint32_t ptrId) {
8889
ptrInst = get_def_use_mgr()->GetDef(varId);
8990
}
9091
const spv::Op op = ptrInst->opcode();
91-
if (op == spv::Op::OpVariable || IsNonPtrAccessChain(op)) return true;
92+
if (op == spv::Op::OpVariable || op == spv::Op::OpUntypedVariableKHR ||
93+
IsNonPtrAccessChain(op))
94+
return true;
9295
const uint32_t varTypeId = ptrInst->type_id();
9396
if (varTypeId == 0) return false;
9497
const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
95-
return varTypeInst->opcode() == spv::Op::OpTypePointer;
98+
return varTypeInst->opcode() == spv::Op::OpTypePointer ||
99+
varTypeInst->opcode() == spv::Op::OpTypeUntypedPointerKHR;
96100
}
97101

98102
Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) {
@@ -102,11 +106,13 @@ Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) {
102106

103107
switch (ptrInst->opcode()) {
104108
case spv::Op::OpVariable:
109+
case spv::Op::OpUntypedVariableKHR:
105110
case spv::Op::OpFunctionParameter:
106111
varInst = ptrInst;
107112
break;
108113
case spv::Op::OpAccessChain:
109114
case spv::Op::OpInBoundsAccessChain:
115+
case spv::Op::OpUntypedAccessChainKHR:
110116
case spv::Op::OpPtrAccessChain:
111117
case spv::Op::OpInBoundsPtrAccessChain:
112118
case spv::Op::OpImageTexelPointer:
@@ -119,7 +125,8 @@ Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) {
119125
break;
120126
}
121127

122-
if (varInst->opcode() == spv::Op::OpVariable) {
128+
if (varInst->opcode() == spv::Op::OpVariable ||
129+
varInst->opcode() == spv::Op::OpUntypedVariableKHR) {
123130
*varId = varInst->result_id();
124131
} else {
125132
*varId = 0;

test/opt/aggressive_dead_code_elim_test.cpp

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9025,6 +9025,199 @@ TEST_F(AggressiveDCETest, DebugValueWithDeadOperandKeepsDebugScope) {
90259025
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
90269026
}
90279027

9028+
TEST_F(AggressiveDCETest, EliminateUntypedAccessChain) {
9029+
const std::string spirv = R"(
9030+
OpCapability Shader
9031+
OpCapability Sampled1D
9032+
OpCapability DescriptorHeapEXT
9033+
OpCapability UntypedPointersKHR
9034+
OpExtension "SPV_EXT_descriptor_heap"
9035+
OpExtension "SPV_KHR_untyped_pointers"
9036+
OpMemoryModel Logical GLSL450
9037+
OpEntryPoint Fragment %main "main"
9038+
OpExecutionMode %main OriginUpperLeft
9039+
OpName %main "main"
9040+
%uint = OpTypeInt 32 0
9041+
%uint_0 = OpConstant %uint 0
9042+
%type_untyped_pointer = OpTypeUntypedPointerKHR Uniform
9043+
%void = OpTypeVoid
9044+
%float = OpTypeFloat 32
9045+
%10 = OpTypeFunction %void
9046+
%type_1d_image = OpTypeImage %float 1D 2 0 0 1 Unknown
9047+
%_ptr_Function_type_1d_image = OpTypePointer Function %type_1d_image
9048+
%type_buffer_ext = OpTypeBufferEXT StorageBuffer
9049+
%_runtimearr_type_buffer_ext = OpTypeRuntimeArray %type_buffer_ext
9050+
%resource_heap = OpUntypedVariableKHR %type_untyped_pointer Uniform
9051+
%main = OpFunction %void None %10
9052+
%20 = OpLabel
9053+
%t1d = OpVariable %_ptr_Function_type_1d_image Function
9054+
; CHECK-NOT: OpUntypedAccessChainKHR
9055+
%21 = OpUntypedAccessChainKHR %type_untyped_pointer %_runtimearr_type_buffer_ext %resource_heap %uint_0
9056+
; CHECK-NOT: OpLoad %type_1d_image
9057+
%22 = OpLoad %type_1d_image %21
9058+
; CHECK-NOT: OpStore %t1d
9059+
OpStore %t1d %22
9060+
OpReturn
9061+
OpFunctionEnd
9062+
)";
9063+
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
9064+
}
9065+
9066+
TEST_F(AggressiveDCETest, NoEliminateLiveUntypedAccessChain) {
9067+
const std::string spirv = R"(
9068+
OpCapability Shader
9069+
OpCapability DescriptorHeapEXT
9070+
OpCapability UntypedPointersKHR
9071+
OpExtension "SPV_EXT_descriptor_heap"
9072+
OpExtension "SPV_KHR_untyped_pointers"
9073+
OpMemoryModel Logical GLSL450
9074+
OpEntryPoint Fragment %main "main" %outColor
9075+
OpExecutionMode %main OriginUpperLeft
9076+
OpName %main "main"
9077+
%uint = OpTypeInt 32 0
9078+
%uint_0 = OpConstant %uint 0
9079+
%type_untyped_pointer = OpTypeUntypedPointerKHR Uniform
9080+
%void = OpTypeVoid
9081+
%float = OpTypeFloat 32
9082+
%v4float = OpTypeVector %float 4
9083+
%_ptr_Output_v4float = OpTypePointer Output %v4float
9084+
%outColor = OpVariable %_ptr_Output_v4float Output
9085+
%10 = OpTypeFunction %void
9086+
%type_buffer_ext = OpTypeBufferEXT StorageBuffer
9087+
%_runtimearr_type_buffer_ext = OpTypeRuntimeArray %type_buffer_ext
9088+
%resource_heap = OpUntypedVariableKHR %type_untyped_pointer Uniform
9089+
%main = OpFunction %void None %10
9090+
%20 = OpLabel
9091+
; CHECK: OpUntypedAccessChainKHR
9092+
%21 = OpUntypedAccessChainKHR %type_untyped_pointer %_runtimearr_type_buffer_ext %resource_heap %uint_0
9093+
; CHECK: OpLoad
9094+
%22 = OpLoad %v4float %21
9095+
OpStore %outColor %22
9096+
OpReturn
9097+
OpFunctionEnd
9098+
)";
9099+
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
9100+
}
9101+
9102+
TEST_F(AggressiveDCETest, EliminateUntypedAccessChainWithCopyObject) {
9103+
const std::string spirv = R"(
9104+
OpCapability Shader
9105+
OpCapability Sampled1D
9106+
OpCapability DescriptorHeapEXT
9107+
OpCapability UntypedPointersKHR
9108+
OpExtension "SPV_EXT_descriptor_heap"
9109+
OpExtension "SPV_KHR_untyped_pointers"
9110+
OpMemoryModel Logical GLSL450
9111+
OpEntryPoint Fragment %main "main"
9112+
OpExecutionMode %main OriginUpperLeft
9113+
OpName %main "main"
9114+
OpName %type_1d_image "type_1d_image"
9115+
%uint = OpTypeInt 32 0
9116+
%uint_0 = OpConstant %uint 0
9117+
%type_untyped_pointer = OpTypeUntypedPointerKHR Uniform
9118+
%void = OpTypeVoid
9119+
%float = OpTypeFloat 32
9120+
%10 = OpTypeFunction %void
9121+
%type_1d_image = OpTypeImage %float 1D 2 0 0 1 Unknown
9122+
%_ptr_Function_type_1d_image = OpTypePointer Function %type_1d_image
9123+
%type_buffer_ext = OpTypeBufferEXT StorageBuffer
9124+
%_runtimearr_type_buffer_ext = OpTypeRuntimeArray %type_buffer_ext
9125+
%resource_heap = OpUntypedVariableKHR %type_untyped_pointer Uniform
9126+
%main = OpFunction %void None %10
9127+
%20 = OpLabel
9128+
%t1d = OpVariable %_ptr_Function_type_1d_image Function
9129+
; CHECK-NOT: OpUntypedAccessChainKHR
9130+
%21 = OpUntypedAccessChainKHR %type_untyped_pointer %_runtimearr_type_buffer_ext %resource_heap %uint_0
9131+
; CHECK-NOT: OpCopyObject
9132+
%22 = OpCopyObject %type_untyped_pointer %21
9133+
; CHECK-NOT: OpLoad %type_1d_image
9134+
%23 = OpLoad %type_1d_image %22
9135+
; CHECK-NOT: OpStore %t1d
9136+
OpStore %t1d %23
9137+
OpReturn
9138+
OpFunctionEnd
9139+
)";
9140+
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
9141+
}
9142+
9143+
// For now, aggressive DCE does not optimizes this pattern. If you implement
9144+
// it, remove this test.
9145+
TEST_F(AggressiveDCETest, EliminateUntypedAtomic) {
9146+
const std::string spirv = R"(
9147+
OpCapability Shader
9148+
OpCapability Int64
9149+
OpCapability DescriptorHeapEXT
9150+
OpCapability UntypedPointersKHR
9151+
OpExtension "SPV_EXT_descriptor_heap"
9152+
OpExtension "SPV_KHR_untyped_pointers"
9153+
OpMemoryModel Logical GLSL450
9154+
OpEntryPoint Fragment %main "main"
9155+
OpExecutionMode %main OriginUpperLeft
9156+
%uint = OpTypeInt 32 0
9157+
%uint_0 = OpConstant %uint 0
9158+
%type_untyped_pointer = OpTypeUntypedPointerKHR Uniform
9159+
%void = OpTypeVoid
9160+
%10 = OpTypeFunction %void
9161+
%type_buffer_ext = OpTypeBufferEXT StorageBuffer
9162+
%_runtimearr_type_buffer_ext = OpTypeRuntimeArray %type_buffer_ext
9163+
%resource_heap = OpUntypedVariableKHR %type_untyped_pointer Uniform
9164+
%main = OpFunction %void None %10
9165+
%20 = OpLabel
9166+
%21 = OpUntypedAccessChainKHR %type_untyped_pointer %_runtimearr_type_buffer_ext %resource_heap %uint_0
9167+
; CHECK: [[ptr:%\w+]] = OpUntypedAccessChainKHR
9168+
%22 = OpAtomicLoad %uint %21 %uint_0 %uint_0
9169+
; CHECK: OpAtomicLoad %uint [[ptr]]
9170+
OpReturn
9171+
OpFunctionEnd
9172+
)";
9173+
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
9174+
}
9175+
9176+
TEST_F(AggressiveDCETest, EliminateUntypedAccessChainLoop) {
9177+
const std::string spirv = R"(
9178+
OpCapability Shader
9179+
OpCapability Sampled1D
9180+
OpCapability DescriptorHeapEXT
9181+
OpCapability UntypedPointersKHR
9182+
OpExtension "SPV_EXT_descriptor_heap"
9183+
OpExtension "SPV_KHR_untyped_pointers"
9184+
OpMemoryModel Logical GLSL450
9185+
OpEntryPoint Fragment %main "main"
9186+
OpExecutionMode %main OriginUpperLeft
9187+
%uint = OpTypeInt 32 0
9188+
%uint_0 = OpConstant %uint 0
9189+
%uint_1 = OpConstant %uint 1
9190+
%uint_10 = OpConstant %uint 10
9191+
%type_untyped_pointer = OpTypeUntypedPointerKHR Uniform
9192+
%void = OpTypeVoid
9193+
%bool = OpTypeBool
9194+
%10 = OpTypeFunction %void
9195+
%type_1d_image = OpTypeImage %uint 1D 2 0 0 1 Unknown
9196+
%type_buffer_ext = OpTypeBufferEXT StorageBuffer
9197+
%_runtimearr_type_buffer_ext = OpTypeRuntimeArray %type_buffer_ext
9198+
%resource_heap = OpUntypedVariableKHR %type_untyped_pointer Uniform
9199+
%main = OpFunction %void None %10
9200+
%20 = OpLabel
9201+
OpBranch %header
9202+
%header = OpLabel
9203+
%count = OpPhi %uint %uint_0 %20 %next %loop
9204+
%cond = OpULessThan %bool %count %uint_10
9205+
OpLoopMerge %exit %loop None
9206+
OpBranchConditional %cond %loop %exit
9207+
%loop = OpLabel
9208+
; CHECK-NOT: OpUntypedAccessChainKHR
9209+
%21 = OpUntypedAccessChainKHR %type_untyped_pointer %_runtimearr_type_buffer_ext %resource_heap %count
9210+
; CHECK-NOT: OpLoad
9211+
%22 = OpLoad %type_1d_image %21
9212+
%next = OpIAdd %uint %count %uint_1
9213+
OpBranch %header
9214+
%exit = OpLabel
9215+
OpReturn
9216+
OpFunctionEnd
9217+
)";
9218+
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
9219+
}
9220+
90289221
} // namespace
90299222
} // namespace opt
90309223
} // namespace spvtools

0 commit comments

Comments
 (0)