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