mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 04:29:21 +00:00
a new simple pass, which will be extended to be more useful in the future.
This pass forward branches through conditions when it can show that the conditions is either always true or false for a predecessor. This currently only handles the most simple cases of this, but is successful at threading across 2489 branches and 65 switch instructions in 176.gcc, which isn't bad. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21306 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
73459d097b
commit
36d12733bb
213
lib/Transforms/Scalar/CondPropagate.cpp
Normal file
213
lib/Transforms/Scalar/CondPropagate.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
//===-- CondPropagate.cpp - Propagate Conditional Expressions -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass propagates information about conditional expressions through the
|
||||
// program, allowing it to eliminate conditional branches in some cases.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "condprop"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
Statistic<>
|
||||
NumBrThread("condprop", "Number of CFG edges threaded through branches");
|
||||
Statistic<>
|
||||
NumSwThread("condprop", "Number of CFG edges threaded through switches");
|
||||
|
||||
struct CondProp : public FunctionPass {
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequiredID(BreakCriticalEdgesID);
|
||||
//AU.addRequired<DominanceFrontier>();
|
||||
}
|
||||
|
||||
private:
|
||||
bool MadeChange;
|
||||
void SimplifyBlock(BasicBlock *BB);
|
||||
void SimplifyPredecessors(BranchInst *BI);
|
||||
void SimplifyPredecessors(SwitchInst *SI);
|
||||
void RevectorBlockTo(BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
};
|
||||
RegisterOpt<CondProp> X("condprop", "Conditional Propagation");
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createCondPropagationPass() {
|
||||
return new CondProp();
|
||||
}
|
||||
|
||||
bool CondProp::runOnFunction(Function &F) {
|
||||
bool EverMadeChange = false;
|
||||
|
||||
// While we are simplifying blocks, keep iterating.
|
||||
do {
|
||||
MadeChange = false;
|
||||
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
|
||||
SimplifyBlock(BB);
|
||||
EverMadeChange = MadeChange;
|
||||
} while (MadeChange);
|
||||
return EverMadeChange;
|
||||
}
|
||||
|
||||
void CondProp::SimplifyBlock(BasicBlock *BB) {
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
|
||||
// If this is a conditional branch based on a phi node that is defined in
|
||||
// this block, see if we can simplify predecessors of this block.
|
||||
if (BI->isConditional() && isa<PHINode>(BI->getCondition()) &&
|
||||
cast<PHINode>(BI->getCondition())->getParent() == BB)
|
||||
SimplifyPredecessors(BI);
|
||||
|
||||
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|
||||
if (isa<PHINode>(SI->getCondition()) &&
|
||||
cast<PHINode>(SI->getCondition())->getParent() == BB)
|
||||
SimplifyPredecessors(SI);
|
||||
}
|
||||
|
||||
// See if we can fold any PHI nodes in this block now.
|
||||
// FIXME: This would not be required if removePredecessor did this for us!!
|
||||
PHINode *PN;
|
||||
for (BasicBlock::iterator I = BB->begin(); PN = dyn_cast<PHINode>(I++); )
|
||||
if (Value *PNV = hasConstantValue(PN))
|
||||
if (!isa<Instruction>(PNV)) {
|
||||
PN->replaceAllUsesWith(PNV);
|
||||
PN->eraseFromParent();
|
||||
MadeChange = true;
|
||||
}
|
||||
|
||||
// If possible, simplify the terminator of this block.
|
||||
if (ConstantFoldTerminator(BB))
|
||||
MadeChange = true;
|
||||
|
||||
// If this block ends with an unconditional branch and the only successor has
|
||||
// only this block as a predecessor, merge the two blocks together.
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator()))
|
||||
if (BI->isUnconditional() && BI->getSuccessor(0)->getSinglePredecessor()) {
|
||||
BasicBlock *Succ = BI->getSuccessor(0);
|
||||
// Remove BI.
|
||||
BI->eraseFromParent();
|
||||
|
||||
// Move over all of the instructions.
|
||||
BB->getInstList().splice(BB->end(), Succ->getInstList());
|
||||
|
||||
// Any phi nodes that had entries for Succ now have entries from BB.
|
||||
Succ->replaceAllUsesWith(BB);
|
||||
|
||||
// Succ is now dead, but we cannot delete it without potentially
|
||||
// invalidating iterators elsewhere. Just insert an unreachable
|
||||
// instruction in it.
|
||||
new UnreachableInst(Succ);
|
||||
MadeChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
// SimplifyPredecessors(branches) - We know that BI is a conditional branch
|
||||
// based on a PHI node defined in this block. If the phi node contains constant
|
||||
// operands, then the blocks corresponding to those operands can be modified to
|
||||
// jump directly to the destination instead of going through this block.
|
||||
void CondProp::SimplifyPredecessors(BranchInst *BI) {
|
||||
// TODO: We currently only handle the most trival case, where the PHI node has
|
||||
// one use (the branch), and is the only instruction besides the branch in the
|
||||
// block.
|
||||
PHINode *PN = cast<PHINode>(BI->getCondition());
|
||||
if (!PN->hasOneUse()) return;
|
||||
|
||||
BasicBlock *BB = BI->getParent();
|
||||
if (&*BB->begin() != PN || &*next(BB->begin()) != BI)
|
||||
return;
|
||||
|
||||
// Ok, we have this really simple case, walk the PHI operands, looking for
|
||||
// constants. Walk from the end to remove operands from the end when
|
||||
// possible, and to avoid invalidating "i".
|
||||
for (unsigned i = PN->getNumIncomingValues(); i != 0; --i)
|
||||
if (ConstantBool *CB = dyn_cast<ConstantBool>(PN->getIncomingValue(i-1))) {
|
||||
// If we have a constant, forward the edge from its current to its
|
||||
// ultimate destination.
|
||||
bool PHIGone = PN->getNumIncomingValues() == 2;
|
||||
RevectorBlockTo(PN->getIncomingBlock(i-1),
|
||||
BI->getSuccessor(CB->getValue() == 0));
|
||||
++NumBrThread;
|
||||
|
||||
// If there were two predecessors before this simplification, the PHI node
|
||||
// will be deleted. Don't iterate through it the last time.
|
||||
if (PHIGone) return;
|
||||
}
|
||||
}
|
||||
|
||||
// SimplifyPredecessors(switch) - We know that SI is switch based on a PHI node
|
||||
// defined in this block. If the phi node contains constant operands, then the
|
||||
// blocks corresponding to those operands can be modified to jump directly to
|
||||
// the destination instead of going through this block.
|
||||
void CondProp::SimplifyPredecessors(SwitchInst *SI) {
|
||||
// TODO: We currently only handle the most trival case, where the PHI node has
|
||||
// one use (the branch), and is the only instruction besides the branch in the
|
||||
// block.
|
||||
PHINode *PN = cast<PHINode>(SI->getCondition());
|
||||
if (!PN->hasOneUse()) return;
|
||||
|
||||
BasicBlock *BB = SI->getParent();
|
||||
if (&*BB->begin() != PN || &*next(BB->begin()) != SI)
|
||||
return;
|
||||
|
||||
bool RemovedPreds = false;
|
||||
|
||||
// Ok, we have this really simple case, walk the PHI operands, looking for
|
||||
// constants. Walk from the end to remove operands from the end when
|
||||
// possible, and to avoid invalidating "i".
|
||||
for (unsigned i = PN->getNumIncomingValues(); i != 0; --i)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(PN->getIncomingValue(i-1))) {
|
||||
// If we have a constant, forward the edge from its current to its
|
||||
// ultimate destination.
|
||||
bool PHIGone = PN->getNumIncomingValues() == 2;
|
||||
unsigned DestCase = SI->findCaseValue(CI);
|
||||
RevectorBlockTo(PN->getIncomingBlock(i-1),
|
||||
SI->getSuccessor(DestCase));
|
||||
++NumSwThread;
|
||||
RemovedPreds = true;
|
||||
|
||||
// If there were two predecessors before this simplification, the PHI node
|
||||
// will be deleted. Don't iterate through it the last time.
|
||||
if (PHIGone) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// RevectorBlockTo - Revector the unconditional branch at the end of FromBB to
|
||||
// the ToBB block, which is one of the successors of its current successor.
|
||||
void CondProp::RevectorBlockTo(BasicBlock *FromBB, BasicBlock *ToBB) {
|
||||
BranchInst *FromBr = cast<BranchInst>(FromBB->getTerminator());
|
||||
assert(FromBr->isUnconditional() && "FromBB should end with uncond br!");
|
||||
|
||||
// Get the old block we are threading through.
|
||||
BasicBlock *OldSucc = FromBr->getSuccessor(0);
|
||||
|
||||
// ToBB should not have any PHI nodes in it to update, because OldSucc had
|
||||
// multiple successors. If OldSucc had multiple successor and ToBB had
|
||||
// multiple predecessors, the edge between them would be critical, which we
|
||||
// already took care of.
|
||||
assert(!isa<PHINode>(ToBB->begin()) && "Critical Edge Found!");
|
||||
|
||||
// Update PHI nodes in OldSucc to know that FromBB no longer branches to it.
|
||||
OldSucc->removePredecessor(FromBB);
|
||||
|
||||
// Change FromBr to branch to the new destination.
|
||||
FromBr->setSuccessor(0, ToBB);
|
||||
|
||||
MadeChange = true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user