|
1 |
| -; This testcase tests for various features the basicaa test should be able to |
| 1 | +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| 2 | +; This testcase tests for various features the basicaa test should be able to |
2 | 3 | ; determine, as noted in the comments.
|
3 | 4 |
|
4 |
| -; RUN: opt < %s -basicaa -gvn -instcombine -dce -S | FileCheck %s |
| 5 | +; RUN: opt < %s -basicaa -gvn -instcombine -dce -S | FileCheck %s --check-prefixes=CHECK,NO_ASSUME |
| 6 | +; RUN: opt < %s -basicaa -gvn -instcombine -dce --enable-knowledge-retention -S | FileCheck %s --check-prefixes=CHECK,USE_ASSUME |
5 | 7 | target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
|
6 | 8 |
|
7 | 9 | @Global = external global { i32 }
|
8 | 10 |
|
9 | 11 | declare void @external(i32*)
|
| 12 | +declare void @llvm.assume(i1) |
10 | 13 |
|
11 |
| -; Array test: Test that operations on one local array do not invalidate |
| 14 | +; Array test: Test that operations on one local array do not invalidate |
12 | 15 | ; operations on another array. Important for scientific codes.
|
13 | 16 | ;
|
14 | 17 | define i32 @different_array_test(i64 %A, i64 %B) {
|
15 |
| - %Array1 = alloca i32, i32 100 |
16 |
| - %Array2 = alloca i32, i32 200 |
17 |
| - |
18 |
| - call void @external(i32* %Array1) |
19 |
| - call void @external(i32* %Array2) |
20 |
| - |
21 |
| - %pointer = getelementptr i32, i32* %Array1, i64 %A |
22 |
| - %val = load i32, i32* %pointer |
23 |
| - |
24 |
| - %pointer2 = getelementptr i32, i32* %Array2, i64 %B |
25 |
| - store i32 7, i32* %pointer2 |
26 |
| - |
27 |
| - %REMOVE = load i32, i32* %pointer ; redundant with above load |
28 |
| - %retval = sub i32 %REMOVE, %val |
29 |
| - ret i32 %retval |
30 |
| -; CHECK: @different_array_test |
31 |
| -; CHECK: ret i32 0 |
| 18 | +; NO_ASSUME-LABEL: @different_array_test( |
| 19 | +; NO_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4 |
| 20 | +; NO_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4 |
| 21 | +; NO_ASSUME-NEXT: [[ARRAY22_SUB:%.*]] = getelementptr inbounds [200 x i32], [200 x i32]* [[ARRAY22]], i64 0, i64 0 |
| 22 | +; NO_ASSUME-NEXT: [[ARRAY11_SUB:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY11]], i64 0, i64 0 |
| 23 | +; NO_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[ARRAY11_SUB]], i32 4) ] |
| 24 | +; NO_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY11_SUB]]) |
| 25 | +; NO_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY22_SUB]]) |
| 26 | +; NO_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr [200 x i32], [200 x i32]* [[ARRAY22]], i64 0, i64 [[B:%.*]] |
| 27 | +; NO_ASSUME-NEXT: store i32 7, i32* [[POINTER2]], align 4 |
| 28 | +; NO_ASSUME-NEXT: ret i32 0 |
| 29 | +; |
| 30 | +; USE_ASSUME-LABEL: @different_array_test( |
| 31 | +; USE_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4 |
| 32 | +; USE_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4 |
| 33 | +; USE_ASSUME-NEXT: [[ARRAY22_SUB:%.*]] = getelementptr inbounds [200 x i32], [200 x i32]* [[ARRAY22]], i64 0, i64 0 |
| 34 | +; USE_ASSUME-NEXT: [[ARRAY11_SUB:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY11]], i64 0, i64 0 |
| 35 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[ARRAY11_SUB]], i32 4) ] |
| 36 | +; USE_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY11_SUB]]) |
| 37 | +; USE_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY22_SUB]]) |
| 38 | +; USE_ASSUME-NEXT: [[POINTER:%.*]] = getelementptr [100 x i32], [100 x i32]* [[ARRAY11]], i64 0, i64 [[A:%.*]] |
| 39 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[POINTER]], i64 4), "nonnull"(i32* [[POINTER]]) ] |
| 40 | +; USE_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr [200 x i32], [200 x i32]* [[ARRAY22]], i64 0, i64 [[B:%.*]] |
| 41 | +; USE_ASSUME-NEXT: store i32 7, i32* [[POINTER2]], align 4 |
| 42 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[POINTER]], i64 4), "nonnull"(i32* [[POINTER]]) ] |
| 43 | +; USE_ASSUME-NEXT: ret i32 0 |
| 44 | +; |
| 45 | + %Array1 = alloca i32, i32 100 |
| 46 | + %Array2 = alloca i32, i32 200 |
| 47 | + call void @llvm.assume(i1 true) ["align"(i32* %Array1, i32 4)] |
| 48 | + |
| 49 | + call void @external(i32* %Array1) |
| 50 | + call void @external(i32* %Array2) |
| 51 | + |
| 52 | + %pointer = getelementptr i32, i32* %Array1, i64 %A |
| 53 | + %val = load i32, i32* %pointer |
| 54 | + |
| 55 | + %pointer2 = getelementptr i32, i32* %Array2, i64 %B |
| 56 | + store i32 7, i32* %pointer2 |
| 57 | + |
| 58 | + %REMOVE = load i32, i32* %pointer ; redundant with above load |
| 59 | + %retval = sub i32 %REMOVE, %val |
| 60 | + ret i32 %retval |
32 | 61 | }
|
33 | 62 |
|
34 |
| -; Constant index test: Constant indexes into the same array should not |
| 63 | +; Constant index test: Constant indexes into the same array should not |
35 | 64 | ; interfere with each other. Again, important for scientific codes.
|
36 | 65 | ;
|
37 | 66 | define i32 @constant_array_index_test() {
|
38 |
| - %Array = alloca i32, i32 100 |
39 |
| - call void @external(i32* %Array) |
40 |
| - |
41 |
| - %P1 = getelementptr i32, i32* %Array, i64 7 |
42 |
| - %P2 = getelementptr i32, i32* %Array, i64 6 |
43 |
| - |
44 |
| - %A = load i32, i32* %P1 |
45 |
| - store i32 1, i32* %P2 ; Should not invalidate load |
46 |
| - %BREMOVE = load i32, i32* %P1 |
47 |
| - %Val = sub i32 %A, %BREMOVE |
48 |
| - ret i32 %Val |
49 |
| -; CHECK: @constant_array_index_test |
50 |
| -; CHECK: ret i32 0 |
| 67 | +; NO_ASSUME-LABEL: @constant_array_index_test( |
| 68 | +; NO_ASSUME-NEXT: [[ARRAY1:%.*]] = alloca [100 x i32], align 4 |
| 69 | +; NO_ASSUME-NEXT: [[ARRAY1_SUB:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY1]], i64 0, i64 0 |
| 70 | +; NO_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY1_SUB]]) |
| 71 | +; NO_ASSUME-NEXT: [[P2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY1]], i64 0, i64 6 |
| 72 | +; NO_ASSUME-NEXT: store i32 1, i32* [[P2]], align 4 |
| 73 | +; NO_ASSUME-NEXT: ret i32 0 |
| 74 | +; |
| 75 | +; USE_ASSUME-LABEL: @constant_array_index_test( |
| 76 | +; USE_ASSUME-NEXT: [[ARRAY1:%.*]] = alloca [100 x i32], align 4 |
| 77 | +; USE_ASSUME-NEXT: [[ARRAY1_SUB:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY1]], i64 0, i64 0 |
| 78 | +; USE_ASSUME-NEXT: call void @external(i32* nonnull [[ARRAY1_SUB]]) |
| 79 | +; USE_ASSUME-NEXT: [[P1:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY1]], i64 0, i64 7 |
| 80 | +; USE_ASSUME-NEXT: [[P2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* [[ARRAY1]], i64 0, i64 6 |
| 81 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]) ] |
| 82 | +; USE_ASSUME-NEXT: store i32 1, i32* [[P2]], align 4 |
| 83 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 4), "nonnull"(i32* [[P1]]) ] |
| 84 | +; USE_ASSUME-NEXT: ret i32 0 |
| 85 | +; |
| 86 | + %Array = alloca i32, i32 100 |
| 87 | + call void @external(i32* %Array) |
| 88 | + |
| 89 | + %P1 = getelementptr i32, i32* %Array, i64 7 |
| 90 | + %P2 = getelementptr i32, i32* %Array, i64 6 |
| 91 | + |
| 92 | + %A = load i32, i32* %P1 |
| 93 | + store i32 1, i32* %P2 ; Should not invalidate load |
| 94 | + %BREMOVE = load i32, i32* %P1 |
| 95 | + %Val = sub i32 %A, %BREMOVE |
| 96 | + ret i32 %Val |
51 | 97 | }
|
52 | 98 |
|
53 |
| -; Test that if two pointers are spaced out by a constant getelementptr, that |
| 99 | +; Test that if two pointers are spaced out by a constant getelementptr, that |
54 | 100 | ; they cannot alias.
|
55 | 101 | define i32 @gep_distance_test(i32* %A) {
|
56 |
| - %REMOVEu = load i32, i32* %A |
57 |
| - %B = getelementptr i32, i32* %A, i64 2 ; Cannot alias A |
58 |
| - store i32 7, i32* %B |
59 |
| - %REMOVEv = load i32, i32* %A |
60 |
| - %r = sub i32 %REMOVEu, %REMOVEv |
61 |
| - ret i32 %r |
62 |
| -; CHECK: @gep_distance_test |
63 |
| -; CHECK: ret i32 0 |
| 102 | +; NO_ASSUME-LABEL: @gep_distance_test( |
| 103 | +; NO_ASSUME-NEXT: [[B:%.*]] = getelementptr i32, i32* [[A:%.*]], i64 2 |
| 104 | +; NO_ASSUME-NEXT: store i32 7, i32* [[B]], align 4 |
| 105 | +; NO_ASSUME-NEXT: ret i32 0 |
| 106 | +; |
| 107 | +; USE_ASSUME-LABEL: @gep_distance_test( |
| 108 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A:%.*]], i64 4), "nonnull"(i32* [[A]]) ] |
| 109 | +; USE_ASSUME-NEXT: [[B:%.*]] = getelementptr i32, i32* [[A]], i64 2 |
| 110 | +; USE_ASSUME-NEXT: store i32 7, i32* [[B]], align 4 |
| 111 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A]], i64 4), "nonnull"(i32* [[A]]) ] |
| 112 | +; USE_ASSUME-NEXT: ret i32 0 |
| 113 | +; |
| 114 | + %REMOVEu = load i32, i32* %A |
| 115 | + %B = getelementptr i32, i32* %A, i64 2 ; Cannot alias A |
| 116 | + store i32 7, i32* %B |
| 117 | + %REMOVEv = load i32, i32* %A |
| 118 | + %r = sub i32 %REMOVEu, %REMOVEv |
| 119 | + ret i32 %r |
64 | 120 | }
|
65 | 121 |
|
66 | 122 | ; Test that if two pointers are spaced out by a constant offset, that they
|
67 | 123 | ; cannot alias, even if there is a variable offset between them...
|
68 | 124 | define i32 @gep_distance_test2({i32,i32}* %A, i64 %distance) {
|
69 |
| - %A1 = getelementptr {i32,i32}, {i32,i32}* %A, i64 0, i32 0 |
70 |
| - %REMOVEu = load i32, i32* %A1 |
71 |
| - %B = getelementptr {i32,i32}, {i32,i32}* %A, i64 %distance, i32 1 |
72 |
| - store i32 7, i32* %B ; B cannot alias A, it's at least 4 bytes away |
73 |
| - %REMOVEv = load i32, i32* %A1 |
74 |
| - %r = sub i32 %REMOVEu, %REMOVEv |
75 |
| - ret i32 %r |
76 |
| -; CHECK: @gep_distance_test2 |
77 |
| -; CHECK: ret i32 0 |
| 125 | +; NO_ASSUME-LABEL: @gep_distance_test2( |
| 126 | +; NO_ASSUME-NEXT: [[B:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[A:%.*]], i64 [[DISTANCE:%.*]], i32 1 |
| 127 | +; NO_ASSUME-NEXT: store i32 7, i32* [[B]], align 4 |
| 128 | +; NO_ASSUME-NEXT: ret i32 0 |
| 129 | +; |
| 130 | +; USE_ASSUME-LABEL: @gep_distance_test2( |
| 131 | +; USE_ASSUME-NEXT: [[A1:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[A:%.*]], i64 0, i32 0 |
| 132 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A1]], i64 4), "nonnull"(i32* [[A1]]) ] |
| 133 | +; USE_ASSUME-NEXT: [[B:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[A]], i64 [[DISTANCE:%.*]], i32 1 |
| 134 | +; USE_ASSUME-NEXT: store i32 7, i32* [[B]], align 4 |
| 135 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A1]], i64 4), "nonnull"(i32* [[A1]]) ] |
| 136 | +; USE_ASSUME-NEXT: ret i32 0 |
| 137 | +; |
| 138 | + %A1 = getelementptr {i32,i32}, {i32,i32}* %A, i64 0, i32 0 |
| 139 | + %REMOVEu = load i32, i32* %A1 |
| 140 | + %B = getelementptr {i32,i32}, {i32,i32}* %A, i64 %distance, i32 1 |
| 141 | + store i32 7, i32* %B ; B cannot alias A, it's at least 4 bytes away |
| 142 | + %REMOVEv = load i32, i32* %A1 |
| 143 | + %r = sub i32 %REMOVEu, %REMOVEv |
| 144 | + ret i32 %r |
78 | 145 | }
|
79 | 146 |
|
80 |
| -; Test that we can do funny pointer things and that distance calc will still |
| 147 | +; Test that we can do funny pointer things and that distance calc will still |
81 | 148 | ; work.
|
82 | 149 | define i32 @gep_distance_test3(i32 * %A) {
|
83 |
| - %X = load i32, i32* %A |
84 |
| - %B = bitcast i32* %A to i8* |
85 |
| - %C = getelementptr i8, i8* %B, i64 4 |
86 |
| - store i8 42, i8* %C |
87 |
| - %Y = load i32, i32* %A |
88 |
| - %R = sub i32 %X, %Y |
89 |
| - ret i32 %R |
90 |
| -; CHECK: @gep_distance_test3 |
91 |
| -; CHECK: ret i32 0 |
| 150 | +; NO_ASSUME-LABEL: @gep_distance_test3( |
| 151 | +; NO_ASSUME-NEXT: [[C1:%.*]] = getelementptr i32, i32* [[A:%.*]], i64 1 |
| 152 | +; NO_ASSUME-NEXT: [[C:%.*]] = bitcast i32* [[C1]] to i8* |
| 153 | +; NO_ASSUME-NEXT: store i8 42, i8* [[C]], align 1 |
| 154 | +; NO_ASSUME-NEXT: ret i32 0 |
| 155 | +; |
| 156 | +; USE_ASSUME-LABEL: @gep_distance_test3( |
| 157 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A:%.*]], i64 4), "nonnull"(i32* [[A]]) ] |
| 158 | +; USE_ASSUME-NEXT: [[C1:%.*]] = getelementptr i32, i32* [[A]], i64 1 |
| 159 | +; USE_ASSUME-NEXT: [[C:%.*]] = bitcast i32* [[C1]] to i8* |
| 160 | +; USE_ASSUME-NEXT: store i8 42, i8* [[C]], align 1 |
| 161 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[A]], i64 4), "nonnull"(i32* [[A]]) ] |
| 162 | +; USE_ASSUME-NEXT: ret i32 0 |
| 163 | +; |
| 164 | + %X = load i32, i32* %A |
| 165 | + %B = bitcast i32* %A to i8* |
| 166 | + %C = getelementptr i8, i8* %B, i64 4 |
| 167 | + store i8 42, i8* %C |
| 168 | + %Y = load i32, i32* %A |
| 169 | + %R = sub i32 %X, %Y |
| 170 | + ret i32 %R |
92 | 171 | }
|
93 | 172 |
|
94 | 173 | ; Test that we can disambiguate globals reached through constantexpr geps
|
95 | 174 | define i32 @constexpr_test() {
|
96 |
| - %X = alloca i32 |
97 |
| - call void @external(i32* %X) |
98 |
| - |
99 |
| - %Y = load i32, i32* %X |
100 |
| - store i32 5, i32* getelementptr ({ i32 }, { i32 }* @Global, i64 0, i32 0) |
101 |
| - %REMOVE = load i32, i32* %X |
102 |
| - %retval = sub i32 %Y, %REMOVE |
103 |
| - ret i32 %retval |
104 |
| -; CHECK: @constexpr_test |
105 |
| -; CHECK: ret i32 0 |
| 175 | +; NO_ASSUME-LABEL: @constexpr_test( |
| 176 | +; NO_ASSUME-NEXT: [[X:%.*]] = alloca i32, align 4 |
| 177 | +; NO_ASSUME-NEXT: call void @external(i32* nonnull [[X]]) |
| 178 | +; NO_ASSUME-NEXT: store i32 5, i32* getelementptr inbounds ({ i32 }, { i32 }* @Global, i64 0, i32 0), align 4 |
| 179 | +; NO_ASSUME-NEXT: ret i32 0 |
| 180 | +; |
| 181 | +; USE_ASSUME-LABEL: @constexpr_test( |
| 182 | +; USE_ASSUME-NEXT: [[X:%.*]] = alloca i32, align 4 |
| 183 | +; USE_ASSUME-NEXT: call void @external(i32* nonnull [[X]]) |
| 184 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[X]], i64 4), "nonnull"(i32* [[X]]) ] |
| 185 | +; USE_ASSUME-NEXT: store i32 5, i32* getelementptr inbounds ({ i32 }, { i32 }* @Global, i64 0, i32 0), align 4 |
| 186 | +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[X]], i64 4), "nonnull"(i32* [[X]]) ] |
| 187 | +; USE_ASSUME-NEXT: ret i32 0 |
| 188 | +; |
| 189 | + %X = alloca i32 |
| 190 | + call void @external(i32* %X) |
| 191 | + |
| 192 | + %Y = load i32, i32* %X |
| 193 | + store i32 5, i32* getelementptr ({ i32 }, { i32 }* @Global, i64 0, i32 0) |
| 194 | + %REMOVE = load i32, i32* %X |
| 195 | + %retval = sub i32 %Y, %REMOVE |
| 196 | + ret i32 %retval |
106 | 197 | }
|
107 | 198 |
|
108 | 199 |
|
109 | 200 |
|
110 | 201 | ; PR7589
|
111 | 202 | ; These two index expressions are different, this cannot be CSE'd.
|
112 | 203 | define i16 @zext_sext_confusion(i16* %row2col, i5 %j) nounwind{
|
| 204 | +; CHECK-LABEL: @zext_sext_confusion( |
| 205 | +; CHECK-NEXT: entry: |
| 206 | +; CHECK-NEXT: [[SUM5_CAST:%.*]] = zext i5 [[J:%.*]] to i64 |
| 207 | +; CHECK-NEXT: [[P1:%.*]] = getelementptr i16, i16* [[ROW2COL:%.*]], i64 [[SUM5_CAST]] |
| 208 | +; CHECK-NEXT: [[ROW2COL_LOAD_1_2:%.*]] = load i16, i16* [[P1]], align 1 |
| 209 | +; CHECK-NEXT: [[SUM13_CAST31:%.*]] = sext i5 [[J]] to i6 |
| 210 | +; CHECK-NEXT: [[SUM13_CAST:%.*]] = zext i6 [[SUM13_CAST31]] to i64 |
| 211 | +; CHECK-NEXT: [[P2:%.*]] = getelementptr i16, i16* [[ROW2COL]], i64 [[SUM13_CAST]] |
| 212 | +; CHECK-NEXT: [[ROW2COL_LOAD_1_6:%.*]] = load i16, i16* [[P2]], align 1 |
| 213 | +; CHECK-NEXT: [[DOTRET:%.*]] = sub i16 [[ROW2COL_LOAD_1_6]], [[ROW2COL_LOAD_1_2]] |
| 214 | +; CHECK-NEXT: ret i16 [[DOTRET]] |
| 215 | +; |
113 | 216 | entry:
|
114 | 217 | %sum5.cast = zext i5 %j to i64 ; <i64> [#uses=1]
|
115 | 218 | %P1 = getelementptr i16, i16* %row2col, i64 %sum5.cast
|
116 | 219 | %row2col.load.1.2 = load i16, i16* %P1, align 1 ; <i16> [#uses=1]
|
117 |
| - |
| 220 | + |
118 | 221 | %sum13.cast31 = sext i5 %j to i6 ; <i6> [#uses=1]
|
119 | 222 | %sum13.cast = zext i6 %sum13.cast31 to i64 ; <i64> [#uses=1]
|
120 | 223 | %P2 = getelementptr i16, i16* %row2col, i64 %sum13.cast
|
121 | 224 | %row2col.load.1.6 = load i16, i16* %P2, align 1 ; <i16> [#uses=1]
|
122 |
| - |
| 225 | + |
123 | 226 | %.ret = sub i16 %row2col.load.1.6, %row2col.load.1.2 ; <i16> [#uses=1]
|
124 | 227 | ret i16 %.ret
|
125 |
| -; CHECK: @zext_sext_confusion |
126 |
| -; CHECK: ret i16 %.ret |
127 | 228 | }
|
0 commit comments