From 19eff2a9f678a11dd3bc16bac94c303368063bc5 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 15 Jul 2010 06:36:08 +0000 Subject: [PATCH] Fix PR7647, handling the case when 'To' ends up being mutated by recursive simplification. This also enhances ReplaceAndSimplifyAllUses to actually do a real RAUW at the end of it, which updates any value handles pointing to "From" to start pointing to "To". This seems useful for debug info and random other VH users. llvm-svn: 108415 --- llvm/lib/Analysis/InstructionSimplify.cpp | 48 +++++++++++++++------ llvm/test/Transforms/JumpThreading/crash.ll | 47 ++++++++++++++++++++ 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index dbefc2dedb2b..24cd3433a2ca 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -440,27 +440,47 @@ void llvm::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. + // 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); while (!From->use_empty()) { // Update the instruction to use the new value. - Use &U = From->use_begin().getUse(); - Instruction *User = cast(U.getUser()); - U = To; + Use &TheUse = From->use_begin().getUse(); + Instruction *User = cast(TheUse.getUser()); + TheUse = To; + + // 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); - // 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; + SimplifiedVal = SimplifyInstruction(User, TD); + if (SimplifiedVal == 0) continue; } + + // Recursively simplify this user to the new value. + ReplaceAndSimplifyAllUses(User, SimplifiedVal, TD); + From = dyn_cast_or_null((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; } + + // If 'From' has value handles referring to it, do a real RAUW to update them. + From->replaceAllUsesWith(To); + From->eraseFromParent(); } diff --git a/llvm/test/Transforms/JumpThreading/crash.ll b/llvm/test/Transforms/JumpThreading/crash.ll index 480b4a04ee96..f0fc61e7370f 100644 --- a/llvm/test/Transforms/JumpThreading/crash.ll +++ b/llvm/test/Transforms/JumpThreading/crash.ll @@ -387,3 +387,50 @@ if.end: ; preds = %land.end69 ret void } +; PR7647 +define void @test15() nounwind { +entry: + ret void + +if.then237: + br label %lbl_664 + +lbl_596: ; preds = %lbl_664, %for.end37 + volatile store i64 undef, i64* undef, align 4 + br label %for.cond111 + +for.cond111: ; preds = %safe_sub_func_int64_t_s_s.exit, %lbl_596 + %storemerge = phi i8 [ undef, %cond.true.i100 ], [ 22, %lbl_596 ] ; [#uses=1] + %l_678.5 = phi i64 [ %l_678.3, %cond.true.i100 ], [ undef, %lbl_596 ] ; [#uses=2] + %cmp114 = icmp slt i8 %storemerge, -2 ; [#uses=1] + br i1 %cmp114, label %lbl_664, label %if.end949 + +lbl_664: ; preds = %for.end1058, %if.then237, %for.cond111 + %l_678.3 = phi i64 [ %l_678.5, %for.cond111 ], [ %l_678.2, %for.cond1035 ], [ 5, %if.then237 ] ; [#uses=1] + %tobool118 = icmp eq i32 undef, 0 ; [#uses=1] + br i1 %tobool118, label %cond.true.i100, label %lbl_596 + +cond.true.i100: ; preds = %for.inc120 + br label %for.cond111 + +lbl_709: + br label %if.end949 + +for.cond603: ; preds = %for.body607, %if.end336 + br i1 undef, label %for.cond603, label %if.end949 + +if.end949: ; preds = %for.cond603, %lbl_709, %for.cond111 + %l_678.2 = phi i64 [ %l_678.5, %for.cond111 ], [ undef, %lbl_709 ], [ 5, %for.cond603 ] ; [#uses=1] + br label %for.body1016 + +for.body1016: ; preds = %for.cond1012 + br label %for.body1016 + +for.cond1035: ; preds = %for.inc1055, %if.then1026 + br i1 undef, label %for.cond1040, label %lbl_664 + +for.cond1040: ; preds = %for.body1044, %for.cond1035 + ret void +} + +