Debug info preservation in redundancy-elimination pass (#3839)

* Debug info preservation in redundancy-elimination pass
This commit is contained in:
Jaebaek Seo 2020-10-01 09:22:16 -04:00 committed by GitHub
parent e246038364
commit 57abfd88c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 168 additions and 1 deletions

View File

@ -49,7 +49,8 @@ uint32_t ValueNumberTable::AssignValueNumber(Instruction* inst) {
// have its own value number.
// OpSampledImage and OpImage must remain in the same basic block in which
// they are used, because of this we will assign each one it own value number.
if (!context()->IsCombinatorInstruction(inst)) {
if (!context()->IsCombinatorInstruction(inst) &&
!inst->IsOpenCL100DebugInstr()) {
value = TakeNextValueNumber();
id_to_value_[inst->result_id()] = value;
return value;
@ -173,6 +174,12 @@ void ValueNumberTable::BuildDominatorTreeValueNumberTable() {
}
}
for (auto& inst : context()->module()->ext_inst_debuginfo()) {
if (inst.result_id() != 0) {
AssignValueNumber(&inst);
}
}
for (Function& func : *context()->module()) {
// For best results we want to traverse the code in reverse post order.
// This happens naturally because of the forward referencing rules.

View File

@ -272,6 +272,67 @@ TEST_F(RedundancyEliminationTest, KeepRedundantAddWithoutPhi) {
EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
}
// Test that it can get a simple case of local redundancy elimination
// when it has OpenCL.DebugInfo.100 instructions.
TEST_F(RedundancyEliminationTest, OpenCLDebugInfo100) {
// When three redundant DebugValues exist, only one DebugValue must remain.
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "OpenCL.DebugInfo.100"
%2 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %3 "main"
OpExecutionMode %3 OriginUpperLeft
OpSource GLSL 430
%4 = OpString "ps.hlsl"
%5 = OpString "float"
%6 = OpString "s0"
%7 = OpString "main"
%void = OpTypeVoid
%9 = OpTypeFunction %void
%float = OpTypeFloat 32
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%uint_32 = OpConstant %uint 32
%_ptr_Function_float = OpTypePointer Function %float
%15 = OpExtInst %void %1 DebugExpression
%16 = OpExtInst %void %1 DebugSource %4
%17 = OpExtInst %void %1 DebugCompilationUnit 1 4 %16 HLSL
%18 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Float
%19 = OpExtInst %void %1 DebugTypeVector %18 4
%20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %19
%21 = OpExtInst %void %1 DebugFunction %7 %20 %16 4 1 %17 %7 FlagIsProtected|FlagIsPrivate 4 %3
; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void {{%\w+}} DebugLocalVariable
%22 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal
%14 = OpExtInst %void %1 DebugLocalVariable %6 %19 %16 0 0 %21 FlagIsLocal
%3 = OpFunction %void None %9
%23 = OpLabel
%24 = OpExtInst %void %1 DebugScope %21
%25 = OpVariable %_ptr_Function_float Function
%26 = OpLoad %float %25
OpLine %4 0 0
; Two `OpFAdd %float %26 %26` are the same. One must be removed.
; After removing one `OpFAdd %float %26 %26`, two DebugValues are the same.
; One must be removed.
;
; CHECK: [[add:%\w+]] = OpFAdd %float [[value:%\w+]]
; CHECK-NEXT: DebugValue [[dbg_local_var]] [[add]]
; CHECK-NEXT: OpFAdd %float [[add]] [[value]]
; CHECK-NEXT: OpReturn
%27 = OpFAdd %float %26 %26
%28 = OpExtInst %void %1 DebugValue %22 %27 %15 %uint_0
OpLine %4 1 0
%29 = OpFAdd %float %26 %26
%30 = OpExtInst %void %1 DebugValue %14 %29 %15 %uint_0
%31 = OpExtInst %void %1 DebugValue %22 %29 %15 %uint_0
%32 = OpFAdd %float %29 %26
%33 = OpFAdd %float %27 %26
OpReturn
OpFunctionEnd
)";
SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
}
} // namespace
} // namespace opt
} // namespace spvtools

View File

@ -728,6 +728,105 @@ TEST_F(ValueTableTest, RedundantSampledImageLoad) {
EXPECT_EQ(vtable.GetValueNumber(load1), vtable.GetValueNumber(load2));
}
TEST_F(ValueTableTest, DifferentDebugLocalVariableSameValue) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
%2 = OpExtInstImport "OpenCL.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %3 "main"
OpExecutionMode %3 OriginUpperLeft
OpSource GLSL 430
%4 = OpString "test"
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpTypeInt 32 0
%8 = OpConstant %7 32
%9 = OpExtInst %5 %2 DebugSource %4
%10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
%11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
%12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
%13 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
%3 = OpFunction %5 None %6
%14 = OpLabel
OpReturn
OpFunctionEnd
)";
auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
ValueNumberTable vtable(context.get());
Instruction* inst1 = context->get_def_use_mgr()->GetDef(12);
Instruction* inst2 = context->get_def_use_mgr()->GetDef(13);
EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
}
TEST_F(ValueTableTest, DifferentDebugValueSameValue) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
%2 = OpExtInstImport "OpenCL.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %3 "main"
OpExecutionMode %3 OriginUpperLeft
OpSource GLSL 430
%4 = OpString "test"
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpTypeInt 32 0
%8 = OpConstant %7 32
%9 = OpExtInst %5 %2 DebugSource %4
%10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
%11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
%12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
%13 = OpExtInst %5 %2 DebugExpression
%3 = OpFunction %5 None %6
%14 = OpLabel
%15 = OpExtInst %5 %2 DebugValue %12 %8 %13
%16 = OpExtInst %5 %2 DebugValue %12 %8 %13
OpReturn
OpFunctionEnd
)";
auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
ValueNumberTable vtable(context.get());
Instruction* inst1 = context->get_def_use_mgr()->GetDef(15);
Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
}
TEST_F(ValueTableTest, DifferentDebugDeclareSameValue) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
%2 = OpExtInstImport "OpenCL.DebugInfo.100"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %3 "main"
OpExecutionMode %3 OriginUpperLeft
OpSource GLSL 430
%4 = OpString "test"
%void = OpTypeVoid
%6 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%_ptr_Function_uint = OpTypePointer Function %uint
%uint_32 = OpConstant %uint 32
%10 = OpExtInst %void %2 DebugSource %4
%11 = OpExtInst %void %2 DebugCompilationUnit 1 4 %10 HLSL
%12 = OpExtInst %void %2 DebugTypeBasic %4 %uint_32 Float
%13 = OpExtInst %void %2 DebugLocalVariable %4 %12 %10 0 0 %11 FlagIsLocal
%14 = OpExtInst %void %2 DebugExpression
%3 = OpFunction %void None %6
%15 = OpLabel
%16 = OpVariable %_ptr_Function_uint Function
%17 = OpExtInst %void %2 DebugDeclare %13 %16 %14
%18 = OpExtInst %void %2 DebugDeclare %13 %16 %14
OpReturn
OpFunctionEnd
)";
auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
ValueNumberTable vtable(context.get());
Instruction* inst1 = context->get_def_use_mgr()->GetDef(17);
Instruction* inst2 = context->get_def_use_mgr()->GetDef(18);
EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
}
} // namespace
} // namespace opt
} // namespace spvtools