1 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s | FileCheck %s
3 ; Test case was generated from the following C code,
4 ; using: clang -g -O1 -S -emit-llvm s.c -o s.ll
6 ; struct s { long long int i, j; };
8 ; extern void bar(struct s, struct s, struct s);
10 ; int f(struct s s1, struct s s2) {
11 ; volatile struct s tmp = {0};
18 ; Catch metadata references for involved variables.
20 ; CHECK-DAG: ![[S1:.*]] = !DILocalVariable(name: "s1"
21 ; CHECK-DAG: ![[S2:.*]] = !DILocalVariable(name: "s2"
23 define dso_local i32 @f(i64 %s1.coerce0, i64 %s1.coerce1, i64 %s2.coerce0, i64 %s2.coerce1) local_unnamed_addr #0 !dbg !7 {
24 ; We expect DBG_VALUE instructions for the arguments at the entry.
25 ; CHECK-LABEL: name: f
26 ; CHECK-NOT: DBG_VALUE
27 ; CHECK-DAG: DBG_VALUE $rdi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64)
28 ; CHECK-DAG: DBG_VALUE $rsi, $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64)
29 ; CHECK-DAG: DBG_VALUE $rdx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 0, 64)
30 ; CHECK-DAG: DBG_VALUE $rcx, $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 64, 64)
31 ; CHECK-NOT: DBG_VALUE
33 ; Then arguments are copied to virtual registers.
34 ; CHECK-NOT: DBG_VALUE
35 ; CHECK-DAG: %[[R1:.*]]:gr64 = COPY $rcx
36 ; CHECK-DAG: DBG_VALUE %[[R1]], $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 64, 64)
37 ; CHECK-DAG: %[[R2:.*]]:gr64 = COPY $rdx
38 ; CHECK-DAG: DBG_VALUE %[[R2]], $noreg, ![[S2]], !DIExpression(DW_OP_LLVM_fragment, 0, 64)
39 ; CHECK-DAG: %[[R3:.*]]:gr64 = COPY $rsi
40 ; CHECK-DAG: DBG_VALUE %[[R3]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64)
41 ; CHECK-DAG: %[[R4:.*]]:gr64 = COPY $rdi
42 ; CHECK-DAG: DBG_VALUE %[[R4]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64)
43 ; CHECK-NOT: DBG_VALUE
45 ; We have the call to bar.
46 ; CHECK: ADJCALLSTACKDOWN
47 ; CHECK: CALL64pcrel32 @bar
49 ; After the call we expect to find new DBG_VALUE instructions for "s1".
50 ; CHECK: ADJCALLSTACKUP
51 ; CHECK-NOT: DBG_VALUE
52 ; CHECK-DAG: DBG_VALUE %[[R2]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 0, 64)
53 ; CHECK-DAG: DBG_VALUE %[[R1]], $noreg, ![[S1]], !DIExpression(DW_OP_LLVM_fragment, 64, 64)
55 ; And then no more DBG_VALUE instructions before the add.
56 ; CHECK-NOT: DBG_VALUE
60 %tmp.sroa.0 = alloca i64, align 8
61 %tmp.sroa.4 = alloca i64, align 8
62 call void @llvm.dbg.declare(metadata i64* %tmp.sroa.0, metadata !19, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !21
63 call void @llvm.dbg.declare(metadata i64* %tmp.sroa.4, metadata !19, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !21
64 call void @llvm.dbg.value(metadata i64 %s1.coerce0, metadata !17, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !22
65 call void @llvm.dbg.value(metadata i64 %s1.coerce1, metadata !17, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !22
66 call void @llvm.dbg.value(metadata i64 %s2.coerce0, metadata !18, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !23
67 call void @llvm.dbg.value(metadata i64 %s2.coerce1, metadata !18, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !23
68 %tmp.sroa.0.0..sroa_cast = bitcast i64* %tmp.sroa.0 to i8*, !dbg !24
69 call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %tmp.sroa.0.0..sroa_cast), !dbg !24
70 %tmp.sroa.4.0..sroa_cast = bitcast i64* %tmp.sroa.4 to i8*, !dbg !24
71 call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %tmp.sroa.4.0..sroa_cast), !dbg !24
72 store volatile i64 0, i64* %tmp.sroa.0, align 8, !dbg !21
73 store volatile i64 0, i64* %tmp.sroa.4, align 8, !dbg !21
74 tail call void @bar(i64 %s1.coerce0, i64 %s1.coerce1, i64 %s2.coerce0, i64 %s2.coerce1, i64 0, i64 0) #4, !dbg !25
75 call void @llvm.dbg.value(metadata i64 %s2.coerce0, metadata !17, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !22
76 call void @llvm.dbg.value(metadata i64 %s2.coerce1, metadata !17, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !22
77 %s2.coerce1.tr = trunc i64 %s2.coerce1 to i32, !dbg !26
78 %conv = shl i32 %s2.coerce1.tr, 1, !dbg !26
79 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %tmp.sroa.0.0..sroa_cast), !dbg !27
80 call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %tmp.sroa.4.0..sroa_cast), !dbg !27
81 ret i32 %conv, !dbg !28
84 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
85 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
86 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #2
87 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #2
89 declare dso_local void @bar(i64, i64, i64, i64, i64, i64) local_unnamed_addr
91 attributes #0 = { nounwind uwtable }
92 attributes #1 = { nounwind readnone speculatable }
93 attributes #2 = { argmemonly nounwind }
94 attributes #4 = { nounwind }
97 !llvm.module.flags = !{!3, !4, !5}
100 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "llvm-svn @ 353529", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
101 !1 = !DIFile(filename: "s.c", directory: "")
103 !3 = !{i32 2, !"Dwarf Version", i32 4}
104 !4 = !{i32 2, !"Debug Info Version", i32 3}
105 !5 = !{i32 1, !"wchar_size", i32 4}
106 !6 = !{!"llvm-svn @ 353529"}
107 !7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
108 !8 = !DISubroutineType(types: !9)
109 !9 = !{!10, !11, !11}
110 !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
111 !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 128, elements: !12)
113 !13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !11, file: !1, line: 1, baseType: !14, size: 64)
114 !14 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
115 !15 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !11, file: !1, line: 1, baseType: !14, size: 64, offset: 64)
116 !16 = !{!17, !18, !19}
117 !17 = !DILocalVariable(name: "s1", arg: 1, scope: !7, file: !1, line: 5, type: !11)
118 !18 = !DILocalVariable(name: "s2", arg: 2, scope: !7, file: !1, line: 5, type: !11)
119 !19 = !DILocalVariable(name: "tmp", scope: !7, file: !1, line: 6, type: !20)
120 !20 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !11)
121 !21 = !DILocation(line: 6, column: 21, scope: !7)
122 !22 = !DILocation(line: 5, column: 16, scope: !7)
123 !23 = !DILocation(line: 5, column: 29, scope: !7)
124 !24 = !DILocation(line: 6, column: 3, scope: !7)
125 !25 = !DILocation(line: 7, column: 3, scope: !7)
126 !26 = !DILocation(line: 10, column: 10, scope: !7)
127 !27 = !DILocation(line: 11, column: 1, scope: !7)
128 !28 = !DILocation(line: 10, column: 3, scope: !7)