mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2025-01-12 17:30:15 +00:00
Allow derived access chain without uses in access chain conversion
This commit is contained in:
parent
ab892f7bd6
commit
b02c9a5802
@ -139,7 +139,17 @@ bool LocalAccessChainConvertPass::IsConstantIndexAccessChain(
|
||||
bool LocalAccessChainConvertPass::HasOnlySupportedRefs(uint32_t ptrId) {
|
||||
if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true;
|
||||
analysis::UseList* uses = get_def_use_mgr()->GetUses(ptrId);
|
||||
assert(uses != nullptr);
|
||||
|
||||
if (!uses) {
|
||||
// This is a variable (or access chain to a variable) that has no uses.
|
||||
// We won't encounter loads or stores for this <result-id> per se, but
|
||||
// this <result-id> may be derived from some other variable (or access
|
||||
// chain). Return true here can unblock the access chain conversion of
|
||||
// the root variable. This particular <result-id> won't be touched and
|
||||
// can be handled in dead code elimination.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto u : *uses) {
|
||||
SpvOp op = u.inst->opcode();
|
||||
if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
|
||||
|
@ -30,7 +30,17 @@ const uint32_t kStoreValIdInIdx = 1;
|
||||
bool LocalSingleBlockLoadStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) {
|
||||
if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true;
|
||||
analysis::UseList* uses = get_def_use_mgr()->GetUses(ptrId);
|
||||
assert(uses != nullptr);
|
||||
|
||||
if (!uses) {
|
||||
// This is a variable (or access chain to a variable) that has no uses.
|
||||
// We won't encounter loads or stores for this <result-id> per se, but
|
||||
// this <result-id> may be derived from some other variable (or access
|
||||
// chain). Return true here can unblock the access chain conversion of
|
||||
// the root variable. This particular <result-id> won't be touched and
|
||||
// can be handled in dead code elimination.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto u : *uses) {
|
||||
SpvOp op = u.inst->opcode();
|
||||
if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
|
||||
|
@ -32,7 +32,17 @@ const uint32_t kStoreValIdInIdx = 1;
|
||||
bool LocalSingleStoreElimPass::HasOnlySupportedRefs(uint32_t ptrId) {
|
||||
if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true;
|
||||
analysis::UseList* uses = get_def_use_mgr()->GetUses(ptrId);
|
||||
assert(uses != nullptr);
|
||||
|
||||
if (!uses) {
|
||||
// This is a variable (or access chain to a variable) that has no uses.
|
||||
// We won't encounter loads or stores for this <result-id> per se, but
|
||||
// this <result-id> may be derived from some other variable (or access
|
||||
// chain). Return true here can unblock the access chain conversion of
|
||||
// the root variable. This particular <result-id> won't be touched and
|
||||
// can be handled in dead code elimination.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto u : *uses) {
|
||||
SpvOp op = u.inst->opcode();
|
||||
if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
|
||||
|
@ -656,6 +656,67 @@ OpFunctionEnd
|
||||
assembly, assembly, false, true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
|
||||
// Based on HLSL source code:
|
||||
// struct S {
|
||||
// float f;
|
||||
// };
|
||||
|
||||
// float main(float input : A) : B {
|
||||
// S local = { input };
|
||||
// return local.f;
|
||||
// }
|
||||
|
||||
const std::string predefs = R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %in_var_A %out_var_B
|
||||
OpName %main "main"
|
||||
OpName %in_var_A "in.var.A"
|
||||
OpName %out_var_B "out.var.B"
|
||||
OpName %S "S"
|
||||
OpName %local "local"
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%S = OpTypeStruct %float
|
||||
%_ptr_Function_S = OpTypePointer Function %S
|
||||
%int_0 = OpConstant %int 0
|
||||
%in_var_A = OpVariable %_ptr_Input_float Input
|
||||
%out_var_B = OpVariable %_ptr_Output_float Output
|
||||
%main = OpFunction %void None %8
|
||||
%15 = OpLabel
|
||||
%local = OpVariable %_ptr_Function_S Function
|
||||
%16 = OpLoad %float %in_var_A
|
||||
%17 = OpCompositeConstruct %S %16
|
||||
OpStore %local %17
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%18 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%19 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%20 = OpLoad %float %18
|
||||
OpStore %out_var_B %20
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%19 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%21 = OpLoad %S %local
|
||||
%22 = OpCompositeExtract %float %21 0
|
||||
OpStore %out_var_B %22
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<opt::LocalAccessChainConvertPass>(
|
||||
predefs + before, predefs + after, true, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Assorted vector and matrix types
|
||||
|
Loading…
Reference in New Issue
Block a user