diff options
Diffstat (limited to 'llvm/lib/Transforms/IPO/Attributor.cpp')
| -rw-r--r-- | llvm/lib/Transforms/IPO/Attributor.cpp | 190 |
1 files changed, 129 insertions, 61 deletions
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 762317425026..edadc79e3a9f 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/NoFolder.h" #include "llvm/IR/ValueHandle.h" @@ -250,10 +251,12 @@ Value *AA::getWithType(Value &V, Type &Ty) { return Constant::getNullValue(&Ty); if (C->getType()->isPointerTy() && Ty.isPointerTy()) return ConstantExpr::getPointerCast(C, &Ty); - if (C->getType()->isIntegerTy() && Ty.isIntegerTy()) - return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true); - if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy()) - return ConstantExpr::getFPTrunc(C, &Ty, /* OnlyIfReduced */ true); + if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) { + if (C->getType()->isIntegerTy() && Ty.isIntegerTy()) + return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true); + if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy()) + return ConstantExpr::getFPTrunc(C, &Ty, /* OnlyIfReduced */ true); + } } return nullptr; } @@ -379,30 +382,30 @@ static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, if (Attr.isEnumAttribute()) { Attribute::AttrKind Kind = Attr.getKindAsEnum(); - if (Attrs.hasAttribute(AttrIdx, Kind)) + if (Attrs.hasAttributeAtIndex(AttrIdx, Kind)) if (!ForceReplace && - isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) + isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind))) return false; - Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); + Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr); return true; } if (Attr.isStringAttribute()) { StringRef Kind = Attr.getKindAsString(); - if (Attrs.hasAttribute(AttrIdx, Kind)) + if (Attrs.hasAttributeAtIndex(AttrIdx, Kind)) if (!ForceReplace && - isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) + isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind))) return false; - Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); + Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr); return true; } if (Attr.isIntAttribute()) { Attribute::AttrKind Kind = Attr.getKindAsEnum(); - if (Attrs.hasAttribute(AttrIdx, Kind)) + if (Attrs.hasAttributeAtIndex(AttrIdx, Kind)) if (!ForceReplace && - isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) + isEqualOrWorse(Attr, Attrs.getAttributeAtIndex(AttrIdx, Kind))) return false; - Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind); - Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); + Attrs = Attrs.removeAttributeAtIndex(Ctx, AttrIdx, Kind); + Attrs = Attrs.addAttributeAtIndex(Ctx, AttrIdx, Attr); return true; } @@ -655,9 +658,9 @@ bool IRPosition::getAttrsFromIRAttr(Attribute::AttrKind AK, else AttrList = getAssociatedFunction()->getAttributes(); - bool HasAttr = AttrList.hasAttribute(getAttrIdx(), AK); + bool HasAttr = AttrList.hasAttributeAtIndex(getAttrIdx(), AK); if (HasAttr) - Attrs.push_back(AttrList.getAttribute(getAttrIdx(), AK)); + Attrs.push_back(AttrList.getAttributeAtIndex(getAttrIdx(), AK)); return HasAttr; } @@ -1023,7 +1026,7 @@ bool Attributor::checkForAllUses(function_ref<bool(const Use &, bool &)> Pred, while (!Worklist.empty()) { const Use *U = Worklist.pop_back_val(); - if (!Visited.insert(U).second) + if (isa<PHINode>(U->getUser()) && !Visited.insert(U).second) continue; LLVM_DEBUG(dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser() << "\n"); @@ -1040,6 +1043,8 @@ bool Attributor::checkForAllUses(function_ref<bool(const Use &, bool &)> Pred, if (auto *SI = dyn_cast<StoreInst>(U->getUser())) { if (&SI->getOperandUse(0) == U) { + if (!Visited.insert(U).second) + continue; SmallSetVector<Value *, 4> PotentialCopies; if (AA::getPotentialCopiesOfStoredValue(*this, *SI, PotentialCopies, QueryingAA, @@ -1118,6 +1123,10 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { if (CE->isCast() && CE->getType()->isPointerTy() && CE->getType()->getPointerElementType()->isFunctionTy()) { + LLVM_DEBUG( + dbgs() << "[Attributor] Use, is constant cast expression, add " + << CE->getNumUses() + << " uses of that expression instead!\n"); for (const Use &CEU : CE->uses()) Uses.push_back(&CEU); continue; @@ -1138,9 +1147,13 @@ bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred, const Use *EffectiveUse = ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U; if (!ACS.isCallee(EffectiveUse)) { - if (!RequireAllCallSites) + if (!RequireAllCallSites) { + LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser() + << " is not a call of " << Fn.getName() + << ", skip use\n"); continue; - LLVM_DEBUG(dbgs() << "[Attributor] User " << EffectiveUse->getUser() + } + LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser() << " is an invalid use of " << Fn.getName() << "\n"); return false; } @@ -1410,6 +1423,16 @@ void Attributor::runTillFixpoint() { } while (!Worklist.empty() && (IterationCounter++ < MaxFixedPointIterations || VerifyMaxFixpointIterations)); + if (IterationCounter > MaxFixedPointIterations && !Worklist.empty()) { + auto Remark = [&](OptimizationRemarkMissed ORM) { + return ORM << "Attributor did not reach a fixpoint after " + << ore::NV("Iterations", MaxFixedPointIterations) + << " iterations."; + }; + Function *F = Worklist.front()->getIRPosition().getAssociatedFunction(); + emitRemark<OptimizationRemarkMissed>(F, "FixedPoint", Remark); + } + LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: " << IterationCounter << "/" << MaxFixpointIterations << " iterations\n"); @@ -1919,55 +1942,91 @@ void Attributor::createShallowWrapper(Function &F) { CallInst *CI = CallInst::Create(&F, Args, "", EntryBB); CI->setTailCall(true); - CI->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); + CI->addFnAttr(Attribute::NoInline); ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB); NumFnShallowWrappersCreated++; } +bool Attributor::isInternalizable(Function &F) { + if (F.isDeclaration() || F.hasLocalLinkage() || + GlobalValue::isInterposableLinkage(F.getLinkage())) + return false; + return true; +} + Function *Attributor::internalizeFunction(Function &F, bool Force) { if (!AllowDeepWrapper && !Force) return nullptr; - if (F.isDeclaration() || F.hasLocalLinkage() || - GlobalValue::isInterposableLinkage(F.getLinkage())) + if (!isInternalizable(F)) return nullptr; - Module &M = *F.getParent(); - FunctionType *FnTy = F.getFunctionType(); + SmallPtrSet<Function *, 2> FnSet = {&F}; + DenseMap<Function *, Function *> InternalizedFns; + internalizeFunctions(FnSet, InternalizedFns); - // create a copy of the current function - Function *Copied = Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), - F.getName() + ".internalized"); - ValueToValueMapTy VMap; - auto *NewFArgIt = Copied->arg_begin(); - for (auto &Arg : F.args()) { - auto ArgName = Arg.getName(); - NewFArgIt->setName(ArgName); - VMap[&Arg] = &(*NewFArgIt++); - } - SmallVector<ReturnInst *, 8> Returns; + return InternalizedFns[&F]; +} - // Copy the body of the original function to the new one - CloneFunctionInto(Copied, &F, VMap, CloneFunctionChangeType::LocalChangesOnly, - Returns); +bool Attributor::internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet, + DenseMap<Function *, Function *> &FnMap) { + for (Function *F : FnSet) + if (!Attributor::isInternalizable(*F)) + return false; - // Set the linakage and visibility late as CloneFunctionInto has some implicit - // requirements. - Copied->setVisibility(GlobalValue::DefaultVisibility); - Copied->setLinkage(GlobalValue::PrivateLinkage); + FnMap.clear(); + // Generate the internalized version of each function. + for (Function *F : FnSet) { + Module &M = *F->getParent(); + FunctionType *FnTy = F->getFunctionType(); - // Copy metadata - SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; - F.getAllMetadata(MDs); - for (auto MDIt : MDs) - if (!Copied->hasMetadata()) - Copied->addMetadata(MDIt.first, *MDIt.second); + // Create a copy of the current function + Function *Copied = + Function::Create(FnTy, F->getLinkage(), F->getAddressSpace(), + F->getName() + ".internalized"); + ValueToValueMapTy VMap; + auto *NewFArgIt = Copied->arg_begin(); + for (auto &Arg : F->args()) { + auto ArgName = Arg.getName(); + NewFArgIt->setName(ArgName); + VMap[&Arg] = &(*NewFArgIt++); + } + SmallVector<ReturnInst *, 8> Returns; - M.getFunctionList().insert(F.getIterator(), Copied); - F.replaceAllUsesWith(Copied); - Copied->setDSOLocal(true); + // Copy the body of the original function to the new one + CloneFunctionInto(Copied, F, VMap, + CloneFunctionChangeType::LocalChangesOnly, Returns); - return Copied; + // Set the linakage and visibility late as CloneFunctionInto has some + // implicit requirements. + Copied->setVisibility(GlobalValue::DefaultVisibility); + Copied->setLinkage(GlobalValue::PrivateLinkage); + + // Copy metadata + SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; + F->getAllMetadata(MDs); + for (auto MDIt : MDs) + if (!Copied->hasMetadata()) + Copied->addMetadata(MDIt.first, *MDIt.second); + + M.getFunctionList().insert(F->getIterator(), Copied); + Copied->setDSOLocal(true); + FnMap[F] = Copied; + } + + // Replace all uses of the old function with the new internalized function + // unless the caller is a function that was just internalized. + for (Function *F : FnSet) { + auto &InternalizedFn = FnMap[F]; + auto IsNotInternalized = [&](Use &U) -> bool { + if (auto *CB = dyn_cast<CallBase>(U.getUser())) + return !FnMap.lookup(CB->getCaller()); + return false; + }; + F->replaceUsesWithIf(InternalizedFn, IsNotInternalized); + } + + return true; } bool Attributor::isValidFunctionSignatureRewrite( @@ -1976,7 +2035,8 @@ bool Attributor::isValidFunctionSignatureRewrite( if (!RewriteSignatures) return false; - auto CallSiteCanBeChanged = [](AbstractCallSite ACS) { + Function *Fn = Arg.getParent(); + auto CallSiteCanBeChanged = [Fn](AbstractCallSite ACS) { // Forbid the call site to cast the function return type. If we need to // rewrite these functions we need to re-create a cast for the new call site // (if the old had uses). @@ -1984,11 +2044,12 @@ bool Attributor::isValidFunctionSignatureRewrite( ACS.getInstruction()->getType() != ACS.getCalledFunction()->getReturnType()) return false; + if (ACS.getCalledOperand()->getType() != Fn->getType()) + return false; // Forbid must-tail calls for now. return !ACS.isCallbackCall() && !ACS.getInstruction()->isMustTailCall(); }; - Function *Fn = Arg.getParent(); // Avoid var-arg functions for now. if (Fn->isVarArg()) { LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n"); @@ -2118,7 +2179,7 @@ ChangeStatus Attributor::rewriteFunctionSignatures( } else { NewArgumentTypes.push_back(Arg.getType()); NewArgumentAttributes.push_back( - OldFnAttributeList.getParamAttributes(Arg.getArgNo())); + OldFnAttributeList.getParamAttrs(Arg.getArgNo())); } } @@ -2149,8 +2210,8 @@ ChangeStatus Attributor::rewriteFunctionSignatures( // the function. LLVMContext &Ctx = OldFn->getContext(); NewFn->setAttributes(AttributeList::get( - Ctx, OldFnAttributeList.getFnAttributes(), - OldFnAttributeList.getRetAttributes(), NewArgumentAttributes)); + Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(), + NewArgumentAttributes)); // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the @@ -2195,7 +2256,7 @@ ChangeStatus Attributor::rewriteFunctionSignatures( } else { NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum)); NewArgOperandAttributes.push_back( - OldCallAttributeList.getParamAttributes(OldArgNum)); + OldCallAttributeList.getParamAttrs(OldArgNum)); } } @@ -2225,8 +2286,8 @@ ChangeStatus Attributor::rewriteFunctionSignatures( NewCB->setCallingConv(OldCB->getCallingConv()); NewCB->takeName(OldCB); NewCB->setAttributes(AttributeList::get( - Ctx, OldCallAttributeList.getFnAttributes(), - OldCallAttributeList.getRetAttributes(), NewArgOperandAttributes)); + Ctx, OldCallAttributeList.getFnAttrs(), + OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes)); CallSitePairs.push_back({OldCB, NewCB}); return true; @@ -2441,6 +2502,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { // Every function can be "readnone/argmemonly/inaccessiblememonly/...". getOrCreateAAFor<AAMemoryLocation>(FPos); + // Every function can track active assumptions. + getOrCreateAAFor<AAAssumptionInfo>(FPos); + // Every function might be applicable for Heap-To-Stack conversion. if (EnableHeapToStack) getOrCreateAAFor<AAHeapToStack>(FPos); @@ -2526,6 +2590,7 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { auto CallSitePred = [&](Instruction &I) -> bool { auto &CB = cast<CallBase>(I); IRPosition CBRetPos = IRPosition::callsite_returned(CB); + IRPosition CBFnPos = IRPosition::callsite_function(CB); // Call sites might be dead if they do not have side effects and no live // users. The return value might be dead if there are no live users. @@ -2537,6 +2602,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { if (!Callee) return true; + // Every call site can track active assumptions. + getOrCreateAAFor<AAAssumptionInfo>(CBFnPos); + // Skip declarations except if annotations on their call sites were // explicitly requested. if (!AnnotateDeclarationCallSites && Callee->isDeclaration() && @@ -2549,7 +2617,7 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) { getOrCreateAAFor<AAValueSimplify>(CBRetPos); } - for (int I = 0, E = CB.getNumArgOperands(); I < E; ++I) { + for (int I = 0, E = CB.arg_size(); I < E; ++I) { IRPosition CBArgPos = IRPosition::callsite_argument(CB, I); |
