Skip to content

Commit 2c48dd7

Browse files
committed
[MemCpyOpt] Add additional call slot tests (NFC)
The case of a destination read between call and memcpy was not covered anywhere (but is handled correctly). However, a potentially throwing call between the call and the memcpy appears to be miscompiled.
1 parent e4e5c42 commit 2c48dd7

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -memcpyopt < %s | FileCheck %s
3+
4+
define i8 @read_dest_between_call_and_memcpy() {
5+
; CHECK-LABEL: @read_dest_between_call_and_memcpy(
6+
; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 16, align 1
7+
; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 16, align 1
8+
; CHECK-NEXT: store i8 1, i8* [[DEST]], align 1
9+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[SRC]], i8 0, i64 16, i1 false)
10+
; CHECK-NEXT: [[X:%.*]] = load i8, i8* [[DEST]], align 1
11+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DEST]], i8 0, i64 16, i1 false)
12+
; CHECK-NEXT: ret i8 [[X]]
13+
;
14+
%dest = alloca i8, i64 16
15+
%src = alloca i8, i64 16
16+
store i8 1, i8* %dest
17+
call void @llvm.memset.p0i8.i64(i8* %src, i8 0, i64 16, i1 false)
18+
%x = load i8, i8* %dest
19+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 16, i1 false)
20+
ret i8 %x
21+
}
22+
23+
define i8 @read_src_between_call_and_memcpy() {
24+
; CHECK-LABEL: @read_src_between_call_and_memcpy(
25+
; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 16, align 1
26+
; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 16, align 1
27+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[SRC]], i8 0, i64 16, i1 false)
28+
; CHECK-NEXT: [[X:%.*]] = load i8, i8* [[SRC]], align 1
29+
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 16, i1 false)
30+
; CHECK-NEXT: ret i8 [[X]]
31+
;
32+
%dest = alloca i8, i64 16
33+
%src = alloca i8, i64 16
34+
call void @llvm.memset.p0i8.i64(i8* %src, i8 0, i64 16, i1 false)
35+
%x = load i8, i8* %src
36+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 16, i1 false)
37+
ret i8 %x
38+
}
39+
40+
define void @write_dest_between_call_and_memcpy() {
41+
; CHECK-LABEL: @write_dest_between_call_and_memcpy(
42+
; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 16, align 1
43+
; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 16, align 1
44+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[SRC]], i8 0, i64 16, i1 false)
45+
; CHECK-NEXT: store i8 1, i8* [[DEST]], align 1
46+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DEST]], i8 0, i64 16, i1 false)
47+
; CHECK-NEXT: ret void
48+
;
49+
%dest = alloca i8, i64 16
50+
%src = alloca i8, i64 16
51+
call void @llvm.memset.p0i8.i64(i8* %src, i8 0, i64 16, i1 false)
52+
store i8 1, i8* %dest
53+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 16, i1 false)
54+
ret void
55+
}
56+
57+
define void @write_src_between_call_and_memcpy() {
58+
; CHECK-LABEL: @write_src_between_call_and_memcpy(
59+
; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 16, align 1
60+
; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 16, align 1
61+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[SRC]], i8 0, i64 16, i1 false)
62+
; CHECK-NEXT: store i8 1, i8* [[SRC]], align 1
63+
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 16, i1 false)
64+
; CHECK-NEXT: ret void
65+
;
66+
%dest = alloca i8, i64 16
67+
%src = alloca i8, i64 16
68+
call void @llvm.memset.p0i8.i64(i8* %src, i8 0, i64 16, i1 false)
69+
store i8 1, i8* %src
70+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 16, i1 false)
71+
ret void
72+
}
73+
74+
; TODO: This is a miscompile.
75+
define void @throw_between_call_and_mempy(i8* dereferenceable(16) %dest) {
76+
; CHECK-LABEL: @throw_between_call_and_mempy(
77+
; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 16, align 1
78+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[DEST:%.*]], i8 0, i64 16, i1 false)
79+
; CHECK-NEXT: call void @may_throw() [[ATTR2:#.*]]
80+
; CHECK-NEXT: ret void
81+
;
82+
%src = alloca i8, i64 16
83+
call void @llvm.memset.p0i8.i64(i8* %src, i8 0, i64 16, i1 false)
84+
call void @may_throw() readnone
85+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dest, i8* %src, i64 16, i1 false)
86+
ret void
87+
}
88+
89+
declare void @may_throw()
90+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
91+
declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1)

0 commit comments

Comments
 (0)