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

    <tr>
        <th>Summary</th>
        <td>
            SimplifyCFGPass makes constant-value variable not available when debugging depending on the code following its declaration
        </td>
    </tr>

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

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

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

<pre>
    
In this minimized C example, variable d, defined within the scope of function c, is not available on the call site upon calling the externally defined function test. This happens at every tested optimization level (-Og/-O1/-O2/-O3). 

>From opt-bisect-limit we found out that the pass that drops the variable’s value is SimplifyCFGPass on function (c). If we stop the optimization pipeline right before it, the variable is visible with its correct value available.

Interestingly, the issue is not present anymore if we remove the loop at lines 8/9.

We provide an analysis of the IR at -Og on x64.

We tested clang and lldb 14.0.0 commit 116dc70 on x64.

```
$ cat a.c
int a;
char b;
void c()
{
    for (; a <= 0; a = 9)
    {
        int d = 8;
        for (; b ;)
            nop();
        test(d);
    }
}
int main()
{
    c();
}

$ cat lib.c
#include <stdio.h>

void nop() {
   printf("\n");
}
 
void test(int d) {
   printf("%d", d);
}
```

LLDB trace:
```
$ clang -Og -g a.c lib.c -o opt
$ lldb opt
(lldb) target create "opt"
Current executable set to '/tmp/opt' (x86_64).
(lldb) b 10
Breakpoint 1: 2 locations.
(lldb) r
Process 160 launched: '/tmp/opt' (x86_64)
Process 160 stopped
* thread #1, name = 'opt', stop reason = breakpoint 1.2
    frame #0: 0x0000000000400580 opt`main [inlined] c at a.c:10:9
   7            int d = 8;
   8            for (; b ;)
   9                nop();
-> 10           test(d);
   11       }
   12   }
   13   int main()
(lldb) frame var
(lldb)
```

IR before SimplifyCFGPass on function (c):
```
@a = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
@b = dso_local local_unnamed_addr global i8 0, align 1, !dbg !6

; Function Attrs: nounwind uwtable
define dso_local void @c() local_unnamed_addr #0 !dbg !14 {
  br label %1, !dbg !22

1:                                                ; preds = %10, %0
  %2 = load i32, i32* @a, align 4, !dbg !23, !tbaa !24
  %3 = icmp slt i32 %2, 1, !dbg !28
  br i1 %3, label %4, label %12, !dbg !29

4:                                                ; preds = %1
  call void @llvm.dbg.value(metadata i32 8, metadata !18, metadata !DIExpression()), !dbg !30
  br label %5, !dbg !31

5:                                                ; preds = %8, %4
  %6 = load i8, i8* @b, align 1, !dbg !32, !tbaa !35
  %7 = icmp eq i8 %6, 0, !dbg !36
  br i1 %7, label %10, label %8, !dbg !36

8:                                                ; preds = %5
  %9 = call i32 (...) @nop() #3, !dbg !37
  br label %5, !dbg !38, !llvm.loop !39

10:                                               ; preds = %5
  %11 = call i32 (i32, ...) bitcast (i32 (...)* @test to i32 (i32, ...)*)(i32 8) #3, !dbg !43
  store i32 9, i32* @a, align 4, !dbg !44, !tbaa !24
  br label %1, !dbg !45, !llvm.loop !46

12:                                               ; preds = %1
  ret void, !dbg !48
}

declare !dbg !49 dso_local i32 @nop(...) local_unnamed_addr #1

declare dso_local i32 @test(...) local_unnamed_addr #1

; Function Attrs: nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #0 !dbg !52 {
  call void @c(), !dbg !55
  ret i32 0, !dbg !56
}
```

IR after SimplifyCFGPass on function (c):
```
@a = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
@b = dso_local local_unnamed_addr global i8 0, align 1, !dbg !6

; Function Attrs: nounwind uwtable
define dso_local void @c() local_unnamed_addr #0 !dbg !14 {
  br label %1, !dbg !22

1:                                                ; preds = %9, %0
  %2 = load i32, i32* @a, align 4, !dbg !23, !tbaa !24
  %3 = icmp slt i32 %2, 1, !dbg !28
  br i1 %3, label %4, label %11, !dbg !29

4:                                                ; preds = %1, %7
  %5 = load i8, i8* @b, align 1, !dbg !30, !tbaa !33
  %6 = icmp eq i8 %5, 0, !dbg !34
  br i1 %6, label %9, label %7, !dbg !34

7:                                                ; preds = %4
  %8 = call i32 (...) @nop() #3, !dbg !35
  br label %4, !dbg !36, !llvm.loop !37

9:                                                ; preds = %4
  %10 = call i32 (i32, ...) bitcast (i32 (...)* @test to i32 (i32, ...)*)(i32 8) #3, !dbg !41
  store i32 9, i32* @a, align 4, !dbg !42, !tbaa !24
  br label %1, !dbg !43, !llvm.loop !44

11:                                               ; preds = %1
  ret void, !dbg !46
}

declare !dbg !47 dso_local i32 @nop(...) local_unnamed_addr #1

declare dso_local i32 @test(...) local_unnamed_addr #1

; Function Attrs: nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #0 !dbg !50 {
  call void @c(), !dbg !53
  ret i32 0, !dbg !54
}
```

In the IR before SimplifyCFG, there is a llvm.dbg.value() intrinsic call that defines the value for the local variable d and this is not present anymore after SimplifyCFGPass. Apparently it completely removes the node where the value definition is done, thus making unavailable the variable’s value during debugging.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztGdlu67bya5QXwoL25cEPSXxSBCjQ4vYC9_GAkmibrUypIp3lfn1nRpJNyXKac06KoothyCI5-8YxWTTV69rxNo53-6iY2UvNDlLJg_y_qNg9Ey_80NbCCe7ZE-8kL2rBKhxVYisVgDxLwEFEwXTZtII1W7Y9qtLIRrESIYGiagzjT1zWhN_04CWva6alEezYIiwMpdrRkngxolMw8Xric6JphDYu-y8KuudtK5Rm3DDxJLpXWgPYpjWoACf4GpZq5gTZ6oedEzysfvDpGdAzdILcZb36_fOhaw5IYFVILUqzqoGSYc-CbZujAtJHAxJyQ2K2XOt-VHVNq2lutJLzKXAyz8lzDVP1UaAZfpJgS7l9vX_47kdEBelOaoGAJQnzuEVu2jQt0Zvo0spWgJEE6-Rub1ghtk0HlA2a2WaOzJ6klviKDgIQzcqm60CjQZyTO1xb-0cFhgcjgiPq15Gq1LqXH93YwrJQ4E71eiDmJG4nDs2TIOi6AcnBJCinZhmYOZ-w-B_YrWueZAUyKPjy-lUDbQgbxH78D-KCq9A4L0k0Rx08XNYcQoWDQ-q6KpgfuZ7rgYYHdJbvJ1WZeksUnMQbvv0wiCDuQBm37CckauaEd_2o3POOFafhUyMrDGnQKR_w02GJwQd8gV4EcMaZE9474YZ542jD8hMWAk8w8YOcKwLMTgzHNYtywXDVpjR-VNMOos3R0WawVM3XnHQzqrE5q3_gUl3VsZyxOJOY2LOWxWhRJwilKusjuBtsok0lG3fvhJ9sNDLsSf6JbdoOZNrSQuDE9wp_lvgzi9KgL1n0TXpBXNHPPauWlZpFCz2__35zx0zHS-GEb0QVBSjG8WqH4dWbhK0aTOgzGEWvNZPhBMpseLcThpWd4FAgQUoEAlkJ7v4ImQzaiRdRHg0lvAZg0wBgCglnDmDKB8JIMXBesuRzEmF1ueADuTNIfQesfmkbtJoPmrEAMrmksqMv0bp-5seuKQUUMj_xWM2hlO1Fhbi_I8YlMpa7FnAHPrdQC0AcyIcg9NE_ih8EJQeQ6gniLBVJgNNYP2GxsFRwAyszO0IPQg-F81680yfyvDjzyAOJh5HPnPhOKqxdlRNvWMmG6hDe-oh8zrvUzr0ryZvZMG8lcc5mn8tkXkHOgK8smCtp7fvD-jk3YDKYT4SD2BfpfnZybzbYU-Yrb2QH1O9hV3rHZnc1gSKvr5mVbj5jFNYUi_Xno8JAqD7zqurYrm4KWJFhAGUWooHXcqdYhK9O4FfFDn_OFIv3U8xsgv6UYDKpd-DMh1GpW2M6jQGmoFN4lrA3HZ8pOXvYvpGxBKBaBYINNXVJIAxZi7cf2bWs6CDnCupt4pmQY6Hon5TOX_hBzWCrr_SQdbHv9Sxib-QP7wGt1g1kKriBmj38uUW1-FWfBOEwNgXnNBFZNEOiKctDy3RtyL3ICVHmWmaWKaRPyAhxsko0GfnBDD23jRR9iJFGgai3HR1c108HF5i61HmBtw_C8IobTsplKNVpBr18MbN5_PSCfZeGMBtyFb-2MqG3FBbxDMi3NY4_QuNsiArbg4kVFbSOT4qJ4mpahcEsJsLYopieY0L8ivmJXBDBm1FJLiIincaANxlmy-j9M_sI-9ha5DRJodFHdea6LjUokWd1P0EYzsRK3-PbUReKNmrCcXYS47SFfaRGsNfMVRrqwKBZIU3JtRkWzioP8YBbGLYtS7gAQs9sSJIly0ThKAy0AvhnBEDz95ahKLpaht4orVG8ZOdoEjlQab7dzqda0kFrh6VkJke22IFXAjrPTtiAubXnkKHHaBt8tLzv-EtULwgNPcj7KX3TjjkwPbcs79gzcY8675mTujz-mZnY9RzfaPdTc2EBJHPDX-mD-Bb-S__bBv292qD8L98FzdH_iC6ot1Fq6RN_TU_gzSwUhhbFZKEniJd6gujCPsnEIvlklC5j98_0I8xjuzn72pYgXgr_WYSFyWJLkNoa5R-tEfxF_XNbgtO--TUtwbwLfV9LEC7ZOZpEjv8V1eeLW4KLnelaS5D-s1sC7wtbgtC2-1JLEM0Nv9gSqPGE-_KEZDhq7-iYnbOLf4yomFSmk0rLshe5v3cge4w3D3iuj8dM_TE8ba6nOxs6LKfrnSsH-Yvtistu25bjYWP9yqTBE_a2FkbAqD_y71mrphLsmeQ_S0KySfIqsKwaJXotj5od-C941XNU50uhN-9OqmOH8JUojrsdvA0HkjfVOqzyMOc3RpparOe9FrAReO-htOHKrHpaJ5NML6VAenVmAG-tUBW-jbdVqOK2qevmGWfxQqVPAToivTl29XpvTIux6wQP8N1JULVwwWIwQIcOP6u2a34WJeTIA12saHiJYVuOb_ZrL8_TNOGhKLNI-CLdVjzbVhnEi-A8jMUNlSC9duI7JwiUeO7vZuhsfHMj14EXBF4UJH7qZWHkJlGRBkDT98oqj7wUAlxAptQuxVfT7W66NYkEWms8qJDa6PMimBBqpBDEDujzo9k33brsAExyBcscfoy4ISHWpMRvDKuP5Q">