aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-10-20 00:42:07 +0000
committerChris Lattner <sabre@nondot.org>2006-10-20 00:42:07 +0000
commitb74b1816305affe25da32c2f29532df41a23cd55 (patch)
tree3f7e05efb0daa08366016031d31946a5b6261f92
parent8a53688a135e9207392b99cdf8270646d06d38ca (diff)
downloadexternal_llvm-b74b1816305affe25da32c2f29532df41a23cd55.zip
external_llvm-b74b1816305affe25da32c2f29532df41a23cd55.tar.gz
external_llvm-b74b1816305affe25da32c2f29532df41a23cd55.tar.bz2
Fix SimplifyCFG/2006-10-19-UncondDiv.ll by disabling a bad xform.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31061 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp63
1 files changed, 40 insertions, 23 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 7ac9444..867455e 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -323,7 +323,14 @@ static Value *GetIfCondition(BasicBlock *BB,
static bool DominatesMergePoint(Value *V, BasicBlock *BB,
std::set<Instruction*> *AggressiveInsts) {
Instruction *I = dyn_cast<Instruction>(V);
- if (!I) return true; // Non-instructions all dominate instructions.
+ if (!I) {
+ // Non-instructions all dominate instructions, but not all constantexprs
+ // can be executed unconditionally.
+ if (ConstantExpr *C = dyn_cast<ConstantExpr>(V))
+ if (C->canTrap())
+ return false;
+ return true;
+ }
BasicBlock *PBB = I->getParent();
// We don't want to allow weird loops that might have the "if condition" in
@@ -1297,28 +1304,38 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
if (FVPN->getParent() == FalseSucc)
FalseValue = FVPN->getIncomingValueForBlock(BI->getParent());
- TrueSucc->removePredecessor(BI->getParent());
- FalseSucc->removePredecessor(BI->getParent());
-
- // Insert a new select instruction.
- Value *NewRetVal;
- Value *BrCond = BI->getCondition();
- if (TrueValue != FalseValue)
- NewRetVal = new SelectInst(BrCond, TrueValue,
- FalseValue, "retval", BI);
- else
- NewRetVal = TrueValue;
-
- DEBUG(std::cerr << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
- << "\n " << *BI << "Select = " << *NewRetVal
- << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc);
-
- new ReturnInst(NewRetVal, BI);
- BI->eraseFromParent();
- if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
- if (isInstructionTriviallyDead(BrCondI))
- BrCondI->eraseFromParent();
- return true;
+ // In order for this transformation to be safe, we must be able to
+ // unconditionally execute both operands to the return. This is
+ // normally the case, but we could have a potentially-trapping
+ // constant expression that prevents this transformation from being
+ // safe.
+ if ((!isa<ConstantExpr>(TrueValue) ||
+ !cast<ConstantExpr>(TrueValue)->canTrap()) &&
+ (!isa<ConstantExpr>(TrueValue) ||
+ !cast<ConstantExpr>(TrueValue)->canTrap())) {
+ TrueSucc->removePredecessor(BI->getParent());
+ FalseSucc->removePredecessor(BI->getParent());
+
+ // Insert a new select instruction.
+ Value *NewRetVal;
+ Value *BrCond = BI->getCondition();
+ if (TrueValue != FalseValue)
+ NewRetVal = new SelectInst(BrCond, TrueValue,
+ FalseValue, "retval", BI);
+ else
+ NewRetVal = TrueValue;
+
+ DEBUG(std::cerr << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
+ << "\n " << *BI << "Select = " << *NewRetVal
+ << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc);
+
+ new ReturnInst(NewRetVal, BI);
+ BI->eraseFromParent();
+ if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
+ if (isInstructionTriviallyDead(BrCondI))
+ BrCondI->eraseFromParent();
+ return true;
+ }
}
}
}