mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[CallGraph] Add support for callback call sites
Summary: This patch changes call graph analysis to recognize callback call sites and add an artificial 'reference' call record from the broker function caller to the callback function in the call graph. A presence of such reference enforces bottom-up traversal order for callback functions in CG SCC pass manager because callback function logically becomes a callee of the broker function caller. Reviewers: jdoerfert, hfinkel, sstefan1, baziotis Reviewed By: jdoerfert Subscribers: hiraditya, kuter, sstefan1, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D82572
This commit is contained in:
parent
c8f56d9b25
commit
1b3aa514d1
@ -175,13 +175,21 @@ class CallGraphNode {
|
||||
public:
|
||||
/// A pair of the calling instruction (a call or invoke)
|
||||
/// and the call graph node being called.
|
||||
using CallRecord = std::pair<WeakTrackingVH, CallGraphNode *>;
|
||||
/// Call graph node may have two types of call records which represent an edge
|
||||
/// in the call graph - reference or a call edge. Reference edges are not
|
||||
/// associated with any call instruction and are created with the first field
|
||||
/// set to `None`, while real call edges have instruction address in this
|
||||
/// field. Therefore, all real call edges are expected to have a value in the
|
||||
/// first field and it is not supposed to be `nullptr`.
|
||||
/// Reference edges, for example, are used for connecting broker function
|
||||
/// caller to the callback function for callback call sites.
|
||||
using CallRecord = std::pair<Optional<WeakTrackingVH>, CallGraphNode *>;
|
||||
|
||||
public:
|
||||
using CalledFunctionsVector = std::vector<CallRecord>;
|
||||
|
||||
/// Creates a node for the specified function.
|
||||
inline CallGraphNode(Function *F) : F(F) {}
|
||||
inline CallGraphNode(CallGraph *CG, Function *F) : CG(CG), F(F) {}
|
||||
|
||||
CallGraphNode(const CallGraphNode &) = delete;
|
||||
CallGraphNode &operator=(const CallGraphNode &) = delete;
|
||||
@ -243,7 +251,8 @@ public:
|
||||
assert(!Call || !Call->getCalledFunction() ||
|
||||
!Call->getCalledFunction()->isIntrinsic() ||
|
||||
!Intrinsic::isLeaf(Call->getCalledFunction()->getIntrinsicID()));
|
||||
CalledFunctions.emplace_back(Call, M);
|
||||
CalledFunctions.emplace_back(
|
||||
Call ? Optional<WeakTrackingVH>(Call) : Optional<WeakTrackingVH>(), M);
|
||||
M->AddRef();
|
||||
}
|
||||
|
||||
@ -279,6 +288,7 @@ public:
|
||||
private:
|
||||
friend class CallGraph;
|
||||
|
||||
CallGraph *CG;
|
||||
Function *F;
|
||||
|
||||
std::vector<CallRecord> CalledFunctions;
|
||||
|
@ -221,6 +221,27 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Apply function Func to each CB's callback call site.
|
||||
template <typename UnaryFunction>
|
||||
void forEachCallbackCallSite(const CallBase &CB, UnaryFunction Func) {
|
||||
SmallVector<const Use *, 4u> CallbackUses;
|
||||
AbstractCallSite::getCallbackUses(CB, CallbackUses);
|
||||
for (const Use *U : CallbackUses) {
|
||||
AbstractCallSite ACS(U);
|
||||
assert(ACS && ACS.isCallbackCall() && "must be a callback call");
|
||||
Func(ACS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply function Func to each CB's callback function.
|
||||
template <typename UnaryFunction>
|
||||
void forEachCallbackFunction(const CallBase &CB, UnaryFunction Func) {
|
||||
forEachCallbackCallSite(CB, [&Func](AbstractCallSite &ACS) {
|
||||
if (Function *Callback = ACS.getCalledFunction())
|
||||
Func(Callback);
|
||||
});
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_IR_ABSTRACTCALLSITE_H
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/IR/AbstractCallSite.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
@ -31,7 +32,7 @@ using namespace llvm;
|
||||
|
||||
CallGraph::CallGraph(Module &M)
|
||||
: M(M), ExternalCallingNode(getOrInsertFunction(nullptr)),
|
||||
CallsExternalNode(std::make_unique<CallGraphNode>(nullptr)) {
|
||||
CallsExternalNode(std::make_unique<CallGraphNode>(this, nullptr)) {
|
||||
// Add every interesting function to the call graph.
|
||||
for (Function &F : M)
|
||||
if (!isDbgInfoIntrinsic(F.getIntrinsicID()))
|
||||
@ -44,6 +45,11 @@ CallGraph::CallGraph(CallGraph &&Arg)
|
||||
CallsExternalNode(std::move(Arg.CallsExternalNode)) {
|
||||
Arg.FunctionMap.clear();
|
||||
Arg.ExternalCallingNode = nullptr;
|
||||
|
||||
// Update parent CG for all call graph's nodes.
|
||||
CallsExternalNode->CG = this;
|
||||
for (auto &P : FunctionMap)
|
||||
P.second->CG = this;
|
||||
}
|
||||
|
||||
CallGraph::~CallGraph() {
|
||||
@ -99,6 +105,11 @@ void CallGraph::populateCallGraphNode(CallGraphNode *Node) {
|
||||
Node->addCalledFunction(Call, CallsExternalNode.get());
|
||||
else if (!Callee->isIntrinsic())
|
||||
Node->addCalledFunction(Call, getOrInsertFunction(Callee));
|
||||
|
||||
// Add reference to callback functions.
|
||||
forEachCallbackFunction(*Call, [=](Function *CB) {
|
||||
Node->addCalledFunction(nullptr, getOrInsertFunction(CB));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,7 +189,7 @@ CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {
|
||||
return CGN.get();
|
||||
|
||||
assert((!F || F->getParent() == &M) && "Function not in current module!");
|
||||
CGN = std::make_unique<CallGraphNode>(const_cast<Function *>(F));
|
||||
CGN = std::make_unique<CallGraphNode>(this, const_cast<Function *>(F));
|
||||
return CGN.get();
|
||||
}
|
||||
|
||||
@ -214,10 +225,15 @@ LLVM_DUMP_METHOD void CallGraphNode::dump() const { print(dbgs()); }
|
||||
void CallGraphNode::removeCallEdgeFor(CallBase &Call) {
|
||||
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
|
||||
assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
|
||||
if (I->first == &Call) {
|
||||
if (I->first && *I->first == &Call) {
|
||||
I->second->DropRef();
|
||||
*I = CalledFunctions.back();
|
||||
CalledFunctions.pop_back();
|
||||
|
||||
// Remove all references to callback functions if there are any.
|
||||
forEachCallbackFunction(Call, [=](Function *CB) {
|
||||
removeOneAbstractEdgeTo(CG->getOrInsertFunction(CB));
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -242,7 +258,7 @@ void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) {
|
||||
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
|
||||
assert(I != CalledFunctions.end() && "Cannot find callee to remove!");
|
||||
CallRecord &CR = *I;
|
||||
if (CR.second == Callee && CR.first == nullptr) {
|
||||
if (CR.second == Callee && !CR.first) {
|
||||
Callee->DropRef();
|
||||
*I = CalledFunctions.back();
|
||||
CalledFunctions.pop_back();
|
||||
@ -258,11 +274,19 @@ void CallGraphNode::replaceCallEdge(CallBase &Call, CallBase &NewCall,
|
||||
CallGraphNode *NewNode) {
|
||||
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
|
||||
assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
|
||||
if (I->first == &Call) {
|
||||
if (I->first && *I->first == &Call) {
|
||||
I->second->DropRef();
|
||||
I->first = &NewCall;
|
||||
I->second = NewNode;
|
||||
NewNode->AddRef();
|
||||
|
||||
// Refresh callback references.
|
||||
forEachCallbackFunction(Call, [=](Function *CB) {
|
||||
removeOneAbstractEdgeTo(CG->getOrInsertFunction(CB));
|
||||
});
|
||||
forEachCallbackFunction(NewCall, [=](Function *CB) {
|
||||
addCalledFunction(nullptr, CG->getOrInsertFunction(CB));
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -227,9 +227,15 @@ bool CGPassManager::RefreshCallGraph(const CallGraphSCC &CurSCC, CallGraph &CG,
|
||||
|
||||
// Get the set of call sites currently in the function.
|
||||
for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) {
|
||||
// Skip "reference" call records that do not have call instruction.
|
||||
if (!I->first) {
|
||||
++I;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this call site is null, then the function pass deleted the call
|
||||
// entirely and the WeakTrackingVH nulled it out.
|
||||
auto *Call = dyn_cast_or_null<CallBase>(I->first);
|
||||
auto *Call = dyn_cast_or_null<CallBase>(*I->first);
|
||||
if (!Call ||
|
||||
// If we've already seen this call site, then the FunctionPass RAUW'd
|
||||
// one call with another, which resulted in two "uses" in the edge
|
||||
|
@ -109,7 +109,7 @@ PreservedAnalyses SyntheticCountsPropagation::run(Module &M,
|
||||
Optional<Scaled64> Res = None;
|
||||
if (!Edge.first)
|
||||
return Res;
|
||||
CallBase &CB = *cast<CallBase>(Edge.first);
|
||||
CallBase &CB = *cast<CallBase>(*Edge.first);
|
||||
Function *Caller = CB.getCaller();
|
||||
auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(*Caller);
|
||||
|
||||
|
@ -149,7 +149,7 @@ bool CallGraphUpdater::replaceCallSite(CallBase &OldCS, CallBase &NewCS) {
|
||||
CG->getOrInsertFunction(NewCS.getCalledFunction());
|
||||
CallGraphNode *CallerNode = (*CG)[Caller];
|
||||
if (llvm::none_of(*CallerNode, [&OldCS](const CallGraphNode::CallRecord &CR) {
|
||||
return CR.first == &OldCS;
|
||||
return CR.first && *CR.first == &OldCS;
|
||||
}))
|
||||
return false;
|
||||
CallerNode->replaceCallEdge(OldCS, NewCS, NewCalleeNode);
|
||||
|
@ -1291,7 +1291,11 @@ static void UpdateCallGraphAfterInlining(CallBase &CB,
|
||||
}
|
||||
|
||||
for (; I != E; ++I) {
|
||||
const Value *OrigCall = I->first;
|
||||
// Skip 'refererence' call records.
|
||||
if (!I->first)
|
||||
continue;
|
||||
|
||||
const Value *OrigCall = *I->first;
|
||||
|
||||
ValueToValueMapTy::iterator VMI = VMap.find(OrigCall);
|
||||
// Only copy the edge if the call was inlined!
|
||||
|
20
test/Analysis/CallGraph/callback-calls.ll
Normal file
20
test/Analysis/CallGraph/callback-calls.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s
|
||||
; RUN: opt < %s -passes=print-callgraph -disable-output 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: Call graph node for function: 'caller'
|
||||
; CHECK-NEXT: CS<{{.*}}> calls function 'broker'
|
||||
; CHECK-NEXT: CS<None> calls function 'callback'
|
||||
|
||||
define void @caller(i32* %arg) {
|
||||
call void @broker(void (i32*)* @callback, i32* %arg)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @callback(i32* %arg) {
|
||||
ret void
|
||||
}
|
||||
|
||||
declare !callback !0 void @broker(void (i32*)*, i32*)
|
||||
|
||||
!0 = !{!1}
|
||||
!1 = !{i64 0, i64 1, i1 false}
|
@ -23,7 +23,7 @@ entry:
|
||||
|
||||
|
||||
; CHECK: Call graph node <<null function>>
|
||||
; CHECK: CS<0x0> calls function 'f'
|
||||
; CHECK: CS<None> calls function 'f'
|
||||
|
||||
; CHECK: Call graph node for function: 'calls_patchpoint'
|
||||
; CHECK-NEXT: CS<[[addr_1:[^>]+]]> calls external node
|
||||
|
@ -58,7 +58,7 @@ define dso_local void @foo(i32 %N) {
|
||||
; IS__CGSCC_OPM-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4
|
||||
; IS__CGSCC_OPM-NEXT: store float 3.000000e+00, float* [[P]], align 4
|
||||
; IS__CGSCC_OPM-NEXT: store i32 7, i32* [[N_ADDR]], align 4
|
||||
; IS__CGSCC_OPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nonnull align 4 dereferenceable(4) [[N_ADDR]], float* nonnull align 4 dereferenceable(4) [[P]], i64 4617315517961601024)
|
||||
; IS__CGSCC_OPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nocapture nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* nocapture nonnull readonly align 4 dereferenceable(4) [[P]], i64 4617315517961601024)
|
||||
; IS__CGSCC_OPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo
|
||||
|
@ -47,10 +47,10 @@ define dso_local i32 @main() {
|
||||
; IS__CGSCC_OPM-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8
|
||||
; IS__CGSCC_OPM-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8
|
||||
; IS__CGSCC_OPM-NEXT: [[THREAD:%.*]] = alloca i64, align 8
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nocapture align 536870912 null)
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @bar, i8* nonnull align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @baz, i8* nocapture nonnull align 8 dereferenceable(1) [[ALLOC1]])
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @buz, i8* nonnull align 8 dereferenceable(1) [[ALLOC2]])
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nocapture nofree readnone align 536870912 null)
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]])
|
||||
; IS__CGSCC_OPM-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]])
|
||||
; IS__CGSCC_OPM-NEXT: ret i32 0
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@main()
|
||||
@ -94,7 +94,7 @@ define internal i8* @bar(i8* %arg) {
|
||||
; IS__TUNIT____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
|
||||
;
|
||||
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar
|
||||
; IS__CGSCC_OPM-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(8) "no-capture-maybe-returned" [[ARG:%.*]])
|
||||
; IS__CGSCC_OPM-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]])
|
||||
; IS__CGSCC_OPM-NEXT: entry:
|
||||
; IS__CGSCC_OPM-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
|
||||
;
|
||||
|
@ -49,7 +49,7 @@ define void @t0_caller(i32* %a) {
|
||||
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
|
||||
; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32
|
||||
; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t0_caller
|
||||
@ -140,7 +140,7 @@ define void @t1_caller(i32* noalias %a) {
|
||||
; IS__TUNIT_NPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t1_caller
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-NEXT: entry:
|
||||
; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32
|
||||
; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64
|
||||
@ -148,7 +148,7 @@ define void @t1_caller(i32* noalias %a) {
|
||||
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
|
||||
; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32
|
||||
; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 99, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_caller
|
||||
@ -238,7 +238,7 @@ define void @t2_caller(i32* noalias %a) {
|
||||
; IS__TUNIT_NPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t2_caller
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-NEXT: entry:
|
||||
; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32
|
||||
; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64
|
||||
@ -246,7 +246,7 @@ define void @t2_caller(i32* noalias %a) {
|
||||
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
|
||||
; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32
|
||||
; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 99, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_caller
|
||||
@ -340,7 +340,7 @@ define void @t3_caller(i32* noalias %a) {
|
||||
; IS__TUNIT_NPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t3_caller
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]])
|
||||
; IS__CGSCC_OPM-NEXT: entry:
|
||||
; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32
|
||||
; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64
|
||||
@ -348,8 +348,8 @@ define void @t3_caller(i32* noalias %a) {
|
||||
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
|
||||
; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32
|
||||
; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 99, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture align 536870912 null, i32* nocapture nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 99, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]])
|
||||
; IS__CGSCC_OPM-NEXT: ret void
|
||||
;
|
||||
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_caller
|
||||
|
Loading…
Reference in New Issue
Block a user