mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 04:38:24 +00:00
Revert commit r207302 since build failures
have been reported. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207303 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -127,15 +127,7 @@ bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|||||||
++NumSimplified;
|
++NumSimplified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool res = RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
|
LocalChanged |= RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
|
||||||
if (res) {
|
|
||||||
// RecursivelyDeleteTriviallyDeadInstruction can remove
|
|
||||||
// more than one instruction, so simply incrementing the
|
|
||||||
// iterator does not work. When instructions get deleted
|
|
||||||
// re-iterate instead.
|
|
||||||
BI = BB->begin(); BE = BB->end();
|
|
||||||
LocalChanged |= res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsSubloopHeader && !isa<PHINode>(I))
|
if (IsSubloopHeader && !isa<PHINode>(I))
|
||||||
break;
|
break;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "llvm/Transforms/Utils/Local.h"
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// CloneBasicBlock - See comments in Cloning.h
|
// CloneBasicBlock - See comments in Cloning.h
|
||||||
@ -272,42 +273,28 @@ namespace {
|
|||||||
NameSuffix(nameSuffix), CodeInfo(codeInfo), DL(DL) {
|
NameSuffix(nameSuffix), CodeInfo(codeInfo), DL(DL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CloneBlock - The specified block is found to be reachable, clone it and
|
/// CloneBlock - The specified block is found to be reachable, so clone it
|
||||||
/// anything that it can reach.
|
/// into newBB.
|
||||||
void CloneBlock(const BasicBlock *BB,
|
void CloneBlock(const BasicBlock *BB,
|
||||||
std::vector<const BasicBlock*> &ToClone);
|
BasicBlock *NewBB,
|
||||||
|
std::vector<const BasicBlock *> &ToClone,
|
||||||
|
std::set<const BasicBlock *> &OrigBBs);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CloneBlock - The specified block is found to be reachable, clone it and
|
/// CloneBlock - The specified block is found to be reachable, so clone it
|
||||||
/// anything that it can reach.
|
/// into newBB.
|
||||||
void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
|
void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
|
||||||
std::vector<const BasicBlock*> &ToClone){
|
BasicBlock *NewBB,
|
||||||
WeakVH &BBEntry = VMap[BB];
|
std::vector<const BasicBlock *> &ToClone,
|
||||||
|
std::set<const BasicBlock *> &OrigBBs) {
|
||||||
// Have we already cloned this block?
|
|
||||||
if (BBEntry) return;
|
|
||||||
|
|
||||||
// Nope, clone it now.
|
// Remove BB from list of blocks to clone.
|
||||||
BasicBlock *NewBB;
|
// When it was not in the list, it has been cloned already, so
|
||||||
BBEntry = NewBB = BasicBlock::Create(BB->getContext());
|
// don't clone again.
|
||||||
if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);
|
if (!OrigBBs.erase(BB)) return;
|
||||||
|
|
||||||
// It is only legal to clone a function if a block address within that
|
// Nope, clone it now.
|
||||||
// function is never referenced outside of the function. Given that, we
|
|
||||||
// want to map block addresses from the old function to block addresses in
|
|
||||||
// the clone. (This is different from the generic ValueMapper
|
|
||||||
// implementation, which generates an invalid blockaddress when
|
|
||||||
// cloning a function.)
|
|
||||||
//
|
|
||||||
// Note that we don't need to fix the mapping for unreachable blocks;
|
|
||||||
// the default mapping there is safe.
|
|
||||||
if (BB->hasAddressTaken()) {
|
|
||||||
Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc),
|
|
||||||
const_cast<BasicBlock*>(BB));
|
|
||||||
VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
|
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
|
||||||
|
|
||||||
@ -425,7 +412,7 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
|||||||
const DataLayout *DL,
|
const DataLayout *DL,
|
||||||
Instruction *TheCall) {
|
Instruction *TheCall) {
|
||||||
assert(NameSuffix && "NameSuffix cannot be null!");
|
assert(NameSuffix && "NameSuffix cannot be null!");
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (Function::const_arg_iterator II = OldFunc->arg_begin(),
|
for (Function::const_arg_iterator II = OldFunc->arg_begin(),
|
||||||
E = OldFunc->arg_end(); II != E; ++II)
|
E = OldFunc->arg_end(); II != E; ++II)
|
||||||
@ -435,15 +422,87 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
|||||||
PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges,
|
PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges,
|
||||||
NameSuffix, CodeInfo, DL);
|
NameSuffix, CodeInfo, DL);
|
||||||
|
|
||||||
// Clone the entry block, and anything recursively reachable from it.
|
// Since all BB address references need to be known before block-by-block
|
||||||
|
// processing, we need to create all reachable blocks before processing
|
||||||
|
// them for instruction cloning and pruning. Some of these blocks may
|
||||||
|
// be removed due to later pruning.
|
||||||
std::vector<const BasicBlock*> CloneWorklist;
|
std::vector<const BasicBlock*> CloneWorklist;
|
||||||
|
//
|
||||||
|
// OrigBBs consists of all blocks reachable from the entry
|
||||||
|
// block.
|
||||||
|
// This list will be pruned down by the CloneFunction() currently
|
||||||
|
// (March 2014) due to two optimizations:
|
||||||
|
// First, when a conditional branch target is known at compile-time,
|
||||||
|
// only the actual branch destination block needs to be cloned.
|
||||||
|
// Second, when a switch statement target is known at compile-time,
|
||||||
|
// only the actual case statement needs to be cloned.
|
||||||
|
std::set<const BasicBlock*> OrigBBs;
|
||||||
|
|
||||||
CloneWorklist.push_back(&OldFunc->getEntryBlock());
|
CloneWorklist.push_back(&OldFunc->getEntryBlock());
|
||||||
while (!CloneWorklist.empty()) {
|
while (!CloneWorklist.empty()) {
|
||||||
const BasicBlock *BB = CloneWorklist.back();
|
const BasicBlock *BB = CloneWorklist.back();
|
||||||
CloneWorklist.pop_back();
|
CloneWorklist.pop_back();
|
||||||
PFC.CloneBlock(BB, CloneWorklist);
|
|
||||||
|
// Don't revisit blocks.
|
||||||
|
if (VMap.count(BB))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BasicBlock *NewBB = BasicBlock::Create(BB->getContext());
|
||||||
|
if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);
|
||||||
|
|
||||||
|
// It is only legal to clone a function if a block address within that
|
||||||
|
// function is never referenced outside of the function. Given that, we
|
||||||
|
// want to map block addresses from the old function to block addresses in
|
||||||
|
// the clone. (This is different from the generic ValueMapper
|
||||||
|
// implementation, which generates an invalid blockaddress when
|
||||||
|
// cloning a function.)
|
||||||
|
//
|
||||||
|
// Note that we don't need to fix the mapping for unreachable blocks;
|
||||||
|
// the default mapping there is safe.
|
||||||
|
if (BB->hasAddressTaken()) {
|
||||||
|
Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc),
|
||||||
|
const_cast<BasicBlock*>(BB));
|
||||||
|
VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
|
||||||
|
}
|
||||||
|
|
||||||
|
OrigBBs.insert(BB);
|
||||||
|
VMap[BB] = NewBB;
|
||||||
|
// Iterate over all possible successors and add them to the CloneWorklist.
|
||||||
|
const TerminatorInst *Term = BB->getTerminator();
|
||||||
|
for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
|
||||||
|
BasicBlock *Succ = Term->getSuccessor(i);
|
||||||
|
CloneWorklist.push_back(Succ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now, fill only the reachable blocks with the cloned contents
|
||||||
|
// of the originals.
|
||||||
|
assert(CloneWorklist.empty() && "Dirty worklist before re-use\n");
|
||||||
|
CloneWorklist.push_back(&OldFunc->getEntryBlock());
|
||||||
|
while (!CloneWorklist.empty()) {
|
||||||
|
const BasicBlock *BB = CloneWorklist.back();
|
||||||
|
CloneWorklist.pop_back();
|
||||||
|
PFC.CloneBlock(BB, cast<BasicBlock>(VMap[BB]), CloneWorklist,
|
||||||
|
OrigBBs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removed BB's that were created that turned out to be prunable.
|
||||||
|
// Actual cloning may have found pruning opportunities since
|
||||||
|
// branch or switch statement target may have been known at compile-time.
|
||||||
|
// Alternatively we could write a routine CloneFunction and add a) a
|
||||||
|
// parameter to actually do the cloning and b) a return parameter that
|
||||||
|
// gives a list of blocks that need to be cloned also. Then we could
|
||||||
|
// call CloneFunction when we collect the blocks to call, but suppress
|
||||||
|
// cloning. And actually *do* the cloning in the while loop above. Also
|
||||||
|
// the cleanup here would become redundant, and so would be the OrigBBs.
|
||||||
|
for (std::set<const BasicBlock *>::iterator Oi = OrigBBs.begin(),
|
||||||
|
Oe = OrigBBs.end(); Oi != Oe; ++Oi) {
|
||||||
|
const BasicBlock *Orig = *Oi;
|
||||||
|
BasicBlock *NewBB = cast<BasicBlock>(VMap[Orig]);
|
||||||
|
delete NewBB;
|
||||||
|
VMap[Orig] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Loop over all of the basic blocks in the old function. If the block was
|
// Loop over all of the basic blocks in the old function. If the block was
|
||||||
// reachable, we have cloned it and the old block is now in the value map:
|
// reachable, we have cloned it and the old block is now in the value map:
|
||||||
// insert it into the new function in the right order. If not, ignore it.
|
// insert it into the new function in the right order. If not, ignore it.
|
||||||
|
@ -76,15 +76,7 @@ namespace {
|
|||||||
++NumSimplified;
|
++NumSimplified;
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
bool res = RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
|
Changed |= RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
|
||||||
if (res) {
|
|
||||||
// RecursivelyDeleteTriviallyDeadInstruction can remove
|
|
||||||
// more than one instruction, so simply incrementing the
|
|
||||||
// iterator does not work. When instructions get deleted
|
|
||||||
// re-iterate instead.
|
|
||||||
BI = BB->begin(); BE = BB->end();
|
|
||||||
Changed |= res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the list of instructions to simplify on the next loop iteration
|
// Place the list of instructions to simplify on the next loop iteration
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
; RUN: opts -instsimplify -S < %s | FileCheck %s
|
|
||||||
|
|
||||||
define void @foo() nounwind {
|
|
||||||
br i1 undef, label %1, label %4
|
|
||||||
|
|
||||||
; <label>:1 ; preds = %1, %0
|
|
||||||
; CHECK-NOT: phi
|
|
||||||
; CHECK-NOT: sub
|
|
||||||
%2 = phi i32 [ %3, %1 ], [ undef, %0 ]
|
|
||||||
%3 = sub i32 0, undef
|
|
||||||
br label %1
|
|
||||||
|
|
||||||
; <label>:4 ; preds = %0
|
|
||||||
ret void
|
|
||||||
}
|
|
Reference in New Issue
Block a user