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() { 10define i8 @simple() { 11entry: 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() { 24define i8 @optimizable1() { 25entry: 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() { 37define i8 @optimizable2() { 38entry: 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() { 55define i8 @unoptimizable1() { 56entry: 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() { 66define void @indirectLoads() { 67entry: 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() { 119define void @combiningBitCastWithLoad() { 120entry: 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() { 147define void @loadCombine() { 148enter: 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() { 164define void @loadCombine1() { 165enter: 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() { 181define void @loadCombine2() { 182enter: 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() { 198define void @loadCombine3() { 199enter: 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() { 215define i8 @unoptimizable2() { 216entry: 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() { 229define i8 @unoptimizable3() { 230entry: 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() { 241define i8 @unoptimizable4() { 242entry: 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() { 253define i8 @volatile1() { 254entry: 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() { 272define i8 @volatile2() { 273entry: 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() { 291define i8 @fun() { 292entry: 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 322declare void @foo(i8*) 323declare void @bar(i8) 324declare i8* @getPointer(i8*) 325declare void @_ZN1A3fooEv(%struct.A*) 326declare void @_ZN1AC1Ev(%struct.A*) 327declare i8* @llvm.invariant.group.barrier(i8*) 328 329; Function Attrs: nounwind 330declare void @llvm.assume(i1 %cmp.vtables) #0 331 332 333attributes #0 = { nounwind } 334; CHECK: ![[OneMD]] = !{!"other ptr"} 335!0 = !{!"magic ptr"} 336!1 = !{!"other ptr"} 337!2 = !{!"vtable_of_a"} 338