Add store for var initializer in inlining.

Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1591.
This commit is contained in:
Steven Perron 2018-05-31 20:28:19 -04:00
parent badcf73d00
commit 9a008835f4
2 changed files with 91 additions and 1 deletions

View File

@ -286,9 +286,20 @@ void InlinePass::GenInlineCode(
switch (cpi->opcode()) {
case SpvOpFunction:
case SpvOpFunctionParameter:
case SpvOpVariable:
// Already processed
break;
case SpvOpVariable:
if (cpi->NumInOperands() == 2) {
assert(callee2caller.count(cpi->result_id()) &&
"Expected the variable to have already been mapped.");
uint32_t new_var_id = callee2caller.at(cpi->result_id());
// The initializer must be a constant or global value. No mapped
// should be used.
uint32_t val_id = cpi->GetSingleWordInOperand(1);
AddStore(new_var_id, val_id, &new_blk_ptr);
}
break;
case SpvOpUnreachable:
case SpvOpKill: {
// Generate a return label so that we split the block with the function

View File

@ -2759,6 +2759,85 @@ OpFunctionEnd
SinglePassRunAndMatch<opt::InlineExhaustivePass>(text, true);
}
TEST_F(InlineTest, OpVariableWithInit) {
// Check that there is a store that corresponds to the initializer. This
// test makes sure that is a store to the variable in the loop and before any
// load.
const std::string text = R"(
; CHECK: OpFunction
; CHECK-NOT: OpFunctionEnd
; CHECK: [[var:%\w+]] = OpVariable %_ptr_Function_float Function %float_0
; CHECK: OpLoopMerge [[outer_merge:%\w+]]
; CHECK-NOT: OpLoad %float [[var]]
; CHECK: OpStore [[var]] %float_0
; CHECK: OpFunctionEnd
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %o
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpDecorate %o Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%_ptr_Function_float = OpTypePointer Function %float
%float_0 = OpConstant %float 0
%bool = OpTypeBool
%float_1 = OpConstant %float 1
%_ptr_Output_float = OpTypePointer Output %float
%o = OpVariable %_ptr_Output_float Output
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%_ptr_Input_int = OpTypePointer Input %int
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%main = OpFunction %void None %3
%5 = OpLabel
OpStore %o %float_0
OpBranch %34
%34 = OpLabel
%39 = OpPhi %int %int_0 %5 %47 %37
OpLoopMerge %36 %37 None
OpBranch %38
%38 = OpLabel
%41 = OpSLessThan %bool %39 %int_2
OpBranchConditional %41 %35 %36
%35 = OpLabel
%42 = OpFunctionCall %float %foo_
%43 = OpLoad %float %o
%44 = OpFAdd %float %43 %42
OpStore %o %44
OpBranch %37
%37 = OpLabel
%47 = OpIAdd %int %39 %int_1
OpBranch %34
%36 = OpLabel
OpReturn
OpFunctionEnd
%foo_ = OpFunction %float None %7
%9 = OpLabel
%n = OpVariable %_ptr_Function_float Function %float_0
%13 = OpLoad %float %n
%15 = OpFOrdEqual %bool %13 %float_0
OpSelectionMerge %17 None
OpBranchConditional %15 %16 %17
%16 = OpLabel
%19 = OpLoad %float %n
%20 = OpFAdd %float %19 %float_1
OpStore %n %20
OpBranch %17
%17 = OpLabel
%21 = OpLoad %float %n
OpReturnValue %21
OpFunctionEnd
)";
SinglePassRunAndMatch<opt::InlineExhaustivePass>(text, true);
}
#endif
// TODO(greg-lunarg): Add tests to verify handling of these cases: