[llvm] [AArch64][InstCombine] Eliminate redundant barrier intrinsics (PR #112023)

Danila Malyutin via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 11 10:01:00 PDT 2024


https://github.com/danilaml created https://github.com/llvm/llvm-project/pull/112023

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.

>From 9f6659b0f08c4782363fb7f7f2402b05313c4288 Mon Sep 17 00:00:00 2001
From: Danila Malyutin <dmalyutin at azul.com>
Date: Fri, 11 Oct 2024 20:47:42 +0400
Subject: [PATCH] [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.
---
 .../AArch64/AArch64TargetTransformInfo.cpp    |  30 +++
 .../InstCombine/AArch64/dmb-intrinsics.ll     | 183 ++++++++++++++++++
 2 files changed, 213 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/AArch64/dmb-intrinsics.ll

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
+}
+
+
+
+



More information about the llvm-commits mailing list