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.launder.invariant.group.p0i8(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 i1 @proveEqualityForStrip( 55define i1 @proveEqualityForStrip(i8* %a) { 56; FIXME: The first call could be also removed by GVN. Right now 57; DCE removes it. The second call is CSE'd with the first one. 58; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) 59 %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) 60; CHECK-NOT: llvm.strip.invariant.group 61 %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) 62 %r = icmp eq i8* %b1, %b2 63; CHECK: ret i1 true 64 ret i1 %r 65} 66; CHECK-LABEL: define i8 @unoptimizable1() { 67define i8 @unoptimizable1() { 68entry: 69 %ptr = alloca i8 70 store i8 42, i8* %ptr 71 call void @foo(i8* %ptr) 72 %a = load i8, i8* %ptr, !invariant.group !0 73; CHECK: ret i8 %a 74 ret i8 %a 75} 76 77; CHECK-LABEL: define void @indirectLoads() { 78define void @indirectLoads() { 79entry: 80 %a = alloca %struct.A*, align 8 81 %0 = bitcast %struct.A** %a to i8* 82 83 %call = call i8* @getPointer(i8* null) 84 %1 = bitcast i8* %call to %struct.A* 85 call void @_ZN1AC1Ev(%struct.A* %1) 86 %2 = bitcast %struct.A* %1 to i8*** 87 88; CHECK: %vtable = load {{.*}} !invariant.group 89 %vtable = load i8**, i8*** %2, align 8, !invariant.group !0 90 %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) 91 call void @llvm.assume(i1 %cmp.vtables) 92 93 store %struct.A* %1, %struct.A** %a, align 8 94 %3 = load %struct.A*, %struct.A** %a, align 8 95 %4 = bitcast %struct.A* %3 to void (%struct.A*)*** 96 97; CHECK: call void @_ZN1A3fooEv( 98 %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0 99 %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 100 %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 101 call void %5(%struct.A* %3) 102 %6 = load %struct.A*, %struct.A** %a, align 8 103 %7 = bitcast %struct.A* %6 to void (%struct.A*)*** 104 105; CHECK: call void @_ZN1A3fooEv( 106 %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !0 107 %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0 108 %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8 109 110 call void %8(%struct.A* %6) 111 %9 = load %struct.A*, %struct.A** %a, align 8 112 %10 = bitcast %struct.A* %9 to void (%struct.A*)*** 113 114 %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !0 115 %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0 116 %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8 117; CHECK: call void @_ZN1A3fooEv( 118 call void %11(%struct.A* %9) 119 120 %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !0 121 %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0 122 %12 = bitcast i8** %vfn6 to void (%struct.A*)** 123 %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8 124; CHECK: call void @_ZN1A3fooEv( 125 call void %13(%struct.A* %9) 126 127 ret void 128} 129 130; CHECK-LABEL: define void @combiningBitCastWithLoad() { 131define void @combiningBitCastWithLoad() { 132entry: 133 %a = alloca %struct.A*, align 8 134 %0 = bitcast %struct.A** %a to i8* 135 136 %call = call i8* @getPointer(i8* null) 137 %1 = bitcast i8* %call to %struct.A* 138 call void @_ZN1AC1Ev(%struct.A* %1) 139 %2 = bitcast %struct.A* %1 to i8*** 140 141; CHECK: %vtable = load {{.*}} !invariant.group 142 %vtable = load i8**, i8*** %2, align 8, !invariant.group !0 143 %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) 144 145 store %struct.A* %1, %struct.A** %a, align 8 146; CHECK-NOT: !invariant.group 147 %3 = load %struct.A*, %struct.A** %a, align 8 148 %4 = bitcast %struct.A* %3 to void (%struct.A*)*** 149 150 %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0 151 %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0 152 %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8 153 call void %5(%struct.A* %3) 154 155 ret void 156} 157 158; CHECK-LABEL:define void @loadCombine() { 159define void @loadCombine() { 160enter: 161 %ptr = alloca i8 162 store i8 42, i8* %ptr 163 call void @foo(i8* %ptr) 164; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group 165 %a = load i8, i8* %ptr, !invariant.group !0 166; CHECK-NOT: load 167 %b = load i8, i8* %ptr, !invariant.group !0 168; CHECK: call void @bar(i8 %[[A]]) 169 call void @bar(i8 %a) 170; CHECK: call void @bar(i8 %[[A]]) 171 call void @bar(i8 %b) 172 ret void 173} 174 175; CHECK-LABEL: define void @loadCombine1() { 176define void @loadCombine1() { 177enter: 178 %ptr = alloca i8 179 store i8 42, i8* %ptr 180 call void @foo(i8* %ptr) 181; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group 182 %c = load i8, i8* %ptr 183; CHECK-NOT: load 184 %d = load i8, i8* %ptr, !invariant.group !0 185; CHECK: call void @bar(i8 %[[D]]) 186 call void @bar(i8 %c) 187; CHECK: call void @bar(i8 %[[D]]) 188 call void @bar(i8 %d) 189 ret void 190} 191 192; CHECK-LABEL: define void @loadCombine2() { 193define void @loadCombine2() { 194enter: 195 %ptr = alloca i8 196 store i8 42, i8* %ptr 197 call void @foo(i8* %ptr) 198; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group 199 %e = load i8, i8* %ptr, !invariant.group !0 200; CHECK-NOT: load 201 %f = load i8, i8* %ptr 202; CHECK: call void @bar(i8 %[[E]]) 203 call void @bar(i8 %e) 204; CHECK: call void @bar(i8 %[[E]]) 205 call void @bar(i8 %f) 206 ret void 207} 208 209; CHECK-LABEL: define void @loadCombine3() { 210define void @loadCombine3() { 211enter: 212 %ptr = alloca i8 213 store i8 42, i8* %ptr 214 call void @foo(i8* %ptr) 215; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group 216 %e = load i8, i8* %ptr, !invariant.group !0 217; CHECK-NOT: load 218 %f = load i8, i8* %ptr, !invariant.group !0 219; CHECK: call void @bar(i8 %[[E]]) 220 call void @bar(i8 %e) 221; CHECK: call void @bar(i8 %[[E]]) 222 call void @bar(i8 %f) 223 ret void 224} 225 226; CHECK-LABEL: define i8 @unoptimizable2() { 227define i8 @unoptimizable2() { 228entry: 229 %ptr = alloca i8 230 store i8 42, i8* %ptr 231 call void @foo(i8* %ptr) 232 %a = load i8, i8* %ptr 233 call void @foo(i8* %ptr) 234 %b = load i8, i8* %ptr, !invariant.group !0 235 236; CHECK: ret i8 %a 237 ret i8 %a 238} 239 240; CHECK-LABEL: define i8 @unoptimizable3() { 241define i8 @unoptimizable3() { 242entry: 243 %ptr = alloca i8 244 store i8 42, i8* %ptr, !invariant.group !0 245 %ptr2 = call i8* @getPointer(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 @optimizable4() { 253define i8 @optimizable4() { 254entry: 255 %ptr = alloca i8 256 store i8 42, i8* %ptr, !invariant.group !0 257 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) 258; CHECK-NOT: load 259 %a = load i8, i8* %ptr2, !invariant.group !0 260 261; CHECK: ret i8 42 262 ret i8 %a 263} 264 265; CHECK-LABEL: define i8 @volatile1() { 266define i8 @volatile1() { 267entry: 268 %ptr = alloca i8 269 store i8 42, i8* %ptr, !invariant.group !0 270 call void @foo(i8* %ptr) 271 %a = load i8, i8* %ptr, !invariant.group !0 272 %b = load volatile i8, i8* %ptr 273; CHECK: call void @bar(i8 %b) 274 call void @bar(i8 %b) 275 276 %c = load volatile i8, i8* %ptr, !invariant.group !0 277; FIXME: we could change %c to 42, preserving volatile load 278; CHECK: call void @bar(i8 %c) 279 call void @bar(i8 %c) 280; CHECK: ret i8 42 281 ret i8 %a 282} 283 284; CHECK-LABEL: define i8 @volatile2() { 285define i8 @volatile2() { 286entry: 287 %ptr = alloca i8 288 store i8 42, i8* %ptr, !invariant.group !0 289 call void @foo(i8* %ptr) 290 %a = load i8, i8* %ptr, !invariant.group !0 291 %b = load volatile i8, i8* %ptr 292; CHECK: call void @bar(i8 %b) 293 call void @bar(i8 %b) 294 295 %c = load volatile i8, i8* %ptr, !invariant.group !0 296; FIXME: we could change %c to 42, preserving volatile load 297; CHECK: call void @bar(i8 %c) 298 call void @bar(i8 %c) 299; CHECK: ret i8 42 300 ret i8 %a 301} 302 303; CHECK-LABEL: define i8 @fun() { 304define i8 @fun() { 305entry: 306 %ptr = alloca i8 307 store i8 42, i8* %ptr, !invariant.group !0 308 call void @foo(i8* %ptr) 309 310 %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change 311; CHECK: call void @bar(i8 42) 312 call void @bar(i8 %a) 313 314 %newPtr = call i8* @getPointer(i8* %ptr) 315 %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr 316; CHECK: call void @bar(i8 %c) 317 call void @bar(i8 %c) 318 319 %unknownValue = load i8, i8* @unknownPtr 320; FIXME: Can assume that %unknownValue == 42 321; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0 322 store i8 %unknownValue, i8* %ptr, !invariant.group !0 323 324 %newPtr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) 325; CHECK-NOT: load 326 %d = load i8, i8* %newPtr2, !invariant.group !0 327; CHECK: ret i8 %unknownValue 328 ret i8 %d 329} 330 331; This test checks if invariant.group understands gep with zeros 332; CHECK-LABEL: define void @testGEP0() { 333define void @testGEP0() { 334 %a = alloca %struct.A, align 8 335 %1 = bitcast %struct.A* %a to i8* 336 %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0 337 store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0 338; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a) 339 call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a) ; This call may change vptr 340 %3 = load i8, i8* @unknownPtr, align 4 341 %4 = icmp eq i8 %3, 0 342 br i1 %4, label %_Z1gR1A.exit, label %5 343 344; This should be devirtualized by invariant.group 345 %6 = bitcast %struct.A* %a to void (%struct.A*)*** 346 %7 = load void (%struct.A*)**, void (%struct.A*)*** %6, align 8, !invariant.group !0 347 %8 = load void (%struct.A*)*, void (%struct.A*)** %7, align 8 348; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a) 349 call void %8(%struct.A* nonnull %a) 350 br label %_Z1gR1A.exit 351 352_Z1gR1A.exit: ; preds = %0, %5 353 ret void 354} 355 356; Check if no optimizations are performed with global pointers. 357; FIXME: we could do the optimizations if we would check if dependency comes 358; from the same function. 359; CHECK-LABEL: define void @testGlobal() { 360define void @testGlobal() { 361; CHECK: %a = load i8, i8* @unknownPtr, !invariant.group !0 362 %a = load i8, i8* @unknownPtr, !invariant.group !0 363 call void @foo2(i8* @unknownPtr, i8 %a) 364; CHECK: %1 = load i8, i8* @unknownPtr, !invariant.group !0 365 %1 = load i8, i8* @unknownPtr, !invariant.group !0 366 call void @bar(i8 %1) 367 368 %b0 = bitcast i8* @unknownPtr to i1* 369 call void @fooBit(i1* %b0, i1 1) 370; Adding regex because of canonicalization of bitcasts 371; CHECK: %2 = load i1, i1* {{.*}}, !invariant.group !0 372 %2 = load i1, i1* %b0, !invariant.group !0 373 call void @fooBit(i1* %b0, i1 %2) 374; CHECK: %3 = load i1, i1* {{.*}}, !invariant.group !0 375 %3 = load i1, i1* %b0, !invariant.group !0 376 call void @fooBit(i1* %b0, i1 %3) 377 ret void 378} 379; And in the case it is not global 380; CHECK-LABEL: define void @testNotGlobal() { 381define void @testNotGlobal() { 382 %a = alloca i8 383 call void @foo(i8* %a) 384; CHECK: %b = load i8, i8* %a, !invariant.group !0 385 %b = load i8, i8* %a, !invariant.group !0 386 call void @foo2(i8* %a, i8 %b) 387 388 %1 = load i8, i8* %a, !invariant.group !0 389; CHECK: call void @bar(i8 %b) 390 call void @bar(i8 %1) 391 392 %b0 = bitcast i8* %a to i1* 393 call void @fooBit(i1* %b0, i1 1) 394; CHECK: %1 = trunc i8 %b to i1 395 %2 = load i1, i1* %b0, !invariant.group !0 396; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1) 397 call void @fooBit(i1* %b0, i1 %2) 398 %3 = load i1, i1* %b0, !invariant.group !0 399; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1) 400 call void @fooBit(i1* %b0, i1 %3) 401 ret void 402} 403 404; CHECK-LABEL: define void @handling_loops() 405define void @handling_loops() { 406 %a = alloca %struct.A, align 8 407 %1 = bitcast %struct.A* %a to i8* 408 %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0 409 store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0 410 %3 = load i8, i8* @unknownPtr, align 4 411 %4 = icmp sgt i8 %3, 0 412 br i1 %4, label %.lr.ph.i, label %_Z2g2R1A.exit 413 414.lr.ph.i: ; preds = %0 415 %5 = bitcast %struct.A* %a to void (%struct.A*)*** 416 %6 = load i8, i8* @unknownPtr, align 4 417 %7 = icmp sgt i8 %6, 1 418 br i1 %7, label %._crit_edge.preheader, label %_Z2g2R1A.exit 419 420._crit_edge.preheader: ; preds = %.lr.ph.i 421 br label %._crit_edge 422 423._crit_edge: ; preds = %._crit_edge.preheader, %._crit_edge 424 %8 = phi i8 [ %10, %._crit_edge ], [ 1, %._crit_edge.preheader ] 425 %.pre = load void (%struct.A*)**, void (%struct.A*)*** %5, align 8, !invariant.group !0 426 %9 = load void (%struct.A*)*, void (%struct.A*)** %.pre, align 8 427 ; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a) 428 call void %9(%struct.A* nonnull %a) #3 429 ; CHECK-NOT: call void % 430 %10 = add nuw nsw i8 %8, 1 431 %11 = load i8, i8* @unknownPtr, align 4 432 %12 = icmp slt i8 %10, %11 433 br i1 %12, label %._crit_edge, label %_Z2g2R1A.exit.loopexit 434 435_Z2g2R1A.exit.loopexit: ; preds = %._crit_edge 436 br label %_Z2g2R1A.exit 437 438_Z2g2R1A.exit: ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0 439 ret void 440} 441 442 443declare void @foo(i8*) 444declare void @foo2(i8*, i8) 445declare void @bar(i8) 446declare i8* @getPointer(i8*) 447declare void @_ZN1A3fooEv(%struct.A*) 448declare void @_ZN1AC1Ev(%struct.A*) 449declare void @fooBit(i1*, i1) 450 451declare i8* @llvm.launder.invariant.group.p0i8(i8*) 452declare i8* @llvm.strip.invariant.group.p0i8(i8*) 453 454 455declare void @llvm.assume(i1 %cmp.vtables) 456 457 458!0 = !{}