Index: lib/Target/AArch64/AArch64.h =================================================================== --- lib/Target/AArch64/AArch64.h +++ lib/Target/AArch64/AArch64.h @@ -30,6 +30,7 @@ FunctionPass *createAArch64ConditionalCompares(); FunctionPass *createAArch64AdvSIMDScalar(); FunctionPass *createAArch64BranchRelaxation(); +FunctionPass *createAArch64OptimizeBarriersPass(); FunctionPass *createAArch64ISelDag(AArch64TargetMachine &TM, CodeGenOpt::Level OptLevel); FunctionPass *createAArch64StorePairSuppressPass(); Index: lib/Target/AArch64/AArch64OptimizeBarriersPass.cpp =================================================================== --- lib/Target/AArch64/AArch64OptimizeBarriersPass.cpp +++ lib/Target/AArch64/AArch64OptimizeBarriersPass.cpp @@ -0,0 +1,75 @@ +//===------------- AArch64OptimizeBarriersPass.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#include "AArch64.h" +#include "AArch64InstrInfo.h" +#include "AArch64MachineFunctionInfo.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +using namespace llvm; + +#define DEBUG_TYPE "double barriers" + +STATISTIC(NumDMBsRemoved, "Number of DMBs removed"); + +namespace { +class AArch64OptimizeBarriersPass : public MachineFunctionPass { + public: + static char ID; + AArch64OptimizeBarriersPass() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &Fn) override; + + const char *getPassName() const override { + return "optimise barriers pass"; + } + }; + char AArch64OptimizeBarriersPass::ID = 0; +} + +static bool CanMovePastDMB(const MachineInstr *MI) { + return !(MI->mayLoad() || MI->mayStore() || + MI->hasUnmodeledSideEffects() || MI->isCall() || + MI->isReturn()); +} + +bool AArch64OptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) { + std::vector ToRemove; + int64_t DMBType = -1; + + for (auto &MBB: MF) { + bool IsRemovableNextDMB = false; + for (auto &MI : MBB) { + if (MI.getOpcode() == AArch64::DMB) { + if (IsRemovableNextDMB) { + if (MI.getOperand(0).getImm() == DMBType) { + ToRemove.push_back(&MI); + } else + DMBType = MI.getOperand(0).getImm(); + } else { + IsRemovableNextDMB = true; + DMBType = MI.getOperand(0).getImm(); + } + } else if (!CanMovePastDMB(&MI)) + IsRemovableNextDMB = false; + } + } + + for (auto MI : ToRemove) { + MI->eraseFromParent(); + ++NumDMBsRemoved; + } + return NumDMBsRemoved > 0; +} + +FunctionPass *llvm::createAArch64OptimizeBarriersPass() { + return new AArch64OptimizeBarriersPass(); +} Index: lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetMachine.cpp +++ lib/Target/AArch64/AArch64TargetMachine.cpp @@ -322,4 +322,5 @@ if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH && Triple(TM->getTargetTriple()).isOSBinFormatMachO()) addPass(createAArch64CollectLOHPass()); + addPass(createAArch64OptimizeBarriersPass()); } Index: lib/Target/AArch64/CMakeLists.txt =================================================================== --- lib/Target/AArch64/CMakeLists.txt +++ lib/Target/AArch64/CMakeLists.txt @@ -34,6 +34,7 @@ AArch64InstrInfo.cpp AArch64LoadStoreOptimizer.cpp AArch64MCInstLower.cpp + AArch64OptimizeBarriersPass.cpp AArch64PromoteConstant.cpp AArch64PBQPRegAlloc.cpp AArch64RegisterInfo.cpp Index: test/CodeGen/AArch64/optimize-dmbs.ll =================================================================== --- test/CodeGen/AArch64/optimize-dmbs.ll +++ test/CodeGen/AArch64/optimize-dmbs.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple arm64-linux-gnueabi -mcpu cortex-a53 | FileCheck %s + +define i32 @t1() { +entry: + fence seq_cst + fence seq_cst + fence seq_cst + fence seq_cst + ret i32 0 +} + +; CHECK: .cfi_startproc +; CHECK-NEXT: // BB#0: // %entry +; CHECK-NEXT: dmb ish +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ret