Skip to content

Commit

Permalink
Revert "[CGP] Split some critical edges coming out of indirect branches"
Browse files Browse the repository at this point in the history
This reverts commit r296149 as it leads to crashes when compiling for
PPC.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296295 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
djasper-gh committed Feb 26, 2017
1 parent 1aaf55c commit e5e8f2a
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 435 deletions.
155 changes: 0 additions & 155 deletions lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@

#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
Expand Down Expand Up @@ -55,10 +53,8 @@
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
#include "llvm/Transforms/Utils/BypassSlowDivision.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SimplifyLibCalls.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;
using namespace llvm::PatternMatch;

Expand Down Expand Up @@ -226,7 +222,6 @@ class TypePromotionTransaction;
unsigned CreatedInstCost);
bool splitBranchCondition(Function &F);
bool simplifyOffsetableRelocate(Instruction &I);
bool splitIndirectCriticalEdges(Function &F);
};
}

Expand Down Expand Up @@ -301,10 +296,6 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
if (!DisableBranchOpts)
EverMadeChange |= splitBranchCondition(F);

// Split some critical edges where one of the sources is an indirect branch,
// to help generate sane code for PHIs involving such edges.
EverMadeChange |= splitIndirectCriticalEdges(F);

bool MadeChange = true;
while (MadeChange) {
MadeChange = false;
Expand Down Expand Up @@ -438,152 +429,6 @@ BasicBlock *CodeGenPrepare::findDestBlockOfMergeableEmptyBlock(BasicBlock *BB) {
return DestBB;
}

// Return the unique indirectbr predecessor of a block. This may return null
// even if such a predecessor exists, if it's not useful for splitting.
// If a predecessor is found, OtherPreds will contain all other (non-indirectbr)
// predecessors of BB.
static BasicBlock *
findIBRPredecessor(BasicBlock *BB, SmallVectorImpl<BasicBlock *> &OtherPreds) {
// If the block doesn't have any PHIs, we don't care about it, since there's
// no point in splitting it.
PHINode *PN = dyn_cast<PHINode>(BB->begin());
if (!PN)
return nullptr;

// Verify we have exactly one IBR predecessor.
// Conservatively bail out if one of the other predecessors is not a "regular"
// terminator (that is, not a switch or a br).
BasicBlock *IBB = nullptr;
for (unsigned Pred = 0, E = PN->getNumIncomingValues(); Pred != E; ++Pred) {
BasicBlock *PredBB = PN->getIncomingBlock(Pred);
TerminatorInst *PredTerm = PredBB->getTerminator();
switch (PredTerm->getOpcode()) {
case Instruction::IndirectBr:
if (IBB)
return nullptr;
IBB = PredBB;
break;
case Instruction::Br:
case Instruction::Switch:
OtherPreds.push_back(PredBB);
continue;
default:
return nullptr;
}
}

return IBB;
}

// Split critical edges where the source of the edge is an indirectbr
// instruction. This isn't always possible, but we can handle some easy cases.
// This is useful because MI is unable to split such critical edges,
// which means it will not be able to sink instructions along those edges.
// This is especially painful for indirect branches with many successors, where
// we end up having to prepare all outgoing values in the origin block.
//
// Our normal algorithm for splitting critical edges requires us to update
// the outgoing edges of the edge origin block, but for an indirectbr this
// is hard, since it would require finding and updating the block addresses
// the indirect branch uses. But if a block only has a single indirectbr
// predecessor, with the others being regular branches, we can do it in a
// different way.
// Say we have A -> D, B -> D, I -> D where only I -> D is an indirectbr.
// We can split D into D0 and D1, where D0 contains only the PHIs from D,
// and D1 is the D block body. We can then duplicate D0 as D0A and D0B, and
// create the following structure:
// A -> D0A, B -> D0A, I -> D0B, D0A -> D1, D0B -> D1
bool CodeGenPrepare::splitIndirectCriticalEdges(Function &F) {
// Check whether the function has any indirectbrs, and collect which blocks
// they may jump to. Since most functions don't have indirect branches,
// this lowers the common case's overhead to O(Blocks) instead of O(Edges).
SmallSetVector<BasicBlock *, 16> Targets;
for (auto &BB : F) {
auto *IBI = dyn_cast<IndirectBrInst>(BB.getTerminator());
if (!IBI)
continue;

for (unsigned Succ = 0, E = IBI->getNumSuccessors(); Succ != E; ++Succ)
Targets.insert(IBI->getSuccessor(Succ));
}

if (Targets.empty())
return false;

bool Changed = false;
for (BasicBlock *Target : Targets) {
SmallVector<BasicBlock *, 16> OtherPreds;
BasicBlock *IBRPred = findIBRPredecessor(Target, OtherPreds);
if (!IBRPred)
continue;

// Don't even think about ehpads/landingpads.
Instruction *FirstNonPHI = Target->getFirstNonPHI();
if (FirstNonPHI->isEHPad() || Target->isLandingPad())
continue;

BasicBlock *BodyBlock = Target->splitBasicBlock(FirstNonPHI, ".split");
// It's possible Target was its own successor through an indirectbr.
// In this case, the indirectbr now comes from BodyBlock.
if (IBRPred == Target)
IBRPred = BodyBlock;

// At this point Target only has PHIs, and BodyBlock has the rest of the
// block's body. Create a copy of Target that will be used by the "direct"
// preds.
ValueToValueMapTy VMap;
BasicBlock *DirectSucc = CloneBasicBlock(Target, VMap, ".clone", &F);

for (BasicBlock *Pred : OtherPreds)
Pred->getTerminator()->replaceUsesOfWith(Target, DirectSucc);

// Ok, now fix up the PHIs. We know the two blocks only have PHIs, and that
// they are clones, so the number of PHIs are the same.
// (a) Remove the edge coming from IBRPred from the "Direct" PHI
// (b) Leave that as the only edge in the "Indirect" PHI.
// (c) Merge the two in the body block.
BasicBlock::iterator Indirect = Target->begin(),
End = Target->getFirstNonPHI()->getIterator();
BasicBlock::iterator Direct = DirectSucc->begin();
BasicBlock::iterator MergeInsert = BodyBlock->getFirstInsertionPt();

assert(&*End == Target->getTerminator() &&
"Block was expected to only contain PHIs");

while (Indirect != End) {
PHINode *DirPHI = cast<PHINode>(Direct);
PHINode *IndPHI = cast<PHINode>(Indirect);

// Now, clean up - the direct block shouldn't get the indirect value,
// and vice versa.
DirPHI->removeIncomingValue(IBRPred);
Direct++;

// Advance the pointer here, to avoid invalidation issues when the old
// PHI is erased.
Indirect++;

PHINode *NewIndPHI = PHINode::Create(IndPHI->getType(), 1, "ind", IndPHI);
NewIndPHI->addIncoming(IndPHI->getIncomingValueForBlock(IBRPred),
IBRPred);

// Create a PHI in the body block, to merge the direct and indirect
// predecessors.
PHINode *MergePHI =
PHINode::Create(IndPHI->getType(), 2, "merge", &*MergeInsert);
MergePHI->addIncoming(NewIndPHI, Target);
MergePHI->addIncoming(DirPHI, DirectSucc);

IndPHI->replaceAllUsesWith(MergePHI);
IndPHI->eraseFromParent();
}

Changed = true;
}

return Changed;
}

/// Eliminate blocks that contain only PHI nodes, debug info directives, and an
/// unconditional branch. Passes before isel (e.g. LSR/loopsimplify) often split
/// edges in ways that are non-optimal for isel. Start by eliminating these
Expand Down
1 change: 0 additions & 1 deletion test/CodeGen/ARM/indirectbr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ L3: ; preds = %L4, %bb2
br label %L2

L2: ; preds = %L3, %bb2
; THUMB-LABEL: %L1.clone
; THUMB: muls
%res.2 = phi i32 [ %res.1, %L3 ], [ 1, %bb2 ] ; <i32> [#uses=1]
%phitmp = mul i32 %res.2, 6 ; <i32> [#uses=1]
Expand Down
2 changes: 1 addition & 1 deletion test/CodeGen/MSP430/indirectbr2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ define internal i16 @foo(i16 %i) nounwind {
entry:
%tmp1 = getelementptr inbounds [5 x i8*], [5 x i8*]* @C.0.2070, i16 0, i16 %i ; <i8**> [#uses=1]
%gotovar.4.0 = load i8*, i8** %tmp1, align 4 ; <i8*> [#uses=1]
; CHECK: br .LC.0.2070(r15)
; CHECK: br .LC.0.2070(r12)
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]

L5: ; preds = %bb2
Expand Down
36 changes: 12 additions & 24 deletions test/CodeGen/PowerPC/indirectbr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,23 @@ entry:
bb2: ; preds = %entry, %bb3
%gotovar.4.0 = phi i8* [ %gotovar.4.0.pre, %bb3 ], [ %0, %entry ] ; <i8*> [#uses=1]
; PIC: mtctr
; PIC-NEXT: li
; PIC-NEXT: li
; PIC-NEXT: li
; PIC-NEXT: li
; PIC-NEXT: bctr
; PIC: li
; PIC: b LBB
; PIC: li
; PIC: b LBB
; PIC: li
; PIC: b LBB
; PIC: li
; PIC: b LBB
; STATIC: mtctr
; STATIC-NEXT: li
; STATIC-NEXT: li
; STATIC-NEXT: li
; STATIC-NEXT: li
; STATIC-NEXT: bctr
; STATIC: li
; STATIC: b LBB
; STATIC: li
; STATIC: b LBB
; STATIC: li
; STATIC: b LBB
; STATIC: li
; STATIC: b LBB
; PPC64: mtctr
; PPC64-NEXT: li
; PPC64-NEXT: li
; PPC64-NEXT: li
; PPC64-NEXT: li
; PPC64-NEXT: bctr
; PPC64: li
; PPC64: b LBB
; PPC64: li
; PPC64: b LBB
; PPC64: li
; PPC64: b LBB
; PPC64: li
; PPC64: b LBB
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]

bb3: ; preds = %entry
Expand Down
Loading

0 comments on commit e5e8f2a

Please sign in to comment.