xref: /llvm-project/llvm/test/Analysis/BasicAA/separate_storage.ll (revision 61042d2806af6b7202f1008d67b00c8dcfca62d6)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes='gvn' -basic-aa-separate-storage -S | FileCheck %s
3
4declare void @llvm.assume(i1)
5
6; Test basic queries.
7
8define i8 @simple_no(ptr %p1, ptr %p2) {
9; CHECK-LABEL: @simple_no(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    store i8 0, ptr [[P1:%.*]], align 1
12; CHECK-NEXT:    store i8 1, ptr [[P2:%.*]], align 1
13; CHECK-NEXT:    [[LOADOFSTORE:%.*]] = load i8, ptr [[P1]], align 1
14; CHECK-NEXT:    ret i8 [[LOADOFSTORE]]
15;
16entry:
17  store i8 0, ptr %p1
18  store i8 1, ptr %p2
19  %loadofstore = load i8, ptr %p1
20  ret i8 %loadofstore
21}
22
23define i8 @simple_yes(ptr %p1, ptr %p2) {
24; CHECK-LABEL: @simple_yes(
25; CHECK-NEXT:  entry:
26; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1:%.*]], ptr [[P2:%.*]]) ]
27; CHECK-NEXT:    store i8 0, ptr [[P1]], align 1
28; CHECK-NEXT:    store i8 1, ptr [[P2]], align 1
29; CHECK-NEXT:    ret i8 0
30;
31entry:
32  call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
33  store i8 0, ptr %p1
34  store i8 1, ptr %p2
35  %loadofstore = load i8, ptr %p1
36  ret i8 %loadofstore
37}
38
39define i8 @ptr_to_ptr_no(ptr %pp) {
40; CHECK-LABEL: @ptr_to_ptr_no(
41; CHECK-NEXT:  entry:
42; CHECK-NEXT:    [[P_BASE:%.*]] = load ptr, ptr [[PP:%.*]], align 8
43; CHECK-NEXT:    store i8 0, ptr [[P_BASE]], align 1
44; CHECK-NEXT:    [[P_BASE2:%.*]] = load ptr, ptr [[PP]], align 8
45; CHECK-NEXT:    [[LOADOFSTORE:%.*]] = load i8, ptr [[P_BASE2]], align 1
46; CHECK-NEXT:    ret i8 [[LOADOFSTORE]]
47;
48entry:
49  %p_base = load ptr, ptr %pp
50  store i8 0, ptr %p_base
51  %p_base2 = load ptr, ptr %pp
52  %loadofstore = load i8, ptr %p_base2
53  ret i8 %loadofstore
54}
55
56define i8 @ptr_to_ptr_yes(ptr %pp) {
57; CHECK-LABEL: @ptr_to_ptr_yes(
58; CHECK-NEXT:  entry:
59; CHECK-NEXT:    [[P_BASE:%.*]] = load ptr, ptr [[PP:%.*]], align 8
60; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P_BASE]], ptr [[PP]]) ]
61; CHECK-NEXT:    store i8 0, ptr [[P_BASE]], align 1
62; CHECK-NEXT:    ret i8 0
63;
64entry:
65  %p_base = load ptr, ptr %pp
66  call void @llvm.assume(i1 1) ["separate_storage"(ptr %p_base, ptr %pp)]
67  store i8 0, ptr %p_base
68  %p_base2 = load ptr, ptr %pp
69  %loadofstore = load i8, ptr %p_base2
70  ret i8 %loadofstore
71}
72
73; The analysis should only kick in if executed (or will be executed) at the
74; given program point.
75
76define i8 @flow_sensitive(ptr %p1, ptr %p2, i1 %cond) {
77; CHECK-LABEL: @flow_sensitive(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    br i1 [[COND:%.*]], label [[TRUE_BRANCH:%.*]], label [[FALSE_BRANCH:%.*]]
80; CHECK:       true_branch:
81; CHECK-NEXT:    store i8 11, ptr [[P1:%.*]], align 1
82; CHECK-NEXT:    store i8 22, ptr [[P2:%.*]], align 1
83; CHECK-NEXT:    [[LOADOFSTORE_TRUE:%.*]] = load i8, ptr [[P1]], align 1
84; CHECK-NEXT:    br label [[ENDIF:%.*]]
85; CHECK:       false_branch:
86; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1]], ptr [[P2]]) ]
87; CHECK-NEXT:    store i8 33, ptr [[P1]], align 1
88; CHECK-NEXT:    store i8 44, ptr [[P2]], align 1
89; CHECK-NEXT:    br label [[ENDIF]]
90; CHECK:       endif:
91; CHECK-NEXT:    [[LOADOFSTORE:%.*]] = phi i8 [ [[LOADOFSTORE_TRUE]], [[TRUE_BRANCH]] ], [ 33, [[FALSE_BRANCH]] ]
92; CHECK-NEXT:    ret i8 [[LOADOFSTORE]]
93;
94entry:
95  br i1 %cond, label %true_branch, label %false_branch
96
97true_branch:
98  store i8 11, ptr %p1
99  store i8 22, ptr %p2
100  %loadofstore_true = load i8, ptr %p1
101  br label %endif
102
103false_branch:
104  call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
105  store i8 33, ptr %p1
106  store i8 44, ptr %p2
107  %loadofstore_false = load i8, ptr %p1
108  br label %endif
109
110endif:
111  %loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ]
112  ret i8 %loadofstore
113}
114
115define i8 @flow_sensitive_with_dominator(ptr %p1, ptr %p2, i1 %cond) {
116; CHECK-LABEL: @flow_sensitive_with_dominator(
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[P1:%.*]], ptr [[P2:%.*]]) ]
119; CHECK-NEXT:    br i1 [[COND:%.*]], label [[TRUE_BRANCH:%.*]], label [[FALSE_BRANCH:%.*]]
120; CHECK:       true_branch:
121; CHECK-NEXT:    store i8 11, ptr [[P1]], align 1
122; CHECK-NEXT:    store i8 22, ptr [[P2]], align 1
123; CHECK-NEXT:    br label [[ENDIF:%.*]]
124; CHECK:       false_branch:
125; CHECK-NEXT:    store i8 33, ptr [[P1]], align 1
126; CHECK-NEXT:    store i8 44, ptr [[P2]], align 1
127; CHECK-NEXT:    br label [[ENDIF]]
128; CHECK:       endif:
129; CHECK-NEXT:    [[LOADOFSTORE:%.*]] = phi i8 [ 11, [[TRUE_BRANCH]] ], [ 33, [[FALSE_BRANCH]] ]
130; CHECK-NEXT:    ret i8 [[LOADOFSTORE]]
131;
132entry:
133  call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)]
134  br i1 %cond, label %true_branch, label %false_branch
135
136true_branch:
137  store i8 11, ptr %p1
138  store i8 22, ptr %p2
139  %loadofstore_true = load i8, ptr %p1
140  br label %endif
141
142false_branch:
143  store i8 33, ptr %p1
144  store i8 44, ptr %p2
145  %loadofstore_false = load i8, ptr %p1
146  br label %endif
147
148endif:
149  %loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ]
150  ret i8 %loadofstore
151}
152
153; Hints are relative to entire regions of storage, not particular pointers
154; inside them. We should know that the whole ranges are disjoint given hints at
155; offsets.
156
157define i8 @offset_agnostic(ptr %p1, ptr %p2) {
158; CHECK-LABEL: @offset_agnostic(
159; CHECK-NEXT:    [[ACCESS1:%.*]] = getelementptr inbounds i8, ptr [[P1:%.*]], i64 12
160; CHECK-NEXT:    [[ACCESS2:%.*]] = getelementptr inbounds i8, ptr [[P2:%.*]], i64 34
161; CHECK-NEXT:    [[HINT1:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 56
162; CHECK-NEXT:    [[HINT2:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 78
163; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[HINT1]], ptr [[HINT2]]) ]
164; CHECK-NEXT:    store i8 0, ptr [[ACCESS1]], align 1
165; CHECK-NEXT:    store i8 1, ptr [[ACCESS2]], align 1
166; CHECK-NEXT:    ret i8 0
167;
168  %access1 = getelementptr inbounds i8, ptr %p1, i64 12
169  %access2 = getelementptr inbounds i8, ptr %p2, i64 34
170
171  %hint1 = getelementptr inbounds i8, ptr %p1, i64 56
172  %hint2 = getelementptr inbounds i8, ptr %p2, i64 78
173  call void @llvm.assume(i1 1) ["separate_storage"(ptr %hint1, ptr %hint2)]
174
175  store i8 0, ptr %access1
176  store i8 1, ptr %access2
177  %loadofstore = load i8, ptr %access1
178  ret i8 %loadofstore
179}
180