mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 00:40:14 +00:00
Place load after OpPhi instructions in block. (#2246)
We currently place the load instructions at the start of the basic block that dominates all of the loads. If that basic block contains OpPhi instructions, then this will generate invalid code. We just need to search for a location that comes after all of the OpPhi instructions. Fixes #2204.
This commit is contained in:
parent
71aa48f91d
commit
9e81c337f9
@ -282,6 +282,7 @@ bool CommonUniformElimPass::UniformAccessChainConvert(Function* func) {
|
||||
uint32_t replId;
|
||||
GenACLoadRepl(ptrInst, &newInsts, &replId);
|
||||
inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
|
||||
assert(inst->opcode() != SpvOpPhi);
|
||||
inst = inst->InsertBefore(std::move(newInsts));
|
||||
modified = true;
|
||||
}
|
||||
@ -355,6 +356,10 @@ bool CommonUniformElimPass::CommonUniformLoadElimination(Function* func) {
|
||||
if (mergeBlockId == bp->id()) {
|
||||
mergeBlockId = 0;
|
||||
insertItr = bp->begin();
|
||||
while (insertItr->opcode() == SpvOpPhi) {
|
||||
++insertItr;
|
||||
}
|
||||
|
||||
// Update insertItr until it will not be removed. Without this code,
|
||||
// ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer.
|
||||
while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr;
|
||||
|
@ -1329,6 +1329,60 @@ TEST_F(CommonUniformElimTest, MixedConstantAndNonConstantIndexes) {
|
||||
SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(CommonUniformElimTest, LoadPlacedAfterPhi) {
|
||||
const std::string text = R"(
|
||||
; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
|
||||
; CHECK: OpSelectionMerge [[merge:%\w+]]
|
||||
; CHECK: [[merge]] = OpLabel
|
||||
; CHECK-NEXT: OpPhi
|
||||
; CHECK-NEXT: OpLoad {{%\w+}} [[var]]
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %2 "main"
|
||||
OpExecutionMode %2 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpMemberDecorate %_struct_3 0 Offset 0
|
||||
OpDecorate %_struct_3 Block
|
||||
OpDecorate %4 DescriptorSet 0
|
||||
OpDecorate %4 Binding 0
|
||||
%void = OpTypeVoid
|
||||
%6 = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%false = OpConstantFalse %bool
|
||||
%uint = OpTypeInt 32 0
|
||||
%v2uint = OpTypeVector %uint 2
|
||||
%_struct_3 = OpTypeStruct %v2uint
|
||||
%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
|
||||
%4 = OpVariable %_ptr_Uniform__struct_3 Uniform
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Uniform_uint = OpTypePointer Uniform %uint
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%2 = OpFunction %void None %6
|
||||
%15 = OpLabel
|
||||
OpSelectionMerge %16 None
|
||||
OpBranchConditional %false %17 %16
|
||||
%17 = OpLabel
|
||||
OpBranch %16
|
||||
%16 = OpLabel
|
||||
%18 = OpPhi %bool %false %15 %false %17
|
||||
OpSelectionMerge %19 None
|
||||
OpBranchConditional %false %20 %21
|
||||
%20 = OpLabel
|
||||
%22 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %uint_0
|
||||
%23 = OpLoad %uint %22
|
||||
OpBranch %19
|
||||
%21 = OpLabel
|
||||
OpBranch %19
|
||||
%19 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Disqualifying cases: extensions, decorations, non-logical addressing,
|
||||
|
Loading…
Reference in New Issue
Block a user