--- /dev/null
+// 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(¶m) so it is not promoted by
+// SROA/mem2reg.
+// 2. InstCombine's LowerDbgDeclare converts the dbg.declare to a set of
+// dbg.values.
+// 3. inlineme(¶m) 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(¶m);
+ fluff(); // DexLabel('s0')
+ return 0;
+}
+
+int main() {
+ return fun(5);
+}
+
+// DexExpectWatchValue('param', 10, on_line='s0')
--- /dev/null
+// 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(¶ma) 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(¶ma);
+ return 0;
+}
+
+int main() {
+ return fun(5, 20);
+}
+
+// DexExpectWatchValue('parama', 20, on_line='s0')
--- /dev/null
+// 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.