[llvm-commits] CVS: llvm/lib/Transforms/IPO/GlobalOpt.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun May 8 15:18:22 PDT 2005
Changes in directory llvm/lib/Transforms/IPO:
GlobalOpt.cpp updated: 1.39 -> 1.40
---
Log message:
Convert non-address taken functions with C calling conventions to fastcc.
---
Diffs of the changes: (+41 -1)
GlobalOpt.cpp | 42 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 41 insertions(+), 1 deletion(-)
Index: llvm/lib/Transforms/IPO/GlobalOpt.cpp
diff -u llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.39 llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.40
--- llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.39 Thu Apr 21 18:39:37 2005
+++ llvm/lib/Transforms/IPO/GlobalOpt.cpp Sun May 8 17:18:06 2005
@@ -15,6 +15,7 @@
#define DEBUG_TYPE "globalopt"
#include "llvm/Transforms/IPO.h"
+#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
@@ -42,6 +43,8 @@
Statistic<> NumLocalized("globalopt", "Number of globals localized");
Statistic<> NumShrunkToBool("globalopt",
"Number of global vars shrunk to booleans");
+ Statistic<> NumFastCallFns("globalopt",
+ "Number of functions converted to fastcc");
struct GlobalOpt : public ModulePass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@@ -1039,6 +1042,32 @@
return false;
}
+/// OnlyCalledDirectly - Return true if the specified function is only called
+/// directly. In other words, its address is never taken.
+static bool OnlyCalledDirectly(Function *F) {
+ for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
+ Instruction *User = dyn_cast<Instruction>(*UI);
+ if (!User) return false;
+ if (!isa<CallInst>(User) && !isa<InvokeInst>(User)) return false;
+
+ // See if the function address is passed as an argument.
+ for (unsigned i = 1, e = User->getNumOperands(); i != e; ++i)
+ if (User->getOperand(i) == F) return false;
+ }
+ return true;
+}
+
+/// ChangeCalleesToFastCall - Walk all of the direct calls of the specified
+/// function, changing them to FastCC.
+static void ChangeCalleesToFastCall(Function *F) {
+ for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
+ Instruction *User = cast<Instruction>(*UI);
+ if (CallInst *CI = dyn_cast<CallInst>(User))
+ CI->setCallingConv(CallingConv::Fast);
+ else
+ cast<InvokeInst>(User)->setCallingConv(CallingConv::Fast);
+ }
+}
bool GlobalOpt::runOnModule(Module &M) {
bool Changed = false;
@@ -1055,6 +1084,16 @@
M.getFunctionList().erase(F);
LocalChange = true;
++NumFnDeleted;
+ } else if (F->hasInternalLinkage() &&
+ F->getCallingConv() == CallingConv::C && !F->isVarArg() &&
+ OnlyCalledDirectly(F)) {
+ // If this function has C calling conventions, is not a varargs
+ // function, and is only called directly, promote it to use the Fast
+ // calling convention.
+ F->setCallingConv(CallingConv::Fast);
+ ChangeCalleesToFastCall(F);
+ ++NumFastCallFns;
+ LocalChange = true;
}
}
Changed |= LocalChange;
@@ -1063,7 +1102,8 @@
LocalChange = true;
while (LocalChange) {
LocalChange = false;
- for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); GVI != E;) {
+ for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
+ GVI != E; ) {
GlobalVariable *GV = GVI++;
if (!GV->isConstant() && GV->hasInternalLinkage() &&
GV->hasInitializer())
More information about the llvm-commits
mailing list