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