mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-30 04:56:49 +00:00
make jump threading recursively simplify expressions instead of doing it
just one level deep. On the testcase we go from getting this: F1: ; preds = %T2 %F = and i1 true, %cond ; <i1> [#uses=1] br i1 %F, label %X, label %Y to a fully threaded: F1: ; preds = %T2 br label %Y This changes gets us to the point where we're forming (too many) switch instructions on doug's strswitch testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86646 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9f3ce36d7e
commit
fddcf47a24
@ -182,6 +182,40 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) {
|
|||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
static void ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
|
||||||
|
const TargetData *TD) {
|
||||||
|
assert(From != To && "ReplaceAndSimplifyAllUses(X,X) is not valid!");
|
||||||
|
|
||||||
|
// FromHandle - This keeps a weakvh on the from value so that we can know if
|
||||||
|
// it gets deleted out from under us in a recursive simplification.
|
||||||
|
WeakVH FromHandle(From);
|
||||||
|
|
||||||
|
while (!From->use_empty()) {
|
||||||
|
// Update the instruction to use the new value.
|
||||||
|
Use &U = From->use_begin().getUse();
|
||||||
|
Instruction *User = cast<Instruction>(U.getUser());
|
||||||
|
U = To;
|
||||||
|
|
||||||
|
// See if we can simplify it.
|
||||||
|
if (Value *V = SimplifyInstruction(User, TD)) {
|
||||||
|
// Recursively simplify this.
|
||||||
|
ReplaceAndSimplifyAllUses(User, V, TD);
|
||||||
|
|
||||||
|
// If the recursive simplification ended up revisiting and deleting 'From'
|
||||||
|
// then we're done.
|
||||||
|
if (FromHandle == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
From->eraseFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this
|
/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this
|
||||||
/// method is called when we're about to delete Pred as a predecessor of BB. If
|
/// method is called when we're about to delete Pred as a predecessor of BB. If
|
||||||
@ -212,26 +246,11 @@ static void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
|
|||||||
Value *PNV = PN->hasConstantValue();
|
Value *PNV = PN->hasConstantValue();
|
||||||
if (PNV == 0) continue;
|
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 && "hasConstantValue broken");
|
assert(PNV != PN && "hasConstantValue broken");
|
||||||
|
|
||||||
// If we're able to simplify the phi to a constant, simplify it into its
|
ReplaceAndSimplifyAllUses(PN, PNV, TD);
|
||||||
// uses.
|
|
||||||
while (!PN->use_empty()) {
|
|
||||||
// Update the instruction to use the new value.
|
|
||||||
Use &U = PN->use_begin().getUse();
|
|
||||||
Instruction *User = cast<Instruction>(U.getUser());
|
|
||||||
U = PNV;
|
|
||||||
|
|
||||||
// See if we can simplify it.
|
|
||||||
if (User != PN)
|
|
||||||
if (Value *V = SimplifyInstruction(User, TD)) {
|
|
||||||
User->replaceAllUsesWith(V);
|
|
||||||
User->eraseFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PN->replaceAllUsesWith(PNV);
|
|
||||||
PN->eraseFromParent();
|
|
||||||
|
|
||||||
// If recursive simplification ended up deleting the next PHI node we would
|
// If recursive simplification ended up deleting the next PHI node we would
|
||||||
// iterate to, then our iterator is invalid, restart scanning from the top
|
// iterate to, then our iterator is invalid, restart scanning from the top
|
||||||
@ -1203,9 +1222,12 @@ bool JumpThreading::ThreadEdge(BasicBlock *BB,
|
|||||||
BI = NewBB->begin();
|
BI = NewBB->begin();
|
||||||
for (BasicBlock::iterator E = NewBB->end(); BI != E; ) {
|
for (BasicBlock::iterator E = NewBB->end(); BI != E; ) {
|
||||||
Instruction *Inst = BI++;
|
Instruction *Inst = BI++;
|
||||||
|
|
||||||
if (Value *V = SimplifyInstruction(Inst, TD)) {
|
if (Value *V = SimplifyInstruction(Inst, TD)) {
|
||||||
Inst->replaceAllUsesWith(V);
|
WeakVH BIHandle(BI);
|
||||||
Inst->eraseFromParent();
|
ReplaceAndSimplifyAllUses(Inst, V, TD);
|
||||||
|
if (BIHandle == 0)
|
||||||
|
BI = NewBB->begin();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,3 +203,35 @@ F2:
|
|||||||
; CHECK-NEXT: phi i32
|
; CHECK-NEXT: phi i32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
declare i1 @test8a()
|
||||||
|
|
||||||
|
define i32 @test8b(i1 %cond, i1 %cond2) {
|
||||||
|
; CHECK: @test8b
|
||||||
|
T0:
|
||||||
|
%A = call i1 @test8a()
|
||||||
|
br i1 %A, label %T1, label %F1
|
||||||
|
T1:
|
||||||
|
%B = call i1 @test8a()
|
||||||
|
br i1 %B, label %T2, label %F1
|
||||||
|
T2:
|
||||||
|
%C = call i1 @test8a()
|
||||||
|
br i1 %cond, label %T3, label %F1
|
||||||
|
T3:
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
F1:
|
||||||
|
; TODO: F1 uncond branch block should be removed, T2 should jump directly to Y.
|
||||||
|
; CHECK: F1:
|
||||||
|
; CHECK-NEXT br label %Y
|
||||||
|
%D = phi i32 [0, %T0], [0, %T1], [1, %T2]
|
||||||
|
%E = icmp eq i32 %D, 1
|
||||||
|
%F = and i1 %E, %cond
|
||||||
|
br i1 %F, label %X, label %Y
|
||||||
|
X:
|
||||||
|
call i1 @test8a()
|
||||||
|
ret i32 1
|
||||||
|
Y:
|
||||||
|
ret i32 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user