xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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