[llvm] [DSE] Stop double-counting the dead slice offset in shortenAssignment (PR #216227)

Orlando Cazalet-Hyams via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 01:03:15 PDT 2026


================
@@ -0,0 +1,96 @@
+; RUN: opt %s -S -passes=dse -o - | FileCheck %s --implicit-check-not="#dbg_"
+
+;; The IR is clang's, cleaned up but not otherwise adjusted, so the variable
+;; fills its alloca and the offsets are the ones clang emitted. That gives up
+;; the coverage shorten-offset.ll buys by adjusting them, and gets a source
+;; listing whose numbers can be checked against the test.
+;;
+;; $ cat shorten.c
+;; void esc(char *);
+;; void shortenBeginPartial(void) {
+;;   char local[80];
+;;   __builtin_memset(local + 8, 0, 72);
+;;   __builtin_memset(local + 4, 8, 64);
+;;   esc(local);
+;; }
+;;
+;; $ clang -O2 -g -c -Xclang -fexperimental-assignment-tracking=forced \
+;;       -mllvm -print-before=dse -mllvm -print-module-scope shorten.c \
+;;       -o /dev/null
+;;
+;; and then, by hand: dropped the target triple and datalayout so this runs
+;; anywhere, dropped the tbaa metadata, llvm.ident, the producer/checksum/
+;; sysroot strings, the key-instruction atoms, the lifetime intrinsics and the
+;; function attributes, converted the debug records to intrinsics, and
+;; renumbered the metadata. The remaining non-debug instructions keep clang's
+;; order and operands, and the assignment offsets are unchanged.
+
+;; 'local' is 640 bits and starts at the alloca, so variable bit N is alloca
+;; byte N/8 throughout, which is what makes the arithmetic readable.
+;;
+;; The first memset covers bytes [8, 80) and the second covers [4, 68), so the
+;; second kills the front of the first and DSE shortens it to [68, 80). The
+;; bytes that died are [8, 68), which is variable bits [64, 544): fragment
+;; (64, 480).
+;;
+;; The dead slice stays inside the fragment, so the record keeps its size and
+;; only the offset can be wrong, and an offset that is off by the store's
+;; distance from the alloca still describes 60 plausible bytes. shorten-offset.ll
+;; covers the two shapes where the slice moves far enough to clip the fragment
+;; or to leave the variable entirely.
+
+; CHECK: @shortenBeginPartial
+; CHECK:      #dbg_assign({{.*}}, ![[VAR:[0-9]+]], !DIExpression(), {{.*}}, ptr %local, !DIExpression(),
+; CHECK:      call void @llvm.memset{{.*}}, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT: #dbg_assign(i8 0, ![[VAR]], !DIExpression(DW_OP_LLVM_fragment, 64, 576), ![[ID]], ptr %add.ptr, !DIExpression(),
+; CHECK-NEXT: #dbg_assign(i8 0, ![[VAR]], !DIExpression(DW_OP_LLVM_fragment, 64, 480), ![[UniqueID:[0-9]+]], ptr poison, !DIExpression(),
+; CHECK:      call void @llvm.memset{{.*}}, !DIAssignID ![[ID2:[0-9]+]]
+; CHECK-NEXT: #dbg_assign(i1 poison, ![[VAR]], !DIExpression(DW_OP_LLVM_fragment, 32, 512), ![[ID2]], ptr %add.ptr2, !DIExpression(),
+
+; CHECK-DAG: ![[ID]] = distinct !DIAssignID()
+; CHECK-DAG: ![[ID2]] = distinct !DIAssignID()
+; CHECK-DAG: ![[UniqueID]] = distinct !DIAssignID()
+
+define void @shortenBeginPartial() !dbg !7 {
+entry:
+  %local = alloca [80 x i8], align 1, !DIAssignID !13
+  call void @llvm.dbg.assign(metadata i1 poison, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %local, metadata !DIExpression()), !dbg !14
----------------
OCHyams wrote:

Can we upgrade these to debug records, like this (indentation intentional)?
```suggestion
    #dbg_assign(i1 poison, !11, !DIExpression(), !13, ptr %local, !DIExpression(), !14)
```

https://github.com/llvm/llvm-project/pull/216227


More information about the llvm-commits mailing list