1; RUN: opt -S -licm < %s | FileCheck %s 2 3; Note: the !invariant.load is there just solely to let us call @use() 4; to add a fake use, and still have the aliasing work out. The call 5; to @use(0) is just to provide a may-unwind exit out of the loop, so 6; that LICM cannot hoist out the load simply because it is guaranteed 7; to execute. 8 9declare void @use(i32) 10 11define void @f_0(i8* align 4 dereferenceable(1024) %ptr) { 12; CHECK-LABEL: @f_0( 13; CHECK: entry: 14; CHECK: %val = load i32, i32* %ptr.i32 15; CHECK: br label %loop 16; CHECK: loop: 17; CHECK: call void @use(i32 0) 18; CHECK-NEXT: call void @use(i32 %val) 19 20 21entry: 22 %ptr.gep = getelementptr i8, i8* %ptr, i32 32 23 %ptr.i32 = bitcast i8* %ptr.gep to i32* 24 br label %loop 25 26loop: 27 call void @use(i32 0) 28 %val = load i32, i32* %ptr.i32, !invariant.load !{} 29 call void @use(i32 %val) 30 br label %loop 31} 32 33define void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) { 34; CHECK-LABEL: @f_1( 35entry: 36 %ptr.gep = getelementptr i8, i8* %ptr, i32 32 37 %ptr.i32 = bitcast i8* %ptr.gep to i32* 38 %ptr_is_null = icmp eq i8* %ptr, null 39 br i1 %ptr_is_null, label %leave, label %loop 40 41; CHECK: loop.preheader: 42; CHECK: %val = load i32, i32* %ptr.i32 43; CHECK: br label %loop 44; CHECK: loop: 45; CHECK: call void @use(i32 0) 46; CHECK-NEXT: call void @use(i32 %val) 47 48loop: 49 call void @use(i32 0) 50 %val = load i32, i32* %ptr.i32, !invariant.load !{} 51 call void @use(i32 %val) 52 br label %loop 53 54leave: 55 ret void 56} 57 58define void @f_2(i8* align 4 dereferenceable_or_null(1024) %ptr) { 59; CHECK-LABEL: @f_2( 60; CHECK-NOT: load 61; CHECK: call void @use(i32 0) 62; CHECK-NEXT: %val = load i32, i32* %ptr.i32, !invariant.load !0 63; CHECK-NEXT: call void @use(i32 %val) 64 65entry: 66 ;; Can't hoist, since the alignment does not work out -- (<4 byte 67 ;; aligned> + 30) is not necessarily 4 byte aligned. 68 69 %ptr.gep = getelementptr i8, i8* %ptr, i32 30 70 %ptr.i32 = bitcast i8* %ptr.gep to i32* 71 %ptr_is_null = icmp eq i8* %ptr, null 72 br i1 %ptr_is_null, label %leave, label %loop 73 74loop: 75 call void @use(i32 0) 76 %val = load i32, i32* %ptr.i32, !invariant.load !{} 77 call void @use(i32 %val) 78 br label %loop 79 80leave: 81 ret void 82} 83 84define void @checkLaunder(i8* align 4 dereferenceable(1024) %p) { 85; CHECK-LABEL: @checkLaunder( 86; CHECK: entry: 87; CHECK: %l = call i8* @llvm.launder.invariant.group.p0i8(i8* %p) 88; CHECK: %val = load i8, i8* %l 89; CHECK: br label %loop 90; CHECK: loop: 91; CHECK: call void @use(i32 0) 92; CHECK-NEXT: call void @use8(i8 %val) 93 94entry: 95 %l = call i8* @llvm.launder.invariant.group.p0i8(i8* %p) 96 br label %loop 97 98loop: 99 call void @use(i32 0) 100 %val = load i8, i8* %l, !invariant.load !{} 101 call void @use8(i8 %val) 102 br label %loop 103} 104 105declare i8* @llvm.launder.invariant.group.p0i8(i8*) 106 107declare void @use8(i8) 108