mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-02 20:38:34 +00:00
Implement SimplifyCFG/branch-phi-thread.ll, the most trivial case of threading
control across branches with determined outcomes. More generality to follow. This triggers a couple thousand times in specint. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23391 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b6e2b7e4cd
commit
eaba3a194c
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/Type.h"
|
#include "llvm/Type.h"
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -889,6 +890,70 @@ HoistTerminator:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FoldCondBranchOnPHI - If we have a conditional branch on a PHI node value
|
||||||
|
/// that is defined in the same block as the branch and if any PHI entries are
|
||||||
|
/// constants, thread edges corresponding to that entry to be branches to their
|
||||||
|
/// ultimate destination.
|
||||||
|
static bool FoldCondBranchOnPHI(BranchInst *BI) {
|
||||||
|
BasicBlock *BB = BI->getParent();
|
||||||
|
PHINode *PN = dyn_cast<PHINode>(BI->getCondition());
|
||||||
|
if (!PN || PN->getParent() != BB) return false;
|
||||||
|
|
||||||
|
// Degenerate case of a single entry PHI.
|
||||||
|
if (PN->getNumIncomingValues() == 1) {
|
||||||
|
if (PN->getIncomingValue(0) != PN)
|
||||||
|
PN->replaceAllUsesWith(PN->getIncomingValue(0));
|
||||||
|
else
|
||||||
|
PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
|
||||||
|
PN->eraseFromParent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we know that this block has multiple preds and two succs.
|
||||||
|
|
||||||
|
// If this basic block contains anything other than the PHI and branch, bail
|
||||||
|
// out. FIXME: improve this in the future.
|
||||||
|
BasicBlock::iterator BBI = BB->begin();
|
||||||
|
if (&*BBI != PN || &*++BBI != BI)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Okay, this is a simple enough basic block. See if any phi values are
|
||||||
|
// constants.
|
||||||
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
||||||
|
if (ConstantBool *CB = dyn_cast<ConstantBool>(PN->getIncomingValue(i))) {
|
||||||
|
// Okay, we now know that all edges from PredBB should be revectored to
|
||||||
|
// branch to RealDest.
|
||||||
|
BasicBlock *PredBB = PN->getIncomingBlock(i);
|
||||||
|
BasicBlock *RealDest = BI->getSuccessor(!CB->getValue());
|
||||||
|
|
||||||
|
// If there are PHI nodes in the destination block, we have to add an
|
||||||
|
// entry for PredBB. Instead of being smart about this, just split the
|
||||||
|
// critical edge, which will eliminate the PHI-ness.
|
||||||
|
if (isa<PHINode>(RealDest->begin())) {
|
||||||
|
SplitCriticalEdge(BI, !CB->getValue());
|
||||||
|
RealDest = BI->getSuccessor(!CB->getValue());
|
||||||
|
}
|
||||||
|
assert(!isa<PHINode>(RealDest->begin()) && "Crit edge split failure!");
|
||||||
|
|
||||||
|
// Loop over all of the edges from PredBB to BB, changing them to branch
|
||||||
|
// to RealDest instead.
|
||||||
|
TerminatorInst *PredBBTI = PredBB->getTerminator();
|
||||||
|
for (unsigned i = 0, e = PredBBTI->getNumSuccessors(); i != e; ++i)
|
||||||
|
if (PredBBTI->getSuccessor(i) == BB) {
|
||||||
|
BB->removePredecessor(PredBB);
|
||||||
|
PredBBTI->setSuccessor(i, RealDest);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << *BB;
|
||||||
|
|
||||||
|
// Recurse, simplifying any other constants.
|
||||||
|
return FoldCondBranchOnPHI(BI) | true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// ConstantIntOrdering - This class implements a stable ordering of constant
|
/// ConstantIntOrdering - This class implements a stable ordering of constant
|
||||||
/// integers that does not depend on their address. This is important for
|
/// integers that does not depend on their address. This is important for
|
||||||
@ -1144,6 +1209,14 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
|||||||
if (FoldValueComparisonIntoPredecessors(BI))
|
if (FoldValueComparisonIntoPredecessors(BI))
|
||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a branch on a phi node in the current block, thread control
|
||||||
|
// through this block if any PHI node entries are constants.
|
||||||
|
if (PHINode *PN = dyn_cast<PHINode>(BI->getCondition()))
|
||||||
|
if (PN->getParent() == BI->getParent())
|
||||||
|
if (FoldCondBranchOnPHI(BI))
|
||||||
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
|
|
||||||
// If this basic block is ONLY a setcc and a branch, and if a predecessor
|
// If this basic block is ONLY a setcc and a branch, and if a predecessor
|
||||||
// branches to us and one of our successors, fold the setcc into the
|
// branches to us and one of our successors, fold the setcc into the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user