mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Refactor the interface to recursively simplifying instructions to be tad
bit simpler by handling a common case explicitly. Also, refactor the implementation to use a worklist based walk of the recursive users, rather than trying to use value handles to detect and recover from RAUWs during the recursive descent. This fixes a very subtle bug in the previous implementation where degenerate control flow structures could cause mutually recursive instructions (PHI nodes) to collapse in just such a way that From became equal to To after some amount of recursion. At that point, we hit the inf-loop that the assert at the top attempted to guard against. This problem is defined away when not using value handles in this manner. There are lots of comments claiming that the WeakVH will protect against just this sort of error, but they're not accurate about the actual implementation of WeakVHs, which do still track RAUWs. I don't have any test case for the bug this fixes because it requires running the recursive simplification on unreachable phi nodes. I've no way to either run this or easily write an input that triggers it. It was found when using instruction simplification inside the inliner when running over the nightly test-suite. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153393 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
afe629dba1
commit
6b980541df
@ -189,16 +189,29 @@ namespace llvm {
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
|
||||
/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then
|
||||
/// delete the From instruction. In addition to a basic RAUW, this does a
|
||||
/// recursive simplification of the updated instructions. This catches
|
||||
/// things where one simplification exposes other opportunities. This only
|
||||
/// simplifies and deletes scalar operations, it does not change the CFG.
|
||||
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
|
||||
/// recursively.
|
||||
///
|
||||
void ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
/// This first performs a normal RAUW of I with SimpleV. It then recursively
|
||||
/// attempts to simplify those users updated by the operation. The 'I'
|
||||
/// instruction must not be equal to the simplified value 'SimpleV'.
|
||||
///
|
||||
/// The function returns true if any simplifications were performed.
|
||||
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Recursively attempt to simplify an instruction.
|
||||
///
|
||||
/// This routine uses SimplifyInstruction to simplify 'I', and if successful
|
||||
/// replaces uses of 'I' with the simplified value. It then recurses on each
|
||||
/// of the users impacted. It returns true if any simplifications were
|
||||
/// performed.
|
||||
bool recursivelySimplifyInstruction(Instruction *I,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -2818,58 +2818,82 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
||||
return Result == I ? UndefValue::get(I->getType()) : Result;
|
||||
}
|
||||
|
||||
/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then
|
||||
/// delete the From instruction. In addition to a basic RAUW, this does a
|
||||
/// recursive simplification of the newly formed instructions. This catches
|
||||
/// things where one simplification exposes other opportunities. This only
|
||||
/// simplifies and deletes scalar operations, it does not change the CFG.
|
||||
/// \brief Implementation of recursive simplification through an instructions
|
||||
/// uses.
|
||||
///
|
||||
void llvm::ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
|
||||
const TargetData *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const DominatorTree *DT) {
|
||||
assert(From != To && "ReplaceAndSimplifyAllUses(X,X) is not valid!");
|
||||
/// This is the common implementation of the recursive simplification routines.
|
||||
/// If we have a pre-simplified value in 'SimpleV', that is forcibly used to
|
||||
/// replace the instruction 'I'. Otherwise, we simply add 'I' to the list of
|
||||
/// instructions to process and attempt to simplify it using
|
||||
/// InstructionSimplify.
|
||||
///
|
||||
/// This routine returns 'true' only when *it* simplifies something. The passed
|
||||
/// in simplified value does not count toward this.
|
||||
static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV,
|
||||
const TargetData *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const DominatorTree *DT) {
|
||||
bool Simplified = false;
|
||||
SmallVector<Instruction *, 8> Worklist;
|
||||
|
||||
// FromHandle/ToHandle - This keeps a WeakVH on the from/to values so that
|
||||
// we can know if it gets deleted out from under us or replaced in a
|
||||
// recursive simplification.
|
||||
WeakVH FromHandle(From);
|
||||
WeakVH ToHandle(To);
|
||||
// If we have an explicit value to collapse to, do that round of the
|
||||
// simplification loop by hand initially.
|
||||
if (SimpleV) {
|
||||
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE;
|
||||
++UI)
|
||||
Worklist.push_back(cast<Instruction>(*UI));
|
||||
|
||||
while (!From->use_empty()) {
|
||||
// Update the instruction to use the new value.
|
||||
Use &TheUse = From->use_begin().getUse();
|
||||
Instruction *User = cast<Instruction>(TheUse.getUser());
|
||||
TheUse = To;
|
||||
// Replace the instruction with its simplified value.
|
||||
I->replaceAllUsesWith(SimpleV);
|
||||
|
||||
// Check to see if the instruction can be folded due to the operand
|
||||
// replacement. For example changing (or X, Y) into (or X, -1) can replace
|
||||
// the 'or' with -1.
|
||||
Value *SimplifiedVal;
|
||||
{
|
||||
// Sanity check to make sure 'User' doesn't dangle across
|
||||
// SimplifyInstruction.
|
||||
AssertingVH<> UserHandle(User);
|
||||
|
||||
SimplifiedVal = SimplifyInstruction(User, TD, TLI, DT);
|
||||
if (SimplifiedVal == 0) continue;
|
||||
}
|
||||
|
||||
// Recursively simplify this user to the new value.
|
||||
ReplaceAndSimplifyAllUses(User, SimplifiedVal, TD, TLI, DT);
|
||||
From = dyn_cast_or_null<Instruction>((Value*)FromHandle);
|
||||
To = ToHandle;
|
||||
|
||||
assert(ToHandle && "To value deleted by recursive simplification?");
|
||||
|
||||
// If the recursive simplification ended up revisiting and deleting
|
||||
// 'From' then we're done.
|
||||
if (From == 0)
|
||||
return;
|
||||
// Gracefully handle edge cases where the instruction is not wired into any
|
||||
// parent block.
|
||||
if (I->getParent())
|
||||
I->eraseFromParent();
|
||||
} else {
|
||||
Worklist.push_back(I);
|
||||
}
|
||||
|
||||
// If 'From' has value handles referring to it, do a real RAUW to update them.
|
||||
From->replaceAllUsesWith(To);
|
||||
while (!Worklist.empty()) {
|
||||
I = Worklist.pop_back_val();
|
||||
|
||||
From->eraseFromParent();
|
||||
// See if this instruction simplifies.
|
||||
SimpleV = SimplifyInstruction(I, TD, TLI, DT);
|
||||
if (!SimpleV)
|
||||
continue;
|
||||
|
||||
Simplified = true;
|
||||
|
||||
// Stash away all the uses of the old instruction so we can check them for
|
||||
// recursive simplifications after a RAUW. This is cheaper than checking all
|
||||
// uses of To on the recursive step in most cases.
|
||||
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE;
|
||||
++UI)
|
||||
Worklist.push_back(cast<Instruction>(*UI));
|
||||
|
||||
// Replace the instruction with its simplified value.
|
||||
I->replaceAllUsesWith(SimpleV);
|
||||
|
||||
// Gracefully handle edge cases where the instruction is not wired into any
|
||||
// parent block.
|
||||
if (I->getParent())
|
||||
I->eraseFromParent();
|
||||
}
|
||||
return Simplified;
|
||||
}
|
||||
|
||||
bool llvm::recursivelySimplifyInstruction(Instruction *I,
|
||||
const TargetData *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const DominatorTree *DT) {
|
||||
return replaceAndRecursivelySimplifyImpl(I, 0, TD, TLI, DT);
|
||||
}
|
||||
|
||||
bool llvm::replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
|
||||
const TargetData *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const DominatorTree *DT) {
|
||||
assert(I != SimpleV && "replaceAndRecursivelySimplify(X,X) is not valid!");
|
||||
assert(SimpleV && "Must provide a simplified value.");
|
||||
return replaceAndRecursivelySimplifyImpl(I, SimpleV, TD, TLI, DT);
|
||||
}
|
||||
|
@ -567,8 +567,8 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) {
|
||||
// happens.
|
||||
WeakVH IterHandle(CurInstIterator);
|
||||
|
||||
ReplaceAndSimplifyAllUses(CI, RetVal, TLI ? TLI->getTargetData() : 0,
|
||||
TLInfo, ModifiedDT ? 0 : DT);
|
||||
replaceAndRecursivelySimplify(CI, RetVal, TLI ? TLI->getTargetData() : 0,
|
||||
TLInfo, ModifiedDT ? 0 : DT);
|
||||
|
||||
// If the iterator instruction was recursively deleted, start over at the
|
||||
// start of the block.
|
||||
|
@ -357,10 +357,9 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD) {
|
||||
bool MadeChange = false;
|
||||
for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) {
|
||||
Instruction *Inst = BI++;
|
||||
|
||||
if (Value *V = SimplifyInstruction(Inst, TD)) {
|
||||
WeakVH BIHandle(BI);
|
||||
ReplaceAndSimplifyAllUses(Inst, V, TD);
|
||||
|
||||
WeakVH BIHandle(BI);
|
||||
if (recursivelySimplifyInstruction(Inst, TD)) {
|
||||
MadeChange = true;
|
||||
if (BIHandle != BI)
|
||||
BI = BB->begin();
|
||||
@ -370,7 +369,6 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD) {
|
||||
if (Inst->isTerminator())
|
||||
break;
|
||||
|
||||
WeakVH BIHandle(BI);
|
||||
MadeChange |= RecursivelyDeleteTriviallyDeadInstructions(Inst);
|
||||
if (BIHandle != BI)
|
||||
BI = BB->begin();
|
||||
@ -408,17 +406,11 @@ void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
|
||||
WeakVH PhiIt = &BB->front();
|
||||
while (PHINode *PN = dyn_cast<PHINode>(PhiIt)) {
|
||||
PhiIt = &*++BasicBlock::iterator(cast<Instruction>(PhiIt));
|
||||
|
||||
Value *PNV = SimplifyInstruction(PN, TD);
|
||||
if (PNV == 0) continue;
|
||||
|
||||
// If we're able to simplify the phi to a single value, substitute the new
|
||||
// value into all of its uses.
|
||||
assert(PNV != PN && "SimplifyInstruction broken!");
|
||||
|
||||
Value *OldPhiIt = PhiIt;
|
||||
ReplaceAndSimplifyAllUses(PN, PNV, TD);
|
||||
|
||||
|
||||
if (!recursivelySimplifyInstruction(PN, TD))
|
||||
continue;
|
||||
|
||||
// If recursive simplification ended up deleting the next PHI node we would
|
||||
// iterate to, then our iterator is invalid, restart scanning from the top
|
||||
// of the block.
|
||||
|
Loading…
Reference in New Issue
Block a user