mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Teach array copy propagation about OpImageTexelPointer.
OpImageTexelPointer acts like a special kind of load. It is not an array load, but it also cannot be removed the same way a regular load can. The type of propagation that needs to be done is similar to what we do for arrays, so I want to merge that code into that optmization. Contributers to #1445.
This commit is contained in:
parent
e64a4656b3
commit
c33af63264
@ -134,6 +134,10 @@ ir::Instruction* CopyPropagateArrays::BuildNewAccessChain(
|
||||
ir::IRContext::kAnalysisDefUse |
|
||||
ir::IRContext::kAnalysisInstrToBlockMapping);
|
||||
|
||||
if (source->AccessChain().size() == 0) {
|
||||
return source->GetVariable();
|
||||
}
|
||||
|
||||
return builder.AddAccessChain(source->GetPointerTypeId(),
|
||||
source->GetVariable()->result_id(),
|
||||
source->AccessChain());
|
||||
@ -150,6 +154,8 @@ bool CopyPropagateArrays::HasNoStores(ir::Instruction* ptr_inst) {
|
||||
return true;
|
||||
} else if (use->opcode() == SpvOpStore) {
|
||||
return false;
|
||||
} else if (use->opcode() == SpvOpImageTexelPointer) {
|
||||
return true;
|
||||
}
|
||||
// Some other instruction. Be conservative.
|
||||
return false;
|
||||
@ -165,7 +171,8 @@ bool CopyPropagateArrays::HasValidReferencesOnly(ir::Instruction* ptr_inst,
|
||||
return get_def_use_mgr()->WhileEachUser(
|
||||
ptr_inst,
|
||||
[this, store_inst, dominator_analysis, ptr_inst](ir::Instruction* use) {
|
||||
if (use->opcode() == SpvOpLoad) {
|
||||
if (use->opcode() == SpvOpLoad ||
|
||||
use->opcode() == SpvOpImageTexelPointer) {
|
||||
// TODO: If there are many load in the same BB as |store_inst| the
|
||||
// time to do the multiple traverses can add up. Consider collecting
|
||||
// those loads and doing a single traversal.
|
||||
@ -455,7 +462,8 @@ bool CopyPropagateArrays::IsPointerToArrayType(uint32_t type_id) {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::Pointer* pointer_type = type_mgr->GetType(type_id)->AsPointer();
|
||||
if (pointer_type) {
|
||||
return pointer_type->pointee_type()->AsArray() != nullptr;
|
||||
return pointer_type->pointee_type()->kind() == analysis::Type::kArray ||
|
||||
pointer_type->pointee_type()->kind() == analysis::Type::kImage;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -544,6 +552,8 @@ bool CopyPropagateArrays::CanUpdateUses(ir::Instruction* original_ptr_inst,
|
||||
// TODO (s-perron): This can be handled by expanding the store into
|
||||
// a series of extracts, composite constructs, and a store.
|
||||
return true;
|
||||
case SpvOpImageTexelPointer:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -673,7 +683,16 @@ void CopyPropagateArrays::UpdateUses(ir::Instruction* original_ptr_inst,
|
||||
context()->AnalyzeUses(use);
|
||||
}
|
||||
break;
|
||||
case SpvOpImageTexelPointer:
|
||||
// We treat an OpImageTexelPointer as a load. The result type should
|
||||
// always have the Image storage class, and should not need to be
|
||||
// updated.
|
||||
|
||||
// Replace the actual use.
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
context()->AnalyzeUses(use);
|
||||
break;
|
||||
default:
|
||||
assert(false && "Don't know how to rewrite instruction");
|
||||
break;
|
||||
|
@ -22,8 +22,8 @@
|
||||
namespace {
|
||||
|
||||
using namespace spvtools;
|
||||
using ir::IRContext;
|
||||
using ir::Instruction;
|
||||
using ir::IRContext;
|
||||
using opt::PassManager;
|
||||
|
||||
using CopyPropArrayPassTest = PassTest<::testing::Test>;
|
||||
@ -1025,4 +1025,80 @@ OpFunctionEnd
|
||||
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
|
||||
}
|
||||
|
||||
TEST_F(CopyPropArrayPassTest, AtomicAdd) {
|
||||
const std::string before = R"(OpCapability SampledBuffer
|
||||
OpCapability StorageImageExtendedFormats
|
||||
OpCapability ImageBuffer
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
|
||||
OpExecutionMode %2 LocalSize 64 1 1
|
||||
OpSource HLSL 600
|
||||
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
|
||||
OpDecorate %4 DescriptorSet 4
|
||||
OpDecorate %4 Binding 70
|
||||
%uint = OpTypeInt 32 0
|
||||
%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
|
||||
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||
%_ptr_Function_6 = OpTypePointer Function %6
|
||||
%void = OpTypeVoid
|
||||
%10 = OpTypeFunction %void
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
||||
%_ptr_Image_uint = OpTypePointer Image %uint
|
||||
%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
||||
%2 = OpFunction %void None %10
|
||||
%17 = OpLabel
|
||||
%16 = OpVariable %_ptr_Function_6 Function
|
||||
%18 = OpLoad %6 %4
|
||||
OpStore %16 %18
|
||||
%19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
|
||||
%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after = R"(OpCapability SampledBuffer
|
||||
OpCapability StorageImageExtendedFormats
|
||||
OpCapability ImageBuffer
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
|
||||
OpExecutionMode %2 LocalSize 64 1 1
|
||||
OpSource HLSL 600
|
||||
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
|
||||
OpDecorate %4 DescriptorSet 4
|
||||
OpDecorate %4 Binding 70
|
||||
%uint = OpTypeInt 32 0
|
||||
%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
|
||||
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||
%_ptr_Function_6 = OpTypePointer Function %6
|
||||
%void = OpTypeVoid
|
||||
%10 = OpTypeFunction %void
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
||||
%_ptr_Image_uint = OpTypePointer Image %uint
|
||||
%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
||||
%2 = OpFunction %void None %10
|
||||
%17 = OpLabel
|
||||
%16 = OpVariable %_ptr_Function_6 Function
|
||||
%18 = OpLoad %6 %4
|
||||
OpStore %16 %18
|
||||
%19 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
|
||||
%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<opt::CopyPropagateArrays>(before, after, true, true);
|
||||
}
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user