mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Remove duplicated DMB instructions
ARM specific optimiztion, finding places in ARM machine code where 2 dmbs follow one another, and eliminating one of them. Patch by Reinoud Elhorst. llvm-svn: 205409
This commit is contained in:
parent
18f37e5fc5
commit
479ae7528b
@ -42,6 +42,7 @@ FunctionPass *createARMGlobalMergePass(const TargetLowering* tli);
|
||||
FunctionPass *createARMConstantIslandPass();
|
||||
FunctionPass *createMLxExpansionPass();
|
||||
FunctionPass *createThumb2ITBlockPass();
|
||||
FunctionPass *createARMOptimizeBarriersPass();
|
||||
FunctionPass *createThumb2SizeReductionPass();
|
||||
|
||||
/// \brief Creates an ARM-specific Target Transformation Info pass.
|
||||
|
101
lib/Target/ARM/ARMOptimizeBarriersPass.cpp
Normal file
101
lib/Target/ARM/ARMOptimizeBarriersPass.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
//===-- ARMOptimizeBarriersPass - two DMBs without a memory access in between,
|
||||
//removed one -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===------------------------------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "double barriers"
|
||||
|
||||
#include "ARM.h"
|
||||
#include "ARMMachineFunctionInfo.h"
|
||||
#include "ARMInstrInfo.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumDMBsRemoved, "Number of DMBs removed");
|
||||
|
||||
namespace {
|
||||
class ARMOptimizeBarriersPass : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &Fn);
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "optimise barriers pass";
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
char ARMOptimizeBarriersPass::ID = 0;
|
||||
}
|
||||
|
||||
// Returns whether the instruction can safely move past a DMB instruction
|
||||
// The current implementation allows this iif MI does not have any possible
|
||||
// memory access
|
||||
static bool CanMovePastDMB(const MachineInstr *MI) {
|
||||
return !(MI->mayLoad() ||
|
||||
MI->mayStore() ||
|
||||
MI->hasUnmodeledSideEffects() ||
|
||||
MI->isCall() ||
|
||||
MI->isReturn());
|
||||
}
|
||||
|
||||
bool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {
|
||||
// Vector to store the DMBs we will remove after the first iteration
|
||||
std::vector<MachineInstr *> ToRemove;
|
||||
// DMBType is the Imm value of the first operand. It determines whether it's a
|
||||
// DMB ish, dmb sy, dmb osh, etc
|
||||
int64_t DMBType = -1;
|
||||
|
||||
// Find a dmb. If we can move it until the next dmb, tag the second one for
|
||||
// removal
|
||||
for (auto &MBB : MF) {
|
||||
// Will be true when we have seen a DMB, and not seen any instruction since
|
||||
// that cannot move past a DMB
|
||||
bool IsRemovableNextDMB = false;
|
||||
for (auto &MI : MBB) {
|
||||
if (MI.getOpcode() == ARM::DMB) {
|
||||
if (IsRemovableNextDMB) {
|
||||
// If the Imm of this DMB is the same as that of the last DMB, we can
|
||||
// tag this second DMB for removal
|
||||
if (MI.getOperand(0).getImm() == DMBType) {
|
||||
ToRemove.push_back(&MI);
|
||||
} else {
|
||||
// If it has a different DMBType, we cannot remove it, but will scan
|
||||
// for the next DMB, recording this DMB's type as last seen DMB type
|
||||
DMBType = MI.getOperand(0).getImm();
|
||||
}
|
||||
} else {
|
||||
// After we see a DMB, a next one is removable
|
||||
IsRemovableNextDMB = true;
|
||||
DMBType = MI.getOperand(0).getImm();
|
||||
}
|
||||
} else if (!CanMovePastDMB(&MI)) {
|
||||
// If we find an instruction unable to pass past a DMB, a next DMB is
|
||||
// not removable
|
||||
IsRemovableNextDMB = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the tagged DMB
|
||||
for (auto MI : ToRemove) {
|
||||
MI->eraseFromParent();
|
||||
++NumDMBsRemoved;
|
||||
}
|
||||
|
||||
return NumDMBsRemoved > 0;
|
||||
}
|
||||
|
||||
/// createARMOptimizeBarriersPass - Returns an instance of the remove double
|
||||
/// barriers
|
||||
/// pass.
|
||||
FunctionPass *llvm::createARMOptimizeBarriersPass() {
|
||||
return new ARMOptimizeBarriersPass();
|
||||
}
|
@ -296,6 +296,7 @@ bool ARMPassConfig::addPreEmitPass() {
|
||||
addPass(&UnpackMachineBundlesID);
|
||||
}
|
||||
|
||||
addPass(createARMOptimizeBarriersPass());
|
||||
addPass(createARMConstantIslandPass());
|
||||
|
||||
return true;
|
||||
|
@ -34,6 +34,7 @@ add_llvm_target(ARMCodeGen
|
||||
ARMMCInstLower.cpp
|
||||
ARMMachineFunctionInfo.cpp
|
||||
ARMRegisterInfo.cpp
|
||||
ARMOptimizeBarriersPass.cpp
|
||||
ARMSelectionDAGInfo.cpp
|
||||
ARMSubtarget.cpp
|
||||
ARMTargetMachine.cpp
|
||||
|
74
test/CodeGen/ARM/optimize-dmbs-v7.ll
Normal file
74
test/CodeGen/ARM/optimize-dmbs-v7.ll
Normal file
@ -0,0 +1,74 @@
|
||||
; RUN: llc < %s -mtriple=armv7 -mattr=+db | FileCheck %s
|
||||
|
||||
@x1 = global i32 0, align 4
|
||||
@x2 = global i32 0, align 4
|
||||
|
||||
define void @test() {
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%i.013 = phi i32 [ 1, %entry ], [ %inc6, %for.body ]
|
||||
store atomic i32 %i.013, i32* @x1 seq_cst, align 4
|
||||
store atomic i32 %i.013, i32* @x1 seq_cst, align 4
|
||||
store atomic i32 %i.013, i32* @x2 seq_cst, align 4
|
||||
%inc6 = add nsw i32 %i.013, 1
|
||||
%exitcond = icmp eq i32 %inc6, 2
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
|
||||
; The for.body contains 3 seq_cst stores.
|
||||
; Hence it should have 3 dmb;str;dmb sequences with the middle dmbs collapsed
|
||||
; CHECK: %for.body
|
||||
; CHECK-NOT: str
|
||||
; CHECK: dmb
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK: str
|
||||
|
||||
; CHECK-NOT: str
|
||||
; CHECK: dmb
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK: str
|
||||
|
||||
; CHECK-NOT: str
|
||||
; CHECK: dmb
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK: str
|
||||
|
||||
; CHECK-NOT: str
|
||||
; CHECK: dmb
|
||||
; CHECK-NOT: dmb
|
||||
; CHECK-NOT: str
|
||||
; CHECK: %for.end
|
||||
}
|
||||
|
||||
define void @test2() {
|
||||
call void @llvm.arm.dmb(i32 11)
|
||||
tail call void @test()
|
||||
call void @llvm.arm.dmb(i32 11)
|
||||
ret void
|
||||
; the call should prevent the two dmbs from collapsing
|
||||
; CHECK: test2:
|
||||
; CHECK: dmb
|
||||
; CHECK-NEXT: bl
|
||||
; CHECK-NEXT: dmb
|
||||
}
|
||||
|
||||
define void @test3() {
|
||||
call void @llvm.arm.dmb(i32 11)
|
||||
call void @llvm.arm.dsb(i32 9)
|
||||
call void @llvm.arm.dmb(i32 11)
|
||||
ret void
|
||||
; the call should prevent the two dmbs from collapsing
|
||||
; CHECK: test3:
|
||||
; CHECK: dmb
|
||||
; CHECK-NEXT: dsb
|
||||
; CHECK-NEXT: dmb
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare void @llvm.arm.dmb(i32)
|
||||
declare void @llvm.arm.dsb(i32)
|
Loading…
Reference in New Issue
Block a user