Skip to content

Commit 6a6fa34

Browse files
committed
[DSE] Remove dead stores in end blocks containing fence
We can remove dead stores in the presence of fence instructions. Fence does not change an otherwise thread local store to visible. reviewers: reames, dexonsmith, jfb Differential Revision: http://reviews.llvm.org/D22001 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274795 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent adafb27 commit 6a6fa34

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,14 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA,
778778
continue;
779779
}
780780

781+
// We can remove the dead stores, irrespective of the fence and its ordering
782+
// (release/acquire/seq_cst). Fences only constraints the ordering of
783+
// already visible stores, it does not make a store visible to other
784+
// threads. So, skipping over a fence does not change a store from being
785+
// dead.
786+
if (isa<FenceInst>(*BBI))
787+
continue;
788+
781789
MemoryLocation LoadedLoc;
782790

783791
// If we encounter a use of the pointer, it is no longer considered dead

test/Transforms/DeadStoreElimination/fence.ll

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,51 @@ define void @test2(i32* %addr.i) {
4646
store i32 5, i32* %addr.i, align 4
4747
ret void
4848
}
49+
50+
; We DSE stack alloc'ed and byval locations, in the presence of fences.
51+
; Fence does not make an otherwise thread local store visible.
52+
; Right now the DSE in presence of fence is only done in end blocks (with no successors),
53+
; but the same logic applies to other basic blocks as well.
54+
; The store to %addr.i can be removed since it is a byval attribute
55+
define void @test3(i32* byval %addr.i) {
56+
; CHECK-LABEL: @test3
57+
; CHECK-NOT: store
58+
; CHECK: fence
59+
; CHECK: ret
60+
store i32 5, i32* %addr.i, align 4
61+
fence release
62+
ret void
63+
}
64+
65+
declare void @foo(i8* nocapture %p)
66+
67+
declare noalias i8* @malloc(i32)
68+
69+
; DSE of stores in locations allocated through library calls.
70+
define void @test_nocapture() {
71+
; CHECK-LABEL: @test_nocapture
72+
; CHECK: malloc
73+
; CHECK: foo
74+
; CHECK-NOT: store
75+
; CHECK: fence
76+
%m = call i8* @malloc(i32 24)
77+
call void @foo(i8* %m)
78+
store i8 4, i8* %m
79+
fence release
80+
ret void
81+
}
82+
83+
84+
; This is a full fence, but it does not make a thread local store visible.
85+
; We can DSE the store in presence of the fence.
86+
define void @fence_seq_cst() {
87+
; CHECK-LABEL: @fence_seq_cst
88+
; CHECK-NEXT: fence seq_cst
89+
; CHECK-NEXT: ret void
90+
%P1 = alloca i32
91+
store i32 0, i32* %P1, align 4
92+
fence seq_cst
93+
store i32 4, i32* %P1, align 4
94+
ret void
95+
}
96+

0 commit comments

Comments
 (0)