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

    <tr>
        <th>Summary</th>
        <td>
            [Debug] WinDbg and SCCPPass leads to variables being "optimized away" in certain cases.
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            debuginfo,
            platform:windows
      </td>
    </tr>

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

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

<pre>
    I have been tracking an issue where a lot of our developers report that variables are usually not inspectable when in lambdas or other smaller scopes. We reduced one of the problem to the following test case:

```
#ifdef __clang__
#define OPTIMIZE_OFF _Pragma("clang optimize off") 
#define OPTIMIZE_ON  _Pragma("clang optimize on")
#else
#define OPTIMIZE_OFF __pragma(optimize("",off))
#define OPTIMIZE_ON  __pragma(optimize("", on))
#endif

OPTIMIZE_OFF
void foo(int param)
{
        (void)param;
}
OPTIMIZE_ON

int main()
{
        [&](int param)
        {
                param++;
                foo(param); // place breakpoint here and check 'param'
        }(1234);
}
```

If you break inside the lambda here you'll see that you can't inspect the variable `param`.

With MSVC I build with `/O2 /Ob0 /Zi` and I can break inside the lambda and inspect `param`. With clang-cl I build with the same flags and when breaking there it says the variable is "optimized away".

The PDB information is pretty similar for both clang and MSVC - here is the output of `llvm-pdbutil dump --symbols`:

Clang: [full output](https://gist.github.com/tru/9b618a8987c31b4c0b1fe5715df92fa0)
```
     352 | S_LOCAL [size = 16] `this`
           type=0x100A (const main::<lambda_0>*), flags = param | optimized away
     368 | S_LOCAL [size = 16] `param`
           type=0x0074 (int), flags = param | optimized away
```

Note how it's flagged to be `optimized away`. Both for `param` and `this`. I specifically investigated `param` here - but the fact that `this` is not available when breaking is also a bit annoying.

MSVC: [full output](https://gist.github.com/tru/3ccd3c8ae51a4c1a0f78e0d10482c826)
```
     508 | S_REGREL32 [size = 20] `this`
           type = 0x10F1 (const main::__l2::<lambda_865e41...), register = RSP, offset = 8
     528 | S_REGREL32 [size = 20] `param`
           type = 0x0074 (int), register = RSP, offset = 16
```

I also inspected with the new llvm-dva util:

Clang
```
Totals by lexical level:

             {CompileUnit} 'simple-lambda.cpp'
               {Function} extern not_inlined 'foo' -> 'void'
                 {Parameter} 'param' -> 'int'
    11           {Line}
                 {Code} 'pushq     %rax'
                 {Code} 'movl      %ecx, 0x4(%rsp)'
    13           {Line}
                 {Code} 'popq      %rax'
                 {Code} 'retq'
               {Function} extern not_inlined 'main' -> 'int'
    18           {InlinedFunction} inlined '::18' -> '<unnamed-tag> __scrt_narrow_environment_policy'
                   {Parameter} 'param' -> 'int'
    17           {Line}
                 {Code} 'subq      $0x28, %rsp'
    21           {Line}
                 {Code} 'movl      $0x4d3, %ecx'
                 {Code} 'callq     -0x1e'
    23           {Line}
                 {Code} 'xorl      %eax, %eax'
                 {Code} 'addq      $0x28, %rsp'
                 {Code} 'retq'
```

MSVC:
```
             {CompileUnit} 'simple-lambda.cpp'
               {Function} extern not_inlined 'foo' -> 'int'
                 {Variable} 'param' -> 'int'
    11           {Line}
                 {Code} 'movl      %ecx, 0x8(%rsp)'
    13           {Line}
                 {Code} 'retq'
               {Function} extern not_inlined 'main' -> 'int'
                 {InlinedFunction} inlined '::22' -> 'void'
    17           {Line}
                 {Code} 'subq      $0x28, %rsp'
    18           {Line}
                 {Code} 'movl      $0x4d3, %ecx'
                 {Code} 'callq     -0x1e'
    23           {Line}
                 {Code} 'xorl      %eax, %eax'
                 {Code} 'addq      $0x28, %rsp'
                 {Code} 'retq'
               {Function} inlined 'operator()' -> '__int64'
                 {Parameter} 'param' -> 'int'
                 {Variable} 'param' -> 'int'
    22           {Line}
    20           {Line}
                 {Code} 'leal      0x1(%rdx), %ecx'
    21           {Line}
                 {Code} 'jmp       0x8'
```

The one thing that sticks out here is the fact that in MSVC it shows up `param` as a variable - but I am not that adept at reading the output of `llvm-dva` yet.

Anyway that lead me to look at the actual IR/ASM to see if there was a huge difference. The thing that struck me was that LLVM converts the `param` bits to a constant. You can look at the compiler explorer output here: https://godbolt.org/z/7ffoYaEEc

With some `--print-after-all` the pass that converted the variable into a constant is the SCCPPass - so I disabled that pass just to see if it fixed the problem and it did. With that pass disabled I was able to debug the `param` variable correctly.

I have also tested opening the same file with lldb on Linux and in there I can debug the variable just fine.

This leads me to think that this is either
1) a problem with WinDbg and the fact that MSVC doesn't do constant folding here might just lead to WinDbg not really handling this case?
2) something in the PDB writer in LLVM. Maybe the "optimized away" flag is added to often?

