[llvm-commits] [llvm] r50199 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll
Chris Lattner
sabre at nondot.org
Wed Apr 23 17:01:20 PDT 2008
Author: lattner
Date: Wed Apr 23 19:01:19 2008
New Revision: 50199
URL: http://llvm.org/viewvc/llvm-project?rev=50199&view=rev
Log:
Split some code out of the main SimplifyCFG loop into its own function.
Fix said code to handle merging return instructions together correctly
when handling multiple return values.
Added:
llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=50199&r1=50198&r2=50199&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Wed Apr 23 19:01:19 2008
@@ -1165,6 +1165,105 @@
return true;
}
+/// SimplifyCondBranchToTwoReturns - If we found a conditional branch that goes
+/// to two returning blocks, try to merge them together into one return,
+/// introducing a select if the return values disagree.
+static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
+ assert(BI->isConditional() && "Must be a conditional branch");
+ BasicBlock *TrueSucc = BI->getSuccessor(0);
+ BasicBlock *FalseSucc = BI->getSuccessor(1);
+ ReturnInst *TrueRet = cast<ReturnInst>(TrueSucc->getTerminator());
+ ReturnInst *FalseRet = cast<ReturnInst>(FalseSucc->getTerminator());
+
+ // Check to ensure both blocks are empty (just a return) or optionally empty
+ // with PHI nodes. If there are other instructions, merging would cause extra
+ // computation on one path or the other.
+ BasicBlock::iterator BBI = TrueRet;
+ if (BBI != TrueSucc->begin() && !isa<PHINode>(--BBI))
+ return false; // Not empty with optional phi nodes.
+ BBI = FalseRet;
+ if (BBI != FalseSucc->begin() && !isa<PHINode>(--BBI))
+ return false; // Not empty with optional phi nodes.
+
+ // Okay, we found a branch that is going to two return nodes. If
+ // there is no return value for this function, just change the
+ // branch into a return.
+ if (FalseRet->getNumOperands() == 0) {
+ TrueSucc->removePredecessor(BI->getParent());
+ FalseSucc->removePredecessor(BI->getParent());
+ ReturnInst::Create(0, BI);
+ BI->eraseFromParent();
+ return true;
+ }
+
+ // Otherwise, build up the result values for the new return.
+ SmallVector<Value*, 4> TrueResult;
+ SmallVector<Value*, 4> FalseResult;
+
+ for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) {
+ // Otherwise, figure out what the true and false return values are
+ // so we can insert a new select instruction.
+ Value *TrueValue = TrueRet->getOperand(i);
+ Value *FalseValue = FalseRet->getOperand(i);
+
+ // Unwrap any PHI nodes in the return blocks.
+ if (PHINode *TVPN = dyn_cast<PHINode>(TrueValue))
+ if (TVPN->getParent() == TrueSucc)
+ TrueValue = TVPN->getIncomingValueForBlock(BI->getParent());
+ if (PHINode *FVPN = dyn_cast<PHINode>(FalseValue))
+ if (FVPN->getParent() == FalseSucc)
+ FalseValue = FVPN->getIncomingValueForBlock(BI->getParent());
+
+ // 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 (ConstantExpr *TCV = dyn_cast<ConstantExpr>(TrueValue))
+ if (TCV->canTrap())
+ return false;
+ if (ConstantExpr *FCV = dyn_cast<ConstantExpr>(FalseValue))
+ if (FCV->canTrap())
+ return false;
+
+ TrueResult.push_back(TrueValue);
+ FalseResult.push_back(FalseValue);
+ }
+
+ // Okay, we collected all the mapped values and checked them for sanity, and
+ // defined to really do this transformation. First, update the CFG.
+ TrueSucc->removePredecessor(BI->getParent());
+ FalseSucc->removePredecessor(BI->getParent());
+
+ // Insert select instructions where needed.
+ Value *BrCond = BI->getCondition();
+ for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) {
+ // Insert a select if the results differ.
+ if (TrueResult[i] == FalseResult[i] || isa<UndefValue>(FalseResult[i]))
+ continue;
+ if (isa<UndefValue>(TrueResult[i])) {
+ TrueResult[i] = FalseResult[i];
+ continue;
+ }
+
+ TrueResult[i] = SelectInst::Create(BrCond, TrueResult[i],
+ FalseResult[i], "retval", BI);
+ }
+
+ Value *RI = ReturnInst::Create(&TrueResult[0], TrueResult.size(), BI);
+
+ DOUT << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
+ << "\n " << *BI << "NewRet = " << *RI
+ << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc;
+
+ BI->eraseFromParent();
+
+ if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
+ ErasePossiblyDeadInstructionTree(BrCondI);
+ return true;
+}
+
+
namespace {
/// ConstantIntOrdering - This class implements a stable ordering of constant
/// integers that does not depend on their address. This is important for
@@ -1292,73 +1391,12 @@
while (!CondBranchPreds.empty()) {
BranchInst *BI = CondBranchPreds.back();
CondBranchPreds.pop_back();
- BasicBlock *TrueSucc = BI->getSuccessor(0);
- BasicBlock *FalseSucc = BI->getSuccessor(1);
- BasicBlock *OtherSucc = TrueSucc == BB ? FalseSucc : TrueSucc;
// Check to see if the non-BB successor is also a return block.
- if (isa<ReturnInst>(OtherSucc->getTerminator())) {
- // Check to see if there are only PHI instructions in this block.
- BasicBlock::iterator OSI = OtherSucc->getTerminator();
- if (OSI == OtherSucc->begin() || isa<PHINode>(--OSI)) {
- // Okay, we found a branch that is going to two return nodes. If
- // there is no return value for this function, just change the
- // branch into a return.
- if (RI->getNumOperands() == 0) {
- TrueSucc->removePredecessor(BI->getParent());
- FalseSucc->removePredecessor(BI->getParent());
- ReturnInst::Create(0, BI);
- BI->getParent()->getInstList().erase(BI);
- return true;
- }
-
- // Otherwise, figure out what the true and false return values are
- // so we can insert a new select instruction.
- Value *TrueValue = TrueSucc->getTerminator()->getOperand(0);
- Value *FalseValue = FalseSucc->getTerminator()->getOperand(0);
-
- // Unwrap any PHI nodes in the return blocks.
- if (PHINode *TVPN = dyn_cast<PHINode>(TrueValue))
- if (TVPN->getParent() == TrueSucc)
- TrueValue = TVPN->getIncomingValueForBlock(BI->getParent());
- if (PHINode *FVPN = dyn_cast<PHINode>(FalseValue))
- if (FVPN->getParent() == FalseSucc)
- FalseValue = FVPN->getIncomingValueForBlock(BI->getParent());
-
- // 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 = SelectInst::Create(BrCond, TrueValue,
- FalseValue, "retval", BI);
- else
- NewRetVal = TrueValue;
-
- DOUT << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
- << "\n " << *BI << "Select = " << *NewRetVal
- << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc;
-
- ReturnInst::Create(NewRetVal, BI);
- BI->eraseFromParent();
- if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
- if (isInstructionTriviallyDead(BrCondI))
- BrCondI->eraseFromParent();
- return true;
- }
- }
- }
+ if (isa<ReturnInst>(BI->getSuccessor(0)->getTerminator()) &&
+ isa<ReturnInst>(BI->getSuccessor(1)->getTerminator()) &&
+ SimplifyCondBranchToTwoReturns(BI))
+ return true;
}
}
} else if (isa<UnwindInst>(BB->begin())) {
Added: llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll?rev=50199&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll Wed Apr 23 19:01:19 2008
@@ -0,0 +1,43 @@
+; RUN: llvm-as < %s | opt -simplifycfg -disable-output
+; rdar://5882392
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin9"
+ %struct.Py_complex = type { double, double }
+
+define %struct.Py_complex @_Py_c_pow(double %a.0, double %a.1, double %b.0, double %b.1) nounwind {
+entry:
+ %tmp7 = fcmp une double %b.0, 0.000000e+00 ; <i1> [#uses=1]
+ %tmp11 = fcmp une double %b.1, 0.000000e+00 ; <i1> [#uses=1]
+ %bothcond = or i1 %tmp7, %tmp11 ; <i1> [#uses=1]
+ br i1 %bothcond, label %bb15, label %bb53
+
+bb15: ; preds = %entry
+ %tmp18 = fcmp une double %a.0, 0.000000e+00 ; <i1> [#uses=1]
+ %tmp24 = fcmp une double %a.1, 0.000000e+00 ; <i1> [#uses=1]
+ %bothcond1 = or i1 %tmp18, %tmp24 ; <i1> [#uses=1]
+ br i1 %bothcond1, label %bb29, label %bb27
+
+bb27: ; preds = %bb15
+ %tmp28 = call i32* @__error( ) nounwind ; <i32*> [#uses=1]
+ store i32 33, i32* %tmp28, align 4
+ ret double undef, double undef
+
+bb29: ; preds = %bb15
+ %tmp36 = fcmp une double %b.1, 0.000000e+00 ; <i1> [#uses=1]
+ br i1 %tmp36, label %bb39, label %bb47
+
+bb39: ; preds = %bb29
+ br label %bb47
+
+bb47: ; preds = %bb39, %bb29
+ ret double undef, double undef
+
+bb53: ; preds = %entry
+ ret double undef, double undef
+}
+
+declare i32* @__error()
+
+declare double @pow(double, double) nounwind readonly
+
+declare double @cos(double) nounwind readonly
More information about the llvm-commits
mailing list