@@ -474,7 +474,8 @@ static bool allCallersPassValidPointerForArgument(
474474// / parts it can be promoted into.
475475static bool findArgParts (Argument *Arg, const DataLayout &DL, AAResults &AAR,
476476 unsigned MaxElements, bool IsRecursive,
477- SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec) {
477+ SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec,
478+ bool ArgNotModified) {
478479 // Quick exit for unused arguments
479480 if (Arg->use_empty ())
480481 return true ;
@@ -696,8 +697,10 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
696697
697698 // If store instructions are allowed, the path from the entry of the function
698699 // to each load may be not free of instructions that potentially invalidate
699- // the load, and this is an admissible situation.
700- if (AreStoresAllowed)
700+ // the load, and this is an admissible situation. If we have already
701+ // determined that the pointer Arg is not modified in the function (for all
702+ // Calls) then we can similarly conclude analysis here.
703+ if (AreStoresAllowed || ArgNotModified)
701704 return true ;
702705
703706 // Okay, now we know that the argument is only used by load instructions, and
@@ -745,6 +748,33 @@ static bool areTypesABICompatible(ArrayRef<Type *> Types, const Function &F,
745748 });
746749}
747750
751+ // Try to prove that all Calls to F do not modify the memory pointed to by Arg.
752+ // This can provide us with more opportunities to perform Argument Promotion in
753+ // cases where simply looking at a Function's instructions is insufficient to
754+ // prove that the pointer argument is not invalidated before all loads from it.
755+ static bool callDoesNotModifyArg (Function *F, unsigned ArgNo,
756+ FunctionAnalysisManager &FAM) {
757+ // Find all Users of F that are Calls, and see if they may modify Arg.
758+ for (User *U : F->users ()) {
759+ auto *Call = dyn_cast<CallInst>(U);
760+ if (!Call)
761+ continue ;
762+
763+ Value *ArgOp = Call->getArgOperand (ArgNo);
764+ assert (ArgOp->getType ()->isPointerTy () && " Argument must be Pointer Type!" );
765+
766+ MemoryLocation Loc = MemoryLocation::getForArgument (Call, ArgNo, nullptr );
767+
768+ AAResults &AAR = FAM.getResult <AAManager>(*Call->getFunction ());
769+ // Bail out as soon as we find a Call where Arg may be modified.
770+ if (isModSet (AAR.getModRefInfo (Call, Loc)))
771+ return false ;
772+ }
773+
774+ // All Calls do not modify the Arg.
775+ return true ;
776+ }
777+
748778// / PromoteArguments - This method checks the specified function to see if there
749779// / are any promotable arguments and if it is safe to promote the function (for
750780// / example, all callers are direct). If safe to promote some arguments, it
@@ -775,11 +805,13 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
775805 return nullptr ;
776806
777807 // First check: see if there are any pointer arguments! If not, quick exit.
778- SmallVector<Argument *, 16 > PointerArgs;
779- for (Argument &I : F->args ())
780- if (I.getType ()->isPointerTy ())
781- PointerArgs.push_back (&I);
782- if (PointerArgs.empty ())
808+ SmallVector<unsigned , 16 > PointerArgNos;
809+ for (unsigned I = 0 ; I < F->arg_size (); ++I) {
810+ Argument *Arg = F->getArg (I);
811+ if (Arg->getType ()->isPointerTy ())
812+ PointerArgNos.push_back (I);
813+ }
814+ if (PointerArgNos.empty ())
783815 return nullptr ;
784816
785817 // Second check: make sure that all callers are direct callers. We can't
@@ -814,7 +846,8 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
814846 // add it to ArgsToPromote.
815847 DenseMap<Argument *, SmallVector<OffsetAndArgPart, 4 >> ArgsToPromote;
816848 unsigned NumArgsAfterPromote = F->getFunctionType ()->getNumParams ();
817- for (Argument *PtrArg : PointerArgs) {
849+ for (const auto &ArgIdx : PointerArgNos) {
850+ Argument *PtrArg = F->getArg (ArgIdx);
818851 // Replace sret attribute with noalias. This reduces register pressure by
819852 // avoiding a register copy.
820853 if (PtrArg->hasStructRetAttr ()) {
@@ -828,10 +861,15 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
828861 }
829862 }
830863
864+ // Check if we can determine ahead of time that the argument is never
865+ // modified by a call to this function.
866+ bool ArgNotModified = callDoesNotModifyArg (F, ArgIdx, FAM);
867+
831868 // If we can promote the pointer to its value.
832869 SmallVector<OffsetAndArgPart, 4 > ArgParts;
833870
834- if (findArgParts (PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts)) {
871+ if (findArgParts (PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts,
872+ ArgNotModified)) {
835873 SmallVector<Type *, 4 > Types;
836874 for (const auto &Pair : ArgParts)
837875 Types.push_back (Pair.second .Ty );
0 commit comments