<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/61272>61272</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Reassociate stops tracking debug value after several steps
</td>
</tr>
<tr>
<th>Labels</th>
<td>
debuginfo,
llvm:optimizations
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
jryans
</td>
</tr>
</table>
<pre>
The `Reassociate` pass rearranges the various steps that keep adding to the
variable `heap`. For the first few steps, it produces debug value expressions
which keep the value available at debug time, but eventually it stops and value
debug info is lost.
## Versions
* Clang: version 17.0.0 (https://github.com/llvm/llvm-project.git 7de0804ea3290e5e43ce38567b4056a34ccad551)
* 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/17jGaczGd)
## Program source
```c
#include <stddef.h>
#include <stdint.h>
struct object {
uint32_t bob;
};
struct object_entry {
uint32_t bob;
};
struct packed {
uint32_t pack_size;
size_t index_size;
};
extern unsigned long count(void);
uint64_t e(struct packed *pack)
{
unsigned long nr_objects = count();
size_t os_cache, heap;
if (!pack || !nr_objects)
return 0;
os_cache = pack->pack_size + pack->index_size;
heap = sizeof(struct object_entry) * nr_objects;
heap += sizeof(struct object *) * nr_objects / 2;
return os_cache + heap;
}
```
## Debug info view
```
$ clang -fno-discard-value-names -fno-inline -g -O1 -c -o example-O1.o
$ llvm-dwarfdump -n heap example-O1.o
0x00000069: DW_TAG_variable
DW_AT_location (0x0000006f:
[0x0000000000000027, 0x0000000000000034): DW_OP_reg0 RAX)
DW_AT_name ("heap")
DW_AT_decl_line (22)
DW_AT_type (0x000000ed "size_t")
$ llvm-dwarfdump --debug-line example-O1.o
Address Line Column File ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
0x0000000000000000 20 0 1 0 0 is_stmt
0x0000000000000009 21 30 1 0 0 is_stmt prologue_end
0x0000000000000011 0 30 1 0 0
0x0000000000000013 24 8 1 0 0 is_stmt
0x0000000000000016 24 13 1 0 0
0x000000000000001d 27 20 1 0 0 is_stmt
0x000000000000001f 28 38 1 0 0 is_stmt
0x0000000000000027 0 38 1 0 0
0x0000000000000031 29 48 1 0 0 is_stmt
0x0000000000000034 27 30 1 0 0 is_stmt
0x0000000000000038 29 8 1 0 0 is_stmt
0x000000000000003b 31 19 1 0 0 is_stmt
0x000000000000003f 32 1 1 0 0 is_stmt
0x0000000000000046 32 1 1 0 0 is_stmt end_sequence
```
The variable `heap` has a location range that ends at `0x34`. Instructions past
that address both read from and write to `heap`, so the value is expected to be
accessible for the rest of the function.
## IR before `Reassociate`
```llvm
if.end: ; preds = %entry
%0 = load i32, ptr %pack, align 8
%conv = zext i32 %0 to i64
%index_size = getelementptr inbounds %struct.packed, ptr %pack, i64 0, i32 1
%1 = load i64, ptr %index_size, align 8
%add = add i64 %1, %conv
call void @llvm.dbg.value(metadata i64 %add, "os_cache", metadata !DIExpression())
%mul = shl i64 %call, 2
call void @llvm.dbg.value(metadata i64 %mul, "heap", metadata !DIExpression())
%div12 = and i64 %mul, 9223372036854775804
%add3 = add i64 %mul, %div12
call void @llvm.dbg.value(metadata i64 %add3, "heap", metadata !DIExpression())
%add4 = add i64 %add, %add3
br label %cleanup
```
## IR after `Reassociate`
```llvm
if.end: ; preds = %entry
%0 = load i32, ptr %pack, align 8
%conv = zext i32 %0 to i64
%index_size = getelementptr inbounds %struct.packed, ptr %pack, i64 0, i32 1
%1 = load i64, ptr %index_size, align 8
call void @llvm.dbg.value(metadata i64 poison, "os_cache", metadata !DIExpression())
%mul = shl i64 %call, 2
call void @llvm.dbg.value(metadata i64 %mul, "heap", metadata !DIExpression())
%div12 = and i64 %mul, 9223372036854775804
call void @llvm.dbg.value(metadata i64 poison, "heap", metadata !DIExpression())
%add = add i64 %div12, %mul
%add3 = add i64 %add, %conv
%add4 = add i64 %add3, %1
br label %cleanup
```
## IR diff before and after `Reassociate`
```diff
@@ -3,12 +3,12 @@
%conv = zext i32 %0 to i64
%index_size = getelementptr inbounds %struct.packed, ptr %pack, i64 0, i32 1
%1 = load i64, ptr %index_size, align 8
- %add = add i64 %1, %conv
- call void @llvm.dbg.value(metadata i64 %add, "os_cache", metadata !DIExpression())
+ call void @llvm.dbg.value(metadata i64 poison, "os_cache", metadata !DIExpression())
%mul = shl i64 %call, 2
call void @llvm.dbg.value(metadata i64 %mul, "heap", metadata !DIExpression())
%div12 = and i64 %mul, 9223372036854775804
- %add3 = add i64 %mul, %div12
- call void @llvm.dbg.value(metadata i64 %add3, "heap", metadata !DIExpression())
- %add4 = add i64 %add, %add3
+ call void @llvm.dbg.value(metadata i64 poison, "heap", metadata !DIExpression())
+ %add = add i64 %div12, %mul
+ %add3 = add i64 %add, %conv
+ %add4 = add i64 %add3, %1
br label %cleanup
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWU9v2zoS_zTMZWBDov764IMd10WBAn3oFvv2ZlDi2GYrk1qScpN--gVJ2ZITpy_xW-SwWCGIFHHmN78ZcoaciBkjdhJxTrIlyVZ3rLN7peff9SOT5q5S_HH-bY9A8ugrMmNULZhFkkfQMmNAI9OayR0asHuEI9NCdQaMxda9YRZ-ILbAOBdyB1Y5KRKtSLRwoqxqPPIeWUvyaAprpT3OVmhjYYs_AxKh9yAstFrxrkYDHKtuB0fWdAj40Go0RihpAvDPvaj3wWyg5KTYkYnGm2O2V7figA646izgEaXtWNM8OjvGqtYAkzwoB9igJORWgTDQKGOnYaD_TRNCE_gn6hGV09AC7hsmdyRZwDEIQFxMo2kEhJZ7a1tDkgWha0LXO2H3XTWt1YHQddMcT7dJq9V3rO10JywUHKMySpEldBZhhmlSY1JmeVGlUZazJK1rxrMsJnQ2UPj8ebV8zsDBEVruhCVpNDKeLF4yrvEoPEBd0gjzqExTxBizbVSmnBdFHmdFXvGo4umMFjRPBxbjSN2rQysa1PDhoW2URv00ZCRbfmmtOAjDrDPXihYbIRGOAn9CZ9yCeijzSZ6G6ILVnfzhnDmwR6j3blWCOqLuZ3pGstXzcCteqcZOld4Ruv5F6Douvn9k9a-P_DrtP7TaaXYAozpd44VAHoWf-qwgZN10HIEk98ZyjtvpniQfXhgW0o6H_W9jdVdbUJWLPpBiGV4DdELahG4sVKoiSf-aFKvh-bn-BqXVj7ejtKz-gfyqvhvaGPELz5oA7s-NBSE5PlyOPbeADxa1hE76WsShUXIHteqkJbQ8KuEn41LF2c7TjQUktHzCkC7c0zCBI8YXFqTehNAYIMnqbHBs7OyHMpua1XtfMny9uqQDILbgdWNnG0hxT4p7IDQejJwJAQBotJ2WED3DORnylBzWhCQfzgEGQpfnt1diC56c13Xv1XaIzngVEDpzYRpFYEAIAHT5MoZTfY4AhK6BPvOnd3Rwiy6fBLBYPcmgK3m3Gsqvy_-riXdSSKH2BWGylWrChamZ5hNfyieSHdCEASF9NZnsYPIlhkkNEwX4wA5tg5Mv8VQNaL4E8p9Mb3l3aGEiQ4ieC0cPkb_ymSu0qz833xYfN6eNro_H6s_N4tumUXWoagBu1ZwVt64yndfIxUWy5UnsdNHCrcanbxNfcQOBL39sNO4i-Lr418XqG67Ax8UlLF_q54bS34pzrJuND5-nP5YOAvaxxTPxwT-fnDRk1NjGtShP_I478Vaeh3rBudv2x9Q-Bz73qukOEtaicX99-scCVsLUWhyEZFZpWDds1-_Pk2cXvHSDa2L9dTn5w-VZ0XCD_hYPj3AaEGZj7MG-ADMLMLG_Jb-BOeG4c1Kjdh1uUPLroHE8JnUJGr2gkgQeaZAtb3QnzscwPehfWOZBpbiI59stb4N-YJ7c6kBP4xS68hUOJCHaNMxkeqvlJB3H4Xcr4fcw5ZjNzROZVIFG8C2e3QoTZiWhg_4tMGn-WphzlqDkG4P_7lCez3HX9p9vfVvzpFeBPTPA4FzHfRMUOh6U3Lg2w0lHD0nqO5tPMuygrjlwrVPvh1dgfS2rlN27jorDVquDb0B-amHR9U2DZVfyjRr1NsK4Jghri9xJVr03rK5dX-Rob_u2SqOxoLahxeqkZ3Oti_n0FSrcKn2l7bu68fpWwb8S26krOskCSLKEViMPRytCs3Du6LcUQrPIDzSKcRAJdV61VruBcHa7B9aInYRypFIrefRav_DBOq2AYxWIPB3JDeciL71Diw0eUFpnQchKdW6KCM3CnEzDufEKBZGn4APubMUjC_GIvOtwzpqjI9lVFxjnXtXdHbrDcpK9dyfJmjUNuIMvkNSHd8qr3TS0o7Q8oGWcWXZCYJwHDDqcUn1Ez4KExqtPH86tcn_IHbZ4QrND14Rj47454ToWDobeRuvQNT2t85ni9ZQIzbg4xjRES_InoDNKk6SgUZKXWVoUWRmll1FOnob5zCbg3hzp5HafeoT0KbXz_AX8XrjS0LAKGz8TDTLZtX99Tv70FdjWov5_5v5XM_cNq6RVwrip_x_Lx7-RkLcG7_YMe5pgIeNDijm-v68UQzqOS_LLudtXhCz-u5nLxXZ72nldhN-SyU63f5VGJI1g4mi56aLL05MfOHd1r03Ld8jLWxNz8vo9dfLemyqhy_evG68sHO9ZN24uHJO3beW3TPDte_nkTZu5WwvvVwX9yntDIRzJv6oWjuRfVQ5fUQ_v-Dzhs2TG7nAe50WZRLM8Lu_285rzuJzRWVGy2ZZhUqV5zBLGaFWlMeb8TsxpRJMoiUoaR3lWTuMyjlnOyjwtaBznlKQRHphopj7mSu_uhDEdzvOYFvTO8zL-4xel_j9OQm5ViDeh1J-PkoXyHyJ--VbPuMFsdafn_j9WVbczbkKFsWYwYYVtcD4q2_1HJatZ_UPI3cUnrFDmDR5RsyZ88brrdDN_25chQtfeMUPo2vv2nwAAAP__SWO18A">