diff options
author | Devang Patel <dpatel@apple.com> | 2008-03-11 22:24:29 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2008-03-11 22:24:29 +0000 |
commit | 7db30ba70111bd082d854e00f0b854c8d91eed76 (patch) | |
tree | 6be1904c52ca3325b767d5e0a55af98ed88bcf6d /lib/Transforms/IPO | |
parent | a0238778db5f96fc1dd104cd3c0c8e024f5e24b3 (diff) | |
download | llvm-7db30ba70111bd082d854e00f0b854c8d91eed76.tar.gz llvm-7db30ba70111bd082d854e00f0b854c8d91eed76.tar.bz2 llvm-7db30ba70111bd082d854e00f0b854c8d91eed76.tar.xz |
Handle multiple ret values.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48254 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r-- | lib/Transforms/IPO/IPConstantPropagation.cpp | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index 88cdbd0d71..6779ef2f0f 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallVector.h" using namespace llvm; STATISTIC(NumArgumentsProped, "Number of args turned into constants"); @@ -142,22 +143,44 @@ bool IPCP::PropagateConstantReturn(Function &F) { return false; // No return value. // Check to see if this function returns a constant. - Value *RetVal = 0; + SmallVector<Value *,4> RetVals; + unsigned N = 0; + const StructType *STy = dyn_cast<StructType>(F.getReturnType()); + if (STy) + N = STy->getNumElements(); + else + N = 1; + for (unsigned i = 0; i < N; ++i) + RetVals.push_back(0); + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { - if (isa<UndefValue>(RI->getOperand(0))) { - // Ignore. - } else if (Constant *C = dyn_cast<Constant>(RI->getOperand(0))) { - if (RetVal == 0) - RetVal = C; - else if (RetVal != C) - return false; // Does not return the same constant. - } else { - return false; // Does not return a constant. + assert (N == RI->getNumOperands() && "Invalid ReturnInst operands!"); + for (unsigned i = 0; i < N; ++i) { + if (isa<UndefValue>(RI->getOperand(i))) { + // Ignore + } else if (Constant *C = dyn_cast<Constant>(RI->getOperand(i))) { + Value *RV = RetVals[i]; + if (RV == 0) + RetVals[i] = C; + else if (RV != C) + return false; // Does not return the same constant. + } else { + return false; // Does not return a constant. + } } } - if (RetVal == 0) RetVal = UndefValue::get(F.getReturnType()); + if (N == 1) { + if (RetVals[0] == 0) + RetVals[0] = UndefValue::get(F.getReturnType()); + } else { + for (unsigned i = 0; i < N; ++i) { + Value *RetVal = RetVals[i]; + if (RetVal == 0) + RetVals[i] = UndefValue::get(STy->getElementType(i)); + } + } // If we got here, the function returns a constant value. Loop over all // users, replacing any uses of the return value with the returned constant. @@ -172,8 +195,18 @@ bool IPCP::PropagateConstantReturn(Function &F) { CS.getCalledFunction() != &F) { ReplacedAllUsers = false; } else { - if (!CS.getInstruction()->use_empty()) { - CS.getInstruction()->replaceAllUsesWith(RetVal); + Instruction *Call = CS.getInstruction(); + if (!Call->use_empty()) { + if (N == 1) + Call->replaceAllUsesWith(RetVals[0]); + else { + for(Value::use_iterator CUI = Call->use_begin(), CUE = Call->use_end(); + CUI != CUE; ++CUI) { + GetResultInst *GR = cast<GetResultInst>(CUI); + GR->replaceAllUsesWith(RetVals[GR->getIndex()]); + GR->eraseFromParent(); + } + } MadeChange = true; } } @@ -182,15 +215,20 @@ bool IPCP::PropagateConstantReturn(Function &F) { // If we replace all users with the returned constant, and there can be no // other callers of the function, replace the constant being returned in the // function with an undef value. - if (ReplacedAllUsers && F.hasInternalLinkage() && !isa<UndefValue>(RetVal)) { - Value *RV = UndefValue::get(RetVal->getType()); - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { - if (RI->getOperand(0) != RV) { - RI->setOperand(0, RV); - MadeChange = true; + if (ReplacedAllUsers && F.hasInternalLinkage()) { + for (unsigned i = 0; i < N; ++i) { + Value *RetVal = RetVals[i]; + if (isa<UndefValue>(RetVal)) + continue; + Value *RV = UndefValue::get(RetVal->getType()); + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { + if (RI->getOperand(i) != RV) { + RI->setOperand(i, RV); + MadeChange = true; + } } - } + } } if (MadeChange) ++NumReturnValProped; |