| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 1 | //===-- CondPropagate.cpp - Propagate Conditional Expressions -------------===// | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 2 | // | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 7 | // | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This pass propagates information about conditional expressions through the | 
|  | 11 | // program, allowing it to eliminate conditional branches in some cases. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #define DEBUG_TYPE "condprop" | 
|  | 16 | #include "llvm/Transforms/Scalar.h" | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 17 | #include "llvm/Instructions.h" | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 18 | #include "llvm/IntrinsicInst.h" | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 19 | #include "llvm/Pass.h" | 
|  | 20 | #include "llvm/Type.h" | 
| Chris Lattner | dc3f6f2 | 2008-12-03 19:44:02 +0000 | [diff] [blame] | 21 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | 
|  | 22 | #include "llvm/Transforms/Utils/Local.h" | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/Statistic.h" | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 24 | #include "llvm/ADT/SmallVector.h" | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 25 | using namespace llvm; | 
|  | 26 |  | 
| Chris Lattner | 79a42ac | 2006-12-19 21:40:18 +0000 | [diff] [blame] | 27 | STATISTIC(NumBrThread, "Number of CFG edges threaded through branches"); | 
|  | 28 | STATISTIC(NumSwThread, "Number of CFG edges threaded through switches"); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 29 |  | 
| Chris Lattner | 79a42ac | 2006-12-19 21:40:18 +0000 | [diff] [blame] | 30 | namespace { | 
| Chris Lattner | 2dd09db | 2009-09-02 06:11:42 +0000 | [diff] [blame] | 31 | struct CondProp : public FunctionPass { | 
| Nick Lewycky | e7da2d6 | 2007-05-06 13:37:16 +0000 | [diff] [blame] | 32 | static char ID; // Pass identification, replacement for typeid | 
| Dan Gohman | a79db30 | 2008-09-04 17:05:41 +0000 | [diff] [blame] | 33 | CondProp() : FunctionPass(&ID) {} | 
| Devang Patel | 09f162c | 2007-05-01 21:15:47 +0000 | [diff] [blame] | 34 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 35 | virtual bool runOnFunction(Function &F); | 
|  | 36 |  | 
|  | 37 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | 38 | AU.addRequiredID(BreakCriticalEdgesID); | 
|  | 39 | //AU.addRequired<DominanceFrontier>(); | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | private: | 
|  | 43 | bool MadeChange; | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 44 | SmallVector<BasicBlock *, 4> DeadBlocks; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 45 | void SimplifyBlock(BasicBlock *BB); | 
|  | 46 | void SimplifyPredecessors(BranchInst *BI); | 
|  | 47 | void SimplifyPredecessors(SwitchInst *SI); | 
|  | 48 | void RevectorBlockTo(BasicBlock *FromBB, BasicBlock *ToBB); | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 49 | bool RevectorBlockTo(BasicBlock *FromBB, Value *Cond, BranchInst *BI); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 50 | }; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 51 | } | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 52 |  | 
|  | 53 | char CondProp::ID = 0; | 
|  | 54 | static RegisterPass<CondProp> X("condprop", "Conditional Propagation"); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 55 |  | 
|  | 56 | FunctionPass *llvm::createCondPropagationPass() { | 
|  | 57 | return new CondProp(); | 
|  | 58 | } | 
|  | 59 |  | 
|  | 60 | bool CondProp::runOnFunction(Function &F) { | 
|  | 61 | bool EverMadeChange = false; | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 62 | DeadBlocks.clear(); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 63 |  | 
|  | 64 | // While we are simplifying blocks, keep iterating. | 
|  | 65 | do { | 
|  | 66 | MadeChange = false; | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 67 | for (Function::iterator BB = F.begin(), E = F.end(); BB != E;) | 
|  | 68 | SimplifyBlock(BB++); | 
| Devang Patel | a51e0a3 | 2007-07-26 20:21:42 +0000 | [diff] [blame] | 69 | EverMadeChange = EverMadeChange || MadeChange; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 70 | } while (MadeChange); | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 71 |  | 
|  | 72 | if (EverMadeChange) { | 
|  | 73 | while (!DeadBlocks.empty()) { | 
|  | 74 | BasicBlock *BB = DeadBlocks.back(); DeadBlocks.pop_back(); | 
|  | 75 | DeleteDeadBlock(BB); | 
|  | 76 | } | 
|  | 77 | } | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 78 | return EverMadeChange; | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | void CondProp::SimplifyBlock(BasicBlock *BB) { | 
|  | 82 | if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) { | 
|  | 83 | // If this is a conditional branch based on a phi node that is defined in | 
|  | 84 | // this block, see if we can simplify predecessors of this block. | 
|  | 85 | if (BI->isConditional() && isa<PHINode>(BI->getCondition()) && | 
|  | 86 | cast<PHINode>(BI->getCondition())->getParent() == BB) | 
|  | 87 | SimplifyPredecessors(BI); | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 88 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 89 | } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) { | 
|  | 90 | if (isa<PHINode>(SI->getCondition()) && | 
|  | 91 | cast<PHINode>(SI->getCondition())->getParent() == BB) | 
|  | 92 | SimplifyPredecessors(SI); | 
|  | 93 | } | 
|  | 94 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 95 | // If possible, simplify the terminator of this block. | 
|  | 96 | if (ConstantFoldTerminator(BB)) | 
|  | 97 | MadeChange = true; | 
|  | 98 |  | 
|  | 99 | // If this block ends with an unconditional branch and the only successor has | 
|  | 100 | // only this block as a predecessor, merge the two blocks together. | 
|  | 101 | if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) | 
| Chris Lattner | 6441cf9 | 2006-08-14 21:38:05 +0000 | [diff] [blame] | 102 | if (BI->isUnconditional() && BI->getSuccessor(0)->getSinglePredecessor() && | 
|  | 103 | BB != BI->getSuccessor(0)) { | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 104 | BasicBlock *Succ = BI->getSuccessor(0); | 
| Chris Lattner | 6441cf9 | 2006-08-14 21:38:05 +0000 | [diff] [blame] | 105 |  | 
| Chris Lattner | dc3f6f2 | 2008-12-03 19:44:02 +0000 | [diff] [blame] | 106 | // If Succ has any PHI nodes, they are all single-entry PHI's.  Eliminate | 
|  | 107 | // them. | 
|  | 108 | FoldSingleEntryPHINodes(Succ); | 
| Chris Lattner | 6441cf9 | 2006-08-14 21:38:05 +0000 | [diff] [blame] | 109 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 110 | // Remove BI. | 
|  | 111 | BI->eraseFromParent(); | 
|  | 112 |  | 
|  | 113 | // Move over all of the instructions. | 
|  | 114 | BB->getInstList().splice(BB->end(), Succ->getInstList()); | 
|  | 115 |  | 
|  | 116 | // Any phi nodes that had entries for Succ now have entries from BB. | 
|  | 117 | Succ->replaceAllUsesWith(BB); | 
|  | 118 |  | 
|  | 119 | // Succ is now dead, but we cannot delete it without potentially | 
|  | 120 | // invalidating iterators elsewhere.  Just insert an unreachable | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 121 | // instruction in it and delete this block later on. | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 122 | new UnreachableInst(BB->getContext(), Succ); | 
| Devang Patel | 58cb603 | 2009-02-05 19:59:42 +0000 | [diff] [blame] | 123 | DeadBlocks.push_back(Succ); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 124 | MadeChange = true; | 
|  | 125 | } | 
|  | 126 | } | 
|  | 127 |  | 
|  | 128 | // SimplifyPredecessors(branches) - We know that BI is a conditional branch | 
|  | 129 | // based on a PHI node defined in this block.  If the phi node contains constant | 
|  | 130 | // operands, then the blocks corresponding to those operands can be modified to | 
|  | 131 | // jump directly to the destination instead of going through this block. | 
|  | 132 | void CondProp::SimplifyPredecessors(BranchInst *BI) { | 
|  | 133 | // TODO: We currently only handle the most trival case, where the PHI node has | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 134 | // one use (the branch), and is the only instruction besides the branch and dbg | 
|  | 135 | // intrinsics in the block. | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 136 | PHINode *PN = cast<PHINode>(BI->getCondition()); | 
| Chris Lattner | 9449991 | 2009-01-26 02:18:20 +0000 | [diff] [blame] | 137 |  | 
|  | 138 | if (PN->getNumIncomingValues() == 1) { | 
|  | 139 | // Eliminate single-entry PHI nodes. | 
|  | 140 | FoldSingleEntryPHINodes(PN->getParent()); | 
|  | 141 | return; | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 145 | if (!PN->hasOneUse()) return; | 
|  | 146 |  | 
|  | 147 | BasicBlock *BB = BI->getParent(); | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 148 | if (&*BB->begin() != PN) | 
|  | 149 | return; | 
|  | 150 | BasicBlock::iterator BBI = BB->begin(); | 
|  | 151 | BasicBlock::iterator BBE = BB->end(); | 
| Bill Wendling | 0bf1ded | 2009-03-05 01:08:35 +0000 | [diff] [blame] | 152 | while (BBI != BBE && isa<DbgInfoIntrinsic>(++BBI)) /* empty */; | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 153 | if (&*BBI != BI) | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 154 | return; | 
|  | 155 |  | 
|  | 156 | // Ok, we have this really simple case, walk the PHI operands, looking for | 
|  | 157 | // constants.  Walk from the end to remove operands from the end when | 
|  | 158 | // possible, and to avoid invalidating "i". | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 159 | for (unsigned i = PN->getNumIncomingValues(); i != 0; --i) { | 
|  | 160 | Value *InVal = PN->getIncomingValue(i-1); | 
|  | 161 | if (!RevectorBlockTo(PN->getIncomingBlock(i-1), InVal, BI)) | 
|  | 162 | continue; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 163 |  | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 164 | ++NumBrThread; | 
|  | 165 |  | 
|  | 166 | // If there were two predecessors before this simplification, or if the | 
|  | 167 | // PHI node contained all the same value except for the one we just | 
|  | 168 | // substituted, the PHI node may be deleted.  Don't iterate through it the | 
|  | 169 | // last time. | 
|  | 170 | if (BI->getCondition() != PN) return; | 
|  | 171 | } | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 172 | } | 
|  | 173 |  | 
|  | 174 | // SimplifyPredecessors(switch) - We know that SI is switch based on a PHI node | 
|  | 175 | // defined in this block.  If the phi node contains constant operands, then the | 
|  | 176 | // blocks corresponding to those operands can be modified to jump directly to | 
|  | 177 | // the destination instead of going through this block. | 
|  | 178 | void CondProp::SimplifyPredecessors(SwitchInst *SI) { | 
|  | 179 | // TODO: We currently only handle the most trival case, where the PHI node has | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 180 | // one use (the branch), and is the only instruction besides the branch and | 
|  | 181 | // dbg intrinsics in the block. | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 182 | PHINode *PN = cast<PHINode>(SI->getCondition()); | 
|  | 183 | if (!PN->hasOneUse()) return; | 
|  | 184 |  | 
|  | 185 | BasicBlock *BB = SI->getParent(); | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 186 | if (&*BB->begin() != PN) | 
|  | 187 | return; | 
|  | 188 | BasicBlock::iterator BBI = BB->begin(); | 
|  | 189 | BasicBlock::iterator BBE = BB->end(); | 
| Bill Wendling | 0bf1ded | 2009-03-05 01:08:35 +0000 | [diff] [blame] | 190 | while (BBI != BBE && isa<DbgInfoIntrinsic>(++BBI)) /* empty */; | 
| Devang Patel | 409b794 | 2009-02-05 23:32:52 +0000 | [diff] [blame] | 191 | if (&*BBI != SI) | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 192 | return; | 
|  | 193 |  | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 194 | // Ok, we have this really simple case, walk the PHI operands, looking for | 
|  | 195 | // constants.  Walk from the end to remove operands from the end when | 
|  | 196 | // possible, and to avoid invalidating "i". | 
|  | 197 | for (unsigned i = PN->getNumIncomingValues(); i != 0; --i) | 
|  | 198 | if (ConstantInt *CI = dyn_cast<ConstantInt>(PN->getIncomingValue(i-1))) { | 
|  | 199 | // If we have a constant, forward the edge from its current to its | 
|  | 200 | // ultimate destination. | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 201 | unsigned DestCase = SI->findCaseValue(CI); | 
|  | 202 | RevectorBlockTo(PN->getIncomingBlock(i-1), | 
|  | 203 | SI->getSuccessor(DestCase)); | 
|  | 204 | ++NumSwThread; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 205 |  | 
| Chris Lattner | d7cb625 | 2007-08-02 04:47:05 +0000 | [diff] [blame] | 206 | // If there were two predecessors before this simplification, or if the | 
|  | 207 | // PHI node contained all the same value except for the one we just | 
|  | 208 | // substituted, the PHI node may be deleted.  Don't iterate through it the | 
|  | 209 | // last time. | 
|  | 210 | if (SI->getCondition() != PN) return; | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 211 | } | 
|  | 212 | } | 
|  | 213 |  | 
|  | 214 |  | 
|  | 215 | // RevectorBlockTo - Revector the unconditional branch at the end of FromBB to | 
|  | 216 | // the ToBB block, which is one of the successors of its current successor. | 
|  | 217 | void CondProp::RevectorBlockTo(BasicBlock *FromBB, BasicBlock *ToBB) { | 
|  | 218 | BranchInst *FromBr = cast<BranchInst>(FromBB->getTerminator()); | 
|  | 219 | assert(FromBr->isUnconditional() && "FromBB should end with uncond br!"); | 
|  | 220 |  | 
|  | 221 | // Get the old block we are threading through. | 
|  | 222 | BasicBlock *OldSucc = FromBr->getSuccessor(0); | 
|  | 223 |  | 
| Devang Patel | 2cb4f83 | 2006-11-01 23:04:45 +0000 | [diff] [blame] | 224 | // OldSucc had multiple successors. If ToBB has multiple predecessors, then | 
|  | 225 | // the edge between them would be critical, which we already took care of. | 
|  | 226 | // If ToBB has single operand PHI node then take care of it here. | 
| Chris Lattner | dc3f6f2 | 2008-12-03 19:44:02 +0000 | [diff] [blame] | 227 | FoldSingleEntryPHINodes(ToBB); | 
| Chris Lattner | 16a50fd | 2005-04-15 19:28:32 +0000 | [diff] [blame] | 228 |  | 
|  | 229 | // Update PHI nodes in OldSucc to know that FromBB no longer branches to it. | 
|  | 230 | OldSucc->removePredecessor(FromBB); | 
|  | 231 |  | 
|  | 232 | // Change FromBr to branch to the new destination. | 
|  | 233 | FromBr->setSuccessor(0, ToBB); | 
|  | 234 |  | 
|  | 235 | MadeChange = true; | 
|  | 236 | } | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 237 |  | 
|  | 238 | bool CondProp::RevectorBlockTo(BasicBlock *FromBB, Value *Cond, BranchInst *BI){ | 
|  | 239 | BranchInst *FromBr = cast<BranchInst>(FromBB->getTerminator()); | 
|  | 240 | if (!FromBr->isUnconditional()) | 
|  | 241 | return false; | 
|  | 242 |  | 
|  | 243 | // Get the old block we are threading through. | 
|  | 244 | BasicBlock *OldSucc = FromBr->getSuccessor(0); | 
|  | 245 |  | 
|  | 246 | // If the condition is a constant, simply revector the unconditional branch at | 
|  | 247 | // the end of FromBB to one of the successors of its current successor. | 
|  | 248 | if (ConstantInt *CB = dyn_cast<ConstantInt>(Cond)) { | 
|  | 249 | BasicBlock *ToBB = BI->getSuccessor(CB->isZero()); | 
|  | 250 |  | 
|  | 251 | // OldSucc had multiple successors. If ToBB has multiple predecessors, then | 
|  | 252 | // the edge between them would be critical, which we already took care of. | 
|  | 253 | // If ToBB has single operand PHI node then take care of it here. | 
|  | 254 | FoldSingleEntryPHINodes(ToBB); | 
|  | 255 |  | 
|  | 256 | // Update PHI nodes in OldSucc to know that FromBB no longer branches to it. | 
|  | 257 | OldSucc->removePredecessor(FromBB); | 
|  | 258 |  | 
|  | 259 | // Change FromBr to branch to the new destination. | 
|  | 260 | FromBr->setSuccessor(0, ToBB); | 
|  | 261 | } else { | 
| Evan Cheng | ffb83a1 | 2009-04-15 00:43:54 +0000 | [diff] [blame] | 262 | BasicBlock *Succ0 = BI->getSuccessor(0); | 
|  | 263 | // Do not perform transform if the new destination has PHI nodes. The | 
|  | 264 | // transform will add new preds to the PHI's. | 
|  | 265 | if (isa<PHINode>(Succ0->begin())) | 
|  | 266 | return false; | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 267 |  | 
| Evan Cheng | ffb83a1 | 2009-04-15 00:43:54 +0000 | [diff] [blame] | 268 | BasicBlock *Succ1 = BI->getSuccessor(1); | 
|  | 269 | if (isa<PHINode>(Succ1->begin())) | 
|  | 270 | return false; | 
|  | 271 |  | 
|  | 272 | // Insert the new conditional branch. | 
|  | 273 | BranchInst::Create(Succ0, Succ1, Cond, FromBr); | 
|  | 274 |  | 
|  | 275 | FoldSingleEntryPHINodes(Succ0); | 
|  | 276 | FoldSingleEntryPHINodes(Succ1); | 
| Evan Cheng | 5ebf2ac | 2009-04-14 23:40:03 +0000 | [diff] [blame] | 277 |  | 
|  | 278 | // Update PHI nodes in OldSucc to know that FromBB no longer branches to it. | 
|  | 279 | OldSucc->removePredecessor(FromBB); | 
|  | 280 |  | 
|  | 281 | // Delete the old branch. | 
|  | 282 | FromBr->eraseFromParent(); | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | MadeChange = true; | 
|  | 286 | return true; | 
|  | 287 | } |