mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
Run branch folding if if-converter make some transformations.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80994 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e93909185f
commit
030a0a0cdb
@ -17,6 +17,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "branchfolding"
|
||||
#include "BranchFolding.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
@ -46,64 +47,28 @@ TailMergeThreshold("tail-merge-threshold",
|
||||
cl::desc("Max number of predecessors to consider tail merging"),
|
||||
cl::init(150), cl::Hidden);
|
||||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN BranchFolder : public MachineFunctionPass {
|
||||
static char ID;
|
||||
explicit BranchFolder(bool defaultEnableTailMerge) :
|
||||
MachineFunctionPass(&ID) {
|
||||
switch (FlagEnableTailMerge) {
|
||||
case cl::BOU_UNSET: EnableTailMerge = defaultEnableTailMerge; break;
|
||||
case cl::BOU_TRUE: EnableTailMerge = true; break;
|
||||
case cl::BOU_FALSE: EnableTailMerge = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
virtual const char *getPassName() const { return "Control Flow Optimizer"; }
|
||||
const TargetInstrInfo *TII;
|
||||
MachineModuleInfo *MMI;
|
||||
bool MadeChange;
|
||||
private:
|
||||
// Tail Merging.
|
||||
bool EnableTailMerge;
|
||||
bool TailMergeBlocks(MachineFunction &MF);
|
||||
bool TryMergeBlocks(MachineBasicBlock* SuccBB,
|
||||
MachineBasicBlock* PredBB);
|
||||
void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst,
|
||||
MachineBasicBlock *NewDest);
|
||||
MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB,
|
||||
MachineBasicBlock::iterator BBI1);
|
||||
unsigned ComputeSameTails(unsigned CurHash, unsigned minCommonTailLength);
|
||||
void RemoveBlocksWithHash(unsigned CurHash, MachineBasicBlock* SuccBB,
|
||||
MachineBasicBlock* PredBB);
|
||||
unsigned CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
|
||||
unsigned maxCommonTailLength);
|
||||
|
||||
typedef std::pair<unsigned,MachineBasicBlock*> MergePotentialsElt;
|
||||
typedef std::vector<MergePotentialsElt>::iterator MPIterator;
|
||||
std::vector<MergePotentialsElt> MergePotentials;
|
||||
|
||||
typedef std::pair<MPIterator, MachineBasicBlock::iterator> SameTailElt;
|
||||
std::vector<SameTailElt> SameTails;
|
||||
|
||||
const TargetRegisterInfo *RegInfo;
|
||||
RegScavenger *RS;
|
||||
// Branch optzn.
|
||||
bool OptimizeBranches(MachineFunction &MF);
|
||||
void OptimizeBlock(MachineBasicBlock *MBB);
|
||||
void RemoveDeadBlock(MachineBasicBlock *MBB);
|
||||
bool OptimizeImpDefsBlock(MachineBasicBlock *MBB);
|
||||
|
||||
bool CanFallThrough(MachineBasicBlock *CurBB);
|
||||
bool CanFallThrough(MachineBasicBlock *CurBB, bool BranchUnAnalyzable,
|
||||
MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond);
|
||||
};
|
||||
char BranchFolder::ID = 0;
|
||||
}
|
||||
char BranchFolderPass::ID = 0;
|
||||
|
||||
FunctionPass *llvm::createBranchFoldingPass(bool DefaultEnableTailMerge) {
|
||||
return new BranchFolder(DefaultEnableTailMerge);
|
||||
return new BranchFolderPass(DefaultEnableTailMerge);
|
||||
}
|
||||
|
||||
bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) {
|
||||
return OptimizeFunction(MF,
|
||||
MF.getTarget().getInstrInfo(),
|
||||
MF.getTarget().getRegisterInfo(),
|
||||
getAnalysisIfAvailable<MachineModuleInfo>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
BranchFolder::BranchFolder(bool defaultEnableTailMerge) {
|
||||
switch (FlagEnableTailMerge) {
|
||||
case cl::BOU_UNSET: EnableTailMerge = defaultEnableTailMerge; break;
|
||||
case cl::BOU_TRUE: EnableTailMerge = true; break;
|
||||
case cl::BOU_FALSE: EnableTailMerge = false; break;
|
||||
}
|
||||
}
|
||||
|
||||
/// RemoveDeadBlock - Remove the specified dead machine basic block from the
|
||||
@ -149,7 +114,7 @@ bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) {
|
||||
break;
|
||||
unsigned Reg = I->getOperand(0).getReg();
|
||||
ImpDefRegs.insert(Reg);
|
||||
for (const unsigned *SubRegs = RegInfo->getSubRegisters(Reg);
|
||||
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
|
||||
unsigned SubReg = *SubRegs; ++SubRegs)
|
||||
ImpDefRegs.insert(SubReg);
|
||||
++I;
|
||||
@ -183,32 +148,37 @@ bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BranchFolder::runOnMachineFunction(MachineFunction &MF) {
|
||||
TII = MF.getTarget().getInstrInfo();
|
||||
if (!TII) return false;
|
||||
/// OptimizeFunction - Perhaps branch folding, tail merging and other
|
||||
/// CFG optimizations on the given function.
|
||||
bool BranchFolder::OptimizeFunction(MachineFunction &MF,
|
||||
const TargetInstrInfo *tii,
|
||||
const TargetRegisterInfo *tri,
|
||||
MachineModuleInfo *mmi) {
|
||||
if (!tii) return false;
|
||||
|
||||
RegInfo = MF.getTarget().getRegisterInfo();
|
||||
TII = tii;
|
||||
TRI = tri;
|
||||
MMI = mmi;
|
||||
|
||||
RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : NULL;
|
||||
|
||||
// Fix CFG. The later algorithms expect it to be right.
|
||||
bool EverMadeChange = false;
|
||||
bool MadeChange = false;
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; I++) {
|
||||
MachineBasicBlock *MBB = I, *TBB = 0, *FBB = 0;
|
||||
SmallVector<MachineOperand, 4> Cond;
|
||||
if (!TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, true))
|
||||
EverMadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty());
|
||||
EverMadeChange |= OptimizeImpDefsBlock(MBB);
|
||||
MadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty());
|
||||
MadeChange |= OptimizeImpDefsBlock(MBB);
|
||||
}
|
||||
|
||||
RS = RegInfo->requiresRegisterScavenging(MF) ? new RegScavenger() : NULL;
|
||||
|
||||
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
|
||||
|
||||
bool MadeChangeThisIteration = true;
|
||||
while (MadeChangeThisIteration) {
|
||||
MadeChangeThisIteration = false;
|
||||
MadeChangeThisIteration |= TailMergeBlocks(MF);
|
||||
MadeChangeThisIteration |= OptimizeBranches(MF);
|
||||
EverMadeChange |= MadeChangeThisIteration;
|
||||
MadeChange |= MadeChangeThisIteration;
|
||||
}
|
||||
|
||||
// See if any jump tables have become mergable or dead as the code generator
|
||||
@ -225,8 +195,12 @@ bool BranchFolder::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
||||
// Scan the jump tables, seeing if there are any duplicates. Note that this
|
||||
// is N^2, which should be fixed someday.
|
||||
for (unsigned i = 1, e = JTs.size(); i != e; ++i)
|
||||
JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs));
|
||||
for (unsigned i = 1, e = JTs.size(); i != e; ++i) {
|
||||
if (JTs[i].MBBs.empty())
|
||||
JTMapping.push_back(i);
|
||||
else
|
||||
JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs));
|
||||
}
|
||||
|
||||
// If a jump table was merge with another one, walk the function rewriting
|
||||
// references to jump tables to reference the new JT ID's. Keep track of
|
||||
@ -253,12 +227,12 @@ bool BranchFolder::runOnMachineFunction(MachineFunction &MF) {
|
||||
for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i)
|
||||
if (!JTIsLive.test(i)) {
|
||||
JTI->RemoveJumpTable(i);
|
||||
EverMadeChange = true;
|
||||
MadeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete RS;
|
||||
return EverMadeChange;
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -398,9 +372,9 @@ MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB,
|
||||
RS->enterBasicBlock(&CurMBB);
|
||||
if (!CurMBB.empty())
|
||||
RS->forward(prior(CurMBB.end()));
|
||||
BitVector RegsLiveAtExit(RegInfo->getNumRegs());
|
||||
BitVector RegsLiveAtExit(TRI->getNumRegs());
|
||||
RS->getRegsUsed(RegsLiveAtExit, false);
|
||||
for (unsigned int i=0, e=RegInfo->getNumRegs(); i!=e; i++)
|
||||
for (unsigned int i=0, e=TRI->getNumRegs(); i!=e; i++)
|
||||
if (RegsLiveAtExit[i])
|
||||
NewMBB->addLiveIn(i);
|
||||
}
|
||||
@ -593,11 +567,12 @@ unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
|
||||
|
||||
bool BranchFolder::TryMergeBlocks(MachineBasicBlock *SuccBB,
|
||||
MachineBasicBlock* PredBB) {
|
||||
bool MadeChange = false;
|
||||
|
||||
// It doesn't make sense to save a single instruction since tail merging
|
||||
// will add a jump.
|
||||
// FIXME: Ask the target to provide the threshold?
|
||||
unsigned minCommonTailLength = (SuccBB ? 1 : 2) + 1;
|
||||
MadeChange = false;
|
||||
|
||||
DEBUG(errs() << "\nTryMergeBlocks " << MergePotentials.size() << '\n');
|
||||
|
||||
@ -668,7 +643,7 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
|
||||
|
||||
if (!EnableTailMerge) return false;
|
||||
|
||||
MadeChange = false;
|
||||
bool MadeChange = false;
|
||||
|
||||
// First find blocks with no successors.
|
||||
MergePotentials.clear();
|
||||
@ -779,14 +754,14 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
|
||||
MadeChange = false;
|
||||
bool MadeChange = false;
|
||||
|
||||
// Make sure blocks are numbered in order
|
||||
MF.RenumberBlocks();
|
||||
|
||||
for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) {
|
||||
MachineBasicBlock *MBB = I++;
|
||||
OptimizeBlock(MBB);
|
||||
MadeChange |= OptimizeBlock(MBB);
|
||||
|
||||
// If it is dead, remove it.
|
||||
if (MBB->pred_empty()) {
|
||||
@ -880,7 +855,9 @@ static bool IsBetterFallthrough(MachineBasicBlock *MBB1,
|
||||
|
||||
/// OptimizeBlock - Analyze and optimize control flow related to the specified
|
||||
/// block. This is never called on the entry block.
|
||||
void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
bool MadeChange = false;
|
||||
|
||||
MachineFunction::iterator FallThrough = MBB;
|
||||
++FallThrough;
|
||||
|
||||
@ -889,7 +866,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
// points to this block.
|
||||
if (MBB->empty() && !MBB->isLandingPad()) {
|
||||
// Dead block? Leave for cleanup later.
|
||||
if (MBB->pred_empty()) return;
|
||||
if (MBB->pred_empty()) return MadeChange;
|
||||
|
||||
if (FallThrough == MBB->getParent()->end()) {
|
||||
// TODO: Simplify preds to not branch here if possible!
|
||||
@ -906,7 +883,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
ReplaceMBBInJumpTables(MBB, FallThrough);
|
||||
MadeChange = true;
|
||||
}
|
||||
return;
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
// Check to see if we can simplify the terminator of the block before this
|
||||
@ -1020,7 +997,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
MBB->moveAfter(--MBB->getParent()->end());
|
||||
MadeChange = true;
|
||||
++NumBranchOpts;
|
||||
return;
|
||||
return MadeChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1122,7 +1099,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
if (DidChange) {
|
||||
++NumBranchOpts;
|
||||
MadeChange = true;
|
||||
if (!HasBranchToSelf) return;
|
||||
if (!HasBranchToSelf) return MadeChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1203,8 +1180,10 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
PrevBB.isSuccessor(FallThrough)) {
|
||||
MBB->moveAfter(--MBB->getParent()->end());
|
||||
MadeChange = true;
|
||||
return;
|
||||
return MadeChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MadeChange;
|
||||
}
|
||||
|
84
lib/CodeGen/BranchFolding.h
Normal file
84
lib/CodeGen/BranchFolding.h
Normal file
@ -0,0 +1,84 @@
|
||||
//===-- BranchFolding.h - Fold machine code branch instructions --*- C++ -*===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_BRANCHFOLDING_HPP
|
||||
#define LLVM_CODEGEN_BRANCHFOLDING_HPP
|
||||
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class MachineFunction;
|
||||
class MachineModuleInfo;
|
||||
class RegScavenger;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
class BranchFolder {
|
||||
public:
|
||||
explicit BranchFolder(bool defaultEnableTailMerge);
|
||||
|
||||
bool OptimizeFunction(MachineFunction &MF,
|
||||
const TargetInstrInfo *tii,
|
||||
const TargetRegisterInfo *tri,
|
||||
MachineModuleInfo *mmi);
|
||||
private:
|
||||
typedef std::pair<unsigned,MachineBasicBlock*> MergePotentialsElt;
|
||||
typedef std::vector<MergePotentialsElt>::iterator MPIterator;
|
||||
std::vector<MergePotentialsElt> MergePotentials;
|
||||
|
||||
typedef std::pair<MPIterator, MachineBasicBlock::iterator> SameTailElt;
|
||||
std::vector<SameTailElt> SameTails;
|
||||
|
||||
bool EnableTailMerge;
|
||||
const TargetInstrInfo *TII;
|
||||
const TargetRegisterInfo *TRI;
|
||||
MachineModuleInfo *MMI;
|
||||
RegScavenger *RS;
|
||||
|
||||
bool TailMergeBlocks(MachineFunction &MF);
|
||||
bool TryMergeBlocks(MachineBasicBlock* SuccBB,
|
||||
MachineBasicBlock* PredBB);
|
||||
void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst,
|
||||
MachineBasicBlock *NewDest);
|
||||
MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB,
|
||||
MachineBasicBlock::iterator BBI1);
|
||||
unsigned ComputeSameTails(unsigned CurHash, unsigned minCommonTailLength);
|
||||
void RemoveBlocksWithHash(unsigned CurHash, MachineBasicBlock* SuccBB,
|
||||
MachineBasicBlock* PredBB);
|
||||
unsigned CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
|
||||
unsigned maxCommonTailLength);
|
||||
|
||||
bool OptimizeBranches(MachineFunction &MF);
|
||||
bool OptimizeBlock(MachineBasicBlock *MBB);
|
||||
void RemoveDeadBlock(MachineBasicBlock *MBB);
|
||||
bool OptimizeImpDefsBlock(MachineBasicBlock *MBB);
|
||||
|
||||
bool CanFallThrough(MachineBasicBlock *CurBB);
|
||||
bool CanFallThrough(MachineBasicBlock *CurBB, bool BranchUnAnalyzable,
|
||||
MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond);
|
||||
};
|
||||
|
||||
|
||||
/// BranchFolderPass - Wrap branch folder in a machine function pass.
|
||||
class BranchFolderPass : public MachineFunctionPass,
|
||||
public BranchFolder {
|
||||
public:
|
||||
static char ID;
|
||||
explicit BranchFolderPass(bool defaultEnableTailMerge)
|
||||
: MachineFunctionPass(&ID), BranchFolder(defaultEnableTailMerge) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
virtual const char *getPassName() const { return "Control Flow Optimizer"; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* LLVM_CODEGEN_BRANCHFOLDING_HPP */
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "ifcvt"
|
||||
#include "BranchFolding.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
@ -360,6 +361,13 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
|
||||
Roots.clear();
|
||||
BBAnalysis.clear();
|
||||
|
||||
if (MadeChange) {
|
||||
BranchFolder BF(false);
|
||||
BF.OptimizeFunction(MF, TII,
|
||||
MF.getTarget().getRegisterInfo(),
|
||||
getAnalysisIfAvailable<MachineModuleInfo>());
|
||||
}
|
||||
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ entry:
|
||||
; CHECK: CountTree:
|
||||
; CHECK: it eq
|
||||
; CHECK: cmpeq
|
||||
; CHECK: beq
|
||||
; CHECK: bne
|
||||
; CHECK: itt eq
|
||||
; CHECK: moveq
|
||||
; CHECK: popeq
|
||||
|
32
test/CodeGen/Thumb2/thumb2-ifcvt3.ll
Normal file
32
test/CodeGen/Thumb2/thumb2-ifcvt3.ll
Normal file
@ -0,0 +1,32 @@
|
||||
; RUN: llvm-as < %s | llc -mtriple=thumbv7-apple-darwin | FileCheck %s
|
||||
|
||||
; There shouldn't be a unconditional branch at end of bb52.
|
||||
; rdar://7184787
|
||||
|
||||
@posed = external global i64 ; <i64*> [#uses=1]
|
||||
|
||||
define i1 @ab_bb52(i64 %.reload78, i64* %.out, i64* %.out1) nounwind {
|
||||
newFuncRoot:
|
||||
br label %bb52
|
||||
|
||||
bb52.bb55_crit_edge.exitStub: ; preds = %bb52
|
||||
store i64 %0, i64* %.out
|
||||
store i64 %2, i64* %.out1
|
||||
ret i1 true
|
||||
|
||||
bb52.bb53_crit_edge.exitStub: ; preds = %bb52
|
||||
store i64 %0, i64* %.out
|
||||
store i64 %2, i64* %.out1
|
||||
ret i1 false
|
||||
|
||||
bb52: ; preds = %newFuncRoot
|
||||
; CHECK: moveq
|
||||
; CHECK: movne
|
||||
; CHECK-NEXT: LBB1_2:
|
||||
; CHECK-NEXT: pop
|
||||
%0 = load i64* @posed, align 4 ; <i64> [#uses=3]
|
||||
%1 = sub i64 %0, %.reload78 ; <i64> [#uses=1]
|
||||
%2 = ashr i64 %1, 1 ; <i64> [#uses=3]
|
||||
%3 = icmp eq i64 %2, 0 ; <i1> [#uses=1]
|
||||
br i1 %3, label %bb52.bb55_crit_edge.exitStub, label %bb52.bb53_crit_edge.exitStub
|
||||
}
|
Loading…
Reference in New Issue
Block a user