[llvm] [DAGCombiner] Merge debug locations when combining stores (PR #225358)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 04:33:02 PDT 2026
================
@@ -0,0 +1,178 @@
+; RUN: llc -O2 -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs -stop-after=finalize-isel -o - %s | FileCheck %s
+
+;; Consecutive stores combined into a single store must merge their locations,
+;; rather than attributing all effects to the lowest-addressed store's scope.
+
+; CHECK-DAG: ![[CALLER:[0-9]+]] = distinct !DISubprogram(name: "siblings",
+; CHECK-DAG: ![[FIRST:[0-9]+]] = distinct !DISubprogram(name: "clear_first",
+; CHECK-DAG: ![[SECOND:[0-9]+]] = distinct !DISubprogram(name: "clear_second",
+; CHECK-DAG: ![[SAME_CALL:[0-9]+]] = !DILocation(line: 21, column: 3, scope: ![[#]])
+; CHECK-DAG: ![[SAME:[0-9]+]] = !DILocation(line: 4, column: 3, scope: ![[FIRST]], inlinedAt: ![[SAME_CALL]])
+; CHECK-DAG: ![[PARTIAL_CALL:[0-9]+]] = !DILocation(line: 41, column: 3, scope: ![[#]])
+; CHECK-DAG: ![[PARTIAL:[0-9]+]] = !DILocation(line: 4, column: 3, scope: ![[FIRST]], inlinedAt: ![[PARTIAL_CALL]])
+; CHECK-DAG: ![[EXTRACT:[0-9]+]] = distinct !DISubprogram(name: "extract_siblings",
+; CHECK-DAG: ![[COPY:[0-9]+]] = distinct !DISubprogram(name: "copy_siblings",
+; CHECK-DAG: ![[INDEPENDENT:[0-9]+]] = distinct !DISubprogram(name: "copy_independent_locations",
+; CHECK-DAG: ![[LOAD_CALL:[0-9]+]] = !DILocation(line: 71, column: 3, scope: ![[INDEPENDENT]])
+; CHECK-DAG: ![[LOAD:[0-9]+]] = !DILocation(line: 4, column: 3, scope: ![[FIRST]], inlinedAt: ![[LOAD_CALL]])
+; CHECK-DAG: ![[STORE_CALL:[0-9]+]] = !DILocation(line: 72, column: 3, scope: ![[INDEPENDENT]])
+; CHECK-DAG: ![[STORE:[0-9]+]] = !DILocation(line: 7, column: 3, scope: ![[SECOND]], inlinedAt: ![[STORE_CALL]])
+; CHECK-DAG: ![[COPY_PARTIAL_CALL:[0-9]+]] = !DILocation(line: 81, column: 3, scope: ![[#]])
+; CHECK-DAG: ![[COPY_PARTIAL:[0-9]+]] = !DILocation(line: 4, column: 3, scope: ![[FIRST]], inlinedAt: ![[COPY_PARTIAL_CALL]])
+
+; CHECK-LABEL: name: siblings
+; CHECK: MOV64mi32 {{.*}}, debug-location !DILocation(line: 0, scope: ![[CALLER]]) :: (store (s64)
+define void @siblings(ptr %p) !dbg !10 {
+ store i32 0, ptr %p, align 4, !dbg !13
+ %q = getelementptr i32, ptr %p, i64 1
+ store i32 0, ptr %q, align 4, !dbg !14
+ ret void
+}
+
+;; Identical locations retain their line and inline scope.
+; CHECK-LABEL: name: same_location
+; CHECK: MOV64mi32 {{.*}}, debug-location ![[SAME]] :: (store (s64)
+define void @same_location(ptr %p) !dbg !20 {
+ store i32 0, ptr %p, align 4, !dbg !22
+ %q = getelementptr i32, ptr %p, i64 1
+ store i32 0, ptr %q, align 4, !dbg !22
+ ret void
+}
+
+;; Do not retain one store's scope when the other's location is unknown.
+; CHECK-LABEL: name: missing_location
+; CHECK: MOV64mi32
+; CHECK-NOT: debug-location
+; CHECK-SAME: :: (store (s64)
+define void @missing_location(ptr %p) !dbg !30 {
+ store i32 0, ptr %p, align 4, !dbg !32
+ %q = getelementptr i32, ptr %p, i64 1
+ store i32 0, ptr %q, align 4
+ ret void
+}
+
+;; Only the first two candidates are merged. Do not include the third store's
+;; location when computing the wider store's location.
+; CHECK-LABEL: name: partial_merge
+; CHECK-DAG: MOV64mi32 {{.*}}, debug-location ![[PARTIAL]] :: (store (s64)
+; CHECK-DAG: MOV32mi
+define void @partial_merge(ptr %p) !dbg !40 {
+ store i32 0, ptr %p, align 4, !dbg !43
+ %q = getelementptr i32, ptr %p, i64 1
+ store i32 0, ptr %q, align 4, !dbg !43
+ %r = getelementptr i32, ptr %p, i64 2
+ store i32 0, ptr %r, align 4, !dbg !44
+ ret void
+}
+
+;; Extracted elements use the same merged-location policy as constants.
+; CHECK-LABEL: name: extract_siblings
+; CHECK: debug-location !DILocation(line: 0, scope: ![[EXTRACT]]) :: (store (s128)
+define void @extract_siblings(ptr %p, <4 x i32> %v) !dbg !50 {
+ %a = extractelement <4 x i32> %v, i64 0
+ %b = extractelement <4 x i32> %v, i64 1
+ %c = extractelement <4 x i32> %v, i64 2
+ %d = extractelement <4 x i32> %v, i64 3
+ store i32 %a, ptr %p, align 16, !dbg !53
+ %q = getelementptr i32, ptr %p, i64 1
+ store i32 %b, ptr %q, align 4, !dbg !53
+ %r = getelementptr i32, ptr %p, i64 2
+ store i32 %c, ptr %r, align 8, !dbg !54
+ %s = getelementptr i32, ptr %p, i64 3
+ store i32 %d, ptr %s, align 4, !dbg !54
+ ret void
+}
+
+;; Both the widened load and store must account for all merged operations.
+; CHECK-LABEL: name: copy_siblings
+; CHECK: MOV64rm {{.*}}, debug-location !DILocation(line: 0, scope: ![[COPY]]) :: (load (s64)
+; CHECK: MOV64mr {{.*}}, debug-location !DILocation(line: 0, scope: ![[COPY]]) :: (store (s64)
+define void @copy_siblings(ptr noalias %d, ptr noalias %s) !dbg !60 {
+ %s1 = getelementptr i32, ptr %s, i64 1
+ %d1 = getelementptr i32, ptr %d, i64 1
+ %a = load i32, ptr %s, align 4, !dbg !63
+ %b = load i32, ptr %s1, align 4, !dbg !64
+ store i32 %a, ptr %d, align 4, !dbg !63
+ store i32 %b, ptr %d1, align 4, !dbg !64
+ ret void
+}
+
+;; Load and store locations must not be mixed together.
+; CHECK-LABEL: name: copy_independent_locations
+; CHECK: MOV64rm {{.*}}, debug-location ![[LOAD]] :: (load (s64)
+; CHECK: MOV64mr {{.*}}, debug-location ![[STORE]] :: (store (s64)
+define void @copy_independent_locations(ptr noalias %d, ptr noalias %s) !dbg !70 {
+ %s1 = getelementptr i32, ptr %s, i64 1
+ %d1 = getelementptr i32, ptr %d, i64 1
+ %a = load i32, ptr %s, align 4, !dbg !73
+ %b = load i32, ptr %s1, align 4, !dbg !73
+ store i32 %a, ptr %d, align 4, !dbg !74
+ store i32 %b, ptr %d1, align 4, !dbg !74
+ ret void
+}
+
+;; The third copy is not merged and must not affect either widened operation.
----------------
jmorse wrote:
I feel this should state the intended outcome, i.e., that the location on two merged loads is preserved. Noteworthy because this portion already passes with existing llc's.
https://github.com/llvm/llvm-project/pull/225358
More information about the llvm-commits
mailing list