[llvm-dev] [SROA][DebugInfo][GSoC] Testing SROA on amalgamated sqlite source

Greg Bedwell via llvm-dev llvm-dev at lists.llvm.org
Wed May 30 10:58:03 PDT 2018


>
>
>   `SROA' is an early stage pass running at the very beginning of the
>   pipeline in `-O{1,2,3}'. Greg Bedwell's report from his DExTer tool
>   shows SROA on function as one of the major culprits of Debug Info
>   loss.
>
>
The methodology I used is with the opt-bisect-limit option on clang, so
it's not strictly the case that the results presented show that the loss in
"debugability" occurs during the SROA pass itself directly but rather that
the effect of running SROA is some loss in debugability to the final
program.  I didn't make that point clear enough during my lightning talk
session!

Looking at some of the results in more detail, I think the reason that the
reason our results differ is because what I'm measuring is not actually
variable info loss directly, but as a consequence of the impact on
stepping.  My standard disclaimer with all results from this tool is that a
non-perfect debugging experience score is not necessarily indicative of
something wrong, but should be looked at in conjunction with all the other
factors such as what the pass is trying to achieve optimization-wise, etc
etc.  That is to say, it's not necessarily a bug, but it can be (especially
when observed as a regression between compiler revisions).

Using the standard Fibonacci example with clang and lldb from this
afternoon:

 1 #ifdef _MSC_VER
 2 # define DEX_NOINLINE __declspec(noinline)
 3 #else
 4 # define DEX_NOINLINE __attribute__((__noinline__))
 5 #endif
 6
 7 DEX_NOINLINE
 8 void Fibonacci(int terms, int& total)
 9 {
10   int first = 0;
11   int second = 1;
12
13   for (int i = 0; i < terms; ++i)
14   {
15     int next = first + second; // DexWatch('i', 'first', 'second',
'total')
16     total += first;            // DexWatch('i', 'first', 'second',
'total', 'next')
17     first = second;            // DexWatch('i', 'first', 'second',
'total', 'next')
18     second = next;             // DexWatch('i', 'first', 'second',
'total', 'next')
19   }
20 }
21
22 int main()
23 {
24   int total = 0;
25   Fibonacci(5, total);
26   return total;
27 }

not running  "SROA on function (_Z9FibonacciiRi)" the DExTer trace output
is:

## BEGIN ##
[1, "main", "tests/fibonacci/test.cpp", 24, 6, "BREAKPOINT", "FUNC", {}]
[2, "main", "tests/fibonacci/test.cpp", 25, 2, "BREAKPOINT", "FORWARD", {}]
.   [3, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 10, 6,
"BREAKPOINT", "FUNC", {}]
.   [4, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 11, 6,
"BREAKPOINT", "FORWARD", {}]
.   [5, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 11,
"BREAKPOINT", "FORWARD", {}]
.   [6, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 14,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"0"}]
.   [7, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 12,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"0", "next": "1"}]
.   [8, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 17, 11,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"0", "next": "1"}]
.   [9, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 18, 12,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"1", "next": "1"}]
.   [10, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [11, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 14,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "0", "first":
"1"}]
.   [12, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 12,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "0", "first":
"1", "next": "2"}]
.   [13, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 17, 11,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "1", "first":
"1", "next": "2"}]
.   [14, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 18, 12,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "1", "first":
"1", "next": "2"}]
.   [15, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [16, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 14,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "1", "first":
"1"}]
.   [17, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 12,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "1", "first":
"1", "next": "3"}]
.   [18, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 17, 11,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "2", "first":
"1", "next": "3"}]
.   [19, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 18, 12,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "2", "first":
"2", "next": "3"}]
.   [20, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [21, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 14,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "2", "first":
"2"}]
.   [22, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 12,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "2", "first":
"2", "next": "5"}]
.   [23, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 17, 11,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "4", "first":
"2", "next": "5"}]
.   [24, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 18, 12,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "4", "first":
"3", "next": "5"}]
.   [25, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [26, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 14,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "4", "first":
"3"}]
.   [27, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 12,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "4", "first":
"3", "next": "8"}]
.   [28, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 17, 11,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "7", "first":
"3", "next": "8"}]
.   [29, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 18, 12,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "7", "first":
"5", "next": "8"}]
.   [30, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [31, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 20, 1,
"BREAKPOINT", "FORWARD", {}]
[32, "main", "tests/fibonacci/test.cpp", 26, 9, "BREAKPOINT", "FUNC", {}]
## END (32 steps) ##

So we do a couple of steps in main, before stepping into Fibonacci(int,
int&) at step 3.  It's fairly easy to see that we iterate the loop 5 times,
stepping on lines 13, 15, 16, 17 and 18 in order each time.

After "SROA on function (_Z9FibonacciiRi)" we now get:

## BEGIN ##
[1, "main", "tests/fibonacci/test.cpp", 24, 6, "BREAKPOINT", "FUNC", {}]
[2, "main", "tests/fibonacci/test.cpp", 25, 2, "BREAKPOINT", "FORWARD", {}]
.   [3, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "FUNC", {}]
.   [4, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 20,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"0"}]
.   [5, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 9,
"BREAKPOINT", "FORWARD", {"i": "0", "second": "1", "total": "0", "first":
"0", "next": "1"}]
.   [6, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29, "STEP",
"BACKWARD", {}]
.   [7, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "BACKWARD", {}]
.   [8, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 20,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "0", "first":
"1"}]
.   [9, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 9,
"BREAKPOINT", "FORWARD", {"i": "1", "second": "1", "total": "0", "first":
"1", "next": "2"}]
.   [10, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [11, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "BACKWARD", {}]
.   [12, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 20,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "1", "first":
"1"}]
.   [13, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 9,
"BREAKPOINT", "FORWARD", {"i": "2", "second": "2", "total": "1", "first":
"1", "next": "3"}]
.   [14, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [15, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "BACKWARD", {}]
.   [16, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 20,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "2", "first":
"2"}]
.   [17, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 9,
"BREAKPOINT", "FORWARD", {"i": "3", "second": "3", "total": "2", "first":
"2", "next": "5"}]
.   [18, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [19, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "BACKWARD", {}]
.   [20, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 15, 20,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "4", "first":
"3"}]
.   [21, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 16, 9,
"BREAKPOINT", "FORWARD", {"i": "4", "second": "5", "total": "4", "first":
"3", "next": "8"}]
.   [22, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 29,
"STEP", "BACKWARD", {}]
.   [23, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 13, 20,
"BREAKPOINT", "BACKWARD", {}]
.   [24, "Fibonacci(int, int&)", "tests/fibonacci/test.cpp", 20, 1,
"BREAKPOINT", "FORWARD", {}]
[25, "main", "tests/fibonacci/test.cpp", 26, 9, "BREAKPOINT", "FUNC", {}]
## END (25 steps) ##

So we've now gained some extra steps at line 13, but at different columns
(the "++i" and "i < terms" are now treated as separate steps), but we're
now also no longer ever stepping onto lines 17 or 18 at all.  Whether these
are the expected effects of SROA are not something DExTer is in the
business of deciding, but it does score it as a difference because it now,
at no point, sees the expression "first" evaluate to a value of 5, or
"total" to a value of 8 which it did previously.  From the source-level
debugging experience, the variables now just get updated between iterations.

So in short, it seems SROA is having some effect on debugging but it seems
that it's not in the form of failing to preserve variable info.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180530/900684fe/attachment.html>


More information about the llvm-dev mailing list