mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-24 08:18:33 +00:00
Initial multiple return values support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48210 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -129,6 +129,21 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// LatticeValIndex - LatticeVal and associated Index. This is used
|
||||||
|
/// to track individual operand Lattice values for multi value ret instructions.
|
||||||
|
class VISIBILITY_HIDDEN LatticeValIndexed {
|
||||||
|
public:
|
||||||
|
LatticeValIndexed(unsigned I = 0) { Index = I; }
|
||||||
|
LatticeVal &getLatticeVal() { return LV; }
|
||||||
|
unsigned getIndex() const { return Index; }
|
||||||
|
|
||||||
|
void setLatticeVal(LatticeVal &L) { LV = L; }
|
||||||
|
void setIndex(unsigned I) { Index = I; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
LatticeVal LV;
|
||||||
|
unsigned Index;
|
||||||
|
};
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
/// SCCPSolver - This class is a general purpose solver for Sparse Conditional
|
/// SCCPSolver - This class is a general purpose solver for Sparse Conditional
|
||||||
@@ -144,10 +159,14 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
|
|||||||
/// overdefined, it's entry is simply removed from this map.
|
/// overdefined, it's entry is simply removed from this map.
|
||||||
DenseMap<GlobalVariable*, LatticeVal> TrackedGlobals;
|
DenseMap<GlobalVariable*, LatticeVal> TrackedGlobals;
|
||||||
|
|
||||||
/// TrackedFunctionRetVals - If we are tracking arguments into and the return
|
/// TrackedRetVals - If we are tracking arguments into and the return
|
||||||
/// value out of a function, it will have an entry in this map, indicating
|
/// value out of a function, it will have an entry in this map, indicating
|
||||||
/// what the known return value for the function is.
|
/// what the known return value for the function is.
|
||||||
DenseMap<Function*, LatticeVal> TrackedFunctionRetVals;
|
DenseMap<Function*, LatticeVal> TrackedRetVals;
|
||||||
|
|
||||||
|
/// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
|
||||||
|
/// that return multiple values.
|
||||||
|
std::multimap<Function*, LatticeValIndexed> TrackedMultipleRetVals;
|
||||||
|
|
||||||
// The reason for two worklists is that overdefined is the lowest state
|
// The reason for two worklists is that overdefined is the lowest state
|
||||||
// on the lattice, and moving things to overdefined as fast as possible
|
// on the lattice, and moving things to overdefined as fast as possible
|
||||||
@@ -198,7 +217,13 @@ public:
|
|||||||
void AddTrackedFunction(Function *F) {
|
void AddTrackedFunction(Function *F) {
|
||||||
assert(F->hasInternalLinkage() && "Can only track internal functions!");
|
assert(F->hasInternalLinkage() && "Can only track internal functions!");
|
||||||
// Add an entry, F -> undef.
|
// Add an entry, F -> undef.
|
||||||
TrackedFunctionRetVals[F];
|
if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
|
||||||
|
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
|
||||||
|
TrackedMultipleRetVals.insert(std::pair<Function *, LatticeValIndexed>
|
||||||
|
(F, LatticeValIndexed(i)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TrackedRetVals[F];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Solve - Solve for constants and executable blocks.
|
/// Solve - Solve for constants and executable blocks.
|
||||||
@@ -224,10 +249,10 @@ public:
|
|||||||
return ValueState;
|
return ValueState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getTrackedFunctionRetVals - Get the inferred return value map.
|
/// getTrackedRetVals - Get the inferred return value map.
|
||||||
///
|
///
|
||||||
const DenseMap<Function*, LatticeVal> &getTrackedFunctionRetVals() {
|
const DenseMap<Function*, LatticeVal> &getTrackedRetVals() {
|
||||||
return TrackedFunctionRetVals;
|
return TrackedRetVals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getTrackedGlobals - Get and return the set of inferred initializers for
|
/// getTrackedGlobals - Get and return the set of inferred initializers for
|
||||||
@@ -374,6 +399,7 @@ private:
|
|||||||
void visitTerminatorInst(TerminatorInst &TI);
|
void visitTerminatorInst(TerminatorInst &TI);
|
||||||
|
|
||||||
void visitCastInst(CastInst &I);
|
void visitCastInst(CastInst &I);
|
||||||
|
void visitGetResultInst(GetResultInst &GRI);
|
||||||
void visitSelectInst(SelectInst &I);
|
void visitSelectInst(SelectInst &I);
|
||||||
void visitBinaryOperator(Instruction &I);
|
void visitBinaryOperator(Instruction &I);
|
||||||
void visitCmpInst(CmpInst &I);
|
void visitCmpInst(CmpInst &I);
|
||||||
@@ -608,20 +634,35 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
|
|||||||
void SCCPSolver::visitReturnInst(ReturnInst &I) {
|
void SCCPSolver::visitReturnInst(ReturnInst &I) {
|
||||||
if (I.getNumOperands() == 0) return; // Ret void
|
if (I.getNumOperands() == 0) return; // Ret void
|
||||||
|
|
||||||
// If we are tracking the return value of this function, merge it in.
|
|
||||||
Function *F = I.getParent()->getParent();
|
Function *F = I.getParent()->getParent();
|
||||||
if (F->hasInternalLinkage() && !TrackedFunctionRetVals.empty()) {
|
// If we are tracking the return value of this function, merge it in.
|
||||||
|
if (!F->hasInternalLinkage())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TrackedRetVals.empty()) {
|
||||||
DenseMap<Function*, LatticeVal>::iterator TFRVI =
|
DenseMap<Function*, LatticeVal>::iterator TFRVI =
|
||||||
TrackedFunctionRetVals.find(F);
|
TrackedRetVals.find(F);
|
||||||
if (TFRVI != TrackedFunctionRetVals.end() &&
|
if (TFRVI != TrackedRetVals.end() &&
|
||||||
!TFRVI->second.isOverdefined()) {
|
!TFRVI->second.isOverdefined()) {
|
||||||
LatticeVal &IV = getValueState(I.getOperand(0));
|
LatticeVal &IV = getValueState(I.getOperand(0));
|
||||||
mergeInValue(TFRVI->second, F, IV);
|
mergeInValue(TFRVI->second, F, IV);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle function that returns multiple values.
|
||||||
|
std::multimap<Function*, LatticeValIndexed>::iterator It, E;
|
||||||
|
tie(It, E) = TrackedMultipleRetVals.equal_range(F);
|
||||||
|
if (It != E) {
|
||||||
|
for (; It != E; ++It) {
|
||||||
|
LatticeValIndexed &LV = It->second;
|
||||||
|
unsigned Idx = LV.getIndex();
|
||||||
|
Value *V = I.getOperand(Idx);
|
||||||
|
mergeInValue(LV.getLatticeVal(), V, getValueState(V));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SCCPSolver::visitTerminatorInst(TerminatorInst &TI) {
|
void SCCPSolver::visitTerminatorInst(TerminatorInst &TI) {
|
||||||
SmallVector<bool, 16> SuccFeasible;
|
SmallVector<bool, 16> SuccFeasible;
|
||||||
getFeasibleSuccessors(TI, SuccFeasible);
|
getFeasibleSuccessors(TI, SuccFeasible);
|
||||||
@@ -644,6 +685,30 @@ void SCCPSolver::visitCastInst(CastInst &I) {
|
|||||||
VState.getConstant(), I.getType()));
|
VState.getConstant(), I.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SCCPSolver::visitGetResultInst(GetResultInst &GRI) {
|
||||||
|
unsigned Idx = GRI.getIndex();
|
||||||
|
Value *Aggr = GRI.getOperand(0);
|
||||||
|
Function *F = NULL;
|
||||||
|
if (CallInst *CI = dyn_cast<CallInst>(Aggr))
|
||||||
|
F = CI->getCalledFunction();
|
||||||
|
else if (InvokeInst *II = dyn_cast<InvokeInst>(Aggr))
|
||||||
|
F = II->getCalledFunction();
|
||||||
|
|
||||||
|
assert (F && "Invalid GetResultInst operands!");
|
||||||
|
|
||||||
|
std::multimap<Function*, LatticeValIndexed>::iterator It, E;
|
||||||
|
tie(It, E) = TrackedMultipleRetVals.equal_range(F);
|
||||||
|
if (It == E)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (; It != E; ++It) {
|
||||||
|
LatticeValIndexed &LIV = It->second;
|
||||||
|
if (LIV.getIndex() == Idx) {
|
||||||
|
mergeInValue(&GRI, LIV.getLatticeVal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SCCPSolver::visitSelectInst(SelectInst &I) {
|
void SCCPSolver::visitSelectInst(SelectInst &I) {
|
||||||
LatticeVal &CondValue = getValueState(I.getCondition());
|
LatticeVal &CondValue = getValueState(I.getCondition());
|
||||||
if (CondValue.isUndefined())
|
if (CondValue.isUndefined())
|
||||||
@@ -1061,13 +1126,23 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
|
|||||||
void SCCPSolver::visitCallSite(CallSite CS) {
|
void SCCPSolver::visitCallSite(CallSite CS) {
|
||||||
Function *F = CS.getCalledFunction();
|
Function *F = CS.getCalledFunction();
|
||||||
|
|
||||||
|
DenseMap<Function*, LatticeVal>::iterator TFRVI =TrackedRetVals.end();
|
||||||
// If we are tracking this function, we must make sure to bind arguments as
|
// If we are tracking this function, we must make sure to bind arguments as
|
||||||
// appropriate.
|
// appropriate.
|
||||||
DenseMap<Function*, LatticeVal>::iterator TFRVI =TrackedFunctionRetVals.end();
|
bool FirstCall = false;
|
||||||
if (F && F->hasInternalLinkage())
|
if (F && F->hasInternalLinkage()) {
|
||||||
TFRVI = TrackedFunctionRetVals.find(F);
|
TFRVI = TrackedRetVals.find(F);
|
||||||
|
if (TFRVI != TrackedRetVals.end())
|
||||||
|
FirstCall = true;
|
||||||
|
else {
|
||||||
|
std::multimap<Function*, LatticeValIndexed>::iterator It, E;
|
||||||
|
tie(It, E) = TrackedMultipleRetVals.equal_range(F);
|
||||||
|
if (It != E)
|
||||||
|
FirstCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TFRVI != TrackedFunctionRetVals.end()) {
|
if (FirstCall) {
|
||||||
// If this is the first call to the function hit, mark its entry block
|
// If this is the first call to the function hit, mark its entry block
|
||||||
// executable.
|
// executable.
|
||||||
if (!BBExecutable.count(F->begin()))
|
if (!BBExecutable.count(F->begin()))
|
||||||
@@ -1091,8 +1166,9 @@ void SCCPSolver::visitCallSite(CallSite CS) {
|
|||||||
LatticeVal &IV = ValueState[I];
|
LatticeVal &IV = ValueState[I];
|
||||||
if (IV.isOverdefined()) return;
|
if (IV.isOverdefined()) return;
|
||||||
|
|
||||||
// Propagate the return value of the function to the value of the instruction.
|
// Propagate the single return value of the function to the value of the
|
||||||
if (TFRVI != TrackedFunctionRetVals.end()) {
|
// instruction.
|
||||||
|
if (TFRVI != TrackedRetVals.end()) {
|
||||||
mergeInValue(IV, I, TFRVI->second);
|
mergeInValue(IV, I, TFRVI->second);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1684,7 +1760,7 @@ bool IPSCCP::runOnModule(Module &M) {
|
|||||||
// all call uses with the inferred value. This means we don't need to bother
|
// all call uses with the inferred value. This means we don't need to bother
|
||||||
// actually returning anything from the function. Replace all return
|
// actually returning anything from the function. Replace all return
|
||||||
// instructions with return undef.
|
// instructions with return undef.
|
||||||
const DenseMap<Function*, LatticeVal> &RV =Solver.getTrackedFunctionRetVals();
|
const DenseMap<Function*, LatticeVal> &RV = Solver.getTrackedRetVals();
|
||||||
for (DenseMap<Function*, LatticeVal>::const_iterator I = RV.begin(),
|
for (DenseMap<Function*, LatticeVal>::const_iterator I = RV.begin(),
|
||||||
E = RV.end(); I != E; ++I)
|
E = RV.end(); I != E; ++I)
|
||||||
if (!I->second.isOverdefined() &&
|
if (!I->second.isOverdefined() &&
|
||||||
|
|||||||
12
test/Transforms/SCCP/2008-03-10-sret.ll
Normal file
12
test/Transforms/SCCP/2008-03-10-sret.ll
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
; RUN: llvm-as < %s | opt -ipsccp -disable-output
|
||||||
|
|
||||||
|
define internal {i32, i32} @bar(i32 %A) {
|
||||||
|
%X = add i32 1, 2
|
||||||
|
ret i32 %A, i32 %A
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @foo() {
|
||||||
|
%X = call {i32, i32} @bar(i32 17)
|
||||||
|
%Y = getresult {i32, i32} %X, 0
|
||||||
|
ret i32 %Y
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user