llvm.org GIT mirror llvm / 87a9fe3
[Attributor] Use abstract call sites for call site callback Summary: When we iterate over uses of functions and expect them to be call sites, we now use abstract call sites to allow callback calls. Reviewers: sstefan1, uenoku Subscribers: hiraditya, bollu, hfinkel, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67871 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@373985 91177308-0d34-0410-b5e6-96231b3b80d8 Johannes Doerfert 1 year, 1 month ago
4 changed file(s) with 121 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
853853 return CI.ParameterEncoding[0];
854854 }
855855
856 /// Return the use of the callee value in the underlying instruction. Only
857 /// valid for callback calls!
858 const Use &getCalleeUseForCallback() const {
859 int CalleeArgIdx = getCallArgOperandNoForCallee();
860 assert(CalleeArgIdx >= 0 &&
861 unsigned(CalleeArgIdx) < getInstruction()->getNumOperands());
862 return getInstruction()->getOperandUse(CalleeArgIdx);
863 }
864
856865 /// Return the pointer to function that is being called.
857866 Value *getCalledValue() const {
858867 if (isDirectCall())
215215 ArgNo);
216216 }
217217
218 /// Create a position describing the argument of \p ACS at position \p ArgNo.
219 static const IRPosition callsite_argument(AbstractCallSite ACS,
220 unsigned ArgNo) {
221 int CSArgNo = ACS.getCallArgOperandNo(ArgNo);
222 if (CSArgNo >= 0)
223 return IRPosition::callsite_argument(
224 cast(*ACS.getInstruction()), CSArgNo);
225 return IRPosition();
226 }
227
218228 /// Create a position with function scope matching the "context" of \p IRP.
219229 /// If \p IRP is a call site (see isAnyCallSitePosition()) then the result
220230 /// will be a call site position, otherwise the function position of the
824834 /// This method will evaluate \p Pred on call sites and return
825835 /// true if \p Pred holds in every call sites. However, this is only possible
826836 /// all call sites are known, hence the function has internal linkage.
827 bool checkForAllCallSites(const function_refCallSite)> &Pred,
837 bool checkForAllCallSites(const function_refAbstractCallSite)> &Pred,
828838 const AbstractAttribute &QueryingAA,
829839 bool RequireAllCallSites);
830840
595595 // The argument number which is also the call site argument number.
596596 unsigned ArgNo = QueryingAA.getIRPosition().getArgNo();
597597
598 auto CallSiteCheck = [&](CallSite CS) {
599 const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
600 const AAType &AA = A.getAAFor(QueryingAA, CSArgPos);
601 LLVM_DEBUG(dbgs() << "[Attributor] CS: " << *CS.getInstruction()
602 << " AA: " << AA.getAsStr() << " @" << CSArgPos << "\n");
598 auto CallSiteCheck = [&](AbstractCallSite ACS) {
599 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
600 // Check if a coresponding argument was found or if it is on not associated
601 // (which can happen for callback calls).
602 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
603 return false;
604
605 const AAType &AA = A.getAAFor(QueryingAA, ACSArgPos);
606 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
607 << " AA: " << AA.getAsStr() << " @" << ACSArgPos << "\n");
603608 const StateType &AAS = static_cast(AA.getState());
604609 if (T.hasValue())
605610 *T &= AAS;
30993104 ChangeStatus updateImpl(Attributor &A) override {
31003105 bool HasValueBefore = SimplifiedAssociatedValue.hasValue();
31013106
3102 auto PredForCallSite = [&](CallSite CS) {
3103 return checkAndUpdate(A, *this, *CS.getArgOperand(getArgNo()),
3104 SimplifiedAssociatedValue);
3107 auto PredForCallSite = [&](AbstractCallSite ACS) {
3108 // Check if we have an associated argument or not (which can happen for
3109 // callback calls).
3110 if (Value *ArgOp = ACS.getCallArgOperand(getArgNo()))
3111 return checkAndUpdate(A, *this, *ArgOp, SimplifiedAssociatedValue);
3112 return false;
31053113 };
31063114
31073115 if (!A.checkForAllCallSites(PredForCallSite, *this, true))
39133921 return true;
39143922 }
39153923
3916 bool Attributor::checkForAllCallSites(const function_ref &Pred,
3917 const AbstractAttribute &QueryingAA,
3918 bool RequireAllCallSites) {
3924 bool Attributor::checkForAllCallSites(
3925 const function_ref &Pred,
3926 const AbstractAttribute &QueryingAA, bool RequireAllCallSites) {
39193927 // We can try to determine information from
39203928 // the call sites. However, this is only possible all call sites are known,
39213929 // hence the function has internal linkage.
39333941 }
39343942
39353943 for (const Use &U : AssociatedFunction->uses()) {
3936 Instruction *I = dyn_cast(U.getUser());
3937 // TODO: Deal with abstract call sites here.
3938 if (!I)
3944 AbstractCallSite ACS(&U);
3945 if (!ACS) {
3946 LLVM_DEBUG(dbgs() << "[Attributor] Function "
3947 << AssociatedFunction->getName()
3948 << " has non call site use " << *U.get() << " in "
3949 << *U.getUser() << "\n");
39393950 return false;
3940
3951 }
3952
3953 Instruction *I = ACS.getInstruction();
39413954 Function *Caller = I->getFunction();
39423955
3943 const auto &LivenessAA = getAAFor(
3944 QueryingAA, IRPosition::function(*Caller), /* TrackDependence */ false);
3956 const auto &LivenessAA =
3957 getAAFor(QueryingAA, IRPosition::function(*Caller),
3958 /* TrackDependence */ false);
39453959
39463960 // Skip dead calls.
39473961 if (LivenessAA.isAssumedDead(I)) {
39513965 continue;
39523966 }
39533967
3954 CallSite CS(U.getUser());
3955 if (!CS || !CS.isCallee(&U)) {
3968 const Use *EffectiveUse =
3969 ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
3970 if (!ACS.isCallee(EffectiveUse)) {
39563971 if (!RequireAllCallSites)
39573972 continue;
3958
3959 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
3973 LLVM_DEBUG(dbgs() << "[Attributor] User " << EffectiveUse->getUser()
39603974 << " is an invalid use of "
39613975 << AssociatedFunction->getName() << "\n");
39623976 return false;
39633977 }
39643978
3965 if (Pred(CS))
3979 if (Pred(ACS))
39663980 continue;
39673981
39683982 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
3969 << *CS.getInstruction() << "\n");
3983 << *ACS.getInstruction() << "\n");
39703984 return false;
39713985 }
39723986
43184332 const auto *LivenessAA =
43194333 lookupAAFor(IRPosition::function(*F));
43204334 if (LivenessAA &&
4321 !checkForAllCallSites([](CallSite CS) { return false; },
4335 !checkForAllCallSites([](AbstractCallSite ACS) { return false; },
43224336 *LivenessAA, true))
43234337 continue;
43244338
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s
2 ; ModuleID = 'callback_simple.c'
3 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
4
5 ; Test 0
6 ;
7 ; Make sure we propagate information from the caller to the callback callee but
8 ; only for arguments that are mapped through the callback metadata. Here, the
9 ; first two arguments of the call and the callback callee do not correspond to
10 ; each other but argument 3-5 of the transitive call site in the caller match
11 ; arguments 2-4 of the callback callee. Here we should see information and value
12 ; transfer in both directions.
13 ; FIXME: The callee -> call site direction is not working yet.
14
15 define void @t0_caller(i32* %a) {
16 ; CHECK: @t0_caller(i32* [[A:%.*]])
17 ; CHECK-NEXT: entry:
18 ; CHECK-NEXT: [[B:%.*]] = alloca i32, align 32
19 ; CHECK-NEXT: [[C:%.*]] = alloca i32*, align 64
20 ; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 128
21 ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
22 ; CHECK-NEXT: store i32 42, i32* [[B]], align 32
23 ; CHECK-NEXT: store i32* [[B]], i32** [[C]], align 64
24 ; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* [[A:%.*]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
25 ; CHECK-NEXT: ret void
26 ;
27 entry:
28 %b = alloca i32, align 32
29 %c = alloca i32*, align 64
30 %ptr = alloca i32, align 128
31 %0 = bitcast i32* %b to i8*
32 store i32 42, i32* %b, align 4
33 store i32* %b, i32** %c, align 8
34 call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
35 ret void
36 }
37
38 ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
39 ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
40 define internal void @t0_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
41 ; CHECK: @t0_callback_callee(i32* nocapture writeonly [[IS_NOT_NULL:%.*]], i32* nocapture readonly [[PTR:%.*]], i32* [[A:%.*]], i64 [[B:%.*]], i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]])
42 ; CHECK-NEXT: entry:
43 ; CHECK-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR:%.*]], align 8
44 ; CHECK-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL:%.*]]
45 ; CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C:%.*]], align 64
46 ; CHECK-NEXT: tail call void @t0_check(i32* align 256 [[A:%.*]], i64 99, i32* [[TMP0]])
47 ; CHECK-NEXT: ret void
48 ;
49 entry:
50 %ptr_val = load i32, i32* %ptr, align 8
51 store i32 %ptr_val, i32* %is_not_null
52 %0 = load i32*, i32** %c, align 8
53 tail call void @t0_check(i32* %a, i64 %b, i32* %0)
54 ret void
55 }
56
57 declare void @t0_check(i32* align 256, i64, i32*)
58
59 declare !callback !0 void @t0_callback_broker(i32*, i32*, void (i32*, i32*, ...)*, ...)
60
61 !0 = !{!1}
62 !1 = !{i64 2, i64 -1, i64 -1, i1 true}