[debuginfo-tests] b7e5162 - [DebugInfo][dexter] Add dexter tests for merged values

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 19 03:29:39 PST 2021


Author: OCHyams
Date: 2021-01-19T11:11:00Z
New Revision: b7e516202eb66e004c49b89964bd5b30b287af87

URL: https://github.com/llvm/llvm-project/commit/b7e516202eb66e004c49b89964bd5b30b287af87
DIFF: https://github.com/llvm/llvm-project/commit/b7e516202eb66e004c49b89964bd5b30b287af87.diff

LOG: [DebugInfo][dexter] Add dexter tests for merged values

These dexter tests illustrate PR48719, the summary of which is:

Sometimes we insert dbg.values for merged values (PHIs) when promoting
variables, sometimes we don't. Sometimes there is no PHI because the merged
value is never used. It doesn't matter because LiveDebugValues understands these
merged values (implicit or otherwise) and correctly updates the debug
info. Importantly, these merged variable values (which may or may not exist as
PHIs, and may or not be represented with dbg.values) are //always// implicitly
defined by the combination of incoming edges and the incoming variable locations
along those edges by virtue of LiveDebugValues existing. Unfortunately, it is
possible to mess with the CFG and remove / move these edges before
LiveDebugValues runs. In this case our debug info model only works when the
merged value is tracked by a dbg.value. Currently, this is only done rigorously
for variables which are A) promoted in the first round of mem2reg and B) are
used after the merge point.

As an example, compile the following source with -O3 -g and step through with a
debugger. You will see parama=5 throughout the function fun which is incorrect -
we expect to see param=20 after the conditional assignment.

    __attribute__((optnone))
    void esc(int* p) {}

    __attribute__((optnone))
    void fluff() {}

    __attribute__((noinline))
    int fun(int parama, int paramb) {
      if (parama)
        parama = paramb;
      fluff();           // DexLabel('s0')
      esc(&parama);
      return 0;
    }

    int main() {
      return fun(5, 20);
    }

1. parama is escaped by esc(&parama) so it is not promoted by
   SROA/mem2reg (failing condition "A" above).
2. InstCombine's LowerDbgDeclare converts the dbg.declare to a set of
   dbg.values (tracking the stored SSA values).
3. InstCombine replaces the two stores to parama's alloca (the initial
   parameter register store in entry and the assignment in if.then) with a
   PHI+store in the common sucessor.
4. SimplifyCFG folds the blocks together and converts the PHI to a
   select.

The debug info is not updated to account for the merged value in the successor
prior to SimplifyCFG when it exists as a PHI, or during when it becomes a
select.

As with D89543, which added some dexter tests for escaped locals, the idea is
to build a set of source-level tests which highlights existing issues and
might be useful in evaluating a new debug info model.

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D94761

Added: 
    debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c
    debuginfo-tests/dexter-tests/memvars/merged-store.c
    debuginfo-tests/dexter-tests/memvars/unused-merged-value.c

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c b/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c
new file mode 100644
index 000000000000..f2a22e69015a
--- /dev/null
+++ b/debuginfo-tests/dexter-tests/memvars/inline-escaping-function.c
@@ -0,0 +1,45 @@
+// XFAIL: *
+// Incorrect location for variable "param", see PR48719.
+
+// REQUIRES: lldb
+// UNSUPPORTED: system-windows
+// RUN: %dexter --fail-lt 1.0 -w --debugger lldb \
+// RUN:     --builder 'clang-c'  --cflags "-O3 -glldb" -- %s
+
+// 1. param is escaped by inlineme(&param) so it is not promoted by
+//    SROA/mem2reg.
+// 2. InstCombine's LowerDbgDeclare converts the dbg.declare to a set of
+//    dbg.values.
+// 3. inlineme(&param) is inlined.
+// 4. SROA/mem2reg fully promotes param. It does not insert a dbg.value after the
+//    PHI it inserts which merges the values out of entry and if.then in the
+//    sucessor block. This behaviour is inconsistent. If the dbg.declare was
+//    still around (i.e.  if param was promoted in the first round of mem2reg
+//    BEFORE LowerDbgDeclare) we would see a dbg.value insered for the PHI.
+// 5. JumpThreading removes the if.then block, changing entry to
+//    unconditionally branch to if.end.
+// 6. SimplifyCFG stitches entry and if.end together.
+
+// The debug info is not updated to account for the merged value prior to or
+// during JumpThreading/SimplifyCFG so we end up seeing param=5 for the entire
+// function, when we'd expect to see param=10 when stepping onto fluff().
+
+__attribute__((always_inline))
+int inlineme(int* p) { return *p * 2; }
+
+__attribute__((optnone))
+void fluff() {}
+
+__attribute__((noinline))
+int fun(int param) {
+  if (param)
+    param = inlineme(&param);
+  fluff();           // DexLabel('s0')
+  return 0;
+}
+
+int main() {
+  return fun(5);
+}
+
+// DexExpectWatchValue('param', 10, on_line='s0')

