1 ; RUN: opt -S -licm < %s | FileCheck %s
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
11 define void @f_0(i8* align 4 dereferenceable(1024) %ptr) {
14 ; CHECK: %val = load i32, i32* %ptr.i32
15 ; CHECK: br label %loop
17 ; CHECK: call void @use(i32 0)
18 ; CHECK-NEXT: call void @use(i32 %val)
22 %ptr.gep = getelementptr i8, i8* %ptr, i32 32
23 %ptr.i32 = bitcast i8* %ptr.gep to i32*
28 %val = load i32, i32* %ptr.i32, !invariant.load !{}
29 call void @use(i32 %val)
33 define void @f_1(i8* align 4 dereferenceable_or_null(1024) %ptr) {
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
41 ; CHECK: loop.preheader:
42 ; CHECK: %val = load i32, i32* %ptr.i32
43 ; CHECK: br label %loop
45 ; CHECK: call void @use(i32 0)
46 ; CHECK-NEXT: call void @use(i32 %val)
50 %val = load i32, i32* %ptr.i32, !invariant.load !{}
51 call void @use(i32 %val)
58 define void @f_2(i8* align 4 dereferenceable_or_null(1024) %ptr) {
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)
66 ;; Can't hoist, since the alignment does not work out -- (<4 byte
67 ;; aligned> + 30) is not necessarily 4 byte aligned.
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
76 %val = load i32, i32* %ptr.i32, !invariant.load !{}
77 call void @use(i32 %val)
84 define void @checkLaunder(i8* align 4 dereferenceable(1024) %p) {
85 ; CHECK-LABEL: @checkLaunder(
87 ; CHECK: %l = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
88 ; CHECK: %val = load i8, i8* %l
89 ; CHECK: br label %loop
91 ; CHECK: call void @use(i32 0)
92 ; CHECK-NEXT: call void @use8(i8 %val)
95 %l = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
100 %val = load i8, i8* %l, !invariant.load !{}
101 call void @use8(i8 %val)
105 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
107 declare void @use8(i8)