1; RUN: opt < %s -passes=instcombine -S | FileCheck --match-full-lines %s
2
3; Test cases to make sure !annotation metadata is preserved, if possible.
4; Currently we fail to preserve !annotation metadata in many cases.
5
6; Make sure !annotation metadata is added to new instructions, if the source
7; instruction has !annotation metadata.
8define i1 @fold_to_new_instruction(i8* %a, i8* %b) {
9; CHECK-LABEL: define {{.+}} @fold_to_new_instruction({{.+}}
10; CHECK-NEXT:    [[C:%.*]] = icmp uge i8* [[A:%.*]], [[B:%[a-z]*]], !annotation [[ANN:![0-9]+]]
11; CHECK-NEXT:    ret i1 [[C]]
12;
13  %a.c = bitcast i8* %a to i32*, !annotation !0
14  %b.c = bitcast i8* %b to i32*, !annotation !0
15  %c = icmp uge i32* %a.c, %b.c, !annotation !0
16  ret i1 %c
17}
18
19; Make sure !annotation is not added to new instructions if the source
20; instruction does not have it (even if some folded operands do have
21; !annotation).
22define i1 @fold_to_new_instruction2(i8* %a, i8* %b) {
23; CHECK-LABEL: define {{.+}} @fold_to_new_instruction2({{.+}}
24; CHECK-NEXT:    [[C:%.*]] = icmp uge i8* [[A:%.*]], [[B:%[a-z]+]]
25; CHECK-NEXT:    ret i1 [[C]]
26;
27  %a.c = bitcast i8* %a to i32*, !annotation !0
28  %b.c = bitcast i8* %b to i32*, !annotation !0
29  %c = icmp uge i32* %a.c, %b.c
30  ret i1 %c
31}
32
33; Make sure !annotation metadata is *not* added if we replace an instruction
34; with !annotation with an existing one without.
35define i32 @do_not_add_annotation_to_existing_instr(i32 %a, i32 %b) {
36; CHECK-LABEL: define {{.+}} @do_not_add_annotation_to_existing_instr({{.+}}
37; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%[a-z]+]]
38; CHECK-NEXT:    ret i32 [[ADD]]
39;
40  %add = add i32 %a, %b
41  %res = add i32 0, %add, !annotation !0
42  ret i32 %res
43}
44
45; memcpy can be expanded inline with load/store. Verify that we keep the
46; !annotation metadata.
47
48declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
49
50define void @copy_1_byte(i8* %d, i8* %s) {
51; CHECK-LABEL: define {{.+}} @copy_1_byte({{.+}}
52; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
53; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
54; CHECK-NEXT:    ret void
55;
56  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 1, i1 false), !annotation !0
57  ret void
58}
59
60declare i8* @memcpy(i8* noalias returned, i8* noalias nocapture readonly, i64) nofree nounwind
61
62define void @libcallcopy_1_byte(i8* %d, i8* %s) {
63; CHECK-LABEL: define {{.+}} @libcallcopy_1_byte({{.+}}
64; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
65; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
66; CHECK-NEXT:    ret void
67;
68  call i8* @memcpy(i8* %d, i8* %s, i64 1), !annotation !0
69  ret void
70}
71
72declare i8* @__memcpy_chk(i8*, i8*, i64, i64) nofree nounwind
73
74define void @libcallcopy_1_byte_chk(i8* %d, i8* %s) {
75; CHECK-LABEL: define {{.+}} @libcallcopy_1_byte_chk({{.+}}
76; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
77; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
78; CHECK-NEXT:    ret void
79;
80  call i8* @__memcpy_chk(i8* %d, i8* %s, i64 1, i64 1), !annotation !0
81  ret void
82}
83
84declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) nounwind
85
86define void @move_1_byte(i8* %d, i8* %s) {
87; CHECK-LABEL: define {{.+}} @move_1_byte({{.+}}
88; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
89; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
90; CHECK-NEXT:    ret void
91;
92  call void @llvm.memmove.p0i8.p0i8.i32(i8* %d, i8* %s, i32 1, i1 false), !annotation !0
93  ret void
94}
95
96declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) nofree nounwind
97
98define void @libcallmove_1_byte(i8* %d, i8* %s) {
99; CHECK-LABEL: define {{.+}} @libcallmove_1_byte({{.+}}
100; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
101; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
102; CHECK-NEXT:    ret void
103;
104  call i8* @memmove(i8* %d, i8* %s, i64 1), !annotation !0
105  ret void
106}
107
108declare i8* @__memmove_chk(i8*, i8*, i64, i64) nofree nounwind
109
110define void @libcallmove_1_byte_chk(i8* %d, i8* %s) {
111; CHECK-LABEL: define {{.+}} @libcallmove_1_byte_chk({{.+}}
112; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]]
113; CHECK-NEXT:    store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]]
114; CHECK-NEXT:    ret void
115;
116  call i8* @__memmove_chk(i8* %d, i8* %s, i64 1, i64 1), !annotation !0
117  ret void
118}
119
120declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1) argmemonly nounwind
121
122define void @set_1_byte(i8* %d) {
123; CHECK-LABEL: define {{.+}} @set_1_byte({{.+}}
124; CHECK-NEXT:    store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]]
125; CHECK-NEXT:    ret void
126;
127  call void @llvm.memset.p0i8.i32(i8* %d, i8 1, i32 1, i1 false), !annotation !0
128  ret void
129}
130
131declare i8* @memset(i8*, i32, i64) nofree
132
133define void @libcall_set_1_byte(i8* %d) {
134; CHECK-LABEL: define {{.+}} @libcall_set_1_byte({{.+}}
135; CHECK-NEXT:    store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]]
136; CHECK-NEXT:    ret void
137;
138  call i8* @memset(i8* %d, i32 1, i64 1), !annotation !0
139  ret void
140}
141
142declare i8* @__memset_chk(i8*, i32, i64, i64) nofree
143
144define void @libcall_set_1_byte_chk(i8* %d) {
145; CHECK-LABEL: define {{.+}} @libcall_set_1_byte_chk({{.+}}
146; CHECK-NEXT:    store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]]
147; CHECK-NEXT:    ret void
148;
149  call i8* @__memset_chk(i8* %d, i32 1, i64 1, i64 1), !annotation !0
150  ret void
151}
152
153!0 = !{ !"auto-init" }
154