diff  --git a/debuginfo-tests/dexter-tests/memvars/merged-store.c b/debuginfo-tests/dexter-tests/memvars/merged-store.c
new file mode 100644
index 000000000000..06150b9f7cfd
--- /dev/null
+++ b/debuginfo-tests/dexter-tests/memvars/merged-store.c
@@ -0,0 +1,43 @@
+// XFAIL: *
+// Incorrect location for variable "parama", see PR48719.
+
+// REQUIRES: lldb
+// UNSUPPORTED: system-windows
+// RUN: %dexter --fail-lt 1.0 -w --debugger lldb \
+// RUN:     --builder 'clang-c'  --cflags "-O3 -glldb" -- %s
+
+// 1. parama is escaped by esc(&parama) so it is not promoted by
+//    SROA/mem2reg.
+// 2. InstCombine's LowerDbgDeclare converts the dbg.declare to a set of
+//    dbg.values (tracking the stored SSA values).
+// 3. InstCombine replaces the two stores to parama's alloca (the initial
+//    parameter register store in entry and the assignment in if.then) with a
+//    PHI+store in the common sucessor.
+// 4. SimplifyCFG folds the blocks together and converts the PHI to a
+//    select.
+
+// The debug info is not updated to account for the merged value in the
+// sucessor prior to SimplifyCFG when it exists as a PHI, or during when it
+// becomes a select. As a result we see parama=5 for the entire function, when
+// we'd expect to see param=20 when stepping onto fluff().
+
+__attribute__((optnone))
+void esc(int* p) {}
+
+__attribute__((optnone))
+void fluff() {}
+
+__attribute__((noinline))
+int fun(int parama, int paramb) {
+  if (parama)
+    parama = paramb;
+  fluff();           // DexLabel('s0')
+  esc(&parama);
+  return 0;
+}
+
+int main() {
+  return fun(5, 20);
+}
+
+// DexExpectWatchValue('parama', 20, on_line='s0')

diff  --git a/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c b/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c
new file mode 100644
index 000000000000..4830becbd3a0
--- /dev/null
+++ b/debuginfo-tests/dexter-tests/memvars/unused-merged-value.c
@@ -0,0 +1,44 @@
+// XFAIL: *
+// Incorrect location for variable "parama", see PR48719.
+
+// REQUIRES: lldb
+// UNSUPPORTED: system-windows
+// RUN: %dexter --fail-lt 0.1 -w --debugger lldb \
+// RUN:     --builder 'clang-c'  --cflags "-O3 -glldb" -- %s
+// See NOTE at end for more info about the RUN command.
+
+// 1. SROA/mem2reg fully promotes parama.
+// 2. parama's value in the final block is the merge of values for it coming
+//    out of entry and if.then. If the variable were used later in the function
+//    mem2reg would insert a PHI here and add a dbg.value to track the merged
+//    value in debug info. Because it is not used there is no PHI (the merged
+//    value is implicit) and subsequently no dbg.value.
+// 3. SimplifyCFG later folds the blocks together (if.then does nothing besides
+//    provide debug info so it is removed and if.end is folded into the entry
+//    block).
+
+// The debug info is not updated to account for the implicit merged value prior
+// to (e.g. during mem2reg) or during SimplifyCFG so we end up seeing parama=5
+// for the entire function, which is incorrect.
+
+__attribute__((optnone))
+void fluff() {}
+
+__attribute__((noinline))
+int fun(int parama, int paramb) {
+  if (parama)
+    parama = paramb;
+  fluff();            // DexLabel('s0')
+  return paramb;
+}
+
+int main() {
+  return fun(5, 20);
+}
+
+// DexExpectWatchValue('parama', 20, on_line='s0')
+//
+// NOTE: the dexter command uses --fail-lt 0.1 (instead of the standard 1.0)
+// because seeing 'optimized out' would still be a win; it's the best we can do
+// without using conditional DWARF operators in the location expression. Seeing
+// 'optimized out' should result in a score higher than 0.1.


        


More information about the llvm-commits mailing list