<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/63676>63676</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            FlameGraphs incorrect from `llvm-xray stack --stack-format=flame`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          DerickEddington
      </td>
    </tr>
</table>

<pre>
    ## Summary

The numeric values produced by `llvm-xray stack --stack-format=flame --aggregation-type=time --all-stacks` are incorrect because they are the total amount of time spent in each function, but [`flamegraph.pl`](https://github.com/brendangregg/FlameGraph) needs these values to instead be only the amount of time spent directly in each function excluding any time spent in functions called by a function, because `flamegraph.pl` does its own summing of each's total time.

## Description

For the [reproducible example program](#reproducible-example) given farther below:

The incorrect output is like:
```
main; 17797754976
main;f2; 5925051360
main;f2;busy; 5925047168
main;f1; 5941978880
main;f1;busy; 5941971904
main;busy; 5930714592
```
Which renders as an incorrect graph:
![xray-log main jFn5JW](https://github.com/llvm/llvm-project/assets/4731128/116b84d6-5319-4353-8ed3-07430fb86d1a)

But correct output would be like:
```
main; 10144
main;f2; 4192
main;f2;busy; 5925047168
main;f1; 6976
main;f1;busy; 5941971904
main;busy; 5930714592
```
Which renders as the correct graph:
![xray-log main jFn5JW corrected](https://github.com/llvm/llvm-project/assets/4731128/df272bff-c7e1-4d83-bc6e-3b6914bd374f)

I.e., only leafs should have their total amount of time, and non-leafs should have the difference between their total and the sum of all their children's totals, because `flamegraph.pl` itself will sum each non-leaf's value with its descendents' values for showing each non-leaf's total amount of time.

<details>

<summary>More precisely: <i>(click to expand)</i></summary>

```
bad-val(STACK) = total(STACK)
total(STACK) = exit(STACK) - enter(STACK)

bad-val(main) =  17797754976 = exit(main) - enter(main)
enter(main) = 69839874297664
exit(main)  = 69857672052640

bad-val(main;f1) =   5941978880 = exit(main;f1) - enter(main;f1)
enter(main;f1) = 69845805019744
exit(main;f1)  = 69851746998624

...
```
```
good-val(STACK) = total(STACK) - child-sum(STACK)
child-sum(STACK) = total(STACK;CHILD-1) + ... + total(STACK;CHILD-N)

good-val(main) = 10144 = total(main) - child-sum(main)
child-sum(main) = total(main;busy) + total(main;f1) + total(main;f2)
                =       5930714592 +     5941978880 + 5925051360
                =   good-val(main;busy)
                  + good-val(main;f1) + good-val(main;f1;busy)
                  + good-val(main;f2) + good-val(main;f2;busy)

child-sum(main;busy) = 0
child-sum(main;f1) = total(main;f1;busy)
child-sum(main;f2) = total(main;f2;busy)
child-sum(main;f1;busy) = 0
child-sum(main;f2;busy) = 0

...
```
(Hopefully, I didn't screw that up.  I think you'll get the idea.)

</details>

## Reproducible Example

#### `main.c` file
```c
static void busy(void) { for (unsigned i = 4000000000; i > 0; i--) ; }
static void f1(void) { busy(); }
static void f2(void) { busy(); }
int main(void) { busy(); f1(); f2(); }
```

#### Build, run, and generate
```shell
clang -O0 -fxray-instrument -fxray-instruction-threshold=1 main.c -o main
```
```shell
XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1" ./main
```
```shell
X=xray-log.main.$YOURS

llvm-xray stack --stack-format=flame --aggregation-type=time --all-stacks \
 --instr_map=./main $X > $X.flame

flamegraph.pl $X.flame > $X.svg
```

Note: I've also had some other similarly incorrect flame-graphs from my much more complicated programs, that were compiled without `-fxray-instruction-threshold=$T` (i.e. where that threshold was the default larger one), but I didn't analyze their (much more complicated) flame output to prove the incorrectness for those.

## Versions

```
$ llvm-xray --version
LLVM (http://llvm.org/):
 LLVM version 16.0.6
  Optimized build.
```
```
$ clang --version
clang version 16.0.6
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /nix/store/b3qg3lglka8s298plxfkhlaifw5njv5c-clang-16.0.6/bin
```
(Both installed via the [NixOS packages](https://github.com/NixOS/nixpkgs) `llvmPackages_16.libllvm` and `clang_16` (from the `unstable` channel, to have the latest version `16.0.6`).)

Version of `flamegraph.pl`: `d9fcc272b6a08c3e3e5b7919040f0ab5f8952d65` (Git commit of repo).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0WFlz3Dby_zTQSxdZJHg_6MHSeBL__4mdir05nlQg2SQRgcAsAWo0-fRbAEnNRdnyVlbl8sygrx_6AhpMa95KxFuS3JFkc8NG06nhdoMDrx7f1zWXrVHyplT14ZbQiNAIPo99z4YDCTYkeDf9_6VDkGNvheCJiRE17AZVjxXWUB6ApIEQT733PLADaMOqR_A89-k1auiZIdGmEaxH8DzWtgO2zHAlPXPYIYk2hk8UISYhTdIA2IDAZaWGASsDJVZs1Aimw4MjmQ7BKMMEsF6N0oBqwOnRO5QGuARkVQfNKCtritB7KEcD1gtp4LC0A9t1_k6QNCDJhtC8M2anSfSO0C2h25abbiz9SvWEbssBZc2kRd4Sut1a-R-sPKEFSMRaW0AaF-cYBVxqg6yGEkFJcXCAV6HW3O5QHK4wAz5XYrQRAiYPF7tbmDRUTIgpDOx8u7PLVvYLtUIN3GhQewl67HtrRDXOPqGZnl1rTfqneTBnyAZ1NfCds3RC3arBbZMkdwNO-cFLgYDPrN8JtCnTDqyfvE1odMrkzUzWoS1_QgkNG0yHA5Qo1N6G5SIfj8mhRrMbDXANgj_ikTUN5n_uZ8-4JNEdhFlWZFkSF1l6RmiopSYFTYIkjC6kHLEc9eGFJ87CND_nCSdiHBZZnufBNfGowPKERRCf8RzJUZCFcVLQ1Y383vGqA5uROGhgGpg8cYYL89EHNCTJna1LT6gWrCH4ayuT__v9mzlvK3r-8HaD-gsrQ-iWaY1GE7qNsygMbRi3YZiWeVynXhKFhRdHSeTlWEdekMVR0JR5WoeM0OI0fnejgYvo7dUoXLW8KYZBGMcr0YvDxWffHbf0Kh_-hxGzVfK9AVsEsP7nQlc3NKNl03hVhqEX13nklVWKXlSmRRiXdZTFzUXoPvjo2_bimppA1mjQnYtdx55cX-bDame2QkzWIJX0VuWg5k2DA8oKoUSzR5Tn6mTt2PTYW51MiJlcdVzUA8pj59LfaoDcaBQN7LkQTp9rvAsyp8d1cthz07lGWaOubPyk9WC29PlGDXYXe9s-r1WseeG8nUb3NRrGhSbR-wuCnk_h6P3ParC9EyuuURxI9A5IdM-tBM0rwatHe9zg847J2sYquid068ju21HPmYHzBC1Z7T0xQWj--cu7-_-3TZhEm2kDJ4sT8-WqY8Vnbk7XPEBpcLgSvrTnCmnWcdqaT5UuPEed88qk7GLRSaZFHhV5FtMiS9O5Zi-0LXxJlmY0SGgaB1-B6PrBgvOkyV_hXBgvwM7LK4hPNadFHid5kARhkcUrsBfeF-xhFqdFkac0PsXu-_5qmC9-tkq9KezgTSXm6bG_CugaZUVLdHf_44efNt60VXoHvu-7z3W2jxcJcwL1NMzuHDizdsyVU2Bn-bJCuFYx9_YZ7AWpCV8j0BcrcPE3JQ645FkOC6cCLvKJXl9C1nVd-uQF8roQONXXQsfNrNL-W630K1rppdZXAnMShGgDwatcxwK6DtSFpTVp-pr0Fc5122-GSddZv1G0NP9R7bAZhTjYY-0D1Ly2Z50BXQ24B9MxA-POB_gApuPyEQ5qJDQTAlo07sjkNTL_wtvT8fDK-TPd8389vcW_ny_oV2wzM0kDu0-_sudrw184l91U029tmLFTpOI1TL7I7XfnkuzOnaiE5qN0Y2sN3DkqDpY_e9uya-9h-up5kzPvgGSbaws2M870zybdQfmaDH2bDJcGpv7xFW4HYPlOV7RcRvvasXcjF7WN_DDK5RLVosSBmUsf6w6FmPNPMNmC9ykAr3HXSTuQDmNv58ezlWoaxbsBdadETaJNCFMgwVPTBr96lpzY_OPXd38-fPrly4dPHz-TaEMo3TFTdQ-7AacS2JhhRLDGH3pV29nfASmZts7HoVSam4OFQCgFn9Dt99lfFArV-m4PhMZ_fvrXr59PnfuPPlUASe7nzuhNDn3o2Y5EmwU8EBr_4RLWfvGd7lM0Z1fTE56jiH5qv5IqH5Wx4xJ8IDR7QmBCK-hYDVr1CMpN0Jr3XLDBPTEsU4ez4Tm7GppB9dAfoB-rDnp73axUvxO8YgbrZWx3d2rXa_Y4c3CBtbsiq9HY-v9GXhEaf7HNgdCc--jDvkP3ksNsk5rZYD-PRzU2bBQGBBtaHEBJtJUzP-Oc9EAmmTj8vQwettmubcIW5-TWedw0yu5rHjxe3CJRT5d60ym9-vTxGw6aK6m_cpkmNIZjjnne0yQyEX_66befYZ7eXoY3y-2roXW_ipdZEBzzLA5h6gd-upzCn3aG9_xvtE2Ui_pN9z0LbG4L56CmxTVDX6z3jc2v5zx9SGNvlI9S7aUnuByfvVaOy4PMgKwGW9TCcu-U5s_zwCi1cU9UGz644YVuJX-2k4lRAxK6LaN_t5FoxSPLNS3ynXhuHjvBeLNP5F9PSeU5eN4Mi27L1zoCze-UHdcWg_DE2fIg9ZE_f_oMO1Y9shb1Nydoxz4h3T222vX26ZHzl1nFQ5j6gpdu1E4D15TtIWehPoTpnOausByCNBgtrFKgJVUdkxKFqyh1HIAFM6jNSyBIGsybTgNCi8sDfE5FO1muvWlaV6dBXTRVZYf8lAV5FWGESZkVYRHEQROwMmnyIqF1msyAf-DGlk3P3cA64E5Zwzf1bVQXUcFu8DZM8zwJ8yIIbrpbVmJWFIxhXddJmuZRTKsoTTJMi4ymWXPDb2lAoyCzI00QxoHfVFmcB2lWMlrHDaYkDuzZIPylBm641iPeplGapTeClSi0e7umVOIeHJFQSpLNzXDrqqwcW03iQHBt9FGL4Ubg7fGhVp_2PhuVN79ZkzS4GQdx-93vLQ6rJnTr9vKfAAAA__9_2u_D">