Interested in hearing other people's input on this: @zmodem @joker-eph @djtodoro 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWV1z4rgS_TXkRQVlbMzHAw8JJFupSiapmbkztftCyZYMSmTJa8kE5tffbsmAzRAmM9nZp02REGTp9JH6dEtqEs2201uyomtOEs4VsSVNn4VaEqqIMKbi5GXFS04okdoSnRFdlYTxNZe64KUhJS90aYldUUvWtBQ0kdwQCiMqU1Ept0TBOKFMwVOLDxEPoBWRNE8YNUSXRFuwQUwO_fE9BWjTI185oLMq5YxoxdE2dCNFqQElJ1a7j5mWUr8gYcuNJSk1vBNddoJ5J9j9HQb1y38MI5ExnpHFIpVULReLfTu0CjD08Pj59v72r-vFw80NWTyWdJnTTjjuhKEbQHRhRS6-IaMMGjvhhLwO8YGch1AeYQ_AJUzgLKFFsYPboXhk95o5TpMm4klK50EcrRYIV0xkzVVtcvItay0YuEMDkFCWFLSk-QFidLUbDbhj7AvPfJ9o92g0P8b-0DSJqDkVyjE9hRtfdcJhJ56fZgAdmp2D2np4ha-o9cTPYj8-uiKd8AZepJA0hUApOX0uNNrwsaEYSVc8fYZuo3rUqGEVCfXDaOCxjiZ7LE_39zYjW115Qxg8gnGndh8z3ip0ADNSEsO5jz8cklJYn9E-4tyoXVwSsOLpDYNe09xXYVfk_tOXGbklSSUkIy_YgqTCm4cQZ_-QBPj2l4BGN-FbNPUqQ-yxo9C0SpwpFwTdVLbN4XBDc4hpSZfGQbhc4Wy4CHfzFhZ6bU17ZsIAu3CnZUboC91CQ2uWn2HA4_wKeGW6zKkVGlMcJBRu7ZYYGClpCQouSaJ3JB0LtzJdv-rCG9aVLSqXD2FWUq7zbsGSygpJWJUXpNs12zzR0uASttPRDGGhjYBcswrc56G8bFfWFgYHOLkthbG9JSxNlfRSDaK6sSX4_GaSDPtjOp6MR2nUTwZpkPQzHo_6McsmYUaDg-bb2iL4E8Xgz9GMfFrcPcwu75CGwUzUieakj9GDM7IrYdrD_I_dFpBe58GmH0A7EE61MnVUAmt8zbwCFjDv60546fLIrHYp2nBScAyOvNWgOBz_mOJOUq9zDILRgPhc8JMsTsbkB205WekXECBEmHFgSxgGG1HiQusICdV-hUJCRTUIO0kd1rgHQYBxIjKRuv1SqDXsZGJJLWetcU5_XYgYH9UZTet99wCG8sT9lq4piHm_2-4jCB5TaTTs5gmEEVVKb6G5FSUo9vfJM0pTFqVjyuM-HaR9GmSjMQ9YPxiMw3QMGfqcPONg5_uP1398vL6Lwpb7w-ANCnU9UaM3_VMaXSxkeKzW8TDmg36v16uVUnKcHRxGEOrjp0e3KWaZ4da1jJuMw7cxPivYmvL3kv0BEQiHM7uId3adh3kjzSr-QlzWYmtKMG2dTFKnkD9rC6Ak2RLJN6hYeIfD4NF40vyBbXem80JI_j8FsTOa4zYJ6baQvOuXv5cWxX7LJOR49E2lUszWOJRvYDEUinwhlISDDUM0t2GPSBdyDn70x4vTeA7xEX3BAalms9u09wjOAQ2Afr8NcAeW91v4KQszzfgOvDKrv925Jy7p5iyvxqhcr6UfxNMNej3YDNzJJy5N4cTRpBe9g54ufp4d7Jl_v8tj_iB3ZsHHbcRbP7QJ3EDz4dwfNxEhuCulwM2sa-kSGxcLk5Z2oWhZ6pcFV2tRapVzZReFliLdvj75XxTN6Ne9YqrEe2UQbNDrM7LzfMNA-A5V7vUFBgYsqi04rb1NArhbIcUuZFrepvUONW50uZM93exIvV2XlLEfL9uZ8S1dn0yq9f74-g7WAv5X096x_o4Bv9Sn5X8j6Z1IX-Pfkr5-eyY6RnxLJsJb9Jnt6LcnhuPs-V9i-EcTw_c9X1ED1sio1WVdsmhoYgEStMPBP3tKOQb42YAPwx_4Jwx-3YGSU3QgiKLOA2xTn3FPyOs9O9tTXjg74_OJHMsBWFeEm4SrLcBFCq5d6bPBK0_rsn-4aQnliwFYg4CroCFV0b7awf3qUJTwdzU4hefuUuYQKOMF_LVwsKesLmqcqCbAuRzxtty2LmeXagtXS48E68lIzvH-KbV-RkzEAq4VnMpvP8JN7PLTPT7GApHI6vLJi-O4qpacMJFl0KRS3iO4Gq2VKKv0GeGxv2u6u_tyT-Auteal9evSnDncJw3aosRdt6iyPfKnr0e16KV-SywhGRdSl_BPPXkkh_fOozumZomWtqfLJXz6Br-jLNN_0uvr9LsCltG549TtFiUou0szCJ0uJCPk50rH1NRzqaeBt_dWFUm1ZrDz_6fZ7PERx3bBBviTCYPdmcdyqE8VXDEPSw36yMSmht9VrF1NzMJoVpfBDsP3iLfeP0gG0BhPquV3S72nm-qyhIud3LY0Ulfz3dUPa-JYPi-42mnNV9gElgaQg5QsgTAgEGDVpi7b1UrxFb4Dh71dN1ksKh-V12C5UJSmViXK6dlPEm_ruJpcILTv38fCOd2vjmPzVah54otu7cBzUcc0N766yfTBSZmWLpAc51wsV9YTdPEBNGpMjECIOaywrABf-vUATv4rg7qI7ar5KCQfC34tXNXwpRR4DYcWDIQeuafbxJc8TxUeXXXIlVsY8zUiDWpUezu1qxRAehcB7orDAuOXA-7bkIJrOCm6SpNQLjsox9fVZgbBtxwSXo7_PelnkDkvVviBPVnNdKnJBZtGbBJN6IUVVvJpJ76aoyexGNFY5b20veOA5-FLnIQjm5OzA7YpxA_Fd1g-07uoSjk9Lg81KkOY1Oo3iE79BLKFj-4LJgP_xPEkHl-spiEbDykPsyhK4oQN-0nM40maTKJBmGVhOLyQNOHSTF2pP3TSxGpu_a0FvBWSWqzuAosXoRikaHwWzy_ENAzCMBgGk34Ux_24Fw7CgI3TEQsnIz7K-rB4HI6CsoccMd9clFNHF2wYeCiFsebwENZMLBV3C4v4tLIrXU4hbV64WU3dlP4PU1-7IA">