Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / GVN / PRE / invariant-load.ll
blob79cf95155c70caa2fca504852bf7ce96678636d0
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2 ; Test if the !invariant.load metadata is maintained by GVN.
3 ; RUN: opt -passes=gvn -S < %s | FileCheck %s
5 define i32 @test1(ptr nocapture %p, ptr nocapture %q) {
6 ; CHECK-LABEL: define i32 @test1
7 ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr nocapture [[Q:%.*]]) {
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !0
10 ; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[X]] to i8
11 ; CHECK-NEXT:    store i8 [[CONV]], ptr [[Q]], align 1
12 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
13 ; CHECK-NEXT:    ret i32 [[ADD]]
15 entry:
16   %x = load i32, ptr %p, align 4, !invariant.load !0
17   %conv = trunc i32 %x to i8
18   store i8 %conv, ptr %q, align 1
19   %y = load i32, ptr %p, align 4, !invariant.load !0
20   %add = add i32 %y, 1
21   ret i32 %add
24 define i32 @test2(ptr nocapture %p, ptr nocapture %q) {
25 ; CHECK-LABEL: define i32 @test2
26 ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr nocapture [[Q:%.*]]) {
27 ; CHECK-NEXT:  entry:
28 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4
29 ; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[X]] to i8
30 ; CHECK-NEXT:    store i8 [[CONV]], ptr [[Q]], align 1
31 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
32 ; CHECK-NEXT:    ret i32 [[ADD]]
34 entry:
35   %x = load i32, ptr %p, align 4
36   %conv = trunc i32 %x to i8
37   store i8 %conv, ptr %q, align 1
38   %y = load i32, ptr %p, align 4, !invariant.load !0
39   %add = add i32 %y, 1
40   ret i32 %add
43 ; With the invariant.load metadata, what would otherwise
44 ; be a case for PRE becomes a full redundancy.
45 define i32 @test3(i1 %cnd, ptr %p, ptr %q) {
46 ; CHECK-LABEL: define i32 @test3
47 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {
48 ; CHECK-NEXT:  entry:
49 ; CHECK-NEXT:    br i1 [[CND]], label [[BB1:%.*]], label [[BB2:%.*]]
50 ; CHECK:       bb1:
51 ; CHECK-NEXT:    store i32 5, ptr [[Q]], align 4
52 ; CHECK-NEXT:    br label [[BB2]]
53 ; CHECK:       bb2:
54 ; CHECK-NEXT:    ret i32 0
56 entry:
57   %v1 = load i32, ptr %p
58   br i1 %cnd, label %bb1, label %bb2
60 bb1:
61   store i32 5, ptr %q
62   br label %bb2
64 bb2:
65   %v2 = load i32, ptr %p, !invariant.load !0
66   %res = sub i32 %v1, %v2
67   ret i32 %res
70 ; This test is here to document a case which doesn't optimize
71 ; as well as it could.
72 define i32 @test4(i1 %cnd, ptr %p, ptr %q) {
73 ; CHECK-LABEL: define i32 @test4
74 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {
75 ; CHECK-NEXT:  entry:
76 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !0
77 ; CHECK-NEXT:    br i1 [[CND]], label [[BB1:%.*]], label [[BB2:%.*]]
78 ; CHECK:       bb1:
79 ; CHECK-NEXT:    store i32 5, ptr [[Q]], align 4
80 ; CHECK-NEXT:    [[V2_PRE:%.*]] = load i32, ptr [[P]], align 4
81 ; CHECK-NEXT:    br label [[BB2]]
82 ; CHECK:       bb2:
83 ; CHECK-NEXT:    [[V2:%.*]] = phi i32 [ [[V2_PRE]], [[BB1]] ], [ [[V1]], [[ENTRY:%.*]] ]
84 ; CHECK-NEXT:    [[RES:%.*]] = sub i32 [[V1]], [[V2]]
85 ; CHECK-NEXT:    ret i32 [[RES]]
87 ; %v2 is redundant, but GVN currently doesn't catch that
88 entry:
89   %v1 = load i32, ptr %p, !invariant.load !0
90   br i1 %cnd, label %bb1, label %bb2
92 bb1:
93   store i32 5, ptr %q
94   br label %bb2
96 bb2:
97   %v2 = load i32, ptr %p
98   %res = sub i32 %v1, %v2
99   ret i32 %res
102 ; Checks that we return the mustalias store as a def
103 ; so that it contributes to value forwarding.  Note
104 ; that we could and should remove the store too.
105 define i32 @test5(i1 %cnd, ptr %p) {
106 ; CHECK-LABEL: define i32 @test5
107 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {
108 ; CHECK-NEXT:  entry:
109 ; CHECK-NEXT:    store i32 5, ptr [[P]], align 4
110 ; CHECK-NEXT:    ret i32 5
112 entry:
113   %v1 = load i32, ptr %p, !invariant.load !0
114   store i32 5, ptr %p ;; must alias store, want to exploit
115   %v2 = load i32, ptr %p, !invariant.load !0
116   ret i32 %v2
120 declare void @foo()
122 ; Clobbering (mayalias) stores, even in function calls, can be ignored
123 define i32 @test6(i1 %cnd, ptr %p) {
124 ; CHECK-LABEL: define i32 @test6
125 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {
126 ; CHECK-NEXT:  entry:
127 ; CHECK-NEXT:    call void @foo()
128 ; CHECK-NEXT:    ret i32 0
130 entry:
131   %v1 = load i32, ptr %p, !invariant.load !0
132   call void @foo()
133   %v2 = load i32, ptr %p, !invariant.load !0
134   %res = sub i32 %v1, %v2
135   ret i32 %res
138 declare noalias ptr @bar(...)
140 ; Same as previous, but a function with a noalias result (since they're handled
141 ; differently in MDA)
142 define i32 @test7(i1 %cnd, ptr %p) {
143 ; CHECK-LABEL: define i32 @test7
144 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {
145 ; CHECK-NEXT:  entry:
146 ; CHECK-NEXT:    [[TMP0:%.*]] = call ptr (...) @bar(ptr [[P]])
147 ; CHECK-NEXT:    ret i32 0
149 entry:
150   %v1 = load i32, ptr %p, !invariant.load !0
151   call ptr (...) @bar(ptr %p)
152   %v2 = load i32, ptr %p, !invariant.load !0
153   %res = sub i32 %v1, %v2
154   ret i32 %res
157 define i32 @test8(i1 %cnd, ptr %p) {
158 ; CHECK-LABEL: define i32 @test8
159 ; CHECK-SAME: (i1 [[CND:%.*]], ptr [[P:%.*]]) {
160 ; CHECK-NEXT:  entry:
161 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !0
162 ; CHECK-NEXT:    br i1 [[CND]], label [[TAKEN:%.*]], label [[MERGE:%.*]]
163 ; CHECK:       taken:
164 ; CHECK-NEXT:    [[P2:%.*]] = call ptr (...) @bar(ptr [[P]])
165 ; CHECK-NEXT:    [[V2_PRE:%.*]] = load i32, ptr [[P2]], align 4, !invariant.load !0
166 ; CHECK-NEXT:    br label [[MERGE]]
167 ; CHECK:       merge:
168 ; CHECK-NEXT:    [[V2:%.*]] = phi i32 [ [[V1]], [[ENTRY:%.*]] ], [ [[V2_PRE]], [[TAKEN]] ]
169 ; CHECK-NEXT:    [[P3:%.*]] = phi ptr [ [[P]], [[ENTRY]] ], [ [[P2]], [[TAKEN]] ]
170 ; CHECK-NEXT:    [[RES:%.*]] = sub i32 [[V1]], [[V2]]
171 ; CHECK-NEXT:    ret i32 [[RES]]
173 entry:
174   %v1 = load i32, ptr %p, !invariant.load !0
175   br i1 %cnd, label %taken, label %merge
176 taken:
177   %p2 = call ptr (...) @bar(ptr %p)
178   br label %merge
179 merge:
180   %p3 = phi ptr [%p, %entry], [%p2, %taken]
181   %v2 = load i32, ptr %p3, !invariant.load !0
182   %res = sub i32 %v1, %v2
183   ret i32 %res
186 define i32 @metadata_preservation(ptr nocapture %p, ptr nocapture %q) {
187 ; CHECK-LABEL: define i32 @metadata_preservation
188 ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr nocapture [[Q:%.*]]) {
189 ; CHECK-NEXT:  entry:
190 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4, !invariant.load !0
191 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], [[X]]
192 ; CHECK-NEXT:    ret i32 [[ADD]]
194 entry:
195   %x = load i32, ptr %p, align 4, !invariant.load !0
196   %y = load i32, ptr %p, align 4
197   %add = add i32 %x, %y
198   ret i32 %add
201 !0 = !{ }