[llvm-commits] [llvm] r48210 - in /llvm/trunk: lib/Transforms/Scalar/SCCP.cpp test/Transforms/SCCP/2008-03-10-sret.ll
Devang Patel
dpatel at apple.com
Mon Mar 10 22:46:42 PDT 2008
Author: dpatel
Date: Tue Mar 11 00:46:42 2008
New Revision: 48210
URL: http://llvm.org/viewvc/llvm-project?rev=48210&view=rev
Log:
Initial multiple return values support.
Added:
llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=48210&r1=48209&r2=48210&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Tue Mar 11 00:46:42 2008
@@ -129,6 +129,21 @@
}
};
+/// 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
@@ -144,10 +159,14 @@
/// overdefined, it's entry is simply removed from this map.
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
/// 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
// on the lattice, and moving things to overdefined as fast as possible
@@ -198,7 +217,13 @@
void AddTrackedFunction(Function *F) {
assert(F->hasInternalLinkage() && "Can only track internal functions!");
// 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.
@@ -224,10 +249,10 @@
return ValueState;
}
- /// getTrackedFunctionRetVals - Get the inferred return value map.
+ /// getTrackedRetVals - Get the inferred return value map.
///
- const DenseMap<Function*, LatticeVal> &getTrackedFunctionRetVals() {
- return TrackedFunctionRetVals;
+ const DenseMap<Function*, LatticeVal> &getTrackedRetVals() {
+ return TrackedRetVals;
}
/// getTrackedGlobals - Get and return the set of inferred initializers for
@@ -374,6 +399,7 @@
void visitTerminatorInst(TerminatorInst &TI);
void visitCastInst(CastInst &I);
+ void visitGetResultInst(GetResultInst &GRI);
void visitSelectInst(SelectInst &I);
void visitBinaryOperator(Instruction &I);
void visitCmpInst(CmpInst &I);
@@ -608,20 +634,35 @@
void SCCPSolver::visitReturnInst(ReturnInst &I) {
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();
- 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 =
- TrackedFunctionRetVals.find(F);
- if (TFRVI != TrackedFunctionRetVals.end() &&
+ TrackedRetVals.find(F);
+ if (TFRVI != TrackedRetVals.end() &&
!TFRVI->second.isOverdefined()) {
LatticeVal &IV = getValueState(I.getOperand(0));
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) {
SmallVector<bool, 16> SuccFeasible;
getFeasibleSuccessors(TI, SuccFeasible);
@@ -644,6 +685,30 @@
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) {
LatticeVal &CondValue = getValueState(I.getCondition());
if (CondValue.isUndefined())
@@ -1061,18 +1126,28 @@
void SCCPSolver::visitCallSite(CallSite CS) {
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
// appropriate.
- DenseMap<Function*, LatticeVal>::iterator TFRVI =TrackedFunctionRetVals.end();
- if (F && F->hasInternalLinkage())
- TFRVI = TrackedFunctionRetVals.find(F);
+ bool FirstCall = false;
+ if (F && F->hasInternalLinkage()) {
+ 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
// executable.
if (!BBExecutable.count(F->begin()))
MarkBlockExecutable(F->begin());
-
+
CallSite::arg_iterator CAI = CS.arg_begin();
for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
AI != E; ++AI, ++CAI) {
@@ -1091,8 +1166,9 @@
LatticeVal &IV = ValueState[I];
if (IV.isOverdefined()) return;
- // Propagate the return value of the function to the value of the instruction.
- if (TFRVI != TrackedFunctionRetVals.end()) {
+ // Propagate the single return value of the function to the value of the
+ // instruction.
+ if (TFRVI != TrackedRetVals.end()) {
mergeInValue(IV, I, TFRVI->second);
return;
}
@@ -1684,7 +1760,7 @@
// all call uses with the inferred value. This means we don't need to bother
// actually returning anything from the function. Replace all return
// 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(),
E = RV.end(); I != E; ++I)
if (!I->second.isOverdefined() &&
Added: llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll?rev=48210&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll (added)
+++ llvm/trunk/test/Transforms/SCCP/2008-03-10-sret.ll Tue Mar 11 00:46:42 2008
@@ -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
+}
More information about the llvm-commits
mailing list