inter procedural cat
play

Inter-procedural CAT Simone Campanoni - PowerPoint PPT Presentation

Inter-procedural CAT Simone Campanoni simonec@eecs.northwestern.edu Procedures/functions void bar (void){ bar x = 5; Abstraction px = &x; foo Cornerstone of programming foo(px); Introduces barriers to analysis Is x


  1. Inter-procedural CAT Simone Campanoni simonec@eecs.northwestern.edu

  2. Procedures/functions void bar (void){ bar x = 5; • Abstraction px = &x; foo • Cornerstone of programming foo(px); • Introduces barriers to analysis Is x constant? y = x + 5; } • So far looked at intra-procedural analysis • Analyzing a single procedure • Inter-procedural analysis uses calling relationships among procedures (Call Graph) • Enables more precise analysis information

  3. Inter-procedural analysis Goal : Avoid making overly conservative assumptions about the effects of procedures and the state at call sites Terminology int a, e; // Globals void foo(int *b, int *c){ // Formal parameters (*b) = e; } bar(){ int d; // Local variables foo(a, d); // Actual parameters }

  4. Inter-procedural analysis vs. inter-procedural transformation Inter-procedural analysis • Gather information across multiple procedures (up to the entire program) • Can use this information to improve intra-procedural analyses and transformation (e.g., CP) Inter-procedural transformation • Code transformations that involve multiple procedures e.g., Inlining, procedure cloning, function specialization

  5. Outline ①Sensitivity of analysis ②Single compilation ③Separate compilations ④Caller -> callee vs. callee -> caller propagations ⑤Final remarks

  6. Sensitivity of intra-procedural analysis • Flow-sensitive vs. flow-insensitive A B C A B C

  7. Flow sensitivity example Flow-sensitive analysis Is x constant? • Computes one answer for every program point void f (int x){ • x is 4 after A A: x = 4; • x is 5 after B … • Requires iterative data-flow analysis or similar technique B: x = 5; Flow-insensitive analysis } • Computes one answer for the entire procedure • x is not constant • Can compute in linear time • Less accurate (ignores control flows)

  8. Sensitivity of intra-procedural analysis • Flow-sensitive vs. flow-insensitive A B C A B C • Path-sensitive vs. path-insensitive

  9. Path sensitivity example Path-sensitive analysis Is x constant? if (x == 0) • Computes one answer for every execution path • x is 4 at print(x) if you came from the left path • x is 5 at print(x) if you came from the right path x = 4; x = 5; • Subsumes flow-sensitivity • Very expensive print(x) Path-insensitive analysis • Computes one answer for all path • x is not constant at print(x)

  10. Sensitivity of inter-procedural analysis • Flow-sensitive vs. flow-insensitive A B C A B C • Path-sensitive vs. path-insensitive • Context-sensitive vs. context-insensitive

  11. Context sensitivity example Context-sensitive analysis Is x constant? • Computes one answer for every call-site a = id(4); b = id(5); • x is 4 in the first call • x is 5 in the second call • Re-analyzes callee for each caller id (x) { return x;} Context-insensitive analysis • Computes one answer for all call-sites: • x is not constant • Perform one analysis independent of callers • Suffers from unrealizable paths: • Can mistakenly conclude that id(4) can return 5 because we merge information from all call-sites

  12. Call graph • First problem: how do we know void foo (int a, int (*p_to_f)(int v)){ what procedures are called from where? int l = (*p_to_f)(5); a = l + 1; • Especially difficult in higher-order languages, return a; languages where functions are values } • What about C programs? • We’ll ignore this for now • Let’s assume we have a (static) call graph • Indicates which procedures can call which other procedures, and from which program points

  13. Call graph example From now on we assume we have a static call graph

  14. Generating a call graph with LLVM • From the command line: opt -dot-callgraph program.bc -disable-output (see test0) • From your pass: • Explicit iteration • LLVM_callgraph/llvm/[0-3] • CallGraphWrappingPass • LLVM_callgraph/llvm/[4-6]

  15. Generating a call graph with LLVM • From the command line: opt -dot-callgraph program.bc -disable-output (see test0) • From your pass: • Explicit iteration • LLVM_5/llvm/[0-3] • CallGraphWrappingPass • LLVM_5/llvm/[4-6]

  16. DEMO

  17. Using CallGraphWrappingPass • Declaring your pass dependence • Fetching the call graph

  18. Using CallGraphWrappingPass • From a Function to a node of the call graph • From node to callees • From node to Function

  19. DEMO

  20. Outline ①Sensitivity of analysis ②Single compilation ③Separate compilations ④Caller -> callee vs. callee -> caller propagations ⑤Final remarks

  21. Intra-procedural dataflow analysis • How did we do previously? main() { A: x = 7; main p B: r = p(x); IN = { } C: y = 80; A F D: t = p(y); IN = {A} E: print t, r; B IN = { } IN = { } } IN = {A, B} int p (int v) { C G H IN = {A, B, C} F: if (v < 10) G: m = 1; D IN = {G, H} else IN = {A, B, C, D } H: m = 2; I E I: return m; }

  22. Inter-procedural dataflow analysis flow-sensitive • Accuracy? • How can we handle procedure calls? • Performance? • Obvious idea: make one big CFG ( control-flow supergraph ) • No separate analysis main() { A: x = 7; B: r = p(x); C: y = 80; IN = {A, G, H, C} A F D: t = p(y); IN = {A} E: print t, r; B IN = {A,G,H,C} IN = {A,G,H,C} } IN = {A, G, H, C} int p (int v) { C G H IN = {A, G, H, C} F: if (v < 10) G: m = 1; D IN = {A, G, H, C } else IN = {A, G, H, C} H: m = 2; I E I: return m; }

  23. Inter-procedural dataflow analysis flow-sensitive • Accuracy? • Problem of invalid paths: dataflow facts from one call site • How can we handle procedure calls? • Performance? “tainting” results at other call site • Obvious idea: make one big CFG ( control-flow supergraph ) • No separate analysis • p analyzed with merge of dataflow facts from all call sites main() { A: x = 7; • How to address this problem? B: r = p(x); C: y = 80; IN = {A, G, H, C} A F D: t = p(y); IN = {A} E: print t, r; B IN = {A,G,H,C} IN = {A,G,H,C} } IN = {A, G, H, C} int p (int v) { C G H IN = {A, G, H, C} F: if (v < 10) G: m = 1; D IN = {A, G, H, C } else IN = {A, G, H, C} H: m = 2; I E I: return m; }

  24. Inter-procedural dataflow analysis flow/context-sensitive • Accuracy? main() { • Performance? A: x = 7; B: r = p(x); C: y = 80; IN = {B:{A},D:{A,C,G,H}} A F D: t = p(y); IN = {A} E: print t, r; B IN = {B:{A}, IN={B:{A}, D:{A,C,G,H}} D:{A,C,G,H}} } IN = {A, B:{G, H}} int p (int v) { C G H IN = {A, C, B:{G, H}} F: if (v < 10) IN = {B:{A,G,H}, G: m = 1; D D:{A,C,G,H}} else IN = {A, C, B:{G,H}, D:{G,H}} H: m = 2; I E I: return m; }

  25. • Even an inter-procedural flow- and context- sensitive analysis isn’t able to perform the constant propagation we want • We need to make our analysis even more complex • Since this seems hard, let’s try something easier • Let’s try to follow a simpler solution: • We copy the body of the callee inside the caller • Function inlining

  26. Inter-procedural code transformation: function inlining • Function inlining: • Use a new copy of a procedure’s CFG at a call site • Adjust copied code within the caller (e.g., rename variables, map formal parameters to actual parameters) • In LLVM: • You don’t need to implement this transformation, it already exists J • InlineResult InlineFunction(CallBase *, InlineFunctionInfo &, … ) Extra parameters are optional InlineFunctionInfo IFI; #include "llvm/Transforms/Utils/Cloning.h" if (InlineFunction(call, IFI)) { … } else { … }

  27. Function inlining in LLVM and alias analysis • InlineResult InlineFunction( CallBase *, InlineFunctionInfo &, AAResults *CalleeAAR = nullptr, bool InsertLifetime = true ) void f (){ … // pre_g void f (){ call g() %1 = alloca() … // pre_g New … // post_g … // g_body live range of %1 Function inlining } … // post_g void g(){ } But we know %1 can only %1 = alloca(…) be used (directly or indirectly) … // g_body within g_body }

  28. Inter-procedural code transformation: function inlining main p main() { A A: x = 7; B: r = p(x); F C: y = 80; B D: t = p(y); E: print t, r; } C G H int p (int v) { F: if (v < 10) D G: m = 1; else I H: m = 2; E I: return m; Example of function inlining: inline the callee of B }

  29. Inter-procedural code transformation: function inlining main p main() { A A: x = 7; F’ B: r = p(x); F C: y = 80; G’ H’ D: t = p(y); I’ E: print t, r; } C G H int p (int v) { F: if (v < 10) D G: m = 1; else I H: m = 2; E I: return m; Another example of function inlining: inline the callee of D }

  30. Inter-procedural code transformation: function inlining main p main() { A A: x = 7; F’ B: r = p(x); F C: y = 80; G’ H’ D: t = p(y); I’ E: print t, r; } C G H int p (int v) { F’’ F: if (v < 10) G’’ H’’ G: m = 1; I’’ else I H: m = 2; E I: return m; }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend