Files
Vladislav Dzhidzhoev e2a2c03eef [DebugInfo] Add Verifier check for incorrectly-scoped retainedNodes (#166855)
These checks ensure that retained nodes of a DISubprogram belong to the
subprogram.

Tests with incorrect IR are fixed. We should not have variables of one subprogram present in retained nodes of other subprograms.

Also, interface for accessing DISubprogram's retained nodes is slightly
refactored. `DISubprogram::visitRetainedNodes` and
`DISubprogram::forEachRetainedNode` are added to avoid repeating checks
like
```
if (const auto *LV = dyn_cast<DILocalVariable>(N))
  ...
else if (const auto *L = dyn_cast<DILabel>(N))
  ...
else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
  ...
```
2025-11-10 13:13:49 +01:00

189 lines
9.3 KiB
LLVM

; REQUIRES: aarch64-registered-target
; This test needs to be target specific due to the cost estimate in the output.
; RUN: opt -passes=lower-matrix-intrinsics -pass-remarks=lower-matrix-intrinsics -mtriple=arm64-apple-iphoneos < %s 2>&1 | FileCheck %s
; CHECK-LABEL: remark: test.h:40:20: Lowered with 6 stores, 6 loads, 24 compute ops
; CHECK-NEXT: store(
; CHECK-NEXT: transpose.2x6.double(load(addr %A)),
; CHECK-NEXT: addr %B)
define void @transpose(ptr %A, ptr %B) !dbg !23 {
%load = load <12 x double>, ptr %A, !dbg !24
%t = call <12 x double> @llvm.matrix.transpose.v12f64.v12f64(<12 x double> %load, i32 2, i32 6), !dbg !24
store <12 x double> %t, ptr %B, !dbg !24
ret void
}
; CHECK-LABEL: remark: test.h:50:20: Lowered with 2 stores, 12 loads, 22 compute ops
; CHECK-NEXT: store(
; CHECK-NEXT: multiply.2x6.6x2.double(
; CHECK-NEXT: load(addr %A),
; CHECK-NEXT: load(addr %B)),
; CHECK-NEXT: addr %C)
define void @multiply(ptr %A, ptr %B, ptr %C) !dbg !25 {
%A.matrix = load <12 x double>, ptr %A, !dbg !26
%B.matrix = load <12 x double>, ptr %B, !dbg !26
%t = call <4 x double> @llvm.matrix.multiply(<12 x double> %A.matrix, <12 x double> %B.matrix, i32 2, i32 6, i32 2), !dbg !26
store <4 x double> %t, ptr %C, !dbg !26
ret void
}
; CHECK-LABEL: remark: test.h:60:20: Lowered with 6 stores, 6 loads, 0 compute ops
; CHECK-NEXT: store(
; CHECK-NEXT: column.major.load.3x3.double(addr %A, 5),
; CHECK-NEXT: addr %B)
define void @column.major.load(ptr %A, ptr %B) !dbg !27 {
%A.matrix = call <9 x double> @llvm.matrix.column.major.load(ptr %A, i64 5, i1 false, i32 3, i32 3), !dbg !28
store <9 x double> %A.matrix, ptr %B, !dbg !28
ret void
}
; CHECK-LABEL: remark: test.h:70:20: Lowered with 6 stores, 6 loads, 0 compute ops
; CHECK-NEXT: column.major.store.3x3.double(
; CHECK-NEXT: column.major.load.3x3.double(addr %A, 5),
; CHECK-NEXT: addr %B,
; CHECK-NEXT: 10)
define void @column.major.store(ptr %A, ptr %B) !dbg !29 {
%A.matrix = call <9 x double> @llvm.matrix.column.major.load(ptr %A, i64 5, i1 false, i32 3, i32 3), !dbg !30
call void @llvm.matrix.column.major.store(<9 x double> %A.matrix, ptr %B, i64 10, i1 false, i32 3, i32 3), !dbg !30
ret void
}
; CHECK-LABEL: remark: test.h:80:20: Lowered with 6 stores, 6 loads, 12 compute ops
; CHECK-NEXT: column.major.store.3x3.double(
; CHECK-NEXT: fmul(
; CHECK-NEXT: fadd(
; CHECK-NEXT: column.major.load.3x3.double(addr %A, 5)
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: addr %B,
; CHECK-NEXT: 10)
define void @binaryops(ptr %A, ptr %B) !dbg !31 {
%A.matrix = call <9 x double> @llvm.matrix.column.major.load(ptr %A, i64 5, i1 false, i32 3, i32 3), !dbg !32
%R1.matrix = fadd <9 x double> %A.matrix, %A.matrix, !dbg !32
%R2.matrix = fmul <9 x double> %R1.matrix, %A.matrix, !dbg !32
call void @llvm.matrix.column.major.store(<9 x double> %R2.matrix, ptr %B, i64 10, i1 false, i32 3, i32 3), !dbg !32
ret void
}
; CHECK-LABEL: remark: test.h:90:20: Lowered with 6 stores, 6 loads, 12 compute ops
; CHECK-NEXT: column.major.store.3x3.double(
; CHECK-NEXT: fmul(
; CHECK-NEXT: fadd(
; CHECK-NEXT: column.major.load.3x3.double(addr %A, 5)
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: addr %B,
; CHECK-NEXT: 10)
; CHECK-NEXT: remark: test.h:90:20: Lowered with 2 stores, 12 loads, 22 compute ops
; CHECK-NEXT: store(
; CHECK-NEXT: multiply.2x6.6x2.double(
; CHECK-NEXT: load(addr %C),
; CHECK-NEXT: load(addr %D)),
; CHECK-NEXT: addr %E)
define void @multiple_expressions(ptr %A, ptr %B, ptr %C, ptr %D, ptr %E) !dbg !33 {
%A.matrix = call <9 x double> @llvm.matrix.column.major.load(ptr %A, i64 5, i1 false, i32 3, i32 3), !dbg !34
%R1.matrix = fadd <9 x double> %A.matrix, %A.matrix, !dbg !34
%R2.matrix = fmul <9 x double> %R1.matrix, %A.matrix, !dbg !34
call void @llvm.matrix.column.major.store(<9 x double> %R2.matrix, ptr %B, i64 10, i1 false, i32 3, i32 3), !dbg !34
%C.matrix = load <12 x double>, ptr %C, !dbg !34
%D.matrix = load <12 x double>, ptr %D, !dbg !34
%Mult.matrix = call <4 x double> @llvm.matrix.multiply(<12 x double> %C.matrix, <12 x double> %D.matrix, i32 2, i32 6, i32 2), !dbg !34
store <4 x double> %Mult.matrix, ptr %E, !dbg !34
ret void
}
; CHECK-LABEL: remark: test.h:100:20: Lowered with 6 stores, 6 loads, 12 compute ops
; CHECK-NEXT: column.major.store.3x3.double(
; CHECK-NEXT: fmul(
; CHECK-NEXT: fadd(
; CHECK-NEXT: column.major.load.3x3.double(addr %A, 5)
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: (reused) column.major.load.3x3.double(addr %A, 5)),
; CHECK-NEXT: addr %B,
; CHECK-NEXT: 10)
define void @stackaddresses(ptr %A, ptr %B) !dbg !35 {
%A.matrix = call <9 x double> @llvm.matrix.column.major.load(ptr %A, i64 5, i1 false, i32 3, i32 3), !dbg !36
%R1.matrix = fadd <9 x double> %A.matrix, %A.matrix, !dbg !36
%R2.matrix = fmul <9 x double> %R1.matrix, %A.matrix, !dbg !36
call void @llvm.matrix.column.major.store(<9 x double> %R2.matrix, ptr %B, i64 10, i1 false, i32 3, i32 3), !dbg !36
ret void
}
; CHECK-LABEL: remark: test.h:30:20: Lowered with 10 stores, 9 loads, 30 compute ops
; CHECK-NEXT: store(
; CHECK-NEXT: transpose.5x3.double(load(addr %A)),
; CHECK-NEXT: stack addr %s1)
%S1 = type {ptr}
define void @get_underlying_object(ptr %A) !dbg !21 {
entry:
%s1 = alloca <15 x double>, !dbg !22
%a2 = load ptr, ptr %A, !dbg !22
%av = load <15 x double>, ptr %a2, !dbg !22
%t = call <15 x double> @llvm.matrix.transpose.v15f64.v15f64(<15 x double> %av, i32 5, i32 3), !dbg !22
store <15 x double> %t, ptr %s1, !dbg !22
ret void
}
declare <12 x double> @llvm.matrix.transpose.v12f64.v12f64(<12 x double>, i32, i32)
declare <4 x double> @llvm.matrix.multiply(<12 x double>, <12 x double>, i32, i32, i32)
declare <9 x double> @llvm.matrix.column.major.load(ptr, i64, i1, i32, i32)
declare <15 x double> @llvm.matrix.transpose.v15f64.v15f64(<15 x double>, i32, i32)
declare void @llvm.matrix.column.major.store(<9 x double>, ptr, i64, i1, i32, i32)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "test.h", directory: "/test")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!6 = !DISubroutineType(types: !7)
!7 = !{null, !8, !8, !11}
!8 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !9)
!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 32, align: 32)
!10 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
!11 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DILocalVariable(name: "a", arg: 1, scope: !5, file: !1, line: 1, type: !8)
!14 = !DILocation(line: 1, column: 27, scope: !5)
!5 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
!19 = !DILocation(line: 10, column: 20, scope: !5)
!20 = !DILocation(line: 10, column: 10, scope: !5)
!21 = distinct !DISubprogram(name: "fn2", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!22 = !DILocation(line: 30, column: 20, scope: !21)
!23 = distinct !DISubprogram(name: "fn3", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!24 = !DILocation(line: 40, column: 20, scope: !23)
!25 = distinct !DISubprogram(name: "fn4", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!26 = !DILocation(line: 50, column: 20, scope: !25)
!27 = distinct !DISubprogram(name: "fn5", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!28 = !DILocation(line: 60, column: 20, scope: !27)
!29 = distinct !DISubprogram(name: "fn6", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!30 = !DILocation(line: 70, column: 20, scope: !29)
!31 = distinct !DISubprogram(name: "fn7", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!32 = !DILocation(line: 80, column: 20, scope: !31)
!33 = distinct !DISubprogram(name: "fn8", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!34 = !DILocation(line: 90, column: 20, scope: !33)
!35 = distinct !DISubprogram(name: "fn9", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
!36 = !DILocation(line: 100, column: 20, scope: !35)