10b57cec5SDimitry Andric //===- ArgumentPromotion.cpp - Promote by-reference arguments -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass promotes "by reference" arguments to be "by value" arguments. In 100b57cec5SDimitry Andric // practice, this means looking for internal functions that have pointer 110b57cec5SDimitry Andric // arguments. If it can prove, through the use of alias analysis, that an 120b57cec5SDimitry Andric // argument is *only* loaded, then it can pass the value into the function 130b57cec5SDimitry Andric // instead of the address of the value. This can cause recursive simplification 140b57cec5SDimitry Andric // of code and lead to the elimination of allocas (especially in C++ template 150b57cec5SDimitry Andric // code like the STL). 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric // This pass also handles aggregate arguments that are passed into a function, 180b57cec5SDimitry Andric // scalarizing them if the elements of the aggregate are only loaded. Note that 190b57cec5SDimitry Andric // by default it refuses to scalarize aggregates which would require passing in 200b57cec5SDimitry Andric // more than three operands to the function, because passing thousands of 210b57cec5SDimitry Andric // operands for a large array or structure is unprofitable! This limit can be 220b57cec5SDimitry Andric // configured or disabled, however. 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric // Note that this transformation could also be done for arguments that are only 250b57cec5SDimitry Andric // stored to (returning the value instead), but does not currently. This case 260b57cec5SDimitry Andric // would be best handled when and if LLVM begins supporting multiple return 270b57cec5SDimitry Andric // values from functions. 280b57cec5SDimitry Andric // 290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ArgumentPromotion.h" 3281ad6265SDimitry Andric 330b57cec5SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h" 340b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 35e8d8bef9SDimitry Andric #include "llvm/ADT/ScopeExit.h" 360b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 370b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 380b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 390b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 400b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 410b57cec5SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 420b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h" 430b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h" 440b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h" 450b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 4681ad6265SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 470b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 480b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 490b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 500b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 510b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 520b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 530b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 5481ad6265SDimitry Andric #include "llvm/IR/Dominators.h" 550b57cec5SDimitry Andric #include "llvm/IR/Function.h" 560b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 570b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 580b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 590b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 600b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 61*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 620b57cec5SDimitry Andric #include "llvm/IR/NoFolder.h" 630b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 640b57cec5SDimitry Andric #include "llvm/IR/Type.h" 650b57cec5SDimitry Andric #include "llvm/IR/Use.h" 660b57cec5SDimitry Andric #include "llvm/IR/User.h" 670b57cec5SDimitry Andric #include "llvm/IR/Value.h" 680b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 690b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 700b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 7106c3fb27SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 7281ad6265SDimitry Andric #include "llvm/Transforms/Utils/PromoteMemToReg.h" 730b57cec5SDimitry Andric #include <algorithm> 740b57cec5SDimitry Andric #include <cassert> 750b57cec5SDimitry Andric #include <cstdint> 760b57cec5SDimitry Andric #include <utility> 770b57cec5SDimitry Andric #include <vector> 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric using namespace llvm; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric #define DEBUG_TYPE "argpromotion" 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric STATISTIC(NumArgumentsPromoted, "Number of pointer arguments promoted"); 840b57cec5SDimitry Andric STATISTIC(NumArgumentsDead, "Number of dead pointer args eliminated"); 850b57cec5SDimitry Andric 8681ad6265SDimitry Andric namespace { 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric struct ArgPart { 8981ad6265SDimitry Andric Type *Ty; 9081ad6265SDimitry Andric Align Alignment; 9181ad6265SDimitry Andric /// A representative guaranteed-executed load or store instruction for use by 9281ad6265SDimitry Andric /// metadata transfer. 9381ad6265SDimitry Andric Instruction *MustExecInstr; 9481ad6265SDimitry Andric }; 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric using OffsetAndArgPart = std::pair<int64_t, ArgPart>; 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric } // end anonymous namespace 9981ad6265SDimitry Andric 10081ad6265SDimitry Andric static Value *createByteGEP(IRBuilderBase &IRB, const DataLayout &DL, 10181ad6265SDimitry Andric Value *Ptr, Type *ResElemTy, int64_t Offset) { 10206c3fb27SDimitry Andric if (Offset != 0) { 10306c3fb27SDimitry Andric APInt APOffset(DL.getIndexTypeSizeInBits(Ptr->getType()), Offset); 1047a6dacacSDimitry Andric Ptr = IRB.CreatePtrAdd(Ptr, IRB.getInt(APOffset)); 10506c3fb27SDimitry Andric } 10681ad6265SDimitry Andric return Ptr; 10781ad6265SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric /// DoPromotion - This method actually performs the promotion of the specified 1100b57cec5SDimitry Andric /// arguments, and returns the new function. At this point, we know that it's 1110b57cec5SDimitry Andric /// safe to do so. 1120b57cec5SDimitry Andric static Function * 11381ad6265SDimitry Andric doPromotion(Function *F, FunctionAnalysisManager &FAM, 11481ad6265SDimitry Andric const DenseMap<Argument *, SmallVector<OffsetAndArgPart, 4>> 11581ad6265SDimitry Andric &ArgsToPromote) { 1160b57cec5SDimitry Andric // Start by computing a new prototype for the function, which is the same as 1170b57cec5SDimitry Andric // the old function, but has modified arguments. 1180b57cec5SDimitry Andric FunctionType *FTy = F->getFunctionType(); 1190b57cec5SDimitry Andric std::vector<Type *> Params; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Attribute - Keep track of the parameter attributes for the arguments 1220b57cec5SDimitry Andric // that we are *not* promoting. For the ones that we do promote, the parameter 1230b57cec5SDimitry Andric // attributes are lost 1240b57cec5SDimitry Andric SmallVector<AttributeSet, 8> ArgAttrVec; 1255f757f3fSDimitry Andric // Mapping from old to new argument indices. -1 for promoted or removed 1265f757f3fSDimitry Andric // arguments. 1275f757f3fSDimitry Andric SmallVector<unsigned> NewArgIndices; 1280b57cec5SDimitry Andric AttributeList PAL = F->getAttributes(); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // First, determine the new argument list 1315f757f3fSDimitry Andric unsigned ArgNo = 0, NewArgNo = 0; 1320b57cec5SDimitry Andric for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; 1330b57cec5SDimitry Andric ++I, ++ArgNo) { 13481ad6265SDimitry Andric if (!ArgsToPromote.count(&*I)) { 1350b57cec5SDimitry Andric // Unchanged argument 1360b57cec5SDimitry Andric Params.push_back(I->getType()); 137349cc55cSDimitry Andric ArgAttrVec.push_back(PAL.getParamAttrs(ArgNo)); 1385f757f3fSDimitry Andric NewArgIndices.push_back(NewArgNo++); 1390b57cec5SDimitry Andric } else if (I->use_empty()) { 1400b57cec5SDimitry Andric // Dead argument (which are always marked as promotable) 1410b57cec5SDimitry Andric ++NumArgumentsDead; 1425f757f3fSDimitry Andric NewArgIndices.push_back((unsigned)-1); 1430b57cec5SDimitry Andric } else { 14481ad6265SDimitry Andric const auto &ArgParts = ArgsToPromote.find(&*I)->second; 14581ad6265SDimitry Andric for (const auto &Pair : ArgParts) { 14681ad6265SDimitry Andric Params.push_back(Pair.second.Ty); 1470b57cec5SDimitry Andric ArgAttrVec.push_back(AttributeSet()); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric ++NumArgumentsPromoted; 1505f757f3fSDimitry Andric NewArgIndices.push_back((unsigned)-1); 1515f757f3fSDimitry Andric NewArgNo += ArgParts.size(); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric Type *RetTy = FTy->getReturnType(); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric // Construct the new function type using the new arguments. 1580b57cec5SDimitry Andric FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Create the new function body and insert it into the module. 1610b57cec5SDimitry Andric Function *NF = Function::Create(NFTy, F->getLinkage(), F->getAddressSpace(), 1620b57cec5SDimitry Andric F->getName()); 1630b57cec5SDimitry Andric NF->copyAttributesFrom(F); 164e8d8bef9SDimitry Andric NF->copyMetadata(F, 0); 1655f757f3fSDimitry Andric NF->setIsNewDbgInfoFormat(F->IsNewDbgInfoFormat); 1660b57cec5SDimitry Andric 167e8d8bef9SDimitry Andric // The new function will have the !dbg metadata copied from the original 168e8d8bef9SDimitry Andric // function. The original function may not be deleted, and dbg metadata need 16981ad6265SDimitry Andric // to be unique, so we need to drop it. 1700b57cec5SDimitry Andric F->setSubprogram(nullptr); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" 1730b57cec5SDimitry Andric << "From: " << *F); 1740b57cec5SDimitry Andric 17581ad6265SDimitry Andric uint64_t LargestVectorWidth = 0; 17681ad6265SDimitry Andric for (auto *I : Params) 17781ad6265SDimitry Andric if (auto *VT = dyn_cast<llvm::VectorType>(I)) 17881ad6265SDimitry Andric LargestVectorWidth = std::max( 179bdd1243dSDimitry Andric LargestVectorWidth, VT->getPrimitiveSizeInBits().getKnownMinValue()); 18081ad6265SDimitry Andric 1810b57cec5SDimitry Andric // Recompute the parameter attributes list based on the new arguments for 1820b57cec5SDimitry Andric // the function. 183349cc55cSDimitry Andric NF->setAttributes(AttributeList::get(F->getContext(), PAL.getFnAttrs(), 184349cc55cSDimitry Andric PAL.getRetAttrs(), ArgAttrVec)); 1855f757f3fSDimitry Andric 1865f757f3fSDimitry Andric // Remap argument indices in allocsize attribute. 1875f757f3fSDimitry Andric if (auto AllocSize = NF->getAttributes().getFnAttrs().getAllocSizeArgs()) { 1885f757f3fSDimitry Andric unsigned Arg1 = NewArgIndices[AllocSize->first]; 1895f757f3fSDimitry Andric assert(Arg1 != (unsigned)-1 && "allocsize cannot be promoted argument"); 1905f757f3fSDimitry Andric std::optional<unsigned> Arg2; 1915f757f3fSDimitry Andric if (AllocSize->second) { 1925f757f3fSDimitry Andric Arg2 = NewArgIndices[*AllocSize->second]; 1935f757f3fSDimitry Andric assert(Arg2 != (unsigned)-1 && "allocsize cannot be promoted argument"); 1945f757f3fSDimitry Andric } 1955f757f3fSDimitry Andric NF->addFnAttr(Attribute::getWithAllocSizeArgs(F->getContext(), Arg1, Arg2)); 1965f757f3fSDimitry Andric } 1975f757f3fSDimitry Andric 19881ad6265SDimitry Andric AttributeFuncs::updateMinLegalVectorWidthAttr(*NF, LargestVectorWidth); 1990b57cec5SDimitry Andric ArgAttrVec.clear(); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric F->getParent()->getFunctionList().insert(F->getIterator(), NF); 2020b57cec5SDimitry Andric NF->takeName(F); 2030b57cec5SDimitry Andric 20481ad6265SDimitry Andric // Loop over all the callers of the function, transforming the call sites to 20581ad6265SDimitry Andric // pass in the loaded pointers. 2060b57cec5SDimitry Andric SmallVector<Value *, 16> Args; 207*0fca6ea1SDimitry Andric const DataLayout &DL = F->getDataLayout(); 20806c3fb27SDimitry Andric SmallVector<WeakTrackingVH, 16> DeadArgs; 20906c3fb27SDimitry Andric 2100b57cec5SDimitry Andric while (!F->use_empty()) { 2115ffd83dbSDimitry Andric CallBase &CB = cast<CallBase>(*F->user_back()); 2125ffd83dbSDimitry Andric assert(CB.getCalledFunction() == F); 2135ffd83dbSDimitry Andric const AttributeList &CallPAL = CB.getAttributes(); 2145ffd83dbSDimitry Andric IRBuilder<NoFolder> IRB(&CB); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Loop over the operands, inserting GEP and loads in the caller as 2170b57cec5SDimitry Andric // appropriate. 21881ad6265SDimitry Andric auto *AI = CB.arg_begin(); 2190b57cec5SDimitry Andric ArgNo = 0; 2200b57cec5SDimitry Andric for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; 22181ad6265SDimitry Andric ++I, ++AI, ++ArgNo) { 22281ad6265SDimitry Andric if (!ArgsToPromote.count(&*I)) { 2230b57cec5SDimitry Andric Args.push_back(*AI); // Unmodified argument 224349cc55cSDimitry Andric ArgAttrVec.push_back(CallPAL.getParamAttrs(ArgNo)); 2250b57cec5SDimitry Andric } else if (!I->use_empty()) { 2260b57cec5SDimitry Andric Value *V = *AI; 22781ad6265SDimitry Andric const auto &ArgParts = ArgsToPromote.find(&*I)->second; 22881ad6265SDimitry Andric for (const auto &Pair : ArgParts) { 22981ad6265SDimitry Andric LoadInst *LI = IRB.CreateAlignedLoad( 23081ad6265SDimitry Andric Pair.second.Ty, 23181ad6265SDimitry Andric createByteGEP(IRB, DL, V, Pair.second.Ty, Pair.first), 23281ad6265SDimitry Andric Pair.second.Alignment, V->getName() + ".val"); 23381ad6265SDimitry Andric if (Pair.second.MustExecInstr) { 23481ad6265SDimitry Andric LI->setAAMetadata(Pair.second.MustExecInstr->getAAMetadata()); 23581ad6265SDimitry Andric LI->copyMetadata(*Pair.second.MustExecInstr, 23606c3fb27SDimitry Andric {LLVMContext::MD_dereferenceable, 23781ad6265SDimitry Andric LLVMContext::MD_dereferenceable_or_null, 23806c3fb27SDimitry Andric LLVMContext::MD_noundef, 239972a253aSDimitry Andric LLVMContext::MD_nontemporal}); 24006c3fb27SDimitry Andric // Only transfer poison-generating metadata if we also have 24106c3fb27SDimitry Andric // !noundef. 24206c3fb27SDimitry Andric // TODO: Without !noundef, we could merge this metadata across 24306c3fb27SDimitry Andric // all promoted loads. 24406c3fb27SDimitry Andric if (LI->hasMetadata(LLVMContext::MD_noundef)) 24506c3fb27SDimitry Andric LI->copyMetadata(*Pair.second.MustExecInstr, 24606c3fb27SDimitry Andric {LLVMContext::MD_range, LLVMContext::MD_nonnull, 24706c3fb27SDimitry Andric LLVMContext::MD_align}); 2480b57cec5SDimitry Andric } 24981ad6265SDimitry Andric Args.push_back(LI); 2500b57cec5SDimitry Andric ArgAttrVec.push_back(AttributeSet()); 2510b57cec5SDimitry Andric } 25206c3fb27SDimitry Andric } else { 25306c3fb27SDimitry Andric assert(ArgsToPromote.count(&*I) && I->use_empty()); 25406c3fb27SDimitry Andric DeadArgs.emplace_back(AI->get()); 2550b57cec5SDimitry Andric } 25681ad6265SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric // Push any varargs arguments on the list. 2595ffd83dbSDimitry Andric for (; AI != CB.arg_end(); ++AI, ++ArgNo) { 2600b57cec5SDimitry Andric Args.push_back(*AI); 261349cc55cSDimitry Andric ArgAttrVec.push_back(CallPAL.getParamAttrs(ArgNo)); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles; 2655ffd83dbSDimitry Andric CB.getOperandBundlesAsDefs(OpBundles); 2660b57cec5SDimitry Andric 2675ffd83dbSDimitry Andric CallBase *NewCS = nullptr; 2685ffd83dbSDimitry Andric if (InvokeInst *II = dyn_cast<InvokeInst>(&CB)) { 2690b57cec5SDimitry Andric NewCS = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), 270*0fca6ea1SDimitry Andric Args, OpBundles, "", CB.getIterator()); 2710b57cec5SDimitry Andric } else { 272*0fca6ea1SDimitry Andric auto *NewCall = 273*0fca6ea1SDimitry Andric CallInst::Create(NF, Args, OpBundles, "", CB.getIterator()); 2745ffd83dbSDimitry Andric NewCall->setTailCallKind(cast<CallInst>(&CB)->getTailCallKind()); 2750b57cec5SDimitry Andric NewCS = NewCall; 2760b57cec5SDimitry Andric } 2775ffd83dbSDimitry Andric NewCS->setCallingConv(CB.getCallingConv()); 278349cc55cSDimitry Andric NewCS->setAttributes(AttributeList::get(F->getContext(), 279349cc55cSDimitry Andric CallPAL.getFnAttrs(), 280349cc55cSDimitry Andric CallPAL.getRetAttrs(), ArgAttrVec)); 2815ffd83dbSDimitry Andric NewCS->copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg}); 2820b57cec5SDimitry Andric Args.clear(); 2830b57cec5SDimitry Andric ArgAttrVec.clear(); 2840b57cec5SDimitry Andric 28581ad6265SDimitry Andric AttributeFuncs::updateMinLegalVectorWidthAttr(*CB.getCaller(), 28681ad6265SDimitry Andric LargestVectorWidth); 2870b57cec5SDimitry Andric 2885ffd83dbSDimitry Andric if (!CB.use_empty()) { 2895ffd83dbSDimitry Andric CB.replaceAllUsesWith(NewCS); 2905ffd83dbSDimitry Andric NewCS->takeName(&CB); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric // Finally, remove the old call from the program, reducing the use-count of 2940b57cec5SDimitry Andric // F. 2955ffd83dbSDimitry Andric CB.eraseFromParent(); 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 29806c3fb27SDimitry Andric RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadArgs); 29906c3fb27SDimitry Andric 3000b57cec5SDimitry Andric // Since we have now created the new function, splice the body of the old 3010b57cec5SDimitry Andric // function right into the new function, leaving the old rotting hulk of the 3020b57cec5SDimitry Andric // function empty. 303bdd1243dSDimitry Andric NF->splice(NF->begin(), F); 3040b57cec5SDimitry Andric 30581ad6265SDimitry Andric // We will collect all the new created allocas to promote them into registers 30681ad6265SDimitry Andric // after the following loop 30781ad6265SDimitry Andric SmallVector<AllocaInst *, 4> Allocas; 30881ad6265SDimitry Andric 3090b57cec5SDimitry Andric // Loop over the argument list, transferring uses of the old arguments over to 3100b57cec5SDimitry Andric // the new arguments, also transferring over the names as well. 3111fd87a68SDimitry Andric Function::arg_iterator I2 = NF->arg_begin(); 3121fd87a68SDimitry Andric for (Argument &Arg : F->args()) { 31381ad6265SDimitry Andric if (!ArgsToPromote.count(&Arg)) { 3140b57cec5SDimitry Andric // If this is an unmodified argument, move the name and users over to the 3150b57cec5SDimitry Andric // new version. 3161fd87a68SDimitry Andric Arg.replaceAllUsesWith(&*I2); 3171fd87a68SDimitry Andric I2->takeName(&Arg); 3180b57cec5SDimitry Andric ++I2; 3190b57cec5SDimitry Andric continue; 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 322e8d8bef9SDimitry Andric // There potentially are metadata uses for things like llvm.dbg.value. 323e8d8bef9SDimitry Andric // Replace them with undef, after handling the other regular uses. 324e8d8bef9SDimitry Andric auto RauwUndefMetadata = make_scope_exit( 3251fd87a68SDimitry Andric [&]() { Arg.replaceAllUsesWith(UndefValue::get(Arg.getType())); }); 326e8d8bef9SDimitry Andric 3271fd87a68SDimitry Andric if (Arg.use_empty()) 3280b57cec5SDimitry Andric continue; 3290b57cec5SDimitry Andric 33081ad6265SDimitry Andric // Otherwise, if we promoted this argument, we have to create an alloca in 33181ad6265SDimitry Andric // the callee for every promotable part and store each of the new incoming 33281ad6265SDimitry Andric // arguments into the corresponding alloca, what lets the old code (the 33381ad6265SDimitry Andric // store instructions if they are allowed especially) a chance to work as 33481ad6265SDimitry Andric // before. 33581ad6265SDimitry Andric assert(Arg.getType()->isPointerTy() && 33681ad6265SDimitry Andric "Only arguments with a pointer type are promotable"); 3370b57cec5SDimitry Andric 33881ad6265SDimitry Andric IRBuilder<NoFolder> IRB(&NF->begin()->front()); 3390b57cec5SDimitry Andric 34081ad6265SDimitry Andric // Add only the promoted elements, so parts from ArgsToPromote 34181ad6265SDimitry Andric SmallDenseMap<int64_t, AllocaInst *> OffsetToAlloca; 34281ad6265SDimitry Andric for (const auto &Pair : ArgsToPromote.find(&Arg)->second) { 34381ad6265SDimitry Andric int64_t Offset = Pair.first; 34481ad6265SDimitry Andric const ArgPart &Part = Pair.second; 3450b57cec5SDimitry Andric 34681ad6265SDimitry Andric Argument *NewArg = I2++; 34781ad6265SDimitry Andric NewArg->setName(Arg.getName() + "." + Twine(Offset) + ".val"); 34881ad6265SDimitry Andric 34981ad6265SDimitry Andric AllocaInst *NewAlloca = IRB.CreateAlloca( 35081ad6265SDimitry Andric Part.Ty, nullptr, Arg.getName() + "." + Twine(Offset) + ".allc"); 35181ad6265SDimitry Andric NewAlloca->setAlignment(Pair.second.Alignment); 35281ad6265SDimitry Andric IRB.CreateAlignedStore(NewArg, NewAlloca, Pair.second.Alignment); 35381ad6265SDimitry Andric 35481ad6265SDimitry Andric // Collect the alloca to retarget the users to 35581ad6265SDimitry Andric OffsetToAlloca.insert({Offset, NewAlloca}); 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 35881ad6265SDimitry Andric auto GetAlloca = [&](Value *Ptr) { 35981ad6265SDimitry Andric APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0); 36081ad6265SDimitry Andric Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset, 36181ad6265SDimitry Andric /* AllowNonInbounds */ true); 36281ad6265SDimitry Andric assert(Ptr == &Arg && "Not constant offset from arg?"); 36381ad6265SDimitry Andric return OffsetToAlloca.lookup(Offset.getSExtValue()); 36481ad6265SDimitry Andric }; 3650b57cec5SDimitry Andric 36681ad6265SDimitry Andric // Cleanup the code from the dead instructions: GEPs and BitCasts in between 36781ad6265SDimitry Andric // the original argument and its users: loads and stores. Retarget every 36881ad6265SDimitry Andric // user to the new created alloca. 36981ad6265SDimitry Andric SmallVector<Value *, 16> Worklist; 37081ad6265SDimitry Andric SmallVector<Instruction *, 16> DeadInsts; 37181ad6265SDimitry Andric append_range(Worklist, Arg.users()); 37281ad6265SDimitry Andric while (!Worklist.empty()) { 37381ad6265SDimitry Andric Value *V = Worklist.pop_back_val(); 37481ad6265SDimitry Andric if (isa<BitCastInst>(V) || isa<GetElementPtrInst>(V)) { 37581ad6265SDimitry Andric DeadInsts.push_back(cast<Instruction>(V)); 37681ad6265SDimitry Andric append_range(Worklist, V->users()); 37781ad6265SDimitry Andric continue; 37881ad6265SDimitry Andric } 3790b57cec5SDimitry Andric 38081ad6265SDimitry Andric if (auto *LI = dyn_cast<LoadInst>(V)) { 38181ad6265SDimitry Andric Value *Ptr = LI->getPointerOperand(); 38281ad6265SDimitry Andric LI->setOperand(LoadInst::getPointerOperandIndex(), GetAlloca(Ptr)); 38381ad6265SDimitry Andric continue; 3840b57cec5SDimitry Andric } 38581ad6265SDimitry Andric 38681ad6265SDimitry Andric if (auto *SI = dyn_cast<StoreInst>(V)) { 38781ad6265SDimitry Andric assert(!SI->isVolatile() && "Volatile operations can't be promoted."); 38881ad6265SDimitry Andric Value *Ptr = SI->getPointerOperand(); 38981ad6265SDimitry Andric SI->setOperand(StoreInst::getPointerOperandIndex(), GetAlloca(Ptr)); 39081ad6265SDimitry Andric continue; 39181ad6265SDimitry Andric } 39281ad6265SDimitry Andric 39381ad6265SDimitry Andric llvm_unreachable("Unexpected user"); 39481ad6265SDimitry Andric } 39581ad6265SDimitry Andric 39681ad6265SDimitry Andric for (Instruction *I : DeadInsts) { 39781ad6265SDimitry Andric I->replaceAllUsesWith(PoisonValue::get(I->getType())); 39881ad6265SDimitry Andric I->eraseFromParent(); 39981ad6265SDimitry Andric } 40081ad6265SDimitry Andric 40181ad6265SDimitry Andric // Collect the allocas for promotion 40281ad6265SDimitry Andric for (const auto &Pair : OffsetToAlloca) { 40381ad6265SDimitry Andric assert(isAllocaPromotable(Pair.second) && 40481ad6265SDimitry Andric "By design, only promotable allocas should be produced."); 40581ad6265SDimitry Andric Allocas.push_back(Pair.second); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric } 40881ad6265SDimitry Andric 40981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ARG PROMOTION: " << Allocas.size() 41081ad6265SDimitry Andric << " alloca(s) are promotable by Mem2Reg\n"); 41181ad6265SDimitry Andric 41281ad6265SDimitry Andric if (!Allocas.empty()) { 41381ad6265SDimitry Andric // And we are able to call the `promoteMemoryToRegister()` function. 41481ad6265SDimitry Andric // Our earlier checks have ensured that PromoteMemToReg() will 41581ad6265SDimitry Andric // succeed. 41681ad6265SDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(*NF); 41781ad6265SDimitry Andric auto &AC = FAM.getResult<AssumptionAnalysis>(*NF); 41881ad6265SDimitry Andric PromoteMemToReg(Allocas, DT, &AC); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric return NF; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric /// Return true if we can prove that all callees pass in a valid pointer for the 4250b57cec5SDimitry Andric /// specified function argument. 426*0fca6ea1SDimitry Andric static bool allCallersPassValidPointerForArgument( 427*0fca6ea1SDimitry Andric Argument *Arg, SmallPtrSetImpl<CallBase *> &RecursiveCalls, 428*0fca6ea1SDimitry Andric Align NeededAlign, uint64_t NeededDerefBytes) { 4290b57cec5SDimitry Andric Function *Callee = Arg->getParent(); 430*0fca6ea1SDimitry Andric const DataLayout &DL = Callee->getDataLayout(); 43181ad6265SDimitry Andric APInt Bytes(64, NeededDerefBytes); 4320b57cec5SDimitry Andric 43381ad6265SDimitry Andric // Check if the argument itself is marked dereferenceable and aligned. 43481ad6265SDimitry Andric if (isDereferenceableAndAlignedPointer(Arg, NeededAlign, Bytes, DL)) 43581ad6265SDimitry Andric return true; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric // Look at all call sites of the function. At this point we know we only have 4380b57cec5SDimitry Andric // direct callees. 43981ad6265SDimitry Andric return all_of(Callee->users(), [&](User *U) { 4405ffd83dbSDimitry Andric CallBase &CB = cast<CallBase>(*U); 441*0fca6ea1SDimitry Andric // In case of functions with recursive calls, this check 442*0fca6ea1SDimitry Andric // (isDereferenceableAndAlignedPointer) will fail when it tries to look at 443*0fca6ea1SDimitry Andric // the first caller of this function. The caller may or may not have a load, 444*0fca6ea1SDimitry Andric // incase it doesn't load the pointer being passed, this check will fail. 445*0fca6ea1SDimitry Andric // So, it's safe to skip the check incase we know that we are dealing with a 446*0fca6ea1SDimitry Andric // recursive call. For example we have a IR given below. 447*0fca6ea1SDimitry Andric // 448*0fca6ea1SDimitry Andric // def fun(ptr %a) { 449*0fca6ea1SDimitry Andric // ... 450*0fca6ea1SDimitry Andric // %loadres = load i32, ptr %a, align 4 451*0fca6ea1SDimitry Andric // %res = call i32 @fun(ptr %a) 452*0fca6ea1SDimitry Andric // ... 453*0fca6ea1SDimitry Andric // } 454*0fca6ea1SDimitry Andric // 455*0fca6ea1SDimitry Andric // def bar(ptr %x) { 456*0fca6ea1SDimitry Andric // ... 457*0fca6ea1SDimitry Andric // %resbar = call i32 @fun(ptr %x) 458*0fca6ea1SDimitry Andric // ... 459*0fca6ea1SDimitry Andric // } 460*0fca6ea1SDimitry Andric // 461*0fca6ea1SDimitry Andric // Since we record processed recursive calls, we check if the current 462*0fca6ea1SDimitry Andric // CallBase has been processed before. If yes it means that it is a 463*0fca6ea1SDimitry Andric // recursive call and we can skip the check just for this call. So, just 464*0fca6ea1SDimitry Andric // return true. 465*0fca6ea1SDimitry Andric if (RecursiveCalls.contains(&CB)) 466*0fca6ea1SDimitry Andric return true; 467*0fca6ea1SDimitry Andric 46881ad6265SDimitry Andric return isDereferenceableAndAlignedPointer(CB.getArgOperand(Arg->getArgNo()), 46981ad6265SDimitry Andric NeededAlign, Bytes, DL); 47081ad6265SDimitry Andric }); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 47381ad6265SDimitry Andric /// Determine that this argument is safe to promote, and find the argument 47481ad6265SDimitry Andric /// parts it can be promoted into. 47581ad6265SDimitry Andric static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR, 47681ad6265SDimitry Andric unsigned MaxElements, bool IsRecursive, 47781ad6265SDimitry Andric SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec) { 4780b57cec5SDimitry Andric // Quick exit for unused arguments 4790b57cec5SDimitry Andric if (Arg->use_empty()) 4800b57cec5SDimitry Andric return true; 4810b57cec5SDimitry Andric 48281ad6265SDimitry Andric // We can only promote this argument if all the uses are loads at known 48381ad6265SDimitry Andric // offsets. 4840b57cec5SDimitry Andric // 4850b57cec5SDimitry Andric // Promoting the argument causes it to be loaded in the caller 4860b57cec5SDimitry Andric // unconditionally. This is only safe if we can prove that either the load 4870b57cec5SDimitry Andric // would have happened in the callee anyway (ie, there is a load in the entry 4880b57cec5SDimitry Andric // block) or the pointer passed in at every call site is guaranteed to be 4890b57cec5SDimitry Andric // valid. 4900b57cec5SDimitry Andric // In the former case, invalid loads can happen, but would have happened 4910b57cec5SDimitry Andric // anyway, in the latter case, invalid loads won't happen. This prevents us 4920b57cec5SDimitry Andric // from introducing an invalid load that wouldn't have happened in the 4930b57cec5SDimitry Andric // original code. 4940b57cec5SDimitry Andric 49581ad6265SDimitry Andric SmallDenseMap<int64_t, ArgPart, 4> ArgParts; 49681ad6265SDimitry Andric Align NeededAlign(1); 49781ad6265SDimitry Andric uint64_t NeededDerefBytes = 0; 4980b57cec5SDimitry Andric 49981ad6265SDimitry Andric // And if this is a byval argument we also allow to have store instructions. 50081ad6265SDimitry Andric // Only handle in such way arguments with specified alignment; 50181ad6265SDimitry Andric // if it's unspecified, the actual alignment of the argument is 50281ad6265SDimitry Andric // target-specific. 50381ad6265SDimitry Andric bool AreStoresAllowed = Arg->getParamByValType() && Arg->getParamAlign(); 5040b57cec5SDimitry Andric 50581ad6265SDimitry Andric // An end user of a pointer argument is a load or store instruction. 506bdd1243dSDimitry Andric // Returns std::nullopt if this load or store is not based on the argument. 507bdd1243dSDimitry Andric // Return true if we can promote the instruction, false otherwise. 50881ad6265SDimitry Andric auto HandleEndUser = [&](auto *I, Type *Ty, 509bdd1243dSDimitry Andric bool GuaranteedToExecute) -> std::optional<bool> { 51081ad6265SDimitry Andric // Don't promote volatile or atomic instructions. 51181ad6265SDimitry Andric if (!I->isSimple()) 51281ad6265SDimitry Andric return false; 5130b57cec5SDimitry Andric 51481ad6265SDimitry Andric Value *Ptr = I->getPointerOperand(); 51581ad6265SDimitry Andric APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0); 51681ad6265SDimitry Andric Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset, 51781ad6265SDimitry Andric /* AllowNonInbounds */ true); 51881ad6265SDimitry Andric if (Ptr != Arg) 519bdd1243dSDimitry Andric return std::nullopt; 5200b57cec5SDimitry Andric 52181ad6265SDimitry Andric if (Offset.getSignificantBits() >= 64) 52281ad6265SDimitry Andric return false; 52381ad6265SDimitry Andric 52481ad6265SDimitry Andric TypeSize Size = DL.getTypeStoreSize(Ty); 52581ad6265SDimitry Andric // Don't try to promote scalable types. 52681ad6265SDimitry Andric if (Size.isScalable()) 52781ad6265SDimitry Andric return false; 52881ad6265SDimitry Andric 52981ad6265SDimitry Andric // If this is a recursive function and one of the types is a pointer, 53081ad6265SDimitry Andric // then promoting it might lead to recursive promotion. 53181ad6265SDimitry Andric if (IsRecursive && Ty->isPointerTy()) 53281ad6265SDimitry Andric return false; 53381ad6265SDimitry Andric 53481ad6265SDimitry Andric int64_t Off = Offset.getSExtValue(); 53581ad6265SDimitry Andric auto Pair = ArgParts.try_emplace( 53681ad6265SDimitry Andric Off, ArgPart{Ty, I->getAlign(), GuaranteedToExecute ? I : nullptr}); 53781ad6265SDimitry Andric ArgPart &Part = Pair.first->second; 53881ad6265SDimitry Andric bool OffsetNotSeenBefore = Pair.second; 53981ad6265SDimitry Andric 54081ad6265SDimitry Andric // We limit promotion to only promoting up to a fixed number of elements of 54181ad6265SDimitry Andric // the aggregate. 54281ad6265SDimitry Andric if (MaxElements > 0 && ArgParts.size() > MaxElements) { 54381ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 54481ad6265SDimitry Andric << "more than " << MaxElements << " parts\n"); 54581ad6265SDimitry Andric return false; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 54881ad6265SDimitry Andric // For now, we only support loading/storing one specific type at a given 54981ad6265SDimitry Andric // offset. 55081ad6265SDimitry Andric if (Part.Ty != Ty) { 55181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 55281ad6265SDimitry Andric << "accessed as both " << *Part.Ty << " and " << *Ty 55381ad6265SDimitry Andric << " at offset " << Off << "\n"); 55481ad6265SDimitry Andric return false; 55581ad6265SDimitry Andric } 55681ad6265SDimitry Andric 55781ad6265SDimitry Andric // If this instruction is not guaranteed to execute, and we haven't seen a 55881ad6265SDimitry Andric // load or store at this offset before (or it had lower alignment), then we 55981ad6265SDimitry Andric // need to remember that requirement. 56081ad6265SDimitry Andric // Note that skipping instructions of previously seen offsets is only 56181ad6265SDimitry Andric // correct because we only allow a single type for a given offset, which 56281ad6265SDimitry Andric // also means that the number of accessed bytes will be the same. 56381ad6265SDimitry Andric if (!GuaranteedToExecute && 56481ad6265SDimitry Andric (OffsetNotSeenBefore || Part.Alignment < I->getAlign())) { 56581ad6265SDimitry Andric // We won't be able to prove dereferenceability for negative offsets. 56681ad6265SDimitry Andric if (Off < 0) 56781ad6265SDimitry Andric return false; 56881ad6265SDimitry Andric 56981ad6265SDimitry Andric // If the offset is not aligned, an aligned base pointer won't help. 57081ad6265SDimitry Andric if (!isAligned(I->getAlign(), Off)) 57181ad6265SDimitry Andric return false; 57281ad6265SDimitry Andric 57381ad6265SDimitry Andric NeededDerefBytes = std::max(NeededDerefBytes, Off + Size.getFixedValue()); 57481ad6265SDimitry Andric NeededAlign = std::max(NeededAlign, I->getAlign()); 57581ad6265SDimitry Andric } 57681ad6265SDimitry Andric 57781ad6265SDimitry Andric Part.Alignment = std::max(Part.Alignment, I->getAlign()); 5780b57cec5SDimitry Andric return true; 5790b57cec5SDimitry Andric }; 5800b57cec5SDimitry Andric 58181ad6265SDimitry Andric // Look for loads and stores that are guaranteed to execute on entry. 58281ad6265SDimitry Andric for (Instruction &I : Arg->getParent()->getEntryBlock()) { 583bdd1243dSDimitry Andric std::optional<bool> Res{}; 58481ad6265SDimitry Andric if (LoadInst *LI = dyn_cast<LoadInst>(&I)) 58581ad6265SDimitry Andric Res = HandleEndUser(LI, LI->getType(), /* GuaranteedToExecute */ true); 58681ad6265SDimitry Andric else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) 58781ad6265SDimitry Andric Res = HandleEndUser(SI, SI->getValueOperand()->getType(), 58881ad6265SDimitry Andric /* GuaranteedToExecute */ true); 58981ad6265SDimitry Andric if (Res && !*Res) 5900b57cec5SDimitry Andric return false; 5910b57cec5SDimitry Andric 5921fd87a68SDimitry Andric if (!isGuaranteedToTransferExecutionToSuccessor(&I)) 5931fd87a68SDimitry Andric break; 5941fd87a68SDimitry Andric } 5951fd87a68SDimitry Andric 59681ad6265SDimitry Andric // Now look at all loads of the argument. Remember the load instructions 59781ad6265SDimitry Andric // for the aliasing check below. 59881ad6265SDimitry Andric SmallVector<const Use *, 16> Worklist; 59981ad6265SDimitry Andric SmallPtrSet<const Use *, 16> Visited; 6000b57cec5SDimitry Andric SmallVector<LoadInst *, 16> Loads; 601*0fca6ea1SDimitry Andric SmallPtrSet<CallBase *, 4> RecursiveCalls; 60281ad6265SDimitry Andric auto AppendUses = [&](const Value *V) { 60381ad6265SDimitry Andric for (const Use &U : V->uses()) 60481ad6265SDimitry Andric if (Visited.insert(&U).second) 60581ad6265SDimitry Andric Worklist.push_back(&U); 60681ad6265SDimitry Andric }; 60781ad6265SDimitry Andric AppendUses(Arg); 60881ad6265SDimitry Andric while (!Worklist.empty()) { 60981ad6265SDimitry Andric const Use *U = Worklist.pop_back_val(); 61081ad6265SDimitry Andric Value *V = U->getUser(); 61181ad6265SDimitry Andric if (isa<BitCastInst>(V)) { 61281ad6265SDimitry Andric AppendUses(V); 613e8d8bef9SDimitry Andric continue; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 61681ad6265SDimitry Andric if (auto *GEP = dyn_cast<GetElementPtrInst>(V)) { 61781ad6265SDimitry Andric if (!GEP->hasAllConstantIndices()) 6180b57cec5SDimitry Andric return false; 61981ad6265SDimitry Andric AppendUses(V); 62081ad6265SDimitry Andric continue; 62181ad6265SDimitry Andric } 6220b57cec5SDimitry Andric 62381ad6265SDimitry Andric if (auto *LI = dyn_cast<LoadInst>(V)) { 62481ad6265SDimitry Andric if (!*HandleEndUser(LI, LI->getType(), /* GuaranteedToExecute */ false)) 6250b57cec5SDimitry Andric return false; 6260b57cec5SDimitry Andric Loads.push_back(LI); 62781ad6265SDimitry Andric continue; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 63081ad6265SDimitry Andric // Stores are allowed for byval arguments 63181ad6265SDimitry Andric auto *SI = dyn_cast<StoreInst>(V); 63281ad6265SDimitry Andric if (AreStoresAllowed && SI && 63381ad6265SDimitry Andric U->getOperandNo() == StoreInst::getPointerOperandIndex()) { 63481ad6265SDimitry Andric if (!*HandleEndUser(SI, SI->getValueOperand()->getType(), 63581ad6265SDimitry Andric /* GuaranteedToExecute */ false)) 6360b57cec5SDimitry Andric return false; 63781ad6265SDimitry Andric continue; 63881ad6265SDimitry Andric // Only stores TO the argument is allowed, all the other stores are 63981ad6265SDimitry Andric // unknown users 64081ad6265SDimitry Andric } 6410b57cec5SDimitry Andric 642*0fca6ea1SDimitry Andric auto *CB = dyn_cast<CallBase>(V); 643*0fca6ea1SDimitry Andric Value *PtrArg = U->get(); 644*0fca6ea1SDimitry Andric if (CB && CB->getCalledFunction() == CB->getFunction()) { 645*0fca6ea1SDimitry Andric if (PtrArg != Arg) { 646*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 647*0fca6ea1SDimitry Andric << "pointer offset is not equal to zero\n"); 648*0fca6ea1SDimitry Andric return false; 649*0fca6ea1SDimitry Andric } 650*0fca6ea1SDimitry Andric 651*0fca6ea1SDimitry Andric unsigned int ArgNo = Arg->getArgNo(); 652*0fca6ea1SDimitry Andric if (U->getOperandNo() != ArgNo) { 653*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 654*0fca6ea1SDimitry Andric << "arg position is different in callee\n"); 655*0fca6ea1SDimitry Andric return false; 656*0fca6ea1SDimitry Andric } 657*0fca6ea1SDimitry Andric 658*0fca6ea1SDimitry Andric // We limit promotion to only promoting up to a fixed number of elements 659*0fca6ea1SDimitry Andric // of the aggregate. 660*0fca6ea1SDimitry Andric if (MaxElements > 0 && ArgParts.size() > MaxElements) { 661*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 662*0fca6ea1SDimitry Andric << "more than " << MaxElements << " parts\n"); 663*0fca6ea1SDimitry Andric return false; 664*0fca6ea1SDimitry Andric } 665*0fca6ea1SDimitry Andric 666*0fca6ea1SDimitry Andric RecursiveCalls.insert(CB); 667*0fca6ea1SDimitry Andric continue; 668*0fca6ea1SDimitry Andric } 66981ad6265SDimitry Andric // Unknown user. 67081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 67181ad6265SDimitry Andric << "unknown user " << *V << "\n"); 6720b57cec5SDimitry Andric return false; 6730b57cec5SDimitry Andric } 67481ad6265SDimitry Andric 67581ad6265SDimitry Andric if (NeededDerefBytes || NeededAlign > 1) { 67681ad6265SDimitry Andric // Try to prove a required deref / aligned requirement. 677*0fca6ea1SDimitry Andric if (!allCallersPassValidPointerForArgument(Arg, RecursiveCalls, NeededAlign, 67881ad6265SDimitry Andric NeededDerefBytes)) { 67981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: " 68081ad6265SDimitry Andric << "not dereferenceable or aligned\n"); 68181ad6265SDimitry Andric return false; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 68581ad6265SDimitry Andric if (ArgParts.empty()) 6860b57cec5SDimitry Andric return true; // No users, this is a dead argument. 6870b57cec5SDimitry Andric 68881ad6265SDimitry Andric // Sort parts by offset. 68981ad6265SDimitry Andric append_range(ArgPartsVec, ArgParts); 690972a253aSDimitry Andric sort(ArgPartsVec, llvm::less_first()); 69181ad6265SDimitry Andric 69281ad6265SDimitry Andric // Make sure the parts are non-overlapping. 69381ad6265SDimitry Andric int64_t Offset = ArgPartsVec[0].first; 69481ad6265SDimitry Andric for (const auto &Pair : ArgPartsVec) { 69581ad6265SDimitry Andric if (Pair.first < Offset) 69681ad6265SDimitry Andric return false; // Overlap with previous part. 69781ad6265SDimitry Andric 69881ad6265SDimitry Andric Offset = Pair.first + DL.getTypeStoreSize(Pair.second.Ty); 69981ad6265SDimitry Andric } 70081ad6265SDimitry Andric 70181ad6265SDimitry Andric // If store instructions are allowed, the path from the entry of the function 70281ad6265SDimitry Andric // to each load may be not free of instructions that potentially invalidate 70381ad6265SDimitry Andric // the load, and this is an admissible situation. 70481ad6265SDimitry Andric if (AreStoresAllowed) 70581ad6265SDimitry Andric return true; 70681ad6265SDimitry Andric 70781ad6265SDimitry Andric // Okay, now we know that the argument is only used by load instructions, and 7080b57cec5SDimitry Andric // it is safe to unconditionally perform all of them. Use alias analysis to 7090b57cec5SDimitry Andric // check to see if the pointer is guaranteed to not be modified from entry of 7100b57cec5SDimitry Andric // the function to each of the load instructions. 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric for (LoadInst *Load : Loads) { 7130b57cec5SDimitry Andric // Check to see if the load is invalidated from the start of the block to 7140b57cec5SDimitry Andric // the load itself. 7150b57cec5SDimitry Andric BasicBlock *BB = Load->getParent(); 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric MemoryLocation Loc = MemoryLocation::get(Load); 7180b57cec5SDimitry Andric if (AAR.canInstructionRangeModRef(BB->front(), *Load, Loc, ModRefInfo::Mod)) 7190b57cec5SDimitry Andric return false; // Pointer is invalidated! 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric // Now check every path from the entry block to the load for transparency. 7220b57cec5SDimitry Andric // To do this, we perform a depth first search on the inverse CFG from the 7230b57cec5SDimitry Andric // loading block. 7240b57cec5SDimitry Andric for (BasicBlock *P : predecessors(BB)) { 725439352acSDimitry Andric for (BasicBlock *TranspBB : inverse_depth_first(P)) 7260b57cec5SDimitry Andric if (AAR.canBasicBlockModify(*TranspBB, Loc)) 7270b57cec5SDimitry Andric return false; 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // If the path from the entry of the function to each load is free of 7320b57cec5SDimitry Andric // instructions that potentially invalidate the load, we can make the 7330b57cec5SDimitry Andric // transformation! 7340b57cec5SDimitry Andric return true; 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 73781ad6265SDimitry Andric /// Check if callers and callee agree on how promoted arguments would be 73881ad6265SDimitry Andric /// passed. 73981ad6265SDimitry Andric static bool areTypesABICompatible(ArrayRef<Type *> Types, const Function &F, 74081ad6265SDimitry Andric const TargetTransformInfo &TTI) { 74181ad6265SDimitry Andric return all_of(F.uses(), [&](const Use &U) { 7425ffd83dbSDimitry Andric CallBase *CB = dyn_cast<CallBase>(U.getUser()); 7435ffd83dbSDimitry Andric if (!CB) 7445ffd83dbSDimitry Andric return false; 74581ad6265SDimitry Andric 7465ffd83dbSDimitry Andric const Function *Caller = CB->getCaller(); 7475ffd83dbSDimitry Andric const Function *Callee = CB->getCalledFunction(); 74881ad6265SDimitry Andric return TTI.areTypesABICompatible(Caller, Callee, Types); 74981ad6265SDimitry Andric }); 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric /// PromoteArguments - This method checks the specified function to see if there 7530b57cec5SDimitry Andric /// are any promotable arguments and if it is safe to promote the function (for 7540b57cec5SDimitry Andric /// example, all callers are direct). If safe to promote some arguments, it 7550b57cec5SDimitry Andric /// calls the DoPromotion method. 75681ad6265SDimitry Andric static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM, 75781ad6265SDimitry Andric unsigned MaxElements, bool IsRecursive) { 7580b57cec5SDimitry Andric // Don't perform argument promotion for naked functions; otherwise we can end 7590b57cec5SDimitry Andric // up removing parameters that are seemingly 'not used' as they are referred 7600b57cec5SDimitry Andric // to in the assembly. 7610b57cec5SDimitry Andric if (F->hasFnAttribute(Attribute::Naked)) 7620b57cec5SDimitry Andric return nullptr; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric // Make sure that it is local to this module. 7650b57cec5SDimitry Andric if (!F->hasLocalLinkage()) 7660b57cec5SDimitry Andric return nullptr; 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric // Don't promote arguments for variadic functions. Adding, removing, or 7690b57cec5SDimitry Andric // changing non-pack parameters can change the classification of pack 7700b57cec5SDimitry Andric // parameters. Frontends encode that classification at the call site in the 7710b57cec5SDimitry Andric // IR, while in the callee the classification is determined dynamically based 7720b57cec5SDimitry Andric // on the number of registers consumed so far. 7730b57cec5SDimitry Andric if (F->isVarArg()) 7740b57cec5SDimitry Andric return nullptr; 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // Don't transform functions that receive inallocas, as the transformation may 7770b57cec5SDimitry Andric // not be safe depending on calling convention. 7780b57cec5SDimitry Andric if (F->getAttributes().hasAttrSomewhere(Attribute::InAlloca)) 7790b57cec5SDimitry Andric return nullptr; 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric // First check: see if there are any pointer arguments! If not, quick exit. 7820b57cec5SDimitry Andric SmallVector<Argument *, 16> PointerArgs; 7830b57cec5SDimitry Andric for (Argument &I : F->args()) 7840b57cec5SDimitry Andric if (I.getType()->isPointerTy()) 7850b57cec5SDimitry Andric PointerArgs.push_back(&I); 7860b57cec5SDimitry Andric if (PointerArgs.empty()) 7870b57cec5SDimitry Andric return nullptr; 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric // Second check: make sure that all callers are direct callers. We can't 7900b57cec5SDimitry Andric // transform functions that have indirect callers. Also see if the function 79181ad6265SDimitry Andric // is self-recursive. 7920b57cec5SDimitry Andric for (Use &U : F->uses()) { 7935ffd83dbSDimitry Andric CallBase *CB = dyn_cast<CallBase>(U.getUser()); 7940b57cec5SDimitry Andric // Must be a direct call. 79581ad6265SDimitry Andric if (CB == nullptr || !CB->isCallee(&U) || 79681ad6265SDimitry Andric CB->getFunctionType() != F->getFunctionType()) 7970b57cec5SDimitry Andric return nullptr; 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric // Can't change signature of musttail callee 8005ffd83dbSDimitry Andric if (CB->isMustTailCall()) 8010b57cec5SDimitry Andric return nullptr; 8020b57cec5SDimitry Andric 80381ad6265SDimitry Andric if (CB->getFunction() == F) 80481ad6265SDimitry Andric IsRecursive = true; 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric // Can't change signature of musttail caller 8080b57cec5SDimitry Andric // FIXME: Support promoting whole chain of musttail functions 8090b57cec5SDimitry Andric for (BasicBlock &BB : *F) 8100b57cec5SDimitry Andric if (BB.getTerminatingMustTailCall()) 8110b57cec5SDimitry Andric return nullptr; 8120b57cec5SDimitry Andric 813*0fca6ea1SDimitry Andric const DataLayout &DL = F->getDataLayout(); 81481ad6265SDimitry Andric auto &AAR = FAM.getResult<AAManager>(*F); 81581ad6265SDimitry Andric const auto &TTI = FAM.getResult<TargetIRAnalysis>(*F); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Check to see which arguments are promotable. If an argument is promotable, 8180b57cec5SDimitry Andric // add it to ArgsToPromote. 81981ad6265SDimitry Andric DenseMap<Argument *, SmallVector<OffsetAndArgPart, 4>> ArgsToPromote; 82006c3fb27SDimitry Andric unsigned NumArgsAfterPromote = F->getFunctionType()->getNumParams(); 8210b57cec5SDimitry Andric for (Argument *PtrArg : PointerArgs) { 8220b57cec5SDimitry Andric // Replace sret attribute with noalias. This reduces register pressure by 8230b57cec5SDimitry Andric // avoiding a register copy. 8240b57cec5SDimitry Andric if (PtrArg->hasStructRetAttr()) { 8250b57cec5SDimitry Andric unsigned ArgNo = PtrArg->getArgNo(); 8260b57cec5SDimitry Andric F->removeParamAttr(ArgNo, Attribute::StructRet); 8270b57cec5SDimitry Andric F->addParamAttr(ArgNo, Attribute::NoAlias); 8280b57cec5SDimitry Andric for (Use &U : F->uses()) { 8295ffd83dbSDimitry Andric CallBase &CB = cast<CallBase>(*U.getUser()); 8305ffd83dbSDimitry Andric CB.removeParamAttr(ArgNo, Attribute::StructRet); 8315ffd83dbSDimitry Andric CB.addParamAttr(ArgNo, Attribute::NoAlias); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 83581ad6265SDimitry Andric // If we can promote the pointer to its value. 83681ad6265SDimitry Andric SmallVector<OffsetAndArgPart, 4> ArgParts; 8370b57cec5SDimitry Andric 83881ad6265SDimitry Andric if (findArgParts(PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts)) { 83981ad6265SDimitry Andric SmallVector<Type *, 4> Types; 84081ad6265SDimitry Andric for (const auto &Pair : ArgParts) 84181ad6265SDimitry Andric Types.push_back(Pair.second.Ty); 8420b57cec5SDimitry Andric 84381ad6265SDimitry Andric if (areTypesABICompatible(Types, *F, TTI)) { 84406c3fb27SDimitry Andric NumArgsAfterPromote += ArgParts.size() - 1; 84581ad6265SDimitry Andric ArgsToPromote.insert({PtrArg, std::move(ArgParts)}); 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric // No promotable pointer arguments. 85181ad6265SDimitry Andric if (ArgsToPromote.empty()) 8520b57cec5SDimitry Andric return nullptr; 8530b57cec5SDimitry Andric 85406c3fb27SDimitry Andric if (NumArgsAfterPromote > TTI.getMaxNumArgs()) 85506c3fb27SDimitry Andric return nullptr; 85606c3fb27SDimitry Andric 85781ad6265SDimitry Andric return doPromotion(F, FAM, ArgsToPromote); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric PreservedAnalyses ArgumentPromotionPass::run(LazyCallGraph::SCC &C, 8610b57cec5SDimitry Andric CGSCCAnalysisManager &AM, 8620b57cec5SDimitry Andric LazyCallGraph &CG, 8630b57cec5SDimitry Andric CGSCCUpdateResult &UR) { 8640b57cec5SDimitry Andric bool Changed = false, LocalChange; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric // Iterate until we stop promoting from this SCC. 8670b57cec5SDimitry Andric do { 8680b57cec5SDimitry Andric LocalChange = false; 8690b57cec5SDimitry Andric 870349cc55cSDimitry Andric FunctionAnalysisManager &FAM = 871349cc55cSDimitry Andric AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); 872349cc55cSDimitry Andric 87381ad6265SDimitry Andric bool IsRecursive = C.size() > 1; 8740b57cec5SDimitry Andric for (LazyCallGraph::Node &N : C) { 8750b57cec5SDimitry Andric Function &OldF = N.getFunction(); 87681ad6265SDimitry Andric Function *NewF = promoteArguments(&OldF, FAM, MaxElements, IsRecursive); 8770b57cec5SDimitry Andric if (!NewF) 8780b57cec5SDimitry Andric continue; 8790b57cec5SDimitry Andric LocalChange = true; 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric // Directly substitute the functions in the call graph. Note that this 8820b57cec5SDimitry Andric // requires the old function to be completely dead and completely 8830b57cec5SDimitry Andric // replaced by the new function. It does no call graph updates, it merely 8840b57cec5SDimitry Andric // swaps out the particular function mapped to a particular node in the 8850b57cec5SDimitry Andric // graph. 8860b57cec5SDimitry Andric C.getOuterRefSCC().replaceNodeFunction(N, *NewF); 887fe6060f1SDimitry Andric FAM.clear(OldF, OldF.getName()); 8880b57cec5SDimitry Andric OldF.eraseFromParent(); 889349cc55cSDimitry Andric 890349cc55cSDimitry Andric PreservedAnalyses FuncPA; 891349cc55cSDimitry Andric FuncPA.preserveSet<CFGAnalyses>(); 892349cc55cSDimitry Andric for (auto *U : NewF->users()) { 893349cc55cSDimitry Andric auto *UserF = cast<CallBase>(U)->getFunction(); 894349cc55cSDimitry Andric FAM.invalidate(*UserF, FuncPA); 895349cc55cSDimitry Andric } 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric Changed |= LocalChange; 8990b57cec5SDimitry Andric } while (LocalChange); 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric if (!Changed) 9020b57cec5SDimitry Andric return PreservedAnalyses::all(); 9030b57cec5SDimitry Andric 904349cc55cSDimitry Andric PreservedAnalyses PA; 905349cc55cSDimitry Andric // We've cleared out analyses for deleted functions. 906349cc55cSDimitry Andric PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 907349cc55cSDimitry Andric // We've manually invalidated analyses for functions we've modified. 908349cc55cSDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 909349cc55cSDimitry Andric return PA; 9100b57cec5SDimitry Andric } 911