diff options
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Scalar/Reassociate.cpp | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index 7cdfce84559..5cee2248c3b 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -861,6 +861,8 @@ static Value *NegateValue(Value *V, Instruction *BI, if (TheNeg->getParent()->getParent() != BI->getParent()->getParent()) continue; + bool FoundCatchSwitch = false; + BasicBlock::iterator InsertPt; if (Instruction *InstInput = dyn_cast<Instruction>(V)) { if (InvokeInst *II = dyn_cast<InvokeInst>(InstInput)) { @@ -868,10 +870,30 @@ static Value *NegateValue(Value *V, Instruction *BI, } else { InsertPt = ++InstInput->getIterator(); } - while (isa<PHINode>(InsertPt)) ++InsertPt; + + const BasicBlock *BB = InsertPt->getParent(); + + // Make sure we don't move anything before PHIs or exception + // handling pads. + while (InsertPt != BB->end() && (isa<PHINode>(InsertPt) || + InsertPt->isEHPad())) { + if (isa<CatchSwitchInst>(InsertPt)) + // A catchswitch cannot have anything in the block except + // itself and PHIs. We'll bail out below. + FoundCatchSwitch = true; + ++InsertPt; + } } else { InsertPt = TheNeg->getParent()->getParent()->getEntryBlock().begin(); } + + // We found a catchswitch in the block where we want to move the + // neg. We cannot move anything into that block. Bail and just + // create the neg before BI, as if we hadn't found an existing + // neg. + if (FoundCatchSwitch) + break; + TheNeg->moveBefore(&*InsertPt); if (TheNeg->getOpcode() == Instruction::Sub) { TheNeg->setHasNoUnsignedWrap(false); |