Accept OpImageTexelPointer user in scalar-replacement (#4187)

We have to conduct the scalar replacement for an aggregate with an image
type even when it has OpImageTexelPointer users.
This commit is contained in:
Jaebaek Seo 2021-03-16 16:40:51 -04:00 committed by GitHub
parent 042eff73fe
commit 79ab273f99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 0 deletions

View File

@ -861,6 +861,9 @@ bool ScalarReplacementPass::CheckUsesRelaxed(const Instruction* inst) const {
case SpvOpStore: case SpvOpStore:
if (!CheckStore(user, index)) ok = false; if (!CheckStore(user, index)) ok = false;
break; break;
case SpvOpImageTexelPointer:
if (!CheckImageTexelPointer(index)) ok = false;
break;
default: default:
ok = false; ok = false;
break; break;
@ -870,6 +873,10 @@ bool ScalarReplacementPass::CheckUsesRelaxed(const Instruction* inst) const {
return ok; return ok;
} }
bool ScalarReplacementPass::CheckImageTexelPointer(uint32_t index) const {
return index == 2u;
}
bool ScalarReplacementPass::CheckLoad(const Instruction* inst, bool ScalarReplacementPass::CheckLoad(const Instruction* inst,
uint32_t index) const { uint32_t index) const {
if (index != 2u) return false; if (index != 2u) return false;

View File

@ -142,6 +142,10 @@ class ScalarReplacementPass : public Pass {
// of |inst| and the store is not to volatile memory. // of |inst| and the store is not to volatile memory.
bool CheckStore(const Instruction* inst, uint32_t index) const; bool CheckStore(const Instruction* inst, uint32_t index) const;
// Returns true if |index| is the pointer operand of an OpImageTexelPointer
// instruction.
bool CheckImageTexelPointer(uint32_t index) const;
// Creates a variable of type |typeId| from the |index|'th element of // Creates a variable of type |typeId| from the |index|'th element of
// |varInst|. The new variable is added to |replacements|. If the variable // |varInst|. The new variable is added to |replacements|. If the variable
// could not be created, then |nullptr| is appended to |replacements|. // could not be created, then |nullptr| is appended to |replacements|.

View File

@ -2197,6 +2197,46 @@ OpFunctionEnd
SinglePassRunAndMatch<ScalarReplacementPass>(text, true); SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
} }
TEST_F(ScalarReplacementTest, ImageTexelPointer) {
// Test whether the scalar replacement correctly checks the
// OpImageTexelPointer user of an aggregate with an image type.
const std::string text = R"(
;
; CHECK: [[imgTy:%\w+]] = OpTypeImage %uint Buffer 2 0 0 2 R32ui
; CHECK: [[ptrImgTy:%\w+]] = OpTypePointer Function [[imgTy]]
; CHECK: [[img:%\w+]] = OpVariable [[ptrImgTy]] Function
; CHECK: [[imgTexelPtr:%\w+]] = OpImageTexelPointer {{%\w+}} [[img]] %uint_0 %uint_0
; CHECK: OpAtomicIAdd %uint [[imgTexelPtr]] %uint_1 %uint_0 %uint_1
;
OpCapability Shader
OpCapability SampledBuffer
OpCapability ImageBuffer
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %1 "main"
OpExecutionMode %1 LocalSize 64 1 1
%void = OpTypeVoid
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%_ptr_Image_uint = OpTypePointer Image %uint
%type_buffer_image = OpTypeImage %uint Buffer 2 0 0 2 R32ui
%_ptr_Function_type_buffer_image = OpTypePointer Function %type_buffer_image
%image_struct = OpTypeStruct %type_buffer_image %type_buffer_image
%_ptr_Function_image_struct = OpTypePointer Function %image_struct
%func = OpTypeFunction %void
%1 = OpFunction %void None %func
%2 = OpLabel
%3 = OpVariable %_ptr_Function_image_struct Function
%4 = OpAccessChain %_ptr_Function_type_buffer_image %3 %uint_1
%5 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
%6 = OpAtomicIAdd %uint %5 %uint_1 %uint_0 %uint_1
OpReturn
OpFunctionEnd
)";
SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
}
} // namespace } // namespace
} // namespace opt } // namespace opt
} // namespace spvtools } // namespace spvtools