mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +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
|
||||
/// 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();
|
||||
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");
|
||||
|
||||
// If we're able to simplify the phi to a constant, simplify it into its
|
||||
// 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();
|
||||
ReplaceAndSimplifyAllUses(PN, PNV, TD);
|
||||
|
||||
// If recursive simplification ended up deleting the next PHI node we would
|
||||
// iterate to, then our iterator is invalid, restart scanning from the top
|
||||
@ -1203,9 +1222,12 @@ bool JumpThreading::ThreadEdge(BasicBlock *BB,
|
||||
BI = NewBB->begin();
|
||||
for (BasicBlock::iterator E = NewBB->end(); BI != E; ) {
|
||||
Instruction *Inst = BI++;
|
||||
|
||||
if (Value *V = SimplifyInstruction(Inst, TD)) {
|
||||
Inst->replaceAllUsesWith(V);
|
||||
Inst->eraseFromParent();
|
||||
WeakVH BIHandle(BI);
|
||||
ReplaceAndSimplifyAllUses(Inst, V, TD);
|
||||
if (BIHandle == 0)
|
||||
BI = NewBB->begin();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -203,3 +203,35 @@ F2:
|
||||
; 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