Mercurial > projects > ldc
diff gen/passes/SimplifyDRuntimeCalls.cpp @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 8d086d552909 |
children |
line wrap: on
line diff
--- a/gen/passes/SimplifyDRuntimeCalls.cpp Fri Mar 19 09:31:25 2010 +0100 +++ b/gen/passes/SimplifyDRuntimeCalls.cpp Wed May 19 12:42:32 2010 +0200 @@ -18,6 +18,7 @@ #include "Passes.h" +#include "llvm/Function.h" #include "llvm/Pass.h" #include "llvm/Intrinsics.h" #include "llvm/Support/IRBuilder.h" @@ -48,25 +49,25 @@ const TargetData *TD; AliasAnalysis *AA; LLVMContext *Context; - + /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. Value *CastToCStr(Value *V, IRBuilder<> &B); - + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, + Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, IRBuilder<> &B); public: LibCallOptimization() { } virtual ~LibCallOptimization() {} - + /// CallOptimizer - This pure virtual method is implemented by base classes to /// do various optimizations. If this returns null then no transformation was /// performed. If it returns CI, then it transformed the call and CI is to be /// deleted. If it returns something else, replace CI with the new value and /// delete CI. virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0; - + Value *OptimizeCall(CallInst *CI, bool& Changed, const TargetData &TD, AliasAnalysis& AA, IRBuilder<> &B) { Caller = CI->getParent()->getParent(); @@ -116,27 +117,27 @@ FT->getParamType(1) != FT->getParamType(2) || FT->getParamType(3) != FT->getReturnType()) return 0; - + // Whether or not this allocates is irrelevant if the result isn't used. // Just delete if that's the case. if (CI->use_empty()) return CI; - + Value* NewLen = CI->getOperand(2); if (Constant* NewCst = dyn_cast<Constant>(NewLen)) { Value* Data = CI->getOperand(4); - + // For now, we just catch the simplest of cases. // // TODO: Implement a more general way to compare old and new // lengths, to catch cases like "arr.length = arr.length - 1;" // (But beware of unsigned overflow! For example, we can't // safely transform that example if arr.length may be 0) - + // Setting length to 0 never reallocates, so replace by data argument if (NewCst->isNullValue()) return Data; - + // If both lengths are constant integers, see if NewLen <= OldLen Value* OldLen = CI->getOperand(3); if (ConstantInt* OldInt = dyn_cast<ConstantInt>(OldLen)) @@ -157,27 +158,27 @@ if (Callee->arg_size() != 3 || !isa<IntegerType>(RetTy) || FT->getParamType(1) != RetTy || FT->getParamType(2) != RetTy) return 0; - + Value* OldLen = CI->getOperand(1); Value* OldSize = CI->getOperand(2); Value* NewSize = CI->getOperand(3); - + // If the old length was zero, always return zero. if (Constant* LenCst = dyn_cast<Constant>(OldLen)) if (LenCst->isNullValue()) return OldLen; - + // Equal sizes are much faster to check for, so do so now. if (OldSize == NewSize) return OldLen; - + // If both sizes are constant integers, see if OldSize is a multiple of NewSize if (ConstantInt* OldInt = dyn_cast<ConstantInt>(OldSize)) if (ConstantInt* NewInt = dyn_cast<ConstantInt>(NewSize)) { // Don't crash on NewSize == 0, even though it shouldn't happen. if (NewInt->isNullValue()) return 0; - + APInt Quot, Rem; APInt::udivrem(OldInt->getValue(), NewInt->getValue(), Quot, Rem); if (Rem == 0) @@ -195,7 +196,7 @@ // the start of inlined member functions) for (CallInst::use_iterator I = CI->use_begin(), E = CI->use_end() ; I != E;) { Instruction* User = cast<Instruction>(*I++); - + if (ICmpInst* Cmp = dyn_cast<ICmpInst>(User)) { if (!Cmp->isEquality()) continue; @@ -215,7 +216,7 @@ } } } - + // If it's not used (anymore), pre-emptively GC it. if (CI->use_empty()) return CI; @@ -235,23 +236,23 @@ FT->getParamType(2) != VoidPtrTy || FT->getParamType(3) != FT->getParamType(1)) return 0; - + Value* Size = CI->getOperand(2); - + // Check the lengths match if (CI->getOperand(4) != Size) return 0; - + // Assume unknown size unless we have constant size (that fits in an uint) unsigned Sz = ~0U; if (ConstantInt* Int = dyn_cast<ConstantInt>(Size)) if (Int->getValue().isIntN(32)) Sz = Int->getValue().getZExtValue(); - + // Check if the pointers may alias if (AA->alias(CI->getOperand(1), Sz, CI->getOperand(3), Sz)) return 0; - + // Equal length and the pointers definitely don't alias, so it's safe to // replace the call with memcpy return EmitMemCpy(CI->getOperand(1), CI->getOperand(3), Size, 0, B); @@ -271,24 +272,24 @@ /// class VISIBILITY_HIDDEN SimplifyDRuntimeCalls : public FunctionPass { StringMap<LibCallOptimization*> Optimizations; - + // Array operations ArraySetLengthOpt ArraySetLength; ArrayCastLenOpt ArrayCastLen; ArraySliceCopyOpt ArraySliceCopy; - + // GC allocations AllocationOpt Allocation; - + public: static char ID; // Pass identification SimplifyDRuntimeCalls() : FunctionPass(&ID) {} - + void InitOptimizations(); bool runOnFunction(Function &F); - + bool runOnce(Function &F, const TargetData& TD, AliasAnalysis& AA); - + virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<TargetData>(); AU.addRequired<AliasAnalysis>(); @@ -302,7 +303,7 @@ // Public interface to the pass. FunctionPass *createSimplifyDRuntimeCalls() { - return new SimplifyDRuntimeCalls(); + return new SimplifyDRuntimeCalls(); } /// Optimizations - Populate the Optimizations map with all the optimizations @@ -313,7 +314,7 @@ Optimizations["_d_arraysetlengthiT"] = &ArraySetLength; Optimizations["_d_array_cast_len"] = &ArrayCastLen; Optimizations["_d_array_slice_copy"] = &ArraySliceCopy; - + /* Delete calls to runtime functions which aren't needed if their result is * unused. That comes down to functions that don't do anything but * GC-allocate and initialize some memory. @@ -339,10 +340,10 @@ bool SimplifyDRuntimeCalls::runOnFunction(Function &F) { if (Optimizations.empty()) InitOptimizations(); - + const TargetData &TD = getAnalysis<TargetData>(); AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); - + // Iterate to catch opportunities opened up by other optimizations, // such as calls that are only used as arguments to unused calls: // When the second call gets deleted the first call will become unused, but @@ -354,7 +355,7 @@ Changed = runOnce(F, TD, AA); EverChanged |= Changed; } while (Changed); - + return EverChanged; } @@ -367,33 +368,33 @@ // Ignore non-calls. CallInst *CI = dyn_cast<CallInst>(I++); if (!CI) continue; - + // Ignore indirect calls and calls to non-external functions. Function *Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration() || !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage())) continue; - + // Ignore unknown calls. StringMap<LibCallOptimization*>::iterator OMI = Optimizations.find(Callee->getName()); if (OMI == Optimizations.end()) continue; - + DEBUG(errs() << "SimplifyDRuntimeCalls inspecting: " << *CI); - + // Set the builder to the instruction after the call. Builder.SetInsertPoint(BB, I); - + // Try to optimize this call. Value *Result = OMI->second->OptimizeCall(CI, Changed, TD, AA, Builder); if (Result == 0) continue; - + DEBUG(errs() << "SimplifyDRuntimeCalls simplified: " << *CI; errs() << " into: " << *Result << "\n"); - + // Something changed! Changed = true; - + if (Result == CI) { assert(CI->use_empty()); ++NumDeleted; @@ -401,18 +402,18 @@ } else { ++NumSimplified; AA.replaceWithNewValue(CI, Result); - + if (!CI->use_empty()) CI->replaceAllUsesWith(Result); - + if (!Result->hasName()) Result->takeName(CI); } - + // Inspect the instruction after the call (which was potentially just // added) next. I = CI; ++I; - + CI->eraseFromParent(); } }