mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-08 19:25:47 +00:00
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:
@@ -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;
|
||||||
|
20
test/Transforms/IPConstantProp/return-constants.ll
Normal file
20
test/Transforms/IPConstantProp/return-constants.ll
Normal 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
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user