|
| 1 | +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py |
| 2 | +; RUN: opt < %s --data-layout="e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -S -analyze -enable-new-pm=0 -scalar-evolution | FileCheck --check-prefixes=ALL,X64 %s |
| 3 | +; RUN: opt < %s--data-layout="e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -S -disable-output "-passes=print<scalar-evolution>" 2>&1 | FileCheck --check-prefixes=ALL,X64 %s |
| 4 | +; RUN: opt < %s --data-layout="e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128" -S -analyze -enable-new-pm=0 -scalar-evolution | FileCheck --check-prefixes=ALL,X32 %s |
| 5 | +; RUN: opt < %s--data-layout="e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128" -S -disable-output "-passes=print<scalar-evolution>" 2>&1 | FileCheck --check-prefixes=ALL,X32 %s |
| 6 | + |
| 7 | +; While we can't treat inttoptr/ptrtoint casts as fully transparent, |
| 8 | +; for ptrtoint cast, instead of modelling it as fully opaque (unknown), |
| 9 | +; we can at least model it as zext/trunc/self of an unknown, |
| 10 | +; iff it it's argument would be modelled as unknown anyways. |
| 11 | + |
| 12 | +declare void @useptr(i8*) |
| 13 | + |
| 14 | +; Simple ptrtoint of an argument, with casts to potentially different bit widths. |
| 15 | +define void @ptrtoint(i8* %in, i64* %out0, i32* %out1, i16* %out2, i128* %out3) { |
| 16 | +; X64-LABEL: 'ptrtoint' |
| 17 | +; X64-NEXT: Classifying expressions for: @ptrtoint |
| 18 | +; X64-NEXT: %p0 = ptrtoint i8* %in to i64 |
| 19 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 20 | +; X64-NEXT: %p1 = ptrtoint i8* %in to i32 |
| 21 | +; X64-NEXT: --> %p1 U: full-set S: full-set |
| 22 | +; X64-NEXT: %p2 = ptrtoint i8* %in to i16 |
| 23 | +; X64-NEXT: --> %p2 U: full-set S: full-set |
| 24 | +; X64-NEXT: %p3 = ptrtoint i8* %in to i128 |
| 25 | +; X64-NEXT: --> %p3 U: [0,18446744073709551616) S: [-18446744073709551616,18446744073709551616) |
| 26 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint |
| 27 | +; |
| 28 | +; X32-LABEL: 'ptrtoint' |
| 29 | +; X32-NEXT: Classifying expressions for: @ptrtoint |
| 30 | +; X32-NEXT: %p0 = ptrtoint i8* %in to i64 |
| 31 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 32 | +; X32-NEXT: %p1 = ptrtoint i8* %in to i32 |
| 33 | +; X32-NEXT: --> %p1 U: full-set S: full-set |
| 34 | +; X32-NEXT: %p2 = ptrtoint i8* %in to i16 |
| 35 | +; X32-NEXT: --> %p2 U: full-set S: full-set |
| 36 | +; X32-NEXT: %p3 = ptrtoint i8* %in to i128 |
| 37 | +; X32-NEXT: --> %p3 U: [0,4294967296) S: [-4294967296,4294967296) |
| 38 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint |
| 39 | +; |
| 40 | + %p0 = ptrtoint i8* %in to i64 |
| 41 | + %p1 = ptrtoint i8* %in to i32 |
| 42 | + %p2 = ptrtoint i8* %in to i16 |
| 43 | + %p3 = ptrtoint i8* %in to i128 |
| 44 | + store i64 %p0, i64* %out0 |
| 45 | + store i32 %p1, i32* %out1 |
| 46 | + store i16 %p2, i16* %out2 |
| 47 | + store i128 %p3, i128* %out3 |
| 48 | + ret void |
| 49 | +} |
| 50 | + |
| 51 | +; Same, but from non-zero/non-default address space. |
| 52 | +define void @ptrtoint_as1(i8 addrspace(1)* %in, i64* %out0, i32* %out1, i16* %out2, i128* %out3) { |
| 53 | +; X64-LABEL: 'ptrtoint_as1' |
| 54 | +; X64-NEXT: Classifying expressions for: @ptrtoint_as1 |
| 55 | +; X64-NEXT: %p0 = ptrtoint i8 addrspace(1)* %in to i64 |
| 56 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 57 | +; X64-NEXT: %p1 = ptrtoint i8 addrspace(1)* %in to i32 |
| 58 | +; X64-NEXT: --> %p1 U: full-set S: full-set |
| 59 | +; X64-NEXT: %p2 = ptrtoint i8 addrspace(1)* %in to i16 |
| 60 | +; X64-NEXT: --> %p2 U: full-set S: full-set |
| 61 | +; X64-NEXT: %p3 = ptrtoint i8 addrspace(1)* %in to i128 |
| 62 | +; X64-NEXT: --> %p3 U: [0,18446744073709551616) S: [-18446744073709551616,18446744073709551616) |
| 63 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_as1 |
| 64 | +; |
| 65 | +; X32-LABEL: 'ptrtoint_as1' |
| 66 | +; X32-NEXT: Classifying expressions for: @ptrtoint_as1 |
| 67 | +; X32-NEXT: %p0 = ptrtoint i8 addrspace(1)* %in to i64 |
| 68 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 69 | +; X32-NEXT: %p1 = ptrtoint i8 addrspace(1)* %in to i32 |
| 70 | +; X32-NEXT: --> %p1 U: full-set S: full-set |
| 71 | +; X32-NEXT: %p2 = ptrtoint i8 addrspace(1)* %in to i16 |
| 72 | +; X32-NEXT: --> %p2 U: full-set S: full-set |
| 73 | +; X32-NEXT: %p3 = ptrtoint i8 addrspace(1)* %in to i128 |
| 74 | +; X32-NEXT: --> %p3 U: [0,4294967296) S: [-4294967296,4294967296) |
| 75 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_as1 |
| 76 | +; |
| 77 | + %p0 = ptrtoint i8 addrspace(1)* %in to i64 |
| 78 | + %p1 = ptrtoint i8 addrspace(1)* %in to i32 |
| 79 | + %p2 = ptrtoint i8 addrspace(1)* %in to i16 |
| 80 | + %p3 = ptrtoint i8 addrspace(1)* %in to i128 |
| 81 | + store i64 %p0, i64* %out0 |
| 82 | + store i32 %p1, i32* %out1 |
| 83 | + store i16 %p2, i16* %out2 |
| 84 | + store i128 %p3, i128* %out3 |
| 85 | + ret void |
| 86 | +} |
| 87 | + |
| 88 | +; Likewise, ptrtoint of a bitcast is fine, we simply skip it. |
| 89 | +define void @ptrtoint_of_bitcast(i8* %in, i64* %out0) { |
| 90 | +; X64-LABEL: 'ptrtoint_of_bitcast' |
| 91 | +; X64-NEXT: Classifying expressions for: @ptrtoint_of_bitcast |
| 92 | +; X64-NEXT: %in_casted = bitcast i8* %in to float* |
| 93 | +; X64-NEXT: --> %in U: full-set S: full-set |
| 94 | +; X64-NEXT: %p0 = ptrtoint float* %in_casted to i64 |
| 95 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 96 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_bitcast |
| 97 | +; |
| 98 | +; X32-LABEL: 'ptrtoint_of_bitcast' |
| 99 | +; X32-NEXT: Classifying expressions for: @ptrtoint_of_bitcast |
| 100 | +; X32-NEXT: %in_casted = bitcast i8* %in to float* |
| 101 | +; X32-NEXT: --> %in U: full-set S: full-set |
| 102 | +; X32-NEXT: %p0 = ptrtoint float* %in_casted to i64 |
| 103 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 104 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_bitcast |
| 105 | +; |
| 106 | + %in_casted = bitcast i8* %in to float* |
| 107 | + %p0 = ptrtoint float* %in_casted to i64 |
| 108 | + store i64 %p0, i64* %out0 |
| 109 | + ret void |
| 110 | +} |
| 111 | + |
| 112 | +; addrspacecast is fine too, but We don't model addrspacecast, so we stop there. |
| 113 | +define void @ptrtoint_of_addrspacecast(i8* %in, i64* %out0) { |
| 114 | +; X64-LABEL: 'ptrtoint_of_addrspacecast' |
| 115 | +; X64-NEXT: Classifying expressions for: @ptrtoint_of_addrspacecast |
| 116 | +; X64-NEXT: %in_casted = addrspacecast i8* %in to i8 addrspace(1)* |
| 117 | +; X64-NEXT: --> %in_casted U: full-set S: full-set |
| 118 | +; X64-NEXT: %p0 = ptrtoint i8 addrspace(1)* %in_casted to i64 |
| 119 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 120 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_addrspacecast |
| 121 | +; |
| 122 | +; X32-LABEL: 'ptrtoint_of_addrspacecast' |
| 123 | +; X32-NEXT: Classifying expressions for: @ptrtoint_of_addrspacecast |
| 124 | +; X32-NEXT: %in_casted = addrspacecast i8* %in to i8 addrspace(1)* |
| 125 | +; X32-NEXT: --> %in_casted U: full-set S: full-set |
| 126 | +; X32-NEXT: %p0 = ptrtoint i8 addrspace(1)* %in_casted to i64 |
| 127 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 128 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_addrspacecast |
| 129 | +; |
| 130 | + %in_casted = addrspacecast i8* %in to i8 addrspace(1)* |
| 131 | + %p0 = ptrtoint i8 addrspace(1)* %in_casted to i64 |
| 132 | + store i64 %p0, i64* %out0 |
| 133 | + ret void |
| 134 | +} |
| 135 | + |
| 136 | +; inttoptr is fine too, but we don't (and can't) model inttoptr, so we stop there. |
| 137 | +define void @ptrtoint_of_inttoptr(i64 %in, i64* %out0) { |
| 138 | +; X64-LABEL: 'ptrtoint_of_inttoptr' |
| 139 | +; X64-NEXT: Classifying expressions for: @ptrtoint_of_inttoptr |
| 140 | +; X64-NEXT: %in_casted = inttoptr i64 %in to i8* |
| 141 | +; X64-NEXT: --> %in_casted U: full-set S: full-set |
| 142 | +; X64-NEXT: %p0 = ptrtoint i8* %in_casted to i64 |
| 143 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 144 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_inttoptr |
| 145 | +; |
| 146 | +; X32-LABEL: 'ptrtoint_of_inttoptr' |
| 147 | +; X32-NEXT: Classifying expressions for: @ptrtoint_of_inttoptr |
| 148 | +; X32-NEXT: %in_casted = inttoptr i64 %in to i8* |
| 149 | +; X32-NEXT: --> %in_casted U: full-set S: full-set |
| 150 | +; X32-NEXT: %p0 = ptrtoint i8* %in_casted to i64 |
| 151 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 152 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_inttoptr |
| 153 | +; |
| 154 | + %in_casted = inttoptr i64 %in to i8* |
| 155 | + %p0 = ptrtoint i8* %in_casted to i64 |
| 156 | + store i64 %p0, i64* %out0 |
| 157 | + ret void |
| 158 | +} |
| 159 | + |
| 160 | +; However, GEP is something SCEV knows how to model, so in this case ptrtoint |
| 161 | +; can't be modelled as a cast, only as an unknown. |
| 162 | +define void @ptrtoint_of_gep(i8* %in, i64* %out0) { |
| 163 | +; X64-LABEL: 'ptrtoint_of_gep' |
| 164 | +; X64-NEXT: Classifying expressions for: @ptrtoint_of_gep |
| 165 | +; X64-NEXT: %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 166 | +; X64-NEXT: --> (42 + %in)<nsw> U: [-9223372036854775766,-9223372036854775808) S: [-9223372036854775766,-9223372036854775808) |
| 167 | +; X64-NEXT: %p0 = ptrtoint i8* %in_adj to i64 |
| 168 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 169 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_gep |
| 170 | +; |
| 171 | +; X32-LABEL: 'ptrtoint_of_gep' |
| 172 | +; X32-NEXT: Classifying expressions for: @ptrtoint_of_gep |
| 173 | +; X32-NEXT: %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 174 | +; X32-NEXT: --> (42 + %in)<nsw> U: [-2147483606,-2147483648) S: [-2147483606,-2147483648) |
| 175 | +; X32-NEXT: %p0 = ptrtoint i8* %in_adj to i64 |
| 176 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 177 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_gep |
| 178 | +; |
| 179 | + %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 180 | + %p0 = ptrtoint i8* %in_adj to i64 |
| 181 | + store i64 %p0, i64* %out0 |
| 182 | + ret void |
| 183 | +} |
| 184 | + |
| 185 | +; A constant pointer is fine |
| 186 | +define void @ptrtoint_of_nullptr(i64* %out0) { |
| 187 | +; ALL-LABEL: 'ptrtoint_of_nullptr' |
| 188 | +; ALL-NEXT: Classifying expressions for: @ptrtoint_of_nullptr |
| 189 | +; ALL-NEXT: %p0 = ptrtoint i8* null to i64 |
| 190 | +; ALL-NEXT: --> %p0 U: [0,1) S: [-1,1) |
| 191 | +; ALL-NEXT: Determining loop execution counts for: @ptrtoint_of_nullptr |
| 192 | +; |
| 193 | + %p0 = ptrtoint i8* null to i64 |
| 194 | + store i64 %p0, i64* %out0 |
| 195 | + ret void |
| 196 | +} |
| 197 | + |
| 198 | +; A constant inttoptr argument of an ptrtoint is still bad. |
| 199 | +define void @ptrtoint_of_constantexpr_inttoptr(i64* %out0) { |
| 200 | +; ALL-LABEL: 'ptrtoint_of_constantexpr_inttoptr' |
| 201 | +; ALL-NEXT: Classifying expressions for: @ptrtoint_of_constantexpr_inttoptr |
| 202 | +; ALL-NEXT: %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64 |
| 203 | +; ALL-NEXT: --> %p0 U: [42,43) S: [-64,64) |
| 204 | +; ALL-NEXT: Determining loop execution counts for: @ptrtoint_of_constantexpr_inttoptr |
| 205 | +; |
| 206 | + %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64 |
| 207 | + store i64 %p0, i64* %out0 |
| 208 | + ret void |
| 209 | +} |
| 210 | + |
| 211 | +; However, while bitcast would be fine, GEP we can model, so we are back |
| 212 | +; to modelling the whole cast as unknown.. |
| 213 | +define void @ptrtoint_of_bitcast_of_gep(i8* %in, i64* %out0) { |
| 214 | +; X64-LABEL: 'ptrtoint_of_bitcast_of_gep' |
| 215 | +; X64-NEXT: Classifying expressions for: @ptrtoint_of_bitcast_of_gep |
| 216 | +; X64-NEXT: %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 217 | +; X64-NEXT: --> (42 + %in)<nsw> U: [-9223372036854775766,-9223372036854775808) S: [-9223372036854775766,-9223372036854775808) |
| 218 | +; X64-NEXT: %in_adj_casted = bitcast i8* %in_adj to float* |
| 219 | +; X64-NEXT: --> (42 + %in)<nsw> U: [-9223372036854775766,-9223372036854775808) S: [-9223372036854775766,-9223372036854775808) |
| 220 | +; X64-NEXT: %p0 = ptrtoint float* %in_adj_casted to i64 |
| 221 | +; X64-NEXT: --> %p0 U: full-set S: full-set |
| 222 | +; X64-NEXT: Determining loop execution counts for: @ptrtoint_of_bitcast_of_gep |
| 223 | +; |
| 224 | +; X32-LABEL: 'ptrtoint_of_bitcast_of_gep' |
| 225 | +; X32-NEXT: Classifying expressions for: @ptrtoint_of_bitcast_of_gep |
| 226 | +; X32-NEXT: %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 227 | +; X32-NEXT: --> (42 + %in)<nsw> U: [-2147483606,-2147483648) S: [-2147483606,-2147483648) |
| 228 | +; X32-NEXT: %in_adj_casted = bitcast i8* %in_adj to float* |
| 229 | +; X32-NEXT: --> (42 + %in)<nsw> U: [-2147483606,-2147483648) S: [-2147483606,-2147483648) |
| 230 | +; X32-NEXT: %p0 = ptrtoint float* %in_adj_casted to i64 |
| 231 | +; X32-NEXT: --> %p0 U: [0,4294967296) S: [-4294967296,4294967296) |
| 232 | +; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_bitcast_of_gep |
| 233 | +; |
| 234 | + %in_adj = getelementptr inbounds i8, i8* %in, i64 42 |
| 235 | + %in_adj_casted = bitcast i8* %in_adj to float* |
| 236 | + %p0 = ptrtoint float* %in_adj_casted to i64 |
| 237 | + store i64 %p0, i64* %out0 |
| 238 | + ret void |
| 239 | +} |
0 commit comments