From b4098ba03d51a3845bde5aeb4fca893d1a90d3f8 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Mon, 21 Feb 2011 16:27:36 +0000 Subject: [PATCH] Simplify RecursivelyDeleteDeadPHINode. The only functionality change should be that if the phi is used by a side-effect free instruction with no uses then the phi and the instruction now get zapped (checked by the unittest). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126124 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/Local.cpp | 44 ++++++++++------------------ unittests/Transforms/Utils/Local.cpp | 6 ++++ 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 20d798948e2..40a56b0c99a 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -262,12 +262,13 @@ bool llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) { /// areAllUsesEqual - Check whether the uses of a value are all the same. /// This is similar to Instruction::hasOneUse() except this will also return -/// true when there are multiple uses that all refer to the same value. +/// true when there are no uses or multiple uses that all refer to the same +/// value. static bool areAllUsesEqual(Instruction *I) { Value::use_iterator UI = I->use_begin(); Value::use_iterator UE = I->use_end(); if (UI == UE) - return false; + return true; User *TheUse = *UI; for (++UI; UI != UE; ++UI) { @@ -283,34 +284,21 @@ static bool areAllUsesEqual(Instruction *I) { /// delete it. If that makes any of its operands trivially dead, delete them /// too, recursively. Return true if the PHI node is actually deleted. bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) { - if (PN->use_empty()) { - PN->eraseFromParent(); - return true; - } + SmallPtrSet Visited; + for (Instruction *I = PN; areAllUsesEqual(I) && !I->mayHaveSideEffects(); + I = cast(*I->use_begin())) { + if (I->use_empty()) + return RecursivelyDeleteTriviallyDeadInstructions(I); - // We can remove a PHI if it is on a cycle in the def-use graph - // where each node in the cycle has degree one, i.e. only one use, - // and is an instruction with no side effects. - if (!areAllUsesEqual(PN)) - return false; - - bool Changed = false; - SmallPtrSet PHIs; - PHIs.insert(PN); - for (Instruction *I = cast(*PN->use_begin()); - areAllUsesEqual(I) && !I->mayHaveSideEffects(); - I = cast(*I->use_begin())) - // If we find a PHI more than once, we're on a cycle that + // If we find an instruction more than once, we're on a cycle that // won't prove fruitful. - if (PHINode *IP = dyn_cast(I)) - if (!PHIs.insert(IP)) { - // Break the cycle and delete the PHI and its operands. - IP->replaceAllUsesWith(UndefValue::get(IP->getType())); - (void)RecursivelyDeleteTriviallyDeadInstructions(IP); - Changed = true; - break; - } - return Changed; + if (!Visited.insert(I)) { + // Break the cycle and delete the instruction and its operands. + I->replaceAllUsesWith(UndefValue::get(I->getType())); + return RecursivelyDeleteTriviallyDeadInstructions(I); + } + } + return false; } /// SimplifyInstructionsInBlock - Scan the specified basic block and try to diff --git a/unittests/Transforms/Utils/Local.cpp b/unittests/Transforms/Utils/Local.cpp index 2de09ada27a..e0322b37d33 100644 --- a/unittests/Transforms/Utils/Local.cpp +++ b/unittests/Transforms/Utils/Local.cpp @@ -47,6 +47,12 @@ TEST(Local, RecursivelyDeleteDeadPHINodes) { EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi)); + builder.SetInsertPoint(bb0); + phi = builder.CreatePHI(Type::getInt32Ty(C)); + builder.CreateAdd(phi, phi); + + EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi)); + bb0->dropAllReferences(); bb1->dropAllReferences(); delete bb0;