File: memmove-to-from-same-alloca.ll

package info (click to toggle)
llvm-toolchain-16 1%3A16.0.6-15~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,634,792 kB
  • sloc: cpp: 6,179,261; ansic: 1,216,205; asm: 741,319; python: 196,614; objc: 75,325; f90: 49,640; lisp: 32,396; pascal: 12,286; sh: 9,394; perl: 7,442; ml: 5,494; awk: 3,523; makefile: 2,723; javascript: 1,206; xml: 886; fortran: 581; cs: 573
file content (164 lines) | stat: -rw-r--r-- 8,421 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
; RUN: opt %s -passes=sroa -o - -S \
; RUN: | FileCheck %s

;; Generated from this C++ source:
;; __attribute__((nodebug)) struct Blob {int P[6];} Glob;
;; __attribute__((nodebug)) int Cond;
;; __attribute__((nodebug)) Blob *C;
;; __attribute__((nodebug)) void call(int);
;; 
;; void f() {
;;   int A[16];
;;   __attribute__ ((nodebug)) int B[16];
;;   // A[0:6) <- Glob
;;   __builtin_memmove(&A[0], &Glob, sizeof(Blob));
;;   call(0);
;;   // B[8:14) <- Glob
;;   __builtin_memmove(&B[8], &Glob, sizeof(Blob));  
;;   call(A[0]);
;;   // A[8:14) <- A[0:6)
;;   __builtin_memmove(&A[8], &A[0], sizeof(Blob));
;;   call(A[8]);
;;   if (Cond)
;;     // C <- A[8:14)
;;     __builtin_memmove(C, &A[8], sizeof(Blob));
;;   else
;;     // C <- B[8:14)
;;     __builtin_memmove(C, &B[8], sizeof(Blob));    
;; }
;; 
;; using:
;;   clang test.cpp -emit-llvm -S -g -O2 -Xclang -disable-llvm-passes -o - \
;;   | opt -passes=declare-to-assign -o test.ll - -S

;; We're interested in variable A and the second memmove with A as a dest (the
;; third memmove in the source). SROA is going to chop up A so that the only
;; Alloca'd slice remaining is what were originally elements 1 through 5
;; inclusive (element 0 is promoted). Incidentally, the memmove later becomes a
;; memcpy. Check that the dbg.assign address and fragment are correct and
;; ensure the DIAssignID still links it to the memmove(/memcpy).

; CHECK: %A.sroa.0.sroa.5 = alloca [5 x i32]
; CHECK: llvm.memcpy{{.*}}(ptr align 4 %A.sroa.0.sroa.5, ptr align 4 getelementptr inbounds (i8, ptr @Glob, i64 4), i64 20, i1 false){{.*}}!DIAssignID ![[ID:[0-9]+]]
;; Here's the dbg.assign for element 0 - it's not important for the test.
; CHECK-NEXT: llvm.dbg.assign({{.*}}!DIExpression(DW_OP_LLVM_fragment, 0, 32){{.*}})
;; This is the dbg.assign we care about:
; CHECK-NEXT: llvm.dbg.assign(metadata i1 undef, metadata ![[VAR:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 32, 160), metadata ![[ID]], metadata ptr %A.sroa.0.sroa.5, metadata !DIExpression())

; CHECK: ![[VAR]] = !DILocalVariable(name: "A"

source_filename = "test.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.Blob = type { [6 x i32] }

@Glob = dso_local global %struct.Blob zeroinitializer, align 4
@Cond = dso_local global i32 0, align 4
@C = dso_local global ptr null, align 8

; Function Attrs: mustprogress uwtable
define dso_local void @_Z1fv() #0 !dbg !9 {
entry:
  %A = alloca [16 x i32], align 16, !DIAssignID !18
  call void @llvm.dbg.assign(metadata i1 undef, metadata !13, metadata !DIExpression(), metadata !18, metadata ptr %A, metadata !DIExpression()), !dbg !19
  %B = alloca [16 x i32], align 16
  call void @llvm.lifetime.start.p0(i64 64, ptr %A) #5, !dbg !20
  call void @llvm.lifetime.start.p0(i64 64, ptr %B) #5, !dbg !21
  %arrayidx = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 0, !dbg !22
  call void @llvm.memmove.p0.p0.i64(ptr align 16 %arrayidx, ptr align 4 @Glob, i64 24, i1 false), !dbg !23, !DIAssignID !24
  call void @llvm.dbg.assign(metadata i1 undef, metadata !13, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 192), metadata !24, metadata ptr %arrayidx, metadata !DIExpression()), !dbg !19
  call void @_Z4calli(i32 noundef 0), !dbg !25
  %arrayidx1 = getelementptr inbounds [16 x i32], ptr %B, i64 0, i64 8, !dbg !26
  call void @llvm.memmove.p0.p0.i64(ptr align 16 %arrayidx1, ptr align 4 @Glob, i64 24, i1 false), !dbg !27
  %arrayidx2 = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 0, !dbg !28
  %0 = load i32, ptr %arrayidx2, align 16, !dbg !28
  call void @_Z4calli(i32 noundef %0), !dbg !33
  %arrayidx3 = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 8, !dbg !34
  %arrayidx4 = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 0, !dbg !35
  call void @llvm.memmove.p0.p0.i64(ptr align 16 %arrayidx3, ptr align 16 %arrayidx4, i64 24, i1 false), !dbg !36, !DIAssignID !37
  call void @llvm.dbg.assign(metadata i1 undef, metadata !13, metadata !DIExpression(DW_OP_LLVM_fragment, 256, 192), metadata !37, metadata ptr %arrayidx3, metadata !DIExpression()), !dbg !19
  %arrayidx5 = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 8, !dbg !38
  %1 = load i32, ptr %arrayidx5, align 16, !dbg !38
  call void @_Z4calli(i32 noundef %1), !dbg !39
  %2 = load i32, ptr @Cond, align 4, !dbg !40
  %tobool = icmp ne i32 %2, 0, !dbg !40
  br i1 %tobool, label %if.then, label %if.else, !dbg !42

if.then:                                          ; preds = %entry
  %3 = load ptr, ptr @C, align 8, !dbg !43
  %arrayidx6 = getelementptr inbounds [16 x i32], ptr %A, i64 0, i64 8, !dbg !46
  call void @llvm.memmove.p0.p0.i64(ptr align 4 %3, ptr align 16 %arrayidx6, i64 24, i1 false), !dbg !47
  br label %if.end, !dbg !47

if.else:                                          ; preds = %entry
  %4 = load ptr, ptr @C, align 8, !dbg !48
  %arrayidx7 = getelementptr inbounds [16 x i32], ptr %B, i64 0, i64 8, !dbg !49
  call void @llvm.memmove.p0.p0.i64(ptr align 4 %4, ptr align 16 %arrayidx7, i64 24, i1 false), !dbg !50
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  call void @llvm.lifetime.end.p0(i64 64, ptr %B) #5, !dbg !51
  call void @llvm.lifetime.end.p0(i64 64, ptr %A) #5, !dbg !51
  ret void, !dbg !51
}

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg) #3
declare void @_Z4calli(i32 noundef) #4
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #2


!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !1000}
!llvm.ident = !{!8}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 16.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.cpp", directory: "/")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{!"clang version 16.0.0"}
!9 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !1, file: !1, line: 6, type: !10, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
!10 = !DISubroutineType(types: !11)
!11 = !{null}
!12 = !{!13}
!13 = !DILocalVariable(name: "A", scope: !9, file: !1, line: 7, type: !14)
!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 512, elements: !16)
!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!16 = !{!17}
!17 = !DISubrange(count: 16)
!18 = distinct !DIAssignID()
!19 = !DILocation(line: 0, scope: !9)
!20 = !DILocation(line: 7, column: 3, scope: !9)
!21 = !DILocation(line: 8, column: 3, scope: !9)
!22 = !DILocation(line: 10, column: 22, scope: !9)
!23 = !DILocation(line: 10, column: 3, scope: !9)
!24 = distinct !DIAssignID()
!25 = !DILocation(line: 11, column: 3, scope: !9)
!26 = !DILocation(line: 13, column: 22, scope: !9)
!27 = !DILocation(line: 13, column: 3, scope: !9)
!28 = !DILocation(line: 14, column: 8, scope: !9)
!33 = !DILocation(line: 14, column: 3, scope: !9)
!34 = !DILocation(line: 16, column: 22, scope: !9)
!35 = !DILocation(line: 16, column: 29, scope: !9)
!36 = !DILocation(line: 16, column: 3, scope: !9)
!37 = distinct !DIAssignID()
!38 = !DILocation(line: 17, column: 8, scope: !9)
!39 = !DILocation(line: 17, column: 3, scope: !9)
!40 = !DILocation(line: 18, column: 7, scope: !41)
!41 = distinct !DILexicalBlock(scope: !9, file: !1, line: 18, column: 7)
!42 = !DILocation(line: 18, column: 7, scope: !9)
!43 = !DILocation(line: 20, column: 23, scope: !41)
!46 = !DILocation(line: 20, column: 27, scope: !41)
!47 = !DILocation(line: 20, column: 5, scope: !41)
!48 = !DILocation(line: 23, column: 23, scope: !41)
!49 = !DILocation(line: 23, column: 27, scope: !41)
!50 = !DILocation(line: 23, column: 5, scope: !41)
!51 = !DILocation(line: 24, column: 1, scope: !9)
!1000 = !{i32 7, !"debug-info-assignment-tracking", i1 true}