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:
Evan Cheng
2009-09-04 07:47:40 +00:00
parent e93909185f
commit 030a0a0cdb
5 changed files with 188 additions and 85 deletions

View File

@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#define DEBUG_TYPE "branchfolding" #define DEBUG_TYPE "branchfolding"
#include "BranchFolding.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.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::desc("Max number of predecessors to consider tail merging"),
cl::init(150), cl::Hidden); 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); char BranchFolderPass::ID = 0;
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;
}
FunctionPass *llvm::createBranchFoldingPass(bool DefaultEnableTailMerge) { 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 /// RemoveDeadBlock - Remove the specified dead machine basic block from the
@ -149,7 +114,7 @@ bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) {
break; break;
unsigned Reg = I->getOperand(0).getReg(); unsigned Reg = I->getOperand(0).getReg();
ImpDefRegs.insert(Reg); ImpDefRegs.insert(Reg);
for (const unsigned *SubRegs = RegInfo->getSubRegisters(Reg); for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) unsigned SubReg = *SubRegs; ++SubRegs)
ImpDefRegs.insert(SubReg); ImpDefRegs.insert(SubReg);
++I; ++I;
@ -183,32 +148,37 @@ bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) {
return true; return true;
} }
bool BranchFolder::runOnMachineFunction(MachineFunction &MF) { /// OptimizeFunction - Perhaps branch folding, tail merging and other
TII = MF.getTarget().getInstrInfo(); /// CFG optimizations on the given function.
if (!TII) return false; 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. // 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++) { for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; I++) {
MachineBasicBlock *MBB = I, *TBB = 0, *FBB = 0; MachineBasicBlock *MBB = I, *TBB = 0, *FBB = 0;
SmallVector<MachineOperand, 4> Cond; SmallVector<MachineOperand, 4> Cond;
if (!TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, true)) if (!TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, true))
EverMadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); MadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty());
EverMadeChange |= OptimizeImpDefsBlock(MBB); MadeChange |= OptimizeImpDefsBlock(MBB);
} }
RS = RegInfo->requiresRegisterScavenging(MF) ? new RegScavenger() : NULL;
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
bool MadeChangeThisIteration = true; bool MadeChangeThisIteration = true;
while (MadeChangeThisIteration) { while (MadeChangeThisIteration) {
MadeChangeThisIteration = false; MadeChangeThisIteration = false;
MadeChangeThisIteration |= TailMergeBlocks(MF); MadeChangeThisIteration |= TailMergeBlocks(MF);
MadeChangeThisIteration |= OptimizeBranches(MF); MadeChangeThisIteration |= OptimizeBranches(MF);
EverMadeChange |= MadeChangeThisIteration; MadeChange |= MadeChangeThisIteration;
} }
// See if any jump tables have become mergable or dead as the code generator // 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 // Scan the jump tables, seeing if there are any duplicates. Note that this
// is N^2, which should be fixed someday. // is N^2, which should be fixed someday.
for (unsigned i = 1, e = JTs.size(); i != e; ++i) for (unsigned i = 1, e = JTs.size(); i != e; ++i) {
JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs)); 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 // 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 // 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) for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i)
if (!JTIsLive.test(i)) { if (!JTIsLive.test(i)) {
JTI->RemoveJumpTable(i); JTI->RemoveJumpTable(i);
EverMadeChange = true; MadeChange = true;
} }
} }
delete RS; delete RS;
return EverMadeChange; return MadeChange;
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -398,9 +372,9 @@ MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB,
RS->enterBasicBlock(&CurMBB); RS->enterBasicBlock(&CurMBB);
if (!CurMBB.empty()) if (!CurMBB.empty())
RS->forward(prior(CurMBB.end())); RS->forward(prior(CurMBB.end()));
BitVector RegsLiveAtExit(RegInfo->getNumRegs()); BitVector RegsLiveAtExit(TRI->getNumRegs());
RS->getRegsUsed(RegsLiveAtExit, false); 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]) if (RegsLiveAtExit[i])
NewMBB->addLiveIn(i); NewMBB->addLiveIn(i);
} }
@ -593,11 +567,12 @@ unsigned BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB,
bool BranchFolder::TryMergeBlocks(MachineBasicBlock *SuccBB, bool BranchFolder::TryMergeBlocks(MachineBasicBlock *SuccBB,
MachineBasicBlock* PredBB) { MachineBasicBlock* PredBB) {
bool MadeChange = false;
// It doesn't make sense to save a single instruction since tail merging // It doesn't make sense to save a single instruction since tail merging
// will add a jump. // will add a jump.
// FIXME: Ask the target to provide the threshold? // FIXME: Ask the target to provide the threshold?
unsigned minCommonTailLength = (SuccBB ? 1 : 2) + 1; unsigned minCommonTailLength = (SuccBB ? 1 : 2) + 1;
MadeChange = false;
DEBUG(errs() << "\nTryMergeBlocks " << MergePotentials.size() << '\n'); DEBUG(errs() << "\nTryMergeBlocks " << MergePotentials.size() << '\n');
@ -668,7 +643,7 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
if (!EnableTailMerge) return false; if (!EnableTailMerge) return false;
MadeChange = false; bool MadeChange = false;
// First find blocks with no successors. // First find blocks with no successors.
MergePotentials.clear(); MergePotentials.clear();
@ -779,14 +754,14 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
bool BranchFolder::OptimizeBranches(MachineFunction &MF) { bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
MadeChange = false; bool MadeChange = false;
// Make sure blocks are numbered in order // Make sure blocks are numbered in order
MF.RenumberBlocks(); MF.RenumberBlocks();
for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) {
MachineBasicBlock *MBB = I++; MachineBasicBlock *MBB = I++;
OptimizeBlock(MBB); MadeChange |= OptimizeBlock(MBB);
// If it is dead, remove it. // If it is dead, remove it.
if (MBB->pred_empty()) { if (MBB->pred_empty()) {
@ -880,7 +855,9 @@ static bool IsBetterFallthrough(MachineBasicBlock *MBB1,
/// OptimizeBlock - Analyze and optimize control flow related to the specified /// OptimizeBlock - Analyze and optimize control flow related to the specified
/// block. This is never called on the entry block. /// 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; MachineFunction::iterator FallThrough = MBB;
++FallThrough; ++FallThrough;
@ -889,7 +866,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
// points to this block. // points to this block.
if (MBB->empty() && !MBB->isLandingPad()) { if (MBB->empty() && !MBB->isLandingPad()) {
// Dead block? Leave for cleanup later. // Dead block? Leave for cleanup later.
if (MBB->pred_empty()) return; if (MBB->pred_empty()) return MadeChange;
if (FallThrough == MBB->getParent()->end()) { if (FallThrough == MBB->getParent()->end()) {
// TODO: Simplify preds to not branch here if possible! // TODO: Simplify preds to not branch here if possible!
@ -906,7 +883,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
ReplaceMBBInJumpTables(MBB, FallThrough); ReplaceMBBInJumpTables(MBB, FallThrough);
MadeChange = true; MadeChange = true;
} }
return; return MadeChange;
} }
// Check to see if we can simplify the terminator of the block before this // 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()); MBB->moveAfter(--MBB->getParent()->end());
MadeChange = true; MadeChange = true;
++NumBranchOpts; ++NumBranchOpts;
return; return MadeChange;
} }
} }
} }
@ -1122,7 +1099,7 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
if (DidChange) { if (DidChange) {
++NumBranchOpts; ++NumBranchOpts;
MadeChange = true; MadeChange = true;
if (!HasBranchToSelf) return; if (!HasBranchToSelf) return MadeChange;
} }
} }
} }
@ -1203,8 +1180,10 @@ void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
PrevBB.isSuccessor(FallThrough)) { PrevBB.isSuccessor(FallThrough)) {
MBB->moveAfter(--MBB->getParent()->end()); MBB->moveAfter(--MBB->getParent()->end());
MadeChange = true; MadeChange = true;
return; return MadeChange;
} }
} }
} }
return MadeChange;
} }

View 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 */

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#define DEBUG_TYPE "ifcvt" #define DEBUG_TYPE "ifcvt"
#include "BranchFolding.h"
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h"
@ -360,6 +361,13 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
Roots.clear(); Roots.clear();
BBAnalysis.clear(); BBAnalysis.clear();
if (MadeChange) {
BranchFolder BF(false);
BF.OptimizeFunction(MF, TII,
MF.getTarget().getRegisterInfo(),
getAnalysisIfAvailable<MachineModuleInfo>());
}
return MadeChange; return MadeChange;
} }

View File

@ -31,7 +31,7 @@ entry:
; CHECK: CountTree: ; CHECK: CountTree:
; CHECK: it eq ; CHECK: it eq
; CHECK: cmpeq ; CHECK: cmpeq
; CHECK: beq ; CHECK: bne
; CHECK: itt eq ; CHECK: itt eq
; CHECK: moveq ; CHECK: moveq
; CHECK: popeq ; CHECK: popeq

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