1 ; RUN: opt < %s -gvn -S | FileCheck %s 2 3 %struct.A = type { i32 (...)** } 4 @_ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8 5 @_ZTI1A = external constant i8* 6 7 @unknownPtr = external global i8 8 9 ; CHECK-LABEL: define i8 @simple() { 10 define i8 @simple() { 11 entry: 12 %ptr = alloca i8 13 store i8 42, i8* %ptr, !invariant.group !0 14 call void @foo(i8* %ptr) 15 16 %a = load i8, i8* %ptr, !invariant.group !0 17 %b = load i8, i8* %ptr, !invariant.group !0 18 %c = load i8, i8* %ptr, !invariant.group !0 19 ; CHECK: ret i8 42 20 ret i8 %a 21 } 22 23 ; CHECK-LABEL: define i8 @optimizable1() { 24 define i8 @optimizable1() { 25 entry: 26 %ptr = alloca i8 27 store i8 42, i8* %ptr, !invariant.group !0 28 %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) 29 %a = load i8, i8* %ptr, !invariant.group !0 30 31 call void @foo(i8* %ptr2); call to use %ptr2 32 ; CHECK: ret i8 42 33 ret i8 %a 34 } 35 36 ; CHECK-LABEL: define i8 @optimizable2() { 37 define i8 @optimizable2() { 38 entry: 39 %ptr = alloca i8 40 store i8 42, i8* %ptr, !invariant.group !0 41 call void @foo(i8* %ptr) 42 43 store i8 13, i8* %ptr ; can't use this store with invariant.group 44 %a = load i8, i8* %ptr 45 call void @bar(i8 %a) ; call to use %a 46 47 call void @foo(i8* %ptr) 48 %b = load i8, i8* %ptr, !invariant.group !0 49 50 ; CHECK: ret i8 42 51 ret i8 %b 52 } 53 54 ; CHECK-LABEL: define i8 @unoptimizable1() { 55 define i8 @unoptimizable1() { 56 entry: 57 %ptr = alloca i8 58 store i8 42, i8* %ptr 59 call void @foo(i8* %ptr) 60 %a = load i8, i8* %ptr, !invariant.group !0 61 ; CHECK: ret i8 %a 62 ret i8 %a 63 } 64 65 ; CHECK-LABEL: define void @indirectLoads() { 66 define void @indirectLoads() { 67 entry: 68 %a = alloca %struct.A*, align 8 69 %0 = bitcast %struct.A** %a to i8* 70 71 %call = call i8* @getPointer(i8* null) 72 %1 = bitcast i8* %call to %struct.A* 73 call void @_ZN1AC1Ev(%struct.A* %1) 74 %2 = bitcast %struct.A* %1 to i8*** 75 76 ; CHECK: %vtable = load {{.*}} !invariant.group 77 %vtable = load i8**, i8*** %2, align 8, !invariant.group !2 78 %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) 79 call void @llvm.assume(i1 %cmp.vtables) 80 81 store %struct.A* %1, %struct.A** %a, align 8 82 %3 = load %struct.A*, %struct.A** %a, align 8 83 %4 = bitcast %struct.A* %3 to void (%struct.A*)*** 84 85 ; CHECK: call void @_ZN1A3fooEv( 86 %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2 87 %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 88 %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 89 call void %5(%struct.A* %3) 90 %6 = load %struct.A*, %struct.A** %a, align 8 91 %7 = bitcast %struct.A* %6 to void (%struct.A*)*** 92 93 ; CHECK: call void @_ZN1A3fooEv( 94 %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !2 95 %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0 96 %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8 97 98 call void %8(%struct.A* %6) 99 %9 = load %struct.A*, %struct.A** %a, align 8 100 %10 = bitcast %struct.A* %9 to void (%struct.A*)*** 101 102 %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !2 103 %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0 104 %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8 105 ; CHECK: call void @_ZN1A3fooEv( 106 call void %11(%struct.A* %9) 107 108 %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !2 109 %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0 110 %12 = bitcast i8** %vfn6 to void (%struct.A*)** 111 %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8 112 ; CHECK: call void @_ZN1A3fooEv( 113 call void %13(%struct.A* %9) 114 115 ret void 116 } 117 118 ; CHECK-LABEL: define void @combiningBitCastWithLoad() { 119 define void @combiningBitCastWithLoad() { 120 entry: 121 %a = alloca %struct.A*, align 8 122 %0 = bitcast %struct.A** %a to i8* 123 124 %call = call i8* @getPointer(i8* null) 125 %1 = bitcast i8* %call to %struct.A* 126 call void @_ZN1AC1Ev(%struct.A* %1) 127 %2 = bitcast %struct.A* %1 to i8*** 128 129 ; CHECK: %vtable = load {{.*}} !invariant.group 130 %vtable = load i8**, i8*** %2, align 8, !invariant.group !2 131 %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) 132 133 store %struct.A* %1, %struct.A** %a, align 8 134 ; CHECK-NOT: !invariant.group 135 %3 = load %struct.A*, %struct.A** %a, align 8 136 %4 = bitcast %struct.A* %3 to void (%struct.A*)*** 137 138 %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2 139 %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 140 %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 141 call void %5(%struct.A* %3) 142 143 ret void 144 } 145 146 ; CHECK-LABEL:define void @loadCombine() { 147 define void @loadCombine() { 148 enter: 149 %ptr = alloca i8 150 store i8 42, i8* %ptr 151 call void @foo(i8* %ptr) 152 ; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group 153 %a = load i8, i8* %ptr, !invariant.group !0 154 ; CHECK-NOT: load 155 %b = load i8, i8* %ptr, !invariant.group !1 156 ; CHECK: call void @bar(i8 %[[A]]) 157 call void @bar(i8 %a) 158 ; CHECK: call void @bar(i8 %[[A]]) 159 call void @bar(i8 %b) 160 ret void 161 } 162 163 ; CHECK-LABEL: define void @loadCombine1() { 164 define void @loadCombine1() { 165 enter: 166 %ptr = alloca i8 167 store i8 42, i8* %ptr 168 call void @foo(i8* %ptr) 169 ; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group 170 %c = load i8, i8* %ptr 171 ; CHECK-NOT: load 172 %d = load i8, i8* %ptr, !invariant.group !1 173 ; CHECK: call void @bar(i8 %[[D]]) 174 call void @bar(i8 %c) 175 ; CHECK: call void @bar(i8 %[[D]]) 176 call void @bar(i8 %d) 177 ret void 178 } 179 180 ; CHECK-LABEL: define void @loadCombine2() { 181 define void @loadCombine2() { 182 enter: 183 %ptr = alloca i8 184 store i8 42, i8* %ptr 185 call void @foo(i8* %ptr) 186 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group 187 %e = load i8, i8* %ptr, !invariant.group !1 188 ; CHECK-NOT: load 189 %f = load i8, i8* %ptr 190 ; CHECK: call void @bar(i8 %[[E]]) 191 call void @bar(i8 %e) 192 ; CHECK: call void @bar(i8 %[[E]]) 193 call void @bar(i8 %f) 194 ret void 195 } 196 197 ; CHECK-LABEL: define void @loadCombine3() { 198 define void @loadCombine3() { 199 enter: 200 %ptr = alloca i8 201 store i8 42, i8* %ptr 202 call void @foo(i8* %ptr) 203 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group ![[OneMD:[0-9]]] 204 %e = load i8, i8* %ptr, !invariant.group !1 205 ; CHECK-NOT: load 206 %f = load i8, i8* %ptr, !invariant.group !1 207 ; CHECK: call void @bar(i8 %[[E]]) 208 call void @bar(i8 %e) 209 ; CHECK: call void @bar(i8 %[[E]]) 210 call void @bar(i8 %f) 211 ret void 212 } 213 214 ; CHECK-LABEL: define i8 @unoptimizable2() { 215 define i8 @unoptimizable2() { 216 entry: 217 %ptr = alloca i8 218 store i8 42, i8* %ptr 219 call void @foo(i8* %ptr) 220 %a = load i8, i8* %ptr 221 call void @foo(i8* %ptr) 222 %b = load i8, i8* %ptr, !invariant.group !0 223 224 ; CHECK: ret i8 %a 225 ret i8 %a 226 } 227 228 ; CHECK-LABEL: define i8 @unoptimizable3() { 229 define i8 @unoptimizable3() { 230 entry: 231 %ptr = alloca i8 232 store i8 42, i8* %ptr, !invariant.group !0 233 %ptr2 = call i8* @getPointer(i8* %ptr) 234 %a = load i8, i8* %ptr2, !invariant.group !0 235 236 ; CHECK: ret i8 %a 237 ret i8 %a 238 } 239 240 ; CHECK-LABEL: define i8 @unoptimizable4() { 241 define i8 @unoptimizable4() { 242 entry: 243 %ptr = alloca i8 244 store i8 42, i8* %ptr, !invariant.group !0 245 %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) 246 %a = load i8, i8* %ptr2, !invariant.group !0 247 248 ; CHECK: ret i8 %a 249 ret i8 %a 250 } 251 252 ; CHECK-LABEL: define i8 @volatile1() { 253 define i8 @volatile1() { 254 entry: 255 %ptr = alloca i8 256 store i8 42, i8* %ptr, !invariant.group !0 257 call void @foo(i8* %ptr) 258 %a = load i8, i8* %ptr, !invariant.group !0 259 %b = load volatile i8, i8* %ptr 260 ; CHECK: call void @bar(i8 %b) 261 call void @bar(i8 %b) 262 263 %c = load volatile i8, i8* %ptr, !invariant.group !0 264 ; FIXME: we could change %c to 42, preserving volatile load 265 ; CHECK: call void @bar(i8 %c) 266 call void @bar(i8 %c) 267 ; CHECK: ret i8 42 268 ret i8 %a 269 } 270 271 ; CHECK-LABEL: define i8 @volatile2() { 272 define i8 @volatile2() { 273 entry: 274 %ptr = alloca i8 275 store i8 42, i8* %ptr, !invariant.group !0 276 call void @foo(i8* %ptr) 277 %a = load i8, i8* %ptr, !invariant.group !0 278 %b = load volatile i8, i8* %ptr 279 ; CHECK: call void @bar(i8 %b) 280 call void @bar(i8 %b) 281 282 %c = load volatile i8, i8* %ptr, !invariant.group !0 283 ; FIXME: we could change %c to 42, preserving volatile load 284 ; CHECK: call void @bar(i8 %c) 285 call void @bar(i8 %c) 286 ; CHECK: ret i8 42 287 ret i8 %a 288 } 289 290 ; CHECK-LABEL: define i8 @fun() { 291 define i8 @fun() { 292 entry: 293 %ptr = alloca i8 294 store i8 42, i8* %ptr, !invariant.group !0 295 call void @foo(i8* %ptr) 296 297 %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change 298 ; CHECK: call void @bar(i8 42) 299 call void @bar(i8 %a) 300 301 call void @foo(i8* %ptr) 302 %b = load i8, i8* %ptr, !invariant.group !1 ; Can't assume anything, because group changed 303 ; CHECK: call void @bar(i8 %b) 304 call void @bar(i8 %b) 305 306 %newPtr = call i8* @getPointer(i8* %ptr) 307 %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr 308 ; CHECK: call void @bar(i8 %c) 309 call void @bar(i8 %c) 310 311 %unknownValue = load i8, i8* @unknownPtr 312 ; FIXME: Can assume that %unknownValue == 42 313 ; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0 314 store i8 %unknownValue, i8* %ptr, !invariant.group !0 315 316 %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr) 317 %d = load i8, i8* %newPtr2, !invariant.group !0 ; Can't step through invariant.group.barrier to get value of %ptr 318 ; CHECK: ret i8 %d 319 ret i8 %d 320 } 321 322 declare void @foo(i8*) 323 declare void @bar(i8) 324 declare i8* @getPointer(i8*) 325 declare void @_ZN1A3fooEv(%struct.A*) 326 declare void @_ZN1AC1Ev(%struct.A*) 327 declare i8* @llvm.invariant.group.barrier(i8*) 328 329 ; Function Attrs: nounwind 330 declare void @llvm.assume(i1 %cmp.vtables) #0 331 332 333 attributes #0 = { nounwind } 334 ; CHECK: ![[OneMD]] = !{!"other ptr"} 335 !0 = !{!"magic ptr"} 336 !1 = !{!"other ptr"} 337 !2 = !{!"vtable_of_a"} 338