Skip to content

Commit 0112f12

Browse files
authored
[EarlyCSE] Remove void return restriction for call CSE (#145320)
For readonly/readnone calls returning void we can't CSE the return value. However, making these participate in CSE is still useful, because it allows DCE of calls that are not willreturn/nounwind (something no other part of LLVM is capable of removing). The more interesting use-case is CSE for writeonly calls (not yet supported), but I figured this change makes sense independently. There is no impact on compile-time.
1 parent 8ec0552 commit 0112f12

File tree

4 files changed

+55
-37
lines changed

4 files changed

+55
-37
lines changed

llvm/lib/Transforms/Scalar/EarlyCSE.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct SimpleValue {
133133
}
134134
}
135135
}
136-
return CI->doesNotAccessMemory() && !CI->getType()->isVoidTy() &&
136+
return CI->doesNotAccessMemory() &&
137137
// FIXME: Currently the calls which may access the thread id may
138138
// be considered as not accessing the memory. But this is
139139
// problematic for coroutines, since coroutines may resume in a
@@ -492,10 +492,6 @@ struct CallValue {
492492
}
493493

494494
static bool canHandle(Instruction *Inst) {
495-
// Don't value number anything that returns void.
496-
if (Inst->getType()->isVoidTy())
497-
return false;
498-
499495
CallInst *CI = dyn_cast<CallInst>(Inst);
500496
if (!CI || !CI->onlyReadsMemory() ||
501497
// FIXME: Currently the calls which may access the thread id may

llvm/test/Transforms/EarlyCSE/basic.ll

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,28 @@ define i32 @test5(ptr%P) {
146146
ret i32 %Diff
147147
}
148148

149+
declare void @void_func()
150+
151+
define void @void_func_cse_readonly(ptr %P) {
152+
; CHECK-LABEL: @void_func_cse_readonly(
153+
; CHECK-NEXT: call void @void_func(ptr [[P:%.*]]) #[[ATTR1:[0-9]+]]
154+
; CHECK-NEXT: ret void
155+
;
156+
call void @void_func(ptr %P) memory(read)
157+
call void @void_func(ptr %P) memory(read)
158+
ret void
159+
}
160+
161+
define void @void_func_cse_readnone(ptr %P) {
162+
; CHECK-LABEL: @void_func_cse_readnone(
163+
; CHECK-NEXT: call void @void_func(ptr [[P:%.*]]) #[[ATTR2:[0-9]+]]
164+
; CHECK-NEXT: ret void
165+
;
166+
call void @void_func(ptr %P) memory(none)
167+
call void @void_func(ptr %P) memory(none)
168+
ret void
169+
}
170+
149171
!0 = !{!"branch_weights", i32 95}
150172
!1 = !{!"branch_weights", i32 95}
151173

@@ -186,7 +208,7 @@ define void @test7(ptr%P) {
186208
;; Readnone functions aren't invalidated by stores.
187209
define i32 @test8(ptr%P) {
188210
; CHECK-LABEL: @test8(
189-
; CHECK-NEXT: [[V1:%.*]] = call i32 @func(ptr [[P:%.*]]) #[[ATTR2:[0-9]+]]
211+
; CHECK-NEXT: [[V1:%.*]] = call i32 @func(ptr [[P:%.*]]) #[[ATTR2]]
190212
; CHECK-NEXT: store i32 4, ptr [[P]], align 4
191213
; CHECK-NEXT: ret i32 0
192214
;
@@ -202,7 +224,7 @@ define i32 @test8(ptr%P) {
202224
define i32 @test9(ptr%P) {
203225
; CHECK-LABEL: @test9(
204226
; CHECK-NEXT: store i32 4, ptr [[P:%.*]], align 4
205-
; CHECK-NEXT: [[V1:%.*]] = call i32 @func(ptr [[P]]) #[[ATTR1:[0-9]+]]
227+
; CHECK-NEXT: [[V1:%.*]] = call i32 @func(ptr [[P]]) #[[ATTR1]]
206228
; CHECK-NEXT: store i32 5, ptr [[P]], align 4
207229
; CHECK-NEXT: ret i32 [[V1]]
208230
;

llvm/test/Transforms/EarlyCSE/flags.ll

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
; RUN: opt -passes='early-cse<memssa>' -S < %s | FileCheck %s
44

55
declare void @use(i1)
6-
declare void @use.ptr(ptr) memory(read)
6+
declare void @use.ptr(i32, ptr) memory(read)
77

88
define void @test1(float %x, float %y) {
99
; CHECK-LABEL: @test1(
@@ -52,42 +52,42 @@ define void @test_inbounds_program_not_ub_if_first_gep_poison(ptr %ptr, i64 %n)
5252
define void @load_both_nonnull(ptr %p) {
5353
; CHECK-LABEL: @load_both_nonnull(
5454
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull [[META0:![0-9]+]]
55-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
56-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
55+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
56+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
5757
; CHECK-NEXT: ret void
5858
;
5959
%v1 = load ptr, ptr %p, !nonnull !{}
60-
call void @use.ptr(ptr %v1)
60+
call void @use.ptr(i32 0, ptr %v1)
6161
%v2 = load ptr, ptr %p, !nonnull !{}
62-
call void @use.ptr(ptr %v2)
62+
call void @use.ptr(i32 1, ptr %v2)
6363
ret void
6464
}
6565

6666
define void @load_first_nonnull(ptr %p) {
6767
; CHECK-LABEL: @load_first_nonnull(
6868
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P:%.*]], align 8
69-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
70-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
69+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
70+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
7171
; CHECK-NEXT: ret void
7272
;
7373
%v1 = load ptr, ptr %p, !nonnull !{}
74-
call void @use.ptr(ptr %v1)
74+
call void @use.ptr(i32 0, ptr %v1)
7575
%v2 = load ptr, ptr %p
76-
call void @use.ptr(ptr %v2)
76+
call void @use.ptr(i32 1, ptr %v2)
7777
ret void
7878
}
7979

8080
define void @load_first_nonnull_noundef(ptr %p) {
8181
; CHECK-LABEL: @load_first_nonnull_noundef(
8282
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull [[META0]], !noundef [[META0]]
83-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
84-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
83+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
84+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
8585
; CHECK-NEXT: ret void
8686
;
8787
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}
88-
call void @use.ptr(ptr %v1)
88+
call void @use.ptr(i32 0, ptr %v1)
8989
%v2 = load ptr, ptr %p
90-
call void @use.ptr(ptr %v2)
90+
call void @use.ptr(i32 1, ptr %v2)
9191
ret void
9292
}
9393

llvm/test/Transforms/EarlyCSE/noalias-addrspace.ll

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,65 @@
22
; RUN: opt -passes='early-cse<memssa>' -S < %s | FileCheck %s
33

44
declare void @use(i1)
5-
declare void @use.ptr(ptr) memory(read)
5+
declare void @use.ptr(i32, ptr) memory(read)
66

77
define void @load_first_noalias_addrspace(ptr %p) {
88
; CHECK-LABEL: define void @load_first_noalias_addrspace(
99
; CHECK-SAME: ptr [[P:%.*]]) {
1010
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0:![0-9]+]], !noundef [[META0]], !noalias.addrspace [[META1:![0-9]+]]
11-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
12-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
11+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
12+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
1313
; CHECK-NEXT: ret void
1414
;
1515
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
16-
call void @use.ptr(ptr %v1)
16+
call void @use.ptr(i32 0, ptr %v1)
1717
%v2 = load ptr, ptr %p
18-
call void @use.ptr(ptr %v2)
18+
call void @use.ptr(i32 1, ptr %v2)
1919
ret void
2020
}
2121

2222
define void @load_both_same_noalias_addrspace(ptr %p) {
2323
; CHECK-LABEL: define void @load_both_same_noalias_addrspace(
2424
; CHECK-SAME: ptr [[P:%.*]]) {
2525
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
26-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
27-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
26+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
27+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
2828
; CHECK-NEXT: ret void
2929
;
3030
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
31-
call void @use.ptr(ptr %v1)
31+
call void @use.ptr(i32 0, ptr %v1)
3232
%v2 = load ptr, ptr %p, !noalias.addrspace !0
33-
call void @use.ptr(ptr %v2)
33+
call void @use.ptr(i32 1, ptr %v2)
3434
ret void
3535
}
3636

3737
define void @load_both_disjoint_noalias_addrspace(ptr %p) {
3838
; CHECK-LABEL: define void @load_both_disjoint_noalias_addrspace(
3939
; CHECK-SAME: ptr [[P:%.*]]) {
4040
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
41-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
42-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
41+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
42+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
4343
; CHECK-NEXT: ret void
4444
;
4545
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
46-
call void @use.ptr(ptr %v1)
46+
call void @use.ptr(i32 0, ptr %v1)
4747
%v2 = load ptr, ptr %p, !noalias.addrspace !1
48-
call void @use.ptr(ptr %v2)
48+
call void @use.ptr(i32 1, ptr %v2)
4949
ret void
5050
}
5151

5252
define void @load_both_overlap_noalias_addrspace(ptr %p) {
5353
; CHECK-LABEL: define void @load_both_overlap_noalias_addrspace(
5454
; CHECK-SAME: ptr [[P:%.*]]) {
5555
; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META0]], !noundef [[META0]], !noalias.addrspace [[META1]]
56-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
57-
; CHECK-NEXT: call void @use.ptr(ptr [[V1]])
56+
; CHECK-NEXT: call void @use.ptr(i32 0, ptr [[V1]])
57+
; CHECK-NEXT: call void @use.ptr(i32 1, ptr [[V1]])
5858
; CHECK-NEXT: ret void
5959
;
6060
%v1 = load ptr, ptr %p, !nonnull !{}, !noundef !{}, !noalias.addrspace !0
61-
call void @use.ptr(ptr %v1)
61+
call void @use.ptr(i32 0, ptr %v1)
6262
%v2 = load ptr, ptr %p, !noalias.addrspace !2
63-
call void @use.ptr(ptr %v2)
63+
call void @use.ptr(i32 1, ptr %v2)
6464
ret void
6565
}
6666

0 commit comments

Comments
 (0)