Skip to content

Commit 9aa4e64

Browse files
committed
Address review comments
- Bail on unexpected (non CallInst) use of function - Move checks into findArgParts to improve clarity and only run when necessary - Remove FIXMEs from test
1 parent d10cb42 commit 9aa4e64

File tree

2 files changed

+46
-53
lines changed

2 files changed

+46
-53
lines changed

llvm/lib/Transforms/IPO/ArgumentPromotion.cpp

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,39 @@ static bool allCallersPassValidPointerForArgument(
485485
});
486486
}
487487

488+
// Try to prove that all Calls to F do not modify the memory pointed to by Arg,
489+
// using alias analysis local to each caller of F.
490+
static bool isArgUnmodifiedByAllCalls(Function *F, unsigned ArgNo,
491+
FunctionAnalysisManager &FAM) {
492+
// Check if all Users of F are Calls which do not modify Arg.
493+
for (User *U : F->users()) {
494+
495+
// Bail if we find an unexpected (non CallInst) use of the function.
496+
auto *Call = dyn_cast<CallInst>(U);
497+
if (!Call)
498+
return false;
499+
500+
Value *ArgOp = Call->getArgOperand(ArgNo);
501+
assert(ArgOp->getType()->isPointerTy() && "Argument must be Pointer Type!");
502+
503+
MemoryLocation Loc = MemoryLocation::getForArgument(Call, ArgNo, nullptr);
504+
505+
AAResults &AAR = FAM.getResult<AAManager>(*Call->getFunction());
506+
// Bail as soon as we find a Call where Arg may be modified.
507+
if (isModSet(AAR.getModRefInfo(Call, Loc)))
508+
return false;
509+
}
510+
511+
// All Users are Calls which do not modify the Arg.
512+
return true;
513+
}
514+
488515
/// Determine that this argument is safe to promote, and find the argument
489516
/// parts it can be promoted into.
490517
static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
491518
unsigned MaxElements, bool IsRecursive,
492519
SmallVectorImpl<OffsetAndArgPart> &ArgPartsVec,
493-
bool ArgNotModified) {
520+
FunctionAnalysisManager &FAM) {
494521
// Quick exit for unused arguments
495522
if (Arg->use_empty())
496523
return true;
@@ -712,17 +739,21 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
712739

713740
// If store instructions are allowed, the path from the entry of the function
714741
// to each load may be not free of instructions that potentially invalidate
715-
// the load, and this is an admissible situation. If we have already
716-
// determined that the pointer Arg is not modified in the function (for all
717-
// Calls) then we can similarly conclude analysis here.
718-
if (AreStoresAllowed || ArgNotModified)
742+
// the load, and this is an admissible situation.
743+
if (AreStoresAllowed)
719744
return true;
720745

721746
// Okay, now we know that the argument is only used by load instructions, and
722-
// it is safe to unconditionally perform all of them. Use alias analysis to
723-
// check to see if the pointer is guaranteed to not be modified from entry of
724-
// the function to each of the load instructions.
747+
// it is safe to unconditionally perform all of them.
748+
749+
// If we can determine that no call to the Function modifies the memory
750+
// pointed to by Arg, through alias analysis using actual arguments in the
751+
// callers, we know that it is guaranteed to be safe to promote the argument.
752+
if (isArgUnmodifiedByAllCalls(Arg->getParent(), Arg->getArgNo(), FAM))
753+
return true;
725754

755+
// Otherwise, use alias analysis to check if the pointer is guaranteed to not
756+
// be modified from entry of the function to each of the load instructions.
726757
for (LoadInst *Load : Loads) {
727758
// Check to see if the load is invalidated from the start of the block to
728759
// the load itself.
@@ -763,33 +794,6 @@ static bool areTypesABICompatible(ArrayRef<Type *> Types, const Function &F,
763794
});
764795
}
765796

766-
// Try to prove that all Calls to F do not modify the memory pointed to by Arg.
767-
// This can provide us with more opportunities to perform Argument Promotion in
768-
// cases where simply looking at a Function's instructions is insufficient to
769-
// prove that the pointer argument is not invalidated before all loads from it.
770-
static bool callDoesNotModifyArg(Function *F, unsigned ArgNo,
771-
FunctionAnalysisManager &FAM) {
772-
// Find all Users of F that are Calls, and see if they may modify Arg.
773-
for (User *U : F->users()) {
774-
auto *Call = dyn_cast<CallInst>(U);
775-
if (!Call)
776-
continue;
777-
778-
Value *ArgOp = Call->getArgOperand(ArgNo);
779-
assert(ArgOp->getType()->isPointerTy() && "Argument must be Pointer Type!");
780-
781-
MemoryLocation Loc = MemoryLocation::getForArgument(Call, ArgNo, nullptr);
782-
783-
AAResults &AAR = FAM.getResult<AAManager>(*Call->getFunction());
784-
// Bail out as soon as we find a Call where Arg may be modified.
785-
if (isModSet(AAR.getModRefInfo(Call, Loc)))
786-
return false;
787-
}
788-
789-
// All Calls do not modify the Arg.
790-
return true;
791-
}
792-
793797
/// PromoteArguments - This method checks the specified function to see if there
794798
/// are any promotable arguments and if it is safe to promote the function (for
795799
/// example, all callers are direct). If safe to promote some arguments, it
@@ -820,13 +824,11 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
820824
return nullptr;
821825

822826
// First check: see if there are any pointer arguments! If not, quick exit.
823-
SmallVector<unsigned, 16> PointerArgNos;
824-
for (unsigned I = 0; I < F->arg_size(); ++I) {
825-
Argument *Arg = F->getArg(I);
826-
if (Arg->getType()->isPointerTy())
827-
PointerArgNos.push_back(I);
828-
}
829-
if (PointerArgNos.empty())
827+
SmallVector<Argument *, 16> PointerArgs;
828+
for (Argument &I : F->args())
829+
if (I.getType()->isPointerTy())
830+
PointerArgs.push_back(&I);
831+
if (PointerArgs.empty())
830832
return nullptr;
831833

832834
// Second check: make sure that all callers are direct callers. We can't
@@ -861,8 +863,7 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
861863
// add it to ArgsToPromote.
862864
DenseMap<Argument *, SmallVector<OffsetAndArgPart, 4>> ArgsToPromote;
863865
unsigned NumArgsAfterPromote = F->getFunctionType()->getNumParams();
864-
for (const auto &ArgIdx : PointerArgNos) {
865-
Argument *PtrArg = F->getArg(ArgIdx);
866+
for (Argument *PtrArg : PointerArgs) {
866867
// Replace sret attribute with noalias. This reduces register pressure by
867868
// avoiding a register copy.
868869
if (PtrArg->hasStructRetAttr()) {
@@ -876,15 +877,11 @@ static Function *promoteArguments(Function *F, FunctionAnalysisManager &FAM,
876877
}
877878
}
878879

879-
// Check if we can determine ahead of time that the argument is never
880-
// modified by a call to this function.
881-
bool ArgNotModified = callDoesNotModifyArg(F, ArgIdx, FAM);
882-
883880
// If we can promote the pointer to its value.
884881
SmallVector<OffsetAndArgPart, 4> ArgParts;
885882

886883
if (findArgParts(PtrArg, DL, AAR, MaxElements, IsRecursive, ArgParts,
887-
ArgNotModified)) {
884+
FAM)) {
888885
SmallVector<Type *, 4> Types;
889886
for (const auto &Pair : ArgParts)
890887
Types.push_back(Pair.second.Ty);

llvm/test/Transforms/ArgumentPromotion/actual-arguments.ll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ define internal i32 @test_cannot_promote_3(ptr %p, ptr nocapture readonly %test_
6868
ret i32 %sum
6969
}
7070

71-
; FIXME: We should perform ArgPromotion here!
72-
;
7371
; This is called only by @caller_safe_args_1, from which we can prove that
7472
; %test_c does not alias %p for any Call to the function, so we can promote it.
7573
;
@@ -89,8 +87,6 @@ define internal i32 @test_can_promote_1(ptr %p, ptr nocapture readonly %test_c)
8987
ret i32 %sum
9088
}
9189

92-
; FIXME: We should perform ArgPromotion here!
93-
;
9490
; This is called by multiple callers (@caller_safe_args_1, @caller_safe_args_2),
9591
; from which we can prove that %test_c does not alias %p for any Call to the
9692
; function, so we can promote it.

0 commit comments

Comments
 (0)