<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/62051>62051</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
InstCombine drops debug value when sinking select
</td>
</tr>
<tr>
<th>Labels</th>
<td>
debuginfo,
llvm:instcombine
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
jryans
</td>
</tr>
</table>
<pre>
The `InstCombine` pass sinks the speculated / `select`-based computation of `st`
down to the end of the function. The `st` debug value is then set to `undef` for
all locations before the end of function.
It should be possible to use e.g. `DIArgList` to keep the value of `st` alive
for the whole scope.
## Versions
* Clang: version 17.0.0 (https://github.com/llvm/llvm-project.git 5b461d5ec172d21029da492064704fe3da6f8bab)
* LLDB: version 17.0.0git (git@github.com:llvm/llvm-project.git revision c820e60844ee1e5f084dd7761576bd0bd4927264)
## Compiler Explorer
* [Optimisation pipeline view using x86-64 Clang trunk (may change over time)](https://godbolt.org/z/TsWfeoKEf)
## Program source
```c
#include <string.h>
char b;
int a();
int c() {
int st = a();
if (a())
st = 1;
if (strcmp(&b, ""))
a();
return st;
}
```
## Debug info view
```
$ clang -fno-discard-value-names -fno-inline -g -O1 -c -o example-O1.o
$ llvm-dwarfdump -n st example-O1.o
0x00000096: DW_TAG_variable
DW_AT_location (0x000000f7:
[0x0000000000000019, 0x0000000000000029): DW_OP_reg15 R15
[0x0000000000000075, 0x000000000000007e): DW_OP_reg0 RAX)
DW_AT_name ("st")
DW_AT_decl_line (28)
DW_AT_type (0x0000003d "int")
$ llvm-dwarfdump --debug-line example-O1.o
Address Line Column File ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
0x0000000000000000 27 0 1 0 0 is_stmt
0x0000000000000011 28 11 1 0 0 is_stmt prologue_end
0x0000000000000019 29 6 1 0 0 is_stmt
0x0000000000000029 32 7 1 0 0 is_stmt
0x000000000000003a 32 6 1 0 0
0x000000000000003c 33 17 1 0 0 is_stmt
0x0000000000000047 34 19 1 0 0 is_stmt
0x0000000000000049 34 7 1 0 0
0x000000000000004b 39 7 1 0 0 is_stmt
0x000000000000005c 39 6 1 0 0
0x000000000000005e 40 24 1 0 0 is_stmt
0x0000000000000069 29 6 1 0 0 is_stmt
0x0000000000000075 42 2 1 0 0 is_stmt
0x000000000000007e 35 4 1 0 0 is_stmt
0x0000000000000091 35 4 1 0 0 is_stmt end_sequence
```
`st`'s location range (shown above) is missing most of its scope after sinking.
## IR before `InstCombine`
```llvm
define dso_local i32 @c() local_unnamed_addr #0 !dbg !19 {
entry:
%call = call i32 (...) @a() #4, !dbg !25
call void @llvm.dbg.value(metadata i32 %call, metadata !24, metadata !DIExpression()), !dbg !26
%call1 = call i32 (...) @a() #4, !dbg !27
%tobool.not = icmp eq i32 %call1, 0, !dbg !27
%spec.select = select i1 %tobool.not, i32 %call, i32 1, !dbg !29
call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !26
%strcmpload = load i8, ptr @b, align 1, !dbg !30
%tobool3.not = icmp eq i8 %strcmpload, 0, !dbg !30
br i1 %tobool3.not, label %if.end6, label %if.then4, !dbg !32
if.then4: ; preds = %entry
%call5 = call i32 (...) @a() #4, !dbg !33
br label %if.end6, !dbg !33
if.end6: ; preds = %if.then4, %entry
ret i32 %spec.select, !dbg !34
}
```
## IR after `InstCombine`
```llvm
define dso_local i32 @c() local_unnamed_addr #0 !dbg !19 {
entry:
%call = call i32 (...) @a() #4, !dbg !25
call void @llvm.dbg.value(metadata i32 %call, metadata !24, metadata !DIExpression()), !dbg !26
%call1 = call i32 (...) @a() #4, !dbg !27
call void @llvm.dbg.value(metadata i32 poison, metadata !24, metadata !DIExpression()), !dbg !26
%strcmpload = load i8, ptr @b, align 1, !dbg !29
%tobool3.not = icmp eq i8 %strcmpload, 0, !dbg !29
br i1 %tobool3.not, label %if.end6, label %if.then4, !dbg !31
if.then4: ; preds = %entry
%call5 = call i32 (...) @a() #4, !dbg !32
br label %if.end6, !dbg !32
if.end6: ; preds = %if.then4, %entry
%tobool.not = icmp eq i32 %call1, 0, !dbg !27
%spec.select = select i1 %tobool.not, i32 %call, i32 1, !dbg !33
call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !26
ret i32 %spec.select, !dbg !34
}
```
## IR diff before and after `InstCombine`
```diff
@@ -3,17 +3,18 @@
%call = call i32 (...) @a() #4, !dbg !25
call void @llvm.dbg.value(metadata i32 %call, metadata !24, metadata !DIExpression()), !dbg !26
%call1 = call i32 (...) @a() #4, !dbg !27
- %tobool.not = icmp eq i32 %call1, 0, !dbg !27
- %spec.select = select i1 %tobool.not, i32 %call, i32 1, !dbg !29
- call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !26
- %strcmpload = load i8, ptr @b, align 1, !dbg !30
- %tobool3.not = icmp eq i8 %strcmpload, 0, !dbg !30
- br i1 %tobool3.not, label %if.end6, label %if.then4, !dbg !32
+ call void @llvm.dbg.value(metadata i32 poison, metadata !24, metadata !DIExpression()), !dbg !26
+ %strcmpload = load i8, ptr @b, align 1, !dbg !29
+ %tobool3.not = icmp eq i8 %strcmpload, 0, !dbg !29
+ br i1 %tobool3.not, label %if.end6, label %if.then4, !dbg !31
if.then4: ; preds = %entry
- %call5 = call i32 (...) @a() #4, !dbg !33
- br label %if.end6, !dbg !33
+ %call5 = call i32 (...) @a() #4, !dbg !32
+ br label %if.end6, !dbg !32
if.end6: ; preds = %if.then4, %entry
+ %tobool.not = icmp eq i32 %call1, 0, !dbg !27
+ %spec.select = select i1 %tobool.not, i32 %call, i32 1, !dbg !33
+ call void @llvm.dbg.value(metadata i32 %spec.select, metadata !24, metadata !DIExpression()), !dbg !26
ret i32 %spec.select, !dbg !34
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWUtv4zgS_jX0pSBBol72wQcnbi-CbaAHvY2dvRmUSMmclkkNSTnJ_voFScuWHxnE6QSTwwpBLFNVXz1YqvokE615Ixibo-wOZcsJ6c1Gqvkf6pkIPSklfZ7_2DBAefQgtLmX25ILhvIIOqI1aC5-ajAbBrpjVd8SwyggvLLymrWsMiiPgpJoRqGS2643xHApQNZOwl5F0RJFCyofBRjpoJigVsCe1r2orEIIeyecClBW9g3sSNsz4M6-AM2MBUB51AvKaitWS-XRSdtCKytnW0PJaqnY2NTBjBf3_x8M6I3sWwolg05qzcuWWRO9ZsDCJrS2lg8L1Xzl3i0j4SdjnUP2zo3iBNLyHfPQtVRO6HEjWwa6kh07MY1wgnAC_2ZKW49PLy3gviWiQckCdl4A4iKMwggQnm6M6TRKFgivEF413Gz6MqzkFuFV2-6Gj6BT8g9WmbDhBrIyzWOasSouMMVxhGeUpDMc5WkRpTVLKMnraUlKhGdHF75-Xd5demDhEJ423KA0GhlPFi8ZV2zHHUA1xRHLo2maMhazrI6mKaVFkcdZkZc0Kmk6wwXO06MX40zdy23HW6bgy1PXSsXUecpQdvetM3zLtS_Ajnes5YLBjrNH6DUXDTxN8yBPfXbBqF78tMFsyTNUGyIaBnLHFBi-ZdaJbHmZbklL2ZpQqgbh1X8RXv3Qv9dM_vNLfd3t35RsFNmClr2q2IlAHvm_6qDARdX2lAFK7rVRXDThBiVf_OVqQxSUKLnzX7kwQBCeWqvjtcqvASr2iwB2WRtAyfJCA4DXNgPD-hACAAwq8YWwNqradk4jLxG-B4Sx-zvVv7SlmOmVAG0Oa6hYniXjSgqXrhVwUUu3lVdzOCikULm9DWohA8p1RRQN3I0aCLJl2l_gwhVG0EDwLYaggkACeyLbrmXBtziURzRXzfSRqJr22w4C6_0V0egpcscst3fM8vf1j8U_1juiOClbdkzJ8Vj-vl78WA8Ny64gPB1Q6sLWm9dC2d2wPBzxzCb9fNVn31v_9ttasSbO4HucvYxTZNdwCnaOE8H3xX-OW-tdt9kcgnEbjbXZF8GL4VJWtWuXeafjy2MMap67MejgWmIHDubixMC13Qnc1AicictNWlCqmNZjv756Z-5l228FrHhrvz38awFLrivFt1wQIxWsWtLsW3RwccBLH3BNbH-cls3xcF7hwnvnv0HsTiMArtfabM113Tj2ulOvE1_XhU7JVjY9WzNBXwCaeSD_AfktTuyVEuyVirHu-Ij-GiYhJzCnLrygUnmVxIu-1XLqFZPUq8_eCjMbw5zm4YUA0tKrzH4tdVl1AvOa1GX-nkv3xZe-0XL-F3VzA0yReW_2e4_fCuODSjwavDWoWfxamMMdxgRda_Znz8Rh3l8dbgM5xoU-MFdQjoXYIbuxdJmUcmf7saXAW64dh9lKbSzr5EZ7XgmkNkw5om4pw5UJ-vB9YMQXJP_qNHVUzpN2VtsWSbV0w6oFnmBAaTTQDLe47oUdB3RNKFWAcGJ5akzLxn7EIy7ChFHPx9kGCGeVJe6WZ7gTh46nYRg6DpNGZKAzOEk91Rhw8TDZnOJOcmrlrechLZvQzXzL7ZghlBiyh3b2LNBh3UKl5yvLhy9PnR0WXIojNTq1n59FEb8tjGIY0DgzspSyDYX0zItX2w7Yn2PPYzexX0CwQvYZLfSPZQ5jf8rjU3yLcJYQ-zU-Qz7M8ttyPHLi_VPt2WcrCXUBuhM-tQqdUdY9R0lJyxtxHk8SjXB8MpLLbE9PrVzJ-BGnVCepTYbctqRkrV3ndcgEzc_X7OPsWSEkeHwrHmSSBaDkDjrFqHZ-Ipz52-i0-rI3VV-SjCK55vSl6ME_J3LNvdP4Tr1VzLxQJSNL6Q0PBw_f9-3v_53ts3a2G8LoJNfWr0_UNI5N8NeaxhHnPZtG_Hc0Dfz6pnHe1N7SND7hZDz2zc8yGT-isVJe1wNxJILe1Git7n4pjVAaQZAgfB8XgPCdO5uCv3B4XfAuLfPWDfmApvk-XTOAX6_74OMoYfBZKj94L1IYvBcrDD6GFuK7v3mQWg_eaZYOUO8wTh3Uh01UeO1IDd6JiAe3MPF9Fn99kg9JvGWYw2iav_q4Yeyf1shbW-ChaD9i-jvwz9EG4TYGAJcUYELnCZ0lMzJh8zifxnE6zZNkspknGaFlmmR1nGZxlZYkYlk0LfOSkDxJUzzhcxzhJErjKC7SJEtCXGZ4VsQVmc6mLK1TlEZsS3gbuvRI1Uy41j2b5zjK4okrOu1-nMbYvcDnopbuVf89wtg9sSULLrSp9pQDY5QtJ2ruXv-XfaNt5rk2-mjAcNOy-YinAFWy0yc_Kz-635T9W7N9QUx61c5v-4EV4ZWLRiO8cgH9LwAA__-1mGVj">