[llvm] [AArch64][InstCombine] Eliminate redundant barrier intrinsics (PR #112023)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 11 10:01:23 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Danila Malyutin (danilaml)
<details>
<summary>Changes</summary>
If there are no memory ops on the path from one dmb to another then one barrier can be eliminated.
Can be improved to consider if the barrier is stronger than instead of identical later.
---
Full diff: https://github.com/llvm/llvm-project/pull/112023.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp (+30)
- (added) llvm/test/Transforms/InstCombine/AArch64/dmb-intrinsics.ll (+183)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 91ab3fcfc4c70e..ac2ca245f34fb5 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -2150,6 +2150,34 @@ static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,
return std::nullopt;
}
+
+static std::optional<Instruction *> instCombineDMB(InstCombiner &IC,
+ IntrinsicInst &II) {
+ // If this barrier is post-dominated by identical one we can remove it
+ auto *NI = II.getNextNonDebugInstruction();
+ int LookaheadThreshold = 10;
+ auto CanSkipOver = [](Instruction *I){
+ return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();
+ };
+ while (--LookaheadThreshold && !isa<IntrinsicInst>(NI)) {
+ if (!CanSkipOver(NI))
+ break;
+ auto *NIBB = NI->getParent();
+ NI = NI->getNextNonDebugInstruction();
+ if (!NI) {
+ if (auto *SuccBB = NIBB->getUniqueSuccessor())
+ NI = SuccBB->getFirstNonPHIOrDbgOrLifetime();
+ else
+ break;
+ }
+ }
+ auto *NextDMB = dyn_cast_or_null<IntrinsicInst>(NI);
+ if (NextDMB && II.isIdenticalTo(NextDMB))
+ return IC.eraseInstFromFunction(II);
+
+ return std::nullopt;
+}
+
std::optional<Instruction *>
AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC,
IntrinsicInst &II) const {
@@ -2157,6 +2185,8 @@ AArch64TTIImpl::instCombineIntrinsic(InstCombiner &IC,
switch (IID) {
default:
break;
+ case Intrinsic::aarch64_dmb:
+ return instCombineDMB(IC, II);
case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
case Intrinsic::aarch64_sve_fcvt_f16f32:
case Intrinsic::aarch64_sve_fcvt_f16f64:
diff --git a/llvm/test/Transforms/InstCombine/AArch64/dmb-intrinsics.ll b/llvm/test/Transforms/InstCombine/AArch64/dmb-intrinsics.ll
new file mode 100644
index 00000000000000..d8e77f89678255
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AArch64/dmb-intrinsics.ll
@@ -0,0 +1,183 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+; ARM64 dmb intrinsics
+
+target triple = "aarch64-unknown-linux-gnu"
+
+declare void @llvm.aarch64.dmb(i32)
+declare void @clobber()
+declare void @pure() memory(none) willreturn nounwind
+
+define void @simple() #0 {
+; CHECK-LABEL: define void @simple() {
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.dmb(i32 10)
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define ptr @simple_safe_instruction(ptr %p) #0 {
+; CHECK-LABEL: define ptr @simple_safe_instruction(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: [[RES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret ptr [[RES]]
+;
+ call void @llvm.aarch64.dmb(i32 10)
+ %res = getelementptr inbounds i8, ptr %p, i32 8
+ call void @llvm.aarch64.dmb(i32 10)
+ ret ptr %res
+}
+
+define void @simple_safe_unsafe_instruction(ptr %p) #0 {
+; CHECK-LABEL: define void @simple_safe_unsafe_instruction(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: store i32 42, ptr [[P]], align 4
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.dmb(i32 10)
+ store i32 42, ptr %p
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @simple_safe_unsafe_call(ptr %p) #0 {
+; CHECK-LABEL: define void @simple_safe_unsafe_call(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: call void @clobber()
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.dmb(i32 10)
+ call void @clobber()
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @simple_safe_safe_call(ptr %p) #0 {
+; CHECK-LABEL: define void @simple_safe_safe_call(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+ call void @llvm.aarch64.dmb(i32 10)
+ call void @pure()
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @multiple_bbs1(i1 %f) #0 {
+; CHECK-LABEL: define void @multiple_bbs1(
+; CHECK-SAME: i1 [[F:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
+; CHECK: [[BB_T]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB_F]]:
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 %f, label %bb_t, label %bb_f
+bb_t:
+ call void @llvm.aarch64.dmb(i32 10)
+ br label %exit
+bb_f:
+ call void @llvm.aarch64.dmb(i32 10)
+ br label %exit
+exit:
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @multiple_bbs2(i1 %f) #0 {
+; CHECK-LABEL: define void @multiple_bbs2(
+; CHECK-SAME: i1 [[F:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
+; CHECK: [[BB_T]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB_F]]:
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 %f, label %bb_t, label %bb_f
+bb_t:
+ call void @llvm.aarch64.dmb(i32 10)
+ br label %exit
+bb_f:
+ br label %exit
+exit:
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @multiple_bbs3(i1 %f, ptr %p) #0 {
+; CHECK-LABEL: define void @multiple_bbs3(
+; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
+; CHECK: [[BB_T]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB_F]]:
+; CHECK-NEXT: store i32 42, ptr [[P]], align 4
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 %f, label %bb_t, label %bb_f
+bb_t:
+ call void @llvm.aarch64.dmb(i32 10)
+ br label %exit
+bb_f:
+ store i32 42, ptr %p
+ br label %exit
+exit:
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+define void @multiple_bbs_unsafe(i1 %f, ptr %p) #0 {
+; CHECK-LABEL: define void @multiple_bbs_unsafe(
+; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]]
+; CHECK: [[BB_T]]:
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: store i32 42, ptr [[P]], align 4
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[BB_F]]:
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10)
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 %f, label %bb_t, label %bb_f
+bb_t:
+ call void @llvm.aarch64.dmb(i32 10)
+ store i32 42, ptr %p
+ br label %exit
+bb_f:
+ call void @llvm.aarch64.dmb(i32 10)
+ br label %exit
+exit:
+ call void @llvm.aarch64.dmb(i32 10)
+ ret void
+}
+
+
+
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/112023
More information about the llvm-commits
mailing list