Handle multiple ret values.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel
2008-03-11 22:24:29 +00:00
parent a0238778db
commit 7db30ba701
2 changed files with 79 additions and 21 deletions

View File

@@ -24,6 +24,7 @@
#include "llvm/Support/CallSite.h" #include "llvm/Support/CallSite.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm; using namespace llvm;
STATISTIC(NumArgumentsProped, "Number of args turned into constants"); STATISTIC(NumArgumentsProped, "Number of args turned into constants");
@@ -142,22 +143,44 @@ bool IPCP::PropagateConstantReturn(Function &F) {
return false; // No return value. return false; // No return value.
// Check to see if this function returns a constant. // 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) for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
if (isa<UndefValue>(RI->getOperand(0))) { assert (N == RI->getNumOperands() && "Invalid ReturnInst operands!");
// Ignore. for (unsigned i = 0; i < N; ++i) {
} else if (Constant *C = dyn_cast<Constant>(RI->getOperand(0))) { if (isa<UndefValue>(RI->getOperand(i))) {
if (RetVal == 0) // Ignore
RetVal = C; } else if (Constant *C = dyn_cast<Constant>(RI->getOperand(i))) {
else if (RetVal != C) Value *RV = RetVals[i];
return false; // Does not return the same constant. if (RV == 0)
} else { RetVals[i] = C;
return false; // Does not return a constant. 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 // 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. // users, replacing any uses of the return value with the returned constant.
@@ -172,8 +195,18 @@ bool IPCP::PropagateConstantReturn(Function &F) {
CS.getCalledFunction() != &F) { CS.getCalledFunction() != &F) {
ReplacedAllUsers = false; ReplacedAllUsers = false;
} else { } else {
if (!CS.getInstruction()->use_empty()) { Instruction *Call = CS.getInstruction();
CS.getInstruction()->replaceAllUsesWith(RetVal); 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; 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 // 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 // other callers of the function, replace the constant being returned in the
// function with an undef value. // function with an undef value.
if (ReplacedAllUsers && F.hasInternalLinkage() && !isa<UndefValue>(RetVal)) { if (ReplacedAllUsers && F.hasInternalLinkage()) {
Value *RV = UndefValue::get(RetVal->getType()); for (unsigned i = 0; i < N; ++i) {
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) Value *RetVal = RetVals[i];
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { if (isa<UndefValue>(RetVal))
if (RI->getOperand(0) != RV) { continue;
RI->setOperand(0, RV); Value *RV = UndefValue::get(RetVal->getType());
MadeChange = true; 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; if (MadeChange) ++NumReturnValProped;

View File

@@ -0,0 +1,20 @@
; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis | grep {add i32 21, 21}
define internal {i32, i32} @foo(i1 %C) {
br i1 %C, label %T, label %F
T: ; preds = %0
ret i32 21, i32 21
F: ; preds = %0
ret i32 21, i32 21
}
define i32 @caller(i1 %C) {
%X = call {i32, i32} @foo( i1 %C )
%A = getresult {i32, i32} %X, 0
%B = getresult {i32, i32} %X, 1
%Y = add i32 %A, %B
ret i32 %Y
}