//===-- IPConstantPropagation.cpp - Propagate constants through calls -----===//
-//
+//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
//===----------------------------------------------------------------------===//
//
// This pass implements an _extremely_ simple interprocedural constant
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "ipconstprop"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CallSite.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/SmallVector.h"
using namespace llvm;
-namespace {
- Statistic<> NumArgumentsProped("ipconstprop",
- "Number of args turned into constants");
- Statistic<> NumReturnValProped("ipconstprop",
- "Number of return values turned into constants");
+STATISTIC(NumArgumentsProped, "Number of args turned into constants");
+STATISTIC(NumReturnValProped, "Number of return values turned into constants");
+namespace {
/// IPCP - The interprocedural constant propagation pass
///
- struct IPCP : public ModulePass {
+ struct VISIBILITY_HIDDEN IPCP : public ModulePass {
+ static char ID; // Pass identification, replacement for typeid
+ IPCP() : ModulePass((intptr_t)&ID) {}
+
bool runOnModule(Module &M);
private:
bool PropagateConstantsIntoArguments(Function &F);
bool PropagateConstantReturn(Function &F);
};
- RegisterOpt<IPCP> X("ipconstprop", "Interprocedural constant propagation");
+ char IPCP::ID = 0;
+ RegisterPass<IPCP> X("ipconstprop", "Interprocedural constant propagation");
}
ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }
while (LocalChange) {
LocalChange = false;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (!I->isExternal()) {
+ if (!I->isDeclaration()) {
// Delete any klingons.
I->removeDeadConstantUsers();
if (I->hasInternalLinkage())
/// constant in for an argument, propagate that constant in as the argument.
///
bool IPCP::PropagateConstantsIntoArguments(Function &F) {
- if (F.aempty() || F.use_empty()) return false; // No arguments? Early exit.
+ if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit.
std::vector<std::pair<Constant*, bool> > ArgumentConstants;
- ArgumentConstants.resize(F.asize());
+ ArgumentConstants.resize(F.arg_size());
unsigned NumNonconstant = 0;
return false; // Used by a non-instruction, do not transform
else {
CallSite CS = CallSite::get(cast<Instruction>(*I));
- if (CS.getInstruction() == 0 ||
+ if (CS.getInstruction() == 0 ||
CS.getCalledFunction() != &F)
return false; // Not a direct call site?
-
+
// Check out all of the potentially constant arguments
CallSite::arg_iterator AI = CS.arg_begin();
- Function::aiterator Arg = F.abegin();
+ Function::arg_iterator Arg = F.arg_begin();
for (unsigned i = 0, e = ArgumentConstants.size(); i != e;
++i, ++AI, ++Arg) {
if (*AI == &F) return false; // Passes the function into itself
// If we got to this point, there is a constant argument!
assert(NumNonconstant != ArgumentConstants.size());
- Function::aiterator AI = F.abegin();
+ Function::arg_iterator AI = F.arg_begin();
bool MadeChange = false;
for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI)
// Do we have a constant argument!?
return false; // No return value.
// Check to see if this function returns a constant.
- Value *RetVal = 0;
+ SmallVector<Value *,4> RetVals;
+ const StructType *STy = dyn_cast<StructType>(F.getReturnType());
+ if (STy)
+ RetVals.assign(STy->getNumElements(), 0);
+ else
+ RetVals.push_back(0);
+
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
- if (isa<UndefValue>(RI->getOperand(0))) {
- // Ignore.
- } else if (Constant *C = dyn_cast<Constant>(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.
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+ unsigned RetValsSize = RetVals.size();
+ assert (RetValsSize == RI->getNumOperands() && "Invalid ReturnInst operands!");
+ for (unsigned i = 0; i < RetValsSize; ++i) {
+ if (isa<UndefValue>(RI->getOperand(i))) {
+ // Ignore
+ } else if (Constant *C = dyn_cast<Constant>(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 (STy) {
+ for (unsigned i = 0, e = RetVals.size(); i < e; ++i)
+ if (RetVals[i] == 0)
+ RetVals[i] = UndefValue::get(STy->getElementType(i));
+ } else {
+ if (RetVals.size() == 1)
+ if (RetVals[0] == 0)
+ RetVals[0] = UndefValue::get(F.getReturnType());
+ }
// 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.
ReplacedAllUsers = false;
else {
CallSite CS = CallSite::get(cast<Instruction>(*I));
- if (CS.getInstruction() == 0 ||
+ if (CS.getInstruction() == 0 ||
CS.getCalledFunction() != &F) {
ReplacedAllUsers = false;
} else {
- if (!CS.getInstruction()->use_empty()) {
- CS.getInstruction()->replaceAllUsesWith(RetVal);
+ Instruction *Call = CS.getInstruction();
+ if (!Call->use_empty()) {
+ if (RetVals.size() == 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);
+ if (RetVals[GR->getIndex()]) {
+ GR->replaceAllUsesWith(RetVals[GR->getIndex()]);
+ GR->eraseFromParent();
+ }
+ }
+ }
MadeChange = true;
}
}
// 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<UndefValue>(RetVal)) {
- Value *RV = UndefValue::get(RetVal->getType());
- for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
- RI->setOperand(0, RV);
- MadeChange = true;
+ if (ReplacedAllUsers && F.hasInternalLinkage()) {
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
+ for (unsigned i = 0, e = RetVals.size(); i < e; ++i) {
+ Value *RetVal = RetVals[i];
+ if (isa<UndefValue>(RetVal))
+ continue;
+ Value *RV = UndefValue::get(RetVal->getType());
+ if (RI->getOperand(i) != RV) {
+ RI->setOperand(i, RV);
+ MadeChange = true;
+ }
+ }
+ }
+ }
}
if (MadeChange) ++NumReturnValProped;