@@ -474,7 +474,8 @@ static bool allCallersPassValidPointerForArgument(
474
474
// / parts it can be promoted into.
475
475
static bool findArgParts (Argument *Arg, const DataLayout &DL, AAResults &AAR,
476
476
unsigned MaxElements, bool IsRecursive,
477
- SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec) {
477
+ SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec,
478
+ bool ArgNotModified) {
478
479
// Quick exit for unused arguments
479
480
if (Arg->use_empty ())
480
481
return true ;
@@ -696,8 +697,10 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
696
697
697
698
// If store instructions are allowed, the path from the entry of the function
698
699
// 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)
701
704
return true ;
702
705
703
706
// 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,
745
748
});
746
749
}
747
750
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
+
748
778
// / PromoteArguments - This method checks the specified function to see if there
749
779
// / are any promotable arguments and if it is safe to promote the function (for
750
780
// / example, all callers are direct). If safe to promote some arguments, it
@@ -775,11 +805,13 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
775
805
return nullptr ;
776
806
777
807
// 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 ())
783
815
return nullptr ;
784
816
785
817
// Second check: make sure that all callers are direct callers. We can't
@@ -814,7 +846,8 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
814
846
// add it to ArgsToPromote.
815
847
DenseMap<Argument *, SmallVector<OffsetAndArgPart, 4 >> ArgsToPromote;
816
848
unsigned NumArgsAfterPromote = F->getFunctionType ()->getNumParams ();
817
- for (Argument *PtrArg : PointerArgs) {
849
+ for (const auto &ArgIdx : PointerArgNos) {
850
+ Argument *PtrArg = F->getArg (ArgIdx);
818
851
// Replace sret attribute with noalias. This reduces register pressure by
819
852
// avoiding a register copy.
820
853
if (PtrArg->hasStructRetAttr ()) {
@@ -828,10 +861,15 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
828
861
}
829
862
}
830
863
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
+
831
868
// If we can promote the pointer to its value.
832
869
SmallVector<OffsetAndArgPart, 4 > ArgParts;
833
870
834
- if (findArgParts (PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts)) {
871
+ if (findArgParts (PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts,
872
+ ArgNotModified)) {
835
873
SmallVector<Type *, 4 > Types;
836
874
for (const auto &Pair : ArgParts)
837
875
Types.push_back (Pair.second .Ty );
0 commit comments