MultiStore: Support OpVariable Initialization
authorGregF <greg@LunarG.com>
Fri, 8 Dec 2017 17:44:15 +0000 (10:44 -0700)
committerSteven Perron <stevenperron@google.com>
Mon, 11 Dec 2017 15:37:14 +0000 (10:37 -0500)
Treat an OpVariable with initialization as if it was an OpStore.
With PR #1073, this completes work for issue #1017.

source/opt/mem_pass.cpp
test/opt/local_ssa_elim_test.cpp

index 2a815d7..b21bf00 100644 (file)
@@ -34,6 +34,7 @@ const uint32_t kStorePtrIdInIdx = 0;
 const uint32_t kStoreValIdInIdx = 1;
 const uint32_t kTypePointerStorageClassInIdx = 0;
 const uint32_t kTypePointerTypeIdInIdx = 1;
+const uint32_t kVariableInitIdInIdx = 1;
 
 }  // namespace
 
@@ -582,6 +583,15 @@ Pass::Status MemPass::InsertPhiInstructions(ir::Function* func) {
           label2ssa_map_[label][varId] =
               inst->GetSingleWordInOperand(kStoreValIdInIdx);
         } break;
+        case SpvOpVariable: {
+          // Treat initialized OpVariable like an OpStore
+          if (inst->NumInOperands() < 2) break;
+          uint32_t varId = inst->result_id();
+          if (!IsTargetVar(varId)) break;
+          // Register new stored value for the variable
+          label2ssa_map_[label][varId] =
+              inst->GetSingleWordInOperand(kVariableInitIdInIdx);
+        } break;
         case SpvOpLoad: {
           uint32_t varId;
           (void)GetPtr(inst, &varId);
index c79ef57..4813a16 100644 (file)
@@ -524,7 +524,7 @@ OpLoopMerge %27 %28 None
 OpBranch %29
 %29 = OpLabel
 %30 = OpLoad %int %i
-%31 = OpLoad %int %ie 
+%31 = OpLoad %int %ie
 %32 = OpSLessThan %bool %30 %31
 OpBranchConditional %32 %33 %27
 %33 = OpLabel
@@ -932,20 +932,20 @@ OpDecorate %OutColor Location 0
 %21 = OpLoad %float %f
 %22 = OpFOrdGreaterThanEqual %bool %21 %float_0
 OpSelectionMerge %23 None
-OpBranchConditional %22 %24 %25 
+OpBranchConditional %22 %24 %25
 %24 = OpLabel
 %26 = OpLoad %v4float %BaseColor
 %27 = OpVectorTimesScalar %v4float %26 %float_0_5
-OpStore %v %27 
+OpStore %v %27
 OpBranch %23
 %25 = OpLabel
 %28 = OpLoad %v4float %BaseColor
 %29 = OpFAdd %v4float %28 %18
-OpStore %v %29 
+OpStore %v %29
 OpBranch %23
 %23 = OpLabel
 %30 = OpLoad %v4float %v
-OpStore %OutColor %30 
+OpStore %OutColor %30
 OpReturn
 OpFunctionEnd
 )";
@@ -1306,12 +1306,12 @@ OpBranch %25
 %32 = OpLoad %v4float %v
 %33 = OpCompositeConstruct %v4float %float_0_1 %float_0_1 %float_0_1 %float_0_1
 %34 = OpFAdd %v4float %32 %33
-OpStore %v %34 
+OpStore %v %34
 OpBranch %29
 %29 = OpLabel
 %35 = OpLoad %v4float %v
 %36 = OpVectorTimesScalar %v4float %35 %float_0_7
-OpStore %v %36 
+OpStore %v %36
 OpBranch %25
 %25 = OpLabel
 %37 = OpLoad %v4float %v
@@ -1384,6 +1384,135 @@ OpFunctionEnd
                                                       true);
 }
 
+TEST_F(LocalSSAElimTest, OptInitializedVariableLikeStore) {
+  // Note: SPIR-V edited to change store to v into variable initialization
+  //
+  // #version 450
+  //
+  // layout (location=0) in vec4 iColor;
+  // layout (location=1) in float fi;
+  // layout (location=0) out vec4 oColor;
+  //
+  // void main()
+  // {
+  //     vec4 v = vec4(0.0);
+  //     if (fi < 0.0)
+  //       v.x = iColor.x;
+  //     oColor = v;
+  // }
+
+  const std::string predefs_before =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %fi %iColor %oColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 450
+OpName %main "main"
+OpName %v "v"
+OpName %fi "fi"
+OpName %iColor "iColor"
+OpName %oColor "oColor"
+OpDecorate %fi Location 1
+OpDecorate %iColor Location 0
+OpDecorate %oColor Location 0
+%void = OpTypeVoid
+%8 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%float_0 = OpConstant %float 0
+%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Input_float = OpTypePointer Input %float
+%fi = OpVariable %_ptr_Input_float Input
+%bool = OpTypeBool
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%iColor = OpVariable %_ptr_Input_v4float Input
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%oColor = OpVariable %_ptr_Output_v4float Output
+)";
+
+  const std::string predefs_after =
+      R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %fi %iColor %oColor
+OpExecutionMode %main OriginUpperLeft
+OpSource GLSL 450
+OpName %main "main"
+OpName %fi "fi"
+OpName %iColor "iColor"
+OpName %oColor "oColor"
+OpDecorate %fi Location 1
+OpDecorate %iColor Location 0
+OpDecorate %oColor Location 0
+%void = OpTypeVoid
+%8 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%float_0 = OpConstant %float 0
+%13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Input_float = OpTypePointer Input %float
+%fi = OpVariable %_ptr_Input_float Input
+%bool = OpTypeBool
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%iColor = OpVariable %_ptr_Input_v4float Input
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%oColor = OpVariable %_ptr_Output_v4float Output
+)";
+
+  const std::string func_before =
+      R"(%main = OpFunction %void None %8
+%21 = OpLabel
+%v = OpVariable %_ptr_Function_v4float Function %13
+%22 = OpLoad %float %fi
+%23 = OpFOrdLessThan %bool %22 %float_0
+OpSelectionMerge %24 None
+OpBranchConditional %23 %25 %24
+%25 = OpLabel
+%26 = OpAccessChain %_ptr_Input_float %iColor %uint_0
+%27 = OpLoad %float %26
+%28 = OpLoad %v4float %v
+%29 = OpCompositeInsert %v4float %27 %28 0
+OpStore %v %29
+OpBranch %24
+%24 = OpLabel
+%30 = OpLoad %v4float %v
+OpStore %oColor %30
+OpReturn
+OpFunctionEnd
+)";
+
+  const std::string func_after =
+      R"(%main = OpFunction %void None %8
+%21 = OpLabel
+%22 = OpLoad %float %fi
+%23 = OpFOrdLessThan %bool %22 %float_0
+OpSelectionMerge %24 None
+OpBranchConditional %23 %25 %24
+%25 = OpLabel
+%26 = OpAccessChain %_ptr_Input_float %iColor %uint_0
+%27 = OpLoad %float %26
+%29 = OpCompositeInsert %v4float %27 %13 0
+OpBranch %24
+%24 = OpLabel
+%31 = OpPhi %v4float %13 %21 %29 %25
+OpStore %oColor %31
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndCheck<opt::LocalMultiStoreElimPass>(
+      predefs_before + func_before, predefs_after + func_after, true, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    No optimization in the presence of