summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/BranchFolding.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-10-04 02:22:52 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-10-04 02:22:52 +0000
commit161935520d5a9cd1fcaddee39bb8438bcfec5552 (patch)
tree63b25b0718d66c622eb27efa8213105ef4e984fc /llvm/lib/CodeGen/BranchFolding.cpp
parent65b9056f3dbba45ffd16d780b058a3d044115a59 (diff)
downloadbcm5719-llvm-161935520d5a9cd1fcaddee39bb8438bcfec5552.tar.gz
bcm5719-llvm-161935520d5a9cd1fcaddee39bb8438bcfec5552.zip
[WinEH] Permit branch folding in the face of funclets
Track which basic blocks belong to which funclets. Permit branch folding to fire but only if it can prove that doing so will not cause code in one funclet to be reused in another. llvm-svn: 249257
Diffstat (limited to 'llvm/lib/CodeGen/BranchFolding.cpp')
-rw-r--r--llvm/lib/CodeGen/BranchFolding.cpp58
1 files changed, 45 insertions, 13 deletions
diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp
index 2cc851f3973..64b0df28100 100644
--- a/llvm/lib/CodeGen/BranchFolding.cpp
+++ b/llvm/lib/CodeGen/BranchFolding.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -94,10 +95,8 @@ bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) {
TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
// TailMerge can create jump into if branches that make CFG irreducible for
- // HW that requires structurized CFG. It can also cause BBs to get shared
- // between funclets.
+ // HW that requires structurized CFG.
bool EnableTailMerge = !MF.getTarget().requiresStructuredCFG() &&
- !MF.getMMI().hasEHFunclets() &&
PassConfig->getEnableTailMerge();
BranchFolder Folder(EnableTailMerge, /*CommonHoist=*/true,
getAnalysis<MachineBlockFrequencyInfo>(),
@@ -135,6 +134,7 @@ void BranchFolder::RemoveDeadBlock(MachineBasicBlock *MBB) {
// Remove the block.
MF->erase(MBB);
+ FuncletMembership.erase(MBB);
}
/// OptimizeImpDefsBlock - If a basic block is just a bunch of implicit_def
@@ -222,6 +222,9 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF,
MadeChange |= OptimizeImpDefsBlock(&MBB);
}
+ // Recalculate funclet membership.
+ FuncletMembership = getFuncletMembership(MF);
+
bool MadeChangeThisIteration = true;
while (MadeChangeThisIteration) {
MadeChangeThisIteration = TailMergeBlocks(MF);
@@ -448,6 +451,11 @@ MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB,
// For targets that use the register scavenger, we must maintain LiveIns.
MaintainLiveIns(&CurMBB, NewMBB);
+ // Add the new block to the funclet.
+ const auto &FuncletI = FuncletMembership.find(&CurMBB);
+ if (FuncletI != FuncletMembership.end())
+ FuncletMembership[NewMBB] = FuncletI->second;
+
return NewMBB;
}
@@ -552,14 +560,23 @@ static unsigned CountTerminators(MachineBasicBlock *MBB,
/// and decide if it would be profitable to merge those tails. Return the
/// length of the common tail and iterators to the first common instruction
/// in each block.
-static bool ProfitableToMerge(MachineBasicBlock *MBB1,
- MachineBasicBlock *MBB2,
- unsigned minCommonTailLength,
- unsigned &CommonTailLen,
- MachineBasicBlock::iterator &I1,
- MachineBasicBlock::iterator &I2,
- MachineBasicBlock *SuccBB,
- MachineBasicBlock *PredBB) {
+static bool
+ProfitableToMerge(MachineBasicBlock *MBB1, MachineBasicBlock *MBB2,
+ unsigned minCommonTailLength, unsigned &CommonTailLen,
+ MachineBasicBlock::iterator &I1,
+ MachineBasicBlock::iterator &I2, MachineBasicBlock *SuccBB,
+ MachineBasicBlock *PredBB,
+ DenseMap<const MachineBasicBlock *, int> &FuncletMembership) {
+ // It is never profitable to tail-merge blocks from two different funclets.
+ if (!FuncletMembership.empty()) {
+ auto Funclet1 = FuncletMembership.find(MBB1);
+ assert(Funclet1 != FuncletMembership.end());
+ auto Funclet2 = FuncletMembership.find(MBB2);
+ assert(Funclet2 != FuncletMembership.end());
+ if (Funclet1->second != Funclet2->second)
+ return false;
+ }
+
CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2);
if (CommonTailLen == 0)
return false;
@@ -636,7 +653,8 @@ unsigned BranchFolder::ComputeSameTails(unsigned CurHash,
if (ProfitableToMerge(CurMPIter->getBlock(), I->getBlock(),
minCommonTailLength,
CommonTailLen, TrialBBI1, TrialBBI2,
- SuccBB, PredBB)) {
+ SuccBB, PredBB,
+ FuncletMembership)) {
if (CommonTailLen > maxCommonTailLength) {
SameTails.clear();
maxCommonTailLength = CommonTailLen;
@@ -1099,6 +1117,8 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
// Make sure blocks are numbered in order
MF.RenumberBlocks();
+ // Renumbering blocks alters funclet membership, recalculate it.
+ FuncletMembership = getFuncletMembership(MF);
for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end();
I != E; ) {
@@ -1112,6 +1132,7 @@ bool BranchFolder::OptimizeBranches(MachineFunction &MF) {
++NumDeadBlocks;
}
}
+
return MadeChange;
}
@@ -1171,11 +1192,22 @@ ReoptimizeBlock:
MachineFunction::iterator FallThrough = MBB;
++FallThrough;
+ // Make sure MBB and FallThrough belong to the same funclet.
+ bool SameFunclet = true;
+ if (!FuncletMembership.empty() && FallThrough != MF.end()) {
+ auto MBBFunclet = FuncletMembership.find(MBB);
+ assert(MBBFunclet != FuncletMembership.end());
+ auto FallThroughFunclet = FuncletMembership.find(FallThrough);
+ assert(FallThroughFunclet != FuncletMembership.end());
+ SameFunclet = MBBFunclet->second == FallThroughFunclet->second;
+ }
+
// If this block is empty, make everyone use its fall-through, not the block
// explicitly. Landing pads should not do this since the landing-pad table
// points to this block. Blocks with their addresses taken shouldn't be
// optimized away.
- if (IsEmptyBlock(MBB) && !MBB->isEHPad() && !MBB->hasAddressTaken()) {
+ if (IsEmptyBlock(MBB) && !MBB->isEHPad() && !MBB->hasAddressTaken() &&
+ SameFunclet) {
// Dead block? Leave for cleanup later.
if (MBB->pred_empty()) return MadeChange;
OpenPOWER on IntegriCloud