Remove DebugDeclare only for target variables in ssa-rewrite (#3511)
For each local variable, ssa-rewrite should remove its DebugDeclare
if and only if it is replaced by any number of DebugValues for store
and phi instructions.
For example, when we have two variables `a` whose DebugDeclare
will be replaced to DebugValues by ssa-rewrite pass and `b` whose
DebugDeclare will not be replaced, we have to remove only DebugDeclare
for `a`, not `b`.
diff --git a/source/opt/ir_context.cpp b/source/opt/ir_context.cpp
index 0791097..a56ff06 100644
--- a/source/opt/ir_context.cpp
+++ b/source/opt/ir_context.cpp
@@ -222,13 +222,6 @@
return false;
}
-void IRContext::KillDebugDeclareInsts(Function* fn) {
- fn->ForEachInst([this](Instruction* inst) {
- if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare)
- KillInst(inst);
- });
-}
-
bool IRContext::ReplaceAllUsesWith(uint32_t before, uint32_t after) {
return ReplaceAllUsesWithPredicate(
before, after, [](Instruction*, uint32_t) { return true; });
diff --git a/source/opt/ir_context.h b/source/opt/ir_context.h
index 37be836..b193657 100644
--- a/source/opt/ir_context.h
+++ b/source/opt/ir_context.h
@@ -403,9 +403,6 @@
// instruction exists.
Instruction* KillInst(Instruction* inst);
- // Deletes DebugDeclare instructions in the given function |fn|.
- void KillDebugDeclareInsts(Function* fn);
-
// Returns true if all of the given analyses are valid.
bool AreAnalysesValid(Analysis set) { return (set & valid_analyses_) == set; }
diff --git a/source/opt/ssa_rewrite_pass.cpp b/source/opt/ssa_rewrite_pass.cpp
index e1fc4f2..d5bba5e 100644
--- a/source/opt/ssa_rewrite_pass.cpp
+++ b/source/opt/ssa_rewrite_pass.cpp
@@ -615,8 +615,6 @@
<< fp->PrettyPrint(0) << "\n";
#endif
- if (modified) pass_->context()->KillDebugDeclareInsts(fp);
-
return modified ? Pass::Status::SuccessWithChange
: Pass::Status::SuccessWithoutChange;
}
@@ -626,6 +624,12 @@
for (auto& fn : *get_module()) {
status =
CombineStatus(status, SSARewriter(this).RewriteFunctionIntoSSA(&fn));
+ if (status == Status::SuccessWithChange) {
+ // Kill DebugDeclares for target variables.
+ for (auto var_id : seen_target_vars_) {
+ context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
+ }
+ }
if (status == Status::Failure) {
break;
}
diff --git a/test/opt/local_ssa_elim_test.cpp b/test/opt/local_ssa_elim_test.cpp
index 6581ebf..8727e35 100644
--- a/test/opt/local_ssa_elim_test.cpp
+++ b/test/opt/local_ssa_elim_test.cpp
@@ -2165,6 +2165,135 @@
SinglePassRunAndMatch<SSARewritePass>(text, true);
}
+TEST_F(LocalSSAElimTest, PartiallyKillDebugDeclare) {
+ // For a reference variable e.g., int i in the following example,
+ // we do not propagate DebugValue for a store or phi instruction
+ // out of the variable's scope. In that case, we should not remove
+ // DebugDeclare for the variable that we did not add its DebugValue.
+ //
+ // #version 140
+ //
+ // in vec4 BC;
+ // out float fo;
+ //
+ // int j;
+ // void main()
+ // {
+ // float f = 0.0;
+ // for (j=0; j<4; j++) {
+ // int& i = j;
+ // f = f + BC[i];
+ // }
+ // fo = f;
+ // }
+
+ const std::string text = R"(
+; CHECK: [[f_name:%\w+]] = OpString "f"
+; CHECK: [[i_name:%\w+]] = OpString "i"
+; CHECK: [[fn:%\w+]] = OpExtInst %void [[ext:%\d+]] DebugFunction
+; CHECK: [[bb:%\w+]] = OpExtInst %void [[ext]] DebugLexicalBlock
+; CHECK: [[dbg_f:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[f_name]] {{%\w+}} {{%\w+}} 0 0 [[fn]]
+; CHECK: [[dbg_i:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable [[i_name]] {{%\w+}} {{%\w+}} 0 0 [[bb]]
+
+; CHECK: OpStore %f %float_0
+; CHECK-NEXT: OpExtInst %void [[ext]] DebugValue [[dbg_f]] %float_0
+; CHECK-NOT: DebugDeclare [[dbg_f]]
+; CHECK: OpExtInst %void [[ext]] DebugDeclare [[dbg_i]] %j
+
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+%ext = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %BC %fo
+OpExecutionMode %main OriginUpperLeft
+%file_name = OpString "test"
+OpSource GLSL 140
+%float_name = OpString "float"
+%main_name = OpString "main"
+%f_name = OpString "f"
+%i_name = OpString "i"
+%j_name = OpString "j"
+OpName %main "main"
+OpName %f "f"
+OpName %j "j"
+OpName %BC "BC"
+OpName %fo "fo"
+%void = OpTypeVoid
+%8 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%_ptr_Function_float = OpTypePointer Function %float
+%float_0 = OpConstant %float 0
+%int = OpTypeInt 32 1
+%uint = OpTypeInt 32 0
+%uint_32 = OpConstant %uint 32
+%_ptr_Function_int = OpTypePointer Function %int
+%_ptr_Private_int = OpTypePointer Private %int
+%int_0 = OpConstant %int 0
+%int_4 = OpConstant %int 4
+%bool = OpTypeBool
+%v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%BC = OpVariable %_ptr_Input_v4float Input
+%_ptr_Input_float = OpTypePointer Input %float
+%int_1 = OpConstant %int 1
+%_ptr_Output_float = OpTypePointer Output %float
+%fo = OpVariable %_ptr_Output_float Output
+%j = OpVariable %_ptr_Private_int Private
+%null_expr = OpExtInst %void %ext DebugExpression
+%src = OpExtInst %void %ext DebugSource %file_name
+%cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL
+%dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float
+%dbg_v4f = OpExtInst %void %ext DebugTypeVector %dbg_tf 4
+%main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_v4f %dbg_v4f
+%dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main
+%bb = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main
+%dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_v4f %src 0 0 %dbg_main FlagIsLocal
+%dbg_i = OpExtInst %void %ext DebugLocalVariable %i_name %dbg_v4f %src 0 0 %bb FlagIsLocal
+%dbg_j = OpExtInst %void %ext DebugGlobalVariable %j_name %dbg_v4f %src 0 0 %dbg_main %j_name %j FlagIsPrivate
+%main = OpFunction %void None %8
+%22 = OpLabel
+%s0 = OpExtInst %void %ext DebugScope %dbg_main
+%f = OpVariable %_ptr_Function_float Function
+OpStore %f %float_0
+OpStore %j %int_0
+%decl0 = OpExtInst %void %ext DebugDeclare %dbg_f %f %null_expr
+OpBranch %23
+%23 = OpLabel
+%s1 = OpExtInst %void %ext DebugScope %dbg_main
+OpLoopMerge %24 %25 None
+OpBranch %26
+%26 = OpLabel
+%s2 = OpExtInst %void %ext DebugScope %dbg_main
+%27 = OpLoad %int %j
+%28 = OpSLessThan %bool %27 %int_4
+OpBranchConditional %28 %29 %24
+%29 = OpLabel
+%s3 = OpExtInst %void %ext DebugScope %bb
+%decl1 = OpExtInst %void %ext DebugDeclare %dbg_i %j %null_expr
+%30 = OpLoad %float %f
+%31 = OpLoad %int %j
+%32 = OpAccessChain %_ptr_Input_float %BC %31
+%33 = OpLoad %float %32
+%34 = OpFAdd %float %30 %33
+OpStore %f %34
+OpBranch %25
+%25 = OpLabel
+%s4 = OpExtInst %void %ext DebugScope %dbg_main
+%35 = OpLoad %int %j
+%36 = OpIAdd %int %35 %int_1
+OpStore %j %36
+OpBranch %23
+%24 = OpLabel
+%s5 = OpExtInst %void %ext DebugScope %dbg_main
+%37 = OpLoad %float %f
+OpStore %fo %37
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<SSARewritePass>(text, true);
+}
+
TEST_F(LocalSSAElimTest, DebugValueForReferenceVariable) {
// #version 140
//