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 9 declare void @use(i32) 10 11 define 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 21 entry: 22 %ptr.gep = getelementptr i8, i8* %ptr, i32 32 23 %ptr.i32 = bitcast i8* %ptr.gep to i32* 24 br label %loop 25 26 loop: 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 33 define void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) { 34 ; CHECK-LABEL: @f_1( 35 entry: 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 48 loop: 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 54 leave: 55 ret void 56 } 57 58 define 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 65 entry: 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 74 loop: 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 80 leave: 81 ret void 82 } 83