Skip to content

Commit 6b8cc42

Browse files
committed
[AArch64][InstCombine] Eliminate redundant barrier intrinsics
If there are no memory ops on the path from one dmb to another then one barrier can be eliminated.
1 parent 7f1b465 commit 6b8cc42

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,13 +2150,43 @@ static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,
21502150
return std::nullopt;
21512151
}
21522152

2153+
2154+
static std::optional<Instruction *> instCombineDMB(InstCombiner &IC,
2155+
IntrinsicInst &II) {
2156+
// If this barrier is post-dominated by identical one we can remove it
2157+
auto *NI = II.getNextNonDebugInstruction();
2158+
int LookaheadThreshold = 10;
2159+
auto CanSkipOver = [](Instruction *I) {
2160+
return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();
2161+
};
2162+
while (--LookaheadThreshold && !isa<IntrinsicInst>(NI)) {
2163+
if (!CanSkipOver(NI))
2164+
break;
2165+
auto *NIBB = NI->getParent();
2166+
NI = NI->getNextNonDebugInstruction();
2167+
if (!NI) {
2168+
if (auto *SuccBB = NIBB->getUniqueSuccessor())
2169+
NI = SuccBB->getFirstNonPHIOrDbgOrLifetime();
2170+
else
2171+
break;
2172+
}
2173+
}
2174+
auto *NextDMB = dyn_cast_or_null<IntrinsicInst>(NI);
2175+
if (NextDMB && II.isIdenticalTo(NextDMB))
2176+
return IC.eraseInstFromFunction(II);
2177+
2178+
return std::nullopt;
2179+
}
2180+
21532181
std::optional<Instruction *>
21542182
AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC,
21552183
IntrinsicInst &II) const {
21562184
Intrinsic::ID IID = II.getIntrinsicID();
21572185
switch (IID) {
21582186
default:
21592187
break;
2188+
case Intrinsic::aarch64_dmb:
2189+
return instCombineDMB(IC, II);
21602190
case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
21612191
case Intrinsic::aarch64_sve_fcvt_f16f32:
21622192
case Intrinsic::aarch64_sve_fcvt_f16f64:
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
; ARM64 dmb intrinsics
4+
5+
target triple = "aarch64-unknown-linux-gnu"
6+
7+
declare void @llvm.aarch64.dmb(i32)
8+
declare void @clobber()
9+
declare void @pure() memory(none) willreturn nounwind
10+
11+
define void @simple() #0 {
12+
; CHECK-LABEL: define void @simple() {
13+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
14+
; CHECK-NEXT: ret void
15+
;
16+
call void @llvm.aarch64.dmb(i32 10)
17+
call void @llvm.aarch64.dmb(i32 10)
18+
ret void
19+
}
20+
21+
define ptr @simple_safe_instruction(ptr %p) #0 {
22+
; CHECK-LABEL: define ptr @simple_safe_instruction(
23+
; CHECK-SAME: ptr [[P:%.*]]) {
24+
; CHECK-NEXT: [[RES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8
25+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
26+
; CHECK-NEXT: ret ptr [[RES]]
27+
;
28+
call void @llvm.aarch64.dmb(i32 10)
29+
%res = getelementptr inbounds i8, ptr %p, i32 8
30+
call void @llvm.aarch64.dmb(i32 10)
31+
ret ptr %res
32+
}
33+
34+
define void @simple_safe_unsafe_instruction(ptr %p) #0 {
35+
; CHECK-LABEL: define void @simple_safe_unsafe_instruction(
36+
; CHECK-SAME: ptr [[P:%.*]]) {
37+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
38+
; CHECK-NEXT: store i32 42, ptr [[P]], align 4
39+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
40+
; CHECK-NEXT: ret void
41+
;
42+
call void @llvm.aarch64.dmb(i32 10)
43+
store i32 42, ptr %p
44+
call void @llvm.aarch64.dmb(i32 10)
45+
ret void
46+
}
47+
48+
define void @simple_safe_unsafe_call(ptr %p) #0 {
49+
; CHECK-LABEL: define void @simple_safe_unsafe_call(
50+
; CHECK-SAME: ptr [[P:%.*]]) {
51+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
52+
; CHECK-NEXT: call void @clobber()
53+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
54+
; CHECK-NEXT: ret void
55+
;
56+
call void @llvm.aarch64.dmb(i32 10)
57+
call void @clobber()
58+
call void @llvm.aarch64.dmb(i32 10)
59+
ret void
60+
}
61+
62+
define void @simple_safe_safe_call(ptr %p) #0 {
63+
; CHECK-LABEL: define void @simple_safe_safe_call(
64+
; CHECK-SAME: ptr [[P:%.*]]) {
65+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
66+
; CHECK-NEXT: ret void
67+
;
68+
call void @llvm.aarch64.dmb(i32 10)
69+
call void @pure()
70+
call void @llvm.aarch64.dmb(i32 10)
71+
ret void
72+
}
73+
74+
define void @multiple_bbs1(i1 %f) #0 {
75+
; CHECK-LABEL: define void @multiple_bbs1(
76+
; CHECK-SAME: i1 [[F:%.*]]) {
77+
; CHECK-NEXT: [[ENTRY:.*:]]
78+
; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
79+
; CHECK: [[BB_T]]:
80+
; CHECK-NEXT: br label %[[EXIT:.*]]
81+
; CHECK: [[BB_F]]:
82+
; CHECK-NEXT: br label %[[EXIT]]
83+
; CHECK: [[EXIT]]:
84+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
85+
; CHECK-NEXT: ret void
86+
;
87+
entry:
88+
br i1 %f, label %bb_t, label %bb_f
89+
bb_t:
90+
call void @llvm.aarch64.dmb(i32 10)
91+
br label %exit
92+
bb_f:
93+
call void @llvm.aarch64.dmb(i32 10)
94+
br label %exit
95+
exit:
96+
call void @llvm.aarch64.dmb(i32 10)
97+
ret void
98+
}
99+
100+
define void @multiple_bbs2(i1 %f) #0 {
101+
; CHECK-LABEL: define void @multiple_bbs2(
102+
; CHECK-SAME: i1 [[F:%.*]]) {
103+
; CHECK-NEXT: [[ENTRY:.*:]]
104+
; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
105+
; CHECK: [[BB_T]]:
106+
; CHECK-NEXT: br label %[[EXIT:.*]]
107+
; CHECK: [[BB_F]]:
108+
; CHECK-NEXT: br label %[[EXIT]]
109+
; CHECK: [[EXIT]]:
110+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
111+
; CHECK-NEXT: ret void
112+
;
113+
entry:
114+
br i1 %f, label %bb_t, label %bb_f
115+
bb_t:
116+
call void @llvm.aarch64.dmb(i32 10)
117+
br label %exit
118+
bb_f:
119+
br label %exit
120+
exit:
121+
call void @llvm.aarch64.dmb(i32 10)
122+
ret void
123+
}
124+
125+
define void @multiple_bbs3(i1 %f, ptr %p) #0 {
126+
; CHECK-LABEL: define void @multiple_bbs3(
127+
; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) {
128+
; CHECK-NEXT: [[ENTRY:.*:]]
129+
; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
130+
; CHECK: [[BB_T]]:
131+
; CHECK-NEXT: br label %[[EXIT:.*]]
132+
; CHECK: [[BB_F]]:
133+
; CHECK-NEXT: store i32 42, ptr [[P]], align 4
134+
; CHECK-NEXT: br label %[[EXIT]]
135+
; CHECK: [[EXIT]]:
136+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
137+
; CHECK-NEXT: ret void
138+
;
139+
entry:
140+
br i1 %f, label %bb_t, label %bb_f
141+
bb_t:
142+
call void @llvm.aarch64.dmb(i32 10)
143+
br label %exit
144+
bb_f:
145+
store i32 42, ptr %p
146+
br label %exit
147+
exit:
148+
call void @llvm.aarch64.dmb(i32 10)
149+
ret void
150+
}
151+
152+
define void @multiple_bbs_unsafe(i1 %f, ptr %p) #0 {
153+
; CHECK-LABEL: define void @multiple_bbs_unsafe(
154+
; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) {
155+
; CHECK-NEXT: [[ENTRY:.*:]]
156+
; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
157+
; CHECK: [[BB_T]]:
158+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
159+
; CHECK-NEXT: store i32 42, ptr [[P]], align 4
160+
; CHECK-NEXT: br label %[[EXIT:.*]]
161+
; CHECK: [[BB_F]]:
162+
; CHECK-NEXT: br label %[[EXIT]]
163+
; CHECK: [[EXIT]]:
164+
; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
165+
; CHECK-NEXT: ret void
166+
;
167+
entry:
168+
br i1 %f, label %bb_t, label %bb_f
169+
bb_t:
170+
call void @llvm.aarch64.dmb(i32 10)
171+
store i32 42, ptr %p
172+
br label %exit
173+
bb_f:
174+
call void @llvm.aarch64.dmb(i32 10)
175+
br label %exit
176+
exit:
177+
call void @llvm.aarch64.dmb(i32 10)
178+
ret void
179+
}
180+
181+
182+
183+

0 commit comments

Comments
 (0)