1; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=false %s -enable-new-pm=0 | FileCheck %s
2; RUN: opt -S -basic-aa -licm -licm-n2-threshold=0 -enable-mssa-loop-dependency=true %s -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
3; RUN: opt -licm -basic-aa -licm-n2-threshold=200 < %s -S -enable-new-pm=0 | FileCheck %s --check-prefix=ALIAS-N2
4
5; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
6; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=0 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
7; RUN: opt -aa-pipeline=basic-aa -licm-n2-threshold=200 -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s --check-prefix=ALIAS-N2
8
9; We should be able to hoist loads in presence of read only calls and stores
10; that do not alias.
11
12; Since LICM uses the AST mechanism for alias analysis, we will clump
13; together all loads and stores in one set along with the read-only call.
14; This prevents hoisting load that doesn't alias with any other memory
15; operations.
16
17declare void @foo(i64, i32*) readonly
18
19; hoist the load out with the n2-threshold
20; since it doesn't alias with the store.
21; default AST mechanism clumps all memory locations in one set because of the
22; readonly call
23define void @test1(i32* %ptr) {
24; CHECK-LABEL: @test1(
25; CHECK-LABEL: entry:
26; CHECK-LABEL: loop:
27; CHECK: %val = load i32, i32* %ptr
28
29; ALIAS-N2-LABEL: @test1(
30; ALIAS-N2-LABEL: entry:
31; ALIAS-N2:         %val = load i32, i32* %ptr
32; ALIAS-N2-LABEL: loop:
33entry:
34  br label %loop
35
36loop:
37  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
38  %val = load i32, i32* %ptr
39  call void @foo(i64 4, i32* %ptr)
40  %p2 = getelementptr i32, i32* %ptr, i32 1
41  store volatile i32 0, i32* %p2
42  %x.inc = add i32 %x, %val
43  br label %loop
44}
45
46; can hoist out load with the default AST and the alias analysis mechanism.
47define void @test2(i32* %ptr) {
48; CHECK-LABEL: @test2(
49; CHECK-LABEL: entry:
50; CHECK: %val = load i32, i32* %ptr
51; CHECK-LABEL: loop:
52
53; ALIAS-N2-LABEL: @test2(
54; ALIAS-N2-LABEL: entry:
55; ALIAS-N2:         %val = load i32, i32* %ptr
56; ALIAS-N2-LABEL: loop:
57entry:
58  br label %loop
59
60loop:
61  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
62  %val = load i32, i32* %ptr
63  call void @foo(i64 4, i32* %ptr)
64  %x.inc = add i32 %x, %val
65  br label %loop
66}
67
68; cannot hoist load since not guaranteed to execute
69define void @test3(i32* %ptr) {
70; CHECK-LABEL: @test3(
71; CHECK-LABEL: entry:
72; CHECK-LABEL: loop:
73; CHECK: %val = load i32, i32* %ptr
74
75; ALIAS-N2-LABEL: @test3(
76; ALIAS-N2-LABEL: entry:
77; ALIAS-N2-LABEL: loop:
78; ALIAS-N2:         %val = load i32, i32* %ptr
79entry:
80  br label %loop
81
82loop:
83  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
84  call void @foo(i64 4, i32* %ptr)
85  %val = load i32, i32* %ptr
86  %x.inc = add i32 %x, %val
87  br label %loop
88}
89