From 7db30ba70111bd082d854e00f0b854c8d91eed76 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Tue, 11 Mar 2008 22:24:29 +0000 Subject: [PATCH] Handle multiple ret values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48254 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/IPConstantPropagation.cpp | 80 ++++++++++++++----- .../IPConstantProp/return-constants.ll | 20 +++++ 2 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 test/Transforms/IPConstantProp/return-constants.ll diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index 88cdbd0d71b..6779ef2f0fa 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 RetVals; + unsigned N = 0; + const StructType *STy = dyn_cast(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(BB->getTerminator())) { - if (isa(RI->getOperand(0))) { - // Ignore. - } else if (Constant *C = dyn_cast(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(RI->getOperand(i))) { + // Ignore + } else if (Constant *C = dyn_cast(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(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(RetVal)) { - Value *RV = UndefValue::get(RetVal->getType()); - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(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(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(BB->getTerminator())) { + if (RI->getOperand(i) != RV) { + RI->setOperand(i, RV); + MadeChange = true; + } } - } + } } if (MadeChange) ++NumReturnValProped; diff --git a/test/Transforms/IPConstantProp/return-constants.ll b/test/Transforms/IPConstantProp/return-constants.ll new file mode 100644 index 00000000000..40567f80bd8 --- /dev/null +++ b/test/Transforms/IPConstantProp/return-constants.ll @@ -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 +} +