Handle extract with no index in VDCE. (#2305)
It is legal, but not generated by any SPIR-V producer: an OpCompositeExtract
with no indexes. This is essentially just a copy of the object, so we
treat them that way. We simply propagate the live variables of the
result to the operand.
Fixes https://crbug.com/919181.
diff --git a/source/opt/vector_dce.cpp b/source/opt/vector_dce.cpp
index 314d651..92532e3 100644
--- a/source/opt/vector_dce.cpp
+++ b/source/opt/vector_dce.cpp
@@ -66,7 +66,8 @@
switch (current_inst->opcode()) {
case SpvOpCompositeExtract:
- MarkExtractUseAsLive(current_inst, live_components, &work_list);
+ MarkExtractUseAsLive(current_inst, current_item.components,
+ live_components, &work_list);
break;
case SpvOpCompositeInsert:
MarkInsertUsesAsLive(current_item, live_components, &work_list);
@@ -92,6 +93,7 @@
}
void VectorDCE::MarkExtractUseAsLive(const Instruction* current_inst,
+ const utils::BitVector& live_elements,
LiveComponentMap* live_components,
std::vector<WorkListItem>* work_list) {
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
@@ -102,7 +104,11 @@
if (HasVectorOrScalarResult(operand_inst)) {
WorkListItem new_item;
new_item.instruction = operand_inst;
- new_item.components.Set(current_inst->GetSingleWordInOperand(1));
+ if (current_inst->NumInOperands() < 2) {
+ new_item.components = live_elements;
+ } else {
+ new_item.components.Set(current_inst->GetSingleWordInOperand(1));
+ }
AddItemToWorkListIfNeeded(new_item, live_components, work_list);
}
}
diff --git a/source/opt/vector_dce.h b/source/opt/vector_dce.h
index 638b34b..4f039c5 100644
--- a/source/opt/vector_dce.h
+++ b/source/opt/vector_dce.h
@@ -129,6 +129,7 @@
// live. If anything becomes live they are added to |work_list| and
// |live_components| is updated accordingly.
void MarkExtractUseAsLive(const Instruction* current_inst,
+ const utils::BitVector& live_elements,
LiveComponentMap* live_components,
std::vector<WorkListItem>* work_list);
diff --git a/test/opt/vector_dce_test.cpp b/test/opt/vector_dce_test.cpp
index 40f115c..a978a07 100644
--- a/test/opt/vector_dce_test.cpp
+++ b/test/opt/vector_dce_test.cpp
@@ -1190,6 +1190,42 @@
SinglePassRunAndMatch<VectorDCE>(text, true);
}
+TEST_F(VectorDCETest, ExtractWithNoIndices) {
+ const std::string text = R"(
+; CHECK: OpLoad %float
+; CHECK: [[ld:%\w+]] = OpLoad %v4float
+; CHECK: [[ex1:%\w+]] = OpCompositeExtract %v4float [[ld]]
+; CHECK: [[ex2:%\w+]] = OpCompositeExtract %float [[ex1]] 1
+; CHECK: OpStore {{%\w+}} [[ex2]]
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %1 "PSMain" %2 %14 %3
+ OpExecutionMode %1 OriginUpperLeft
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_float = OpTypePointer Input %float
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_float = OpTypePointer Output %float
+ %2 = OpVariable %_ptr_Input_v4float Input
+ %14 = OpVariable %_ptr_Input_float Input
+ %3 = OpVariable %_ptr_Output_float Output
+ %1 = OpFunction %void None %5
+ %10 = OpLabel
+ %13 = OpLoad %float %14
+ %11 = OpLoad %v4float %2
+ %12 = OpCompositeInsert %v4float %13 %11 0
+ %20 = OpCompositeExtract %v4float %12
+ %21 = OpCompositeExtract %float %20 1
+ OpStore %3 %21
+ OpReturn
+ OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<VectorDCE>(text, true);
+}
+
} // namespace
} // namespace opt
} // namespace spvtools