|
4 | 4 | %buf = type [9 x i8] |
5 | 5 |
|
6 | 6 | ; We can forward `memcpy` because the copy location are the same, |
7 | | -define void @forward_offset(ptr %dep_src) { |
| 7 | +define void @forward_offset(ptr %src, ptr %dest) { |
8 | 8 | ; CHECK-LABEL: define void @forward_offset( |
9 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 9 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
10 | 10 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
11 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
12 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
13 | | -; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
14 | | -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEP]], ptr align 1 [[DEP]], i64 6, i1 false) |
| 11 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 12 | +; CHECK-NEXT: [[SRC_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 13 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
| 14 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 6, i1 false) |
15 | 15 | ; CHECK-NEXT: ret void |
16 | 16 | ; |
17 | | - %dep_dest = alloca %buf, align 1 |
18 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
19 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
20 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 1 |
21 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 17 | + %cpy_tmp = alloca %buf, align 1 |
| 18 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 19 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 20 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
22 | 21 | ret void |
23 | 22 | } |
24 | 23 |
|
25 | 24 | ; We need to update the align value of the source of `memcpy` when forwarding. |
26 | | -define void @forward_offset_align(ptr %dep_src) { |
| 25 | +define void @forward_offset_align(ptr %src, ptr %dest) { |
27 | 26 | ; CHECK-LABEL: define void @forward_offset_align( |
28 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 27 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
29 | 28 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
30 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 4 [[DEP_SRC]], i64 9, i1 false) |
31 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 3 |
32 | | -; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 3 |
33 | | -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[DEST]], i64 5, i1 false) |
| 29 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 4 [[SRC]], i64 9, i1 false) |
| 30 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 3 |
| 31 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 3 |
| 32 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 5, i1 false) |
34 | 33 | ; CHECK-NEXT: ret void |
35 | 34 | ; |
36 | | - %dep_dest = alloca %buf, align 1 |
37 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 4 %dep_src, i64 9, i1 false) |
38 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 3 |
39 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 3 |
40 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 5, i1 false) |
| 35 | + %cpy_tmp = alloca %buf, align 1 |
| 36 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 4 %src, i64 9, i1 false) |
| 37 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 3 |
| 38 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 5, i1 false) |
41 | 39 | ret void |
42 | 40 | } |
43 | 41 |
|
44 | 42 | ; We can change the align value to 2 when forwarding. |
45 | | -define void @forward_offset_align_2(ptr %dep_src) { |
| 43 | +define void @forward_offset_align_2(ptr %src, ptr %dest) { |
46 | 44 | ; CHECK-LABEL: define void @forward_offset_align_2( |
47 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 45 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
48 | 46 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
49 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 4 [[DEP_SRC]], i64 9, i1 false) |
50 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 2 |
51 | | -; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 2 |
52 | | -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEP]], ptr align 2 [[DEP]], i64 6, i1 false) |
| 47 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 4 [[SRC]], i64 9, i1 false) |
| 48 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 2 |
| 49 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 2 |
| 50 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 2 [[TMP1]], i64 6, i1 false) |
53 | 51 | ; CHECK-NEXT: ret void |
54 | 52 | ; |
55 | | - %dep_dest = alloca %buf, align 1 |
56 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 4 %dep_src, i64 9, i1 false) |
57 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 2 |
58 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 2 |
59 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 53 | + %cpy_tmp = alloca %buf, align 1 |
| 54 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 4 %src, i64 9, i1 false) |
| 55 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 2 |
| 56 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
| 57 | + ret void |
| 58 | +} |
| 59 | + |
| 60 | +; If the copy destination can be used as the copy source, we don't need to create a GEP instruction. |
| 61 | +define void @forward_offset_without_gep(ptr %src) { |
| 62 | +; CHECK-LABEL: define void @forward_offset_without_gep( |
| 63 | +; CHECK-SAME: ptr [[SRC:%.*]]) { |
| 64 | +; CHECK-NEXT: [[TMP:%.*]] = alloca [9 x i8], align 1 |
| 65 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[TMP]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 66 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 1 |
| 67 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
| 68 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[TMP1]], ptr align 1 [[TMP1]], i64 6, i1 false) |
| 69 | +; CHECK-NEXT: ret void |
| 70 | +; |
| 71 | + %cpy_tmp = alloca %buf, align 1 |
| 72 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 73 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 74 | + %dest = getelementptr inbounds i8, ptr %src, i64 1 |
| 75 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
60 | 76 | ret void |
61 | 77 | } |
62 | 78 |
|
63 | 79 | ; We need to create a GEP instruction when forwarding. |
64 | | -define void @forward_offset_with_gep(ptr %dep_src) { |
| 80 | +define void @forward_offset_with_gep(ptr %src) { |
65 | 81 | ; CHECK-LABEL: define void @forward_offset_with_gep( |
66 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 82 | +; CHECK-SAME: ptr [[SRC:%.*]]) { |
67 | 83 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
68 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
69 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
70 | | -; CHECK-NEXT: [[DEP1:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 2 |
71 | | -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
72 | | -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEP1]], ptr align 1 [[TMP1]], i64 6, i1 false) |
| 84 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 85 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 86 | +; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 2 |
| 87 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
| 88 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 6, i1 false) |
73 | 89 | ; CHECK-NEXT: ret void |
74 | 90 | ; |
75 | | - %dep_dest = alloca %buf, align 1 |
76 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
77 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
78 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 2 |
79 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 91 | + %cpy_tmp = alloca %buf, align 1 |
| 92 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 93 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 94 | + %dest = getelementptr inbounds i8, ptr %src, i64 2 |
| 95 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
80 | 96 | ret void |
81 | 97 | } |
82 | 98 |
|
83 | 99 | ; Make sure we pass the right parameters when calling `memcpy`. |
84 | | -define void @forward_offset_memcpy(ptr %dep_src) { |
| 100 | +define void @forward_offset_memcpy(ptr %src, ptr %dest) { |
85 | 101 | ; CHECK-LABEL: define void @forward_offset_memcpy( |
86 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 102 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
87 | 103 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
88 | | -; CHECK-NEXT: [[DEST:%.*]] = alloca [9 x i8], align 1 |
89 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
90 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
91 | | -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
92 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 6, i1 false) |
| 104 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 105 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 106 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
| 107 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 6, i1 false) |
93 | 108 | ; CHECK-NEXT: call void @use(ptr [[DEST]]) |
94 | 109 | ; CHECK-NEXT: ret void |
95 | 110 | ; |
96 | | - %dep_dest = alloca %buf, align 1 |
97 | | - %dest = alloca %buf, align 1 |
98 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
99 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
100 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 111 | + %cpy_tmp = alloca %buf, align 1 |
| 112 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 113 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 114 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
101 | 115 | call void @use(ptr %dest) |
102 | 116 | ret void |
103 | 117 | } |
104 | 118 |
|
105 | 119 | ; Make sure we pass the right parameters when calling `memcpy.inline`. |
106 | | -define void @forward_offset_memcpy_inline(ptr %dep_src) { |
| 120 | +define void @forward_offset_memcpy_inline(ptr %src, ptr %dest) { |
107 | 121 | ; CHECK-LABEL: define void @forward_offset_memcpy_inline( |
108 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 122 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
109 | 123 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
110 | | -; CHECK-NEXT: [[DEST:%.*]] = alloca [9 x i8], align 1 |
111 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
112 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
113 | | -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
| 124 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 125 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
114 | 126 | ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 6, i1 false) |
115 | 127 | ; CHECK-NEXT: call void @use(ptr [[DEST]]) |
116 | 128 | ; CHECK-NEXT: ret void |
117 | 129 | ; |
118 | | - %dep_dest = alloca %buf, align 1 |
119 | | - %dest = alloca %buf, align 1 |
120 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
121 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
122 | | - call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 130 | + %cpy_tmp = alloca %buf, align 1 |
| 131 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 132 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 133 | + call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
123 | 134 | call void @use(ptr %dest) |
124 | 135 | ret void |
125 | 136 | } |
126 | 137 |
|
127 | 138 | ; We cannot forward `memcpy` because it exceeds the size of `memcpy` it depends on. |
128 | | -define void @do_not_forward_oversize_offset(ptr %dep_src) { |
| 139 | +define void @do_not_forward_oversize_offset(ptr %src, ptr %dest) { |
129 | 140 | ; CHECK-LABEL: define void @do_not_forward_oversize_offset( |
130 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 141 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
131 | 142 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
132 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 6, i1 false) |
133 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
134 | | -; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
135 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP]], ptr align 1 [[SRC]], i64 6, i1 false) |
| 143 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 6, i1 false) |
| 144 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 145 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP_OFFSET]], i64 6, i1 false) |
136 | 146 | ; CHECK-NEXT: ret void |
137 | 147 | ; |
138 | | - %dep_dest = alloca %buf, align 1 |
139 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 6, i1 false) |
140 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
141 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 1 |
142 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 6, i1 false) |
| 148 | + %cpy_tmp = alloca %buf, align 1 |
| 149 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 6, i1 false) |
| 150 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 151 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 6, i1 false) |
143 | 152 | ret void |
144 | 153 | } |
145 | 154 |
|
146 | 155 | ; We can forward `memcpy` because the write operation does not corrupt the location to be copied. |
147 | | -define void @forward_offset_and_store(ptr %dep_src) { |
| 156 | +define void @forward_offset_and_store(ptr %src, ptr %dest) { |
148 | 157 | ; CHECK-LABEL: define void @forward_offset_and_store( |
149 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 158 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
150 | 159 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
151 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
152 | | -; CHECK-NEXT: store i8 1, ptr [[DEP_SRC]], align 1 |
153 | | -; CHECK-NEXT: [[DEP_SRC_END:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 6 |
| 160 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 161 | +; CHECK-NEXT: store i8 1, ptr [[SRC]], align 1 |
| 162 | +; CHECK-NEXT: [[DEP_SRC_END:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 6 |
154 | 163 | ; CHECK-NEXT: store i8 1, ptr [[DEP_SRC_END]], align 1 |
155 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
156 | | -; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
157 | | -; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEP]], ptr align 1 [[DEP]], i64 5, i1 false) |
| 164 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 165 | +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
| 166 | +; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP1]], i64 5, i1 false) |
158 | 167 | ; CHECK-NEXT: ret void |
159 | 168 | ; |
160 | | - %dep_dest = alloca %buf, align 1 |
161 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
162 | | - store i8 1, ptr %dep_src, align 1 |
163 | | - %dep_src_end = getelementptr inbounds i8, ptr %dep_src, i64 6 |
164 | | - store i8 1, ptr %dep_src_end, align 1 |
165 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
166 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 1 |
167 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 5, i1 false) |
| 169 | + %cpy_tmp = alloca %buf, align 1 |
| 170 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 171 | + store i8 1, ptr %src, align 1 |
| 172 | + %src_end = getelementptr inbounds i8, ptr %src, i64 6 |
| 173 | + store i8 1, ptr %src_end, align 1 |
| 174 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 175 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 5, i1 false) |
168 | 176 | ret void |
169 | 177 | } |
170 | 178 |
|
171 | 179 | ; We cannot forward `memcpy` because the write operation alters the location to be copied. |
172 | 180 | ; Also, make sure we have removed the GEP instruction that was created temporarily. |
173 | | -define void @do_not_forward_offset_and_store(ptr %dep_src) { |
| 181 | +define void @do_not_forward_offset_and_store(ptr %src, ptr %dest) { |
174 | 182 | ; CHECK-LABEL: define void @do_not_forward_offset_and_store( |
175 | | -; CHECK-SAME: ptr [[DEP_SRC:%.*]]) { |
| 183 | +; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DEST:%.*]]) { |
176 | 184 | ; CHECK-NEXT: [[DEP_DEST:%.*]] = alloca [9 x i8], align 1 |
177 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[DEP_SRC]], i64 7, i1 false) |
178 | | -; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 1 |
| 185 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEP_DEST]], ptr align 1 [[SRC]], i64 7, i1 false) |
| 186 | +; CHECK-NEXT: [[DEP:%.*]] = getelementptr inbounds i8, ptr [[SRC]], i64 1 |
179 | 187 | ; CHECK-NEXT: store i8 1, ptr [[DEP]], align 1 |
180 | | -; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
181 | | -; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[DEP_SRC]], i64 2 |
182 | | -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[SRC]], i64 5, i1 false) |
| 188 | +; CHECK-NEXT: [[TMP_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DEP_DEST]], i64 1 |
| 189 | +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DEST]], ptr align 1 [[TMP_OFFSET]], i64 5, i1 false) |
183 | 190 | ; CHECK-NEXT: ret void |
184 | 191 | ; |
185 | | - %dep_dest = alloca %buf, align 1 |
186 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dep_dest, ptr align 1 %dep_src, i64 7, i1 false) |
187 | | - %dep_src_offset = getelementptr inbounds i8, ptr %dep_src, i64 1 |
188 | | - store i8 1, ptr %dep_src_offset, align 1 |
189 | | - %src = getelementptr inbounds i8, ptr %dep_dest, i64 1 |
190 | | - %dest = getelementptr inbounds i8, ptr %dep_src, i64 2 |
191 | | - call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %src, i64 5, i1 false) |
| 192 | + %cpy_tmp = alloca %buf, align 1 |
| 193 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %cpy_tmp, ptr align 1 %src, i64 7, i1 false) |
| 194 | + %src_offset = getelementptr inbounds i8, ptr %src, i64 1 |
| 195 | + store i8 1, ptr %src_offset, align 1 |
| 196 | + %cpy_tmp_offset = getelementptr inbounds i8, ptr %cpy_tmp, i64 1 |
| 197 | + call void @llvm.memcpy.p0.p0.i64(ptr align 1 %dest, ptr align 1 %cpy_tmp_offset, i64 5, i1 false) |
192 | 198 | ret void |
193 | 199 | } |
194 | 200 |
|
|
0 commit comments