From: Owen Anderson Date: Tue, 19 Feb 2008 06:35:43 +0000 (+0000) Subject: Major improvements to yesterday's return slot optimization. Remove some unneccessary... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=61c24e96b1ee5245e0b382a35773d2bc41919880;p=oota-llvm.git Major improvements to yesterday's return slot optimization. Remove some unneccessary constraints, and add some others that should have been in from the first place. Document the whole thing better. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47315 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 203bd751e20..93e14b86c0e 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetData.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -721,8 +722,10 @@ namespace { AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } // Helper fuctions @@ -1080,32 +1083,54 @@ static bool isReturnSlotOptznProfitable(Value* dest, MemCpyInst* cpy) { /// rather than using memcpy bool GVN::performReturnSlotOptzn(MemCpyInst* cpy, CallInst* C, SmallVector& toErase) { - // Check that we're copying to an argument... Value* cpyDest = cpy->getDest(); - if (!isa(cpyDest)) - return false; + Value* cpySrc = cpy->getSource(); + CallSite CS = CallSite::get(C); - // And that the argument is the return slot - Argument* sretArg = cast(cpyDest); - if (!sretArg->hasStructRetAttr()) + // Since this is a return slot optimization, we need to make sure that + // the value being copied is, in fact, in a return slot. We also need to + // check that the return slot parameter is marked noalias, so that we can + // be sure that changing it will cause unexpected behavior changes due + // to it being accessed through a global or another parameter. + if (CS.arg_size() == 0 || + cpySrc != CS.getArgument(0) || + !CS.paramHasAttr(1, ParamAttr::NoAlias | ParamAttr::StructRet)) return false; // We only perform the transformation if it will be profitable. - if (!isReturnSlotOptznProfitable(sretArg, cpy)) + if (!isReturnSlotOptznProfitable(cpyDest, cpy)) return false; - // Make sure the call cannot modify the return slot in some unpredicted way - AliasAnalysis& AA = getAnalysis(); - if (AA.getModRefInfo(C, cpy->getRawDest(), ~0UL) != AliasAnalysis::NoModRef) + // Check that something sneaky is not happening involving casting + // return slot types around. + if (CS.getArgument(0)->getType() != cpyDest->getType()) return false; - // If all checks passed, then we can perform the transformation. - CallSite CS = CallSite::get(C); - if (CS.getArgument(0)->getType() != cpyDest->getType()) + // We can only perform the transformation if the size of the memcpy + // is constant and equal to the size of the structure. + if (!isa(cpy->getLength())) return false; - + + ConstantInt* cpyLength = cast(cpy->getLength()); + TargetData& TD = getAnalysis(); + if (TD.getTypeStoreSize(cpyDest->getType()) == cpyLength->getZExtValue()) + return false; + + // In addition to knowing that the call does not access the return slot + // in some unexpected manner, which we derive from the noalias attribute, + // we also need to know that it does not sneakily modify the destination + // slot in the caller. We don't have parameter attributes to go by + // for this one, so we just rely on AA to figure it out for us. + AliasAnalysis& AA = getAnalysis(); + if (AA.getModRefInfo(C, cpy->getRawDest(), cpyLength->getZExtValue()) != + AliasAnalysis::NoModRef) + return false; + + // If all the checks have passed, then we're alright to do the transformation. CS.setArgument(0, cpyDest); + // Drop any cached information about the call, because we may have changed + // its dependence information by changing its parameter. MemoryDependenceAnalysis& MD = getAnalysis(); MD.dropInstruction(C);