Download presentation

Presentation is loading. Please wait.

Published byCaden Kenrick Modified over 2 years ago

1
School of EECS, Peking University “Advanced Compiler Techniques” (Fall 2011) Pointer Analysis

2
2 Fall 2011 “Advanced Compiler Techniques” Pointer Analysis Outline: Outline: What is pointer analysis What is pointer analysis Intraprocedural pointer analysis Intraprocedural pointer analysis Interprocedural pointer analysis Interprocedural pointer analysis Andersen and Steensgaard Andersen and Steensgaard New Directions New Directions

3
3 Fall 2011 “Advanced Compiler Techniques” Pointer and Alias Analysis Aliases: two expressions that denote the same memory location. Aliases: two expressions that denote the same memory location. Aliases are introduced by: Aliases are introduced by: pointers pointers call-by-reference call-by-reference array indexing array indexing C unions C unions

4
4 Fall 2011 “Advanced Compiler Techniques” Useful for what? Improve the precision of analyses that require knowing what is modified or referenced (eg const prop, CSE …) Improve the precision of analyses that require knowing what is modified or referenced (eg const prop, CSE …) Eliminate redundant loads/stores and dead stores. Eliminate redundant loads/stores and dead stores. Parallelization of code Parallelization of code can recursive calls to quick_sort be run in parallel? Yes, provided that they reference distinct regions of the array. can recursive calls to quick_sort be run in parallel? Yes, provided that they reference distinct regions of the array. Identify objects to be tracked in error detection tools Identify objects to be tracked in error detection tools x := *p;... y := *p; // replace with y := x? *x :=...; // is *x dead? x.lock();... y.unlock(); // same object as x?

5
5 Fall 2011 “Advanced Compiler Techniques” Kinds of alias information Points-to information (must or may versions) Points-to information (must or may versions) at program point, compute a set of pairs of the form p->x, where p points to x. at program point, compute a set of pairs of the form p->x, where p points to x. can represent this information can represent this information in a points-to graph Alias pairs Alias pairs at each program point, compute the set of all pairs (e 1,e 2 ) where e 1 and e 2 must/may reference the same memory. at each program point, compute the set of all pairs (e 1,e 2 ) where e 1 and e 2 must/may reference the same memory. Storage shape analysis Storage shape analysis at each program point, compute an at each program point, compute an abstract description of the pointer structure. p x y zp

6
6 Fall 2011 “Advanced Compiler Techniques” Intraprocedural Points-to Analysis Want to compute may-points-to information Want to compute may-points-to information Lattice: Lattice: Domain: 2 {x->y| x ∈ Var, Y ∈ Var} Domain: 2 {x->y| x ∈ Var, Y ∈ Var} Join: set union Join: set union BOT: Empty BOT: Empty TOP: {x->y| x ∈ Var, Y ∈ Var} TOP: {x->y| x ∈ Var, Y ∈ Var}

7
7 Fall 2011 “Advanced Compiler Techniques” Flow functions x := a + b in out F x := a+b (in) = x := k in out F x := k (in) = in – {x, *}

8
8 Fall 2011 “Advanced Compiler Techniques” Flow functions x := &y in out F x := &y (in) = x := y in out F x := y (in) = in – {x, *} U {(x,z) | (y,z) ∈ in } in – {x, *} U {(x, y)}

9
9 Fall 2011 “Advanced Compiler Techniques” Flow functions *x := y in out F *x := y (in) = x := *y in out F x := *y (in) = in – {x, *} U {(x, t) | (y,z) ∈ in && (z,t) ∈ in } In – {} U {(a, b) | (x,a) ∈ in && (y,b) ∈ in }

10
10 Fall 2011 “Advanced Compiler Techniques” Intraprocedural Points-to Analysis Flow functions: Flow functions:

11
11 Fall 2011 “Advanced Compiler Techniques” Pointers to dynamically- allocated memory Handle statements of the form: x := new T Handle statements of the form: x := new T One idea: generate a new variable each time the new statement is analyzed to stand for the new location: One idea: generate a new variable each time the new statement is analyzed to stand for the new location:

12
12 Fall 2011 “Advanced Compiler Techniques” Example l := new Cons p := l t := new Cons *p := t p := t

13
13 Fall 2011 “Advanced Compiler Techniques” Example solved l := new Cons p := l t := new Cons *p := t p := t l p V1 l p tV2 l p V1 t V2 l t V1 p V2 l t V1 p V2 l t V1 p V2V3 l t V1 p V2V3 l t V1 p V2V3

14
14 Fall 2011 “Advanced Compiler Techniques” What went wrong? Lattice was infinitely tall! Lattice was infinitely tall! Instead, we need to summarize the infinitely many allocated objects in a finite way. Instead, we need to summarize the infinitely many allocated objects in a finite way. introduce summary nodes, which will stand for a whole class of allocated objects. introduce summary nodes, which will stand for a whole class of allocated objects. For example: For each new statement with label L, introduce a summary node loc L, which stands for the memory allocated by statement L. For example: For each new statement with label L, introduce a summary node loc L, which stands for the memory allocated by statement L. Summary nodes can use other criterion for merging. Summary nodes can use other criterion for merging.

15
15 Fall 2011 “Advanced Compiler Techniques” Example revisited & solved S1: l := new Cons p := l S2: t := new Cons *p := t p := t l p S1 l p tS2 l p S1 t S2 l t S1 p S2 l t S1 p S2 Iter 1Iter 2Iter 3

16
16 Fall 2011 “Advanced Compiler Techniques” Example revisited & solved S1: l := new Cons p := l S2: t := new Cons *p := t p := t l p S1 l p tS2 l p S1 t S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 Iter 1Iter 2Iter 3

17
17 Fall 2011 “Advanced Compiler Techniques” Array aliasing, and pointers to arrays Array indexing can cause aliasing: Array indexing can cause aliasing: a[i] aliases b[j] if: a[i] aliases b[j] if: a aliases b and i = j a aliases b and i = j a and b overlap, and i = j + k, where k is the amount of overlap. a and b overlap, and i = j + k, where k is the amount of overlap. Can have pointers to elements of an array Can have pointers to elements of an array p := &a[i];...; p++; p := &a[i];...; p++; How can arrays be modeled? How can arrays be modeled? Could treat the whole array as one location. Could treat the whole array as one location. Could try to reason about the array index expressions: array dependence analysis. Could try to reason about the array index expressions: array dependence analysis.

18
18 Fall 2011 “Advanced Compiler Techniques” Fields Can summarize fields using per field summary Can summarize fields using per field summary for each field F, keep a points-to node called F that summarizes all possible values that can ever be stored in F for each field F, keep a points-to node called F that summarizes all possible values that can ever be stored in F Can also use allocation sites Can also use allocation sites for each field F, and each allocation site S, keep a points-to node called (F, S) that summarizes all possible values that can ever be stored in the field F of objects allocated at site S. for each field F, and each allocation site S, keep a points-to node called (F, S) that summarizes all possible values that can ever be stored in the field F of objects allocated at site S.

19
19 Fall 2011 “Advanced Compiler Techniques” Summary We just saw: We just saw: intraprocedural points-to analysis intraprocedural points-to analysis handling dynamically allocated memory handling dynamically allocated memory handling pointers to arrays handling pointers to arrays But, intraprocedural pointer analysis is not enough. But, intraprocedural pointer analysis is not enough. Sharing data structures across multiple procedures is one of the big benefits of pointers: instead of passing the whole data structures around, just pass pointers to them (eg C pass by reference). Sharing data structures across multiple procedures is one of the big benefits of pointers: instead of passing the whole data structures around, just pass pointers to them (eg C pass by reference). So pointers end up pointing to structures shared across procedures. So pointers end up pointing to structures shared across procedures. If you don’t do an interproc analysis, you’ll have to make conservative assumptions functions entries and function calls. If you don’t do an interproc analysis, you’ll have to make conservative assumptions functions entries and function calls.

20
20 Fall 2011 “Advanced Compiler Techniques” Conservative approximation on entry Say we don’t have interprocedural pointer analysis. Say we don’t have interprocedural pointer analysis. What should the information be at the input of the following procedure: What should the information be at the input of the following procedure: global g; void p(x,y) {... } xyg

21
21 Fall 2011 “Advanced Compiler Techniques” Conservative approximation on entry Here are a few solutions: Here are a few solutions: xyg locations from alloc sites prior to this invocation global g; void p(x,y) {... } They are all very conservative! We can try to do better. x,y,g & locations from alloc sites prior to this invocation

22
22 Fall 2011 “Advanced Compiler Techniques” Interprocedural pointer analysis Main difficulty in performing interprocedural pointer analysis is scaling Main difficulty in performing interprocedural pointer analysis is scaling One can use a bottom-up summary based approach (Wilson & Lam 95), but even these are hard to scale One can use a bottom-up summary based approach (Wilson & Lam 95), but even these are hard to scale

23
23 Fall 2011 “Advanced Compiler Techniques” Cost: Cost: space: store one fact at each prog point space: store one fact at each prog point time: iteration time: iteration S1: l := new Cons p := l S2: t := new Cons *p := t p := t l p S1 l p tS2 l p S1 t S2 l t S1 p S2 l t S1 p S2 l t S1 p L2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t L1 p L2 l t S1 p S2 l t S1 p S2 Iter 1Iter 2Iter 3 Example revisited

24
24 Fall 2011 “Advanced Compiler Techniques” New idea: store one dataflow fact Store one dataflow fact for the whole program Store one dataflow fact for the whole program Each statement updates this one dataflow fact Each statement updates this one dataflow fact use the previous flow functions, but now they take the whole program dataflow fact, and return an updated version of it. use the previous flow functions, but now they take the whole program dataflow fact, and return an updated version of it. Process each statement once, ignoring the order of the statements Process each statement once, ignoring the order of the statements This is called a flow-insensitive analysis. This is called a flow-insensitive analysis.

25
25 Fall 2011 “Advanced Compiler Techniques” Flow insensitive pointer analysis S1: l := new Cons p := l S2: t := new Cons *p := t p := t

26
26 Fall 2011 “Advanced Compiler Techniques” Flow insensitive pointer analysis S1: l := new Cons p := l S2: t := new Cons *p := t p := t l p S1 l p tS2 l p S1 t S2 l t S1 p S2

27
27 Fall 2011 “Advanced Compiler Techniques” Flow sensitive vs. insensitive S1: l := new Cons p := l S2: t := new Cons *p := t p := t l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 Flow-sensitive SolnFlow-insensitive Soln l t S1 p S2

28
28 Fall 2011 “Advanced Compiler Techniques” What went wrong? What happened to the link between p and S1? What happened to the link between p and S1? Can’t do strong updates anymore! Can’t do strong updates anymore! Need to remove all the kill sets from the flow functions. Need to remove all the kill sets from the flow functions. What happened to the self loop on S2? What happened to the self loop on S2? We still have to iterate! We still have to iterate!

29
29 Fall 2011 “Advanced Compiler Techniques” Flow insensitive pointer analysis: fixed S1: l := new Cons p := l S2: t := new Cons *p := t p := t l p S1 l p tS2 l p S1 t S2 l t S1 p S2 l t S1 p S2 l t S1 p L2 l t S1 p S2 l t S1 p S2 l t S1 p S2 l t L1 p L2 l t S1 p S2 Iter 1Iter 2Iter 3 l t S1 p S2 Final result This is Andersen’s algorithm ’94

30
30 Fall 2011 “Advanced Compiler Techniques” Flow insensitive loss of precision S1: l := new Cons p := l S2: t := new Cons *p := t p := t l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 Flow-sensitive SolnFlow-insensitive Soln l t S1 p S2

31
31 Fall 2011 “Advanced Compiler Techniques” Flow insensitive loss of precision Flow insensitive analysis leads to loss of precision! Flow insensitive analysis leads to loss of precision! main() { x := &y;... x := &z; } Flow insensitive analysis tells us that x may point to z here! However: –uses less memory (memory can be a big bottleneck to running on large programs) –runs faster

32
32 Fall 2011 “Advanced Compiler Techniques” Worst case complexity of Andersen *x = y x abc y def x abc y def Worst case: N 2 per statement, so at least N 3 for the whole program. Andersen is in fact O(N 3 )

33
33 Fall 2011 “Advanced Compiler Techniques” New idea: one successor per node Make each node have only one successor. Make each node have only one successor. This is an invariant that we want to maintain. This is an invariant that we want to maintain. x a,b,c y d,e,f *x = y x a,b,c y d,e,f

34
34 Fall 2011 “Advanced Compiler Techniques” x *x = y y More general case for *x = y

35
35 Fall 2011 “Advanced Compiler Techniques” x *x = y yxyxy More general case for *x = y

36
36 Fall 2011 “Advanced Compiler Techniques” x x = *y y Handling: x = *y

37
37 Fall 2011 “Advanced Compiler Techniques” x x = *y yxyxy Handling: x = *y

38
38 Fall 2011 “Advanced Compiler Techniques” x x = y y x = &y xy Handling: x = y (what about y = x?) Handling: x = &y

39
39 Fall 2011 “Advanced Compiler Techniques” x x = y yxyxy x = &y xyx y,… xy Handling: x = y (what about y = x?) Handling: x = &y get the same for y = x

40
40 Fall 2011 “Advanced Compiler Techniques” Our favorite example, once more! S1: l := new Cons p := l S2: t := new Cons *p := t p := t 1 2 3 4 5

41
41 Fall 2011 “Advanced Compiler Techniques” Our favorite example, once more! S1: l := new Cons p := l S2: t := new Cons *p := t p := t l S1 t S2 p l S1 l p l t S2 p l S1,S2 tp 1 2 3 4 5 12 3 l S1 t S2 p 4 5

42
42 Fall 2011 “Advanced Compiler Techniques” Flow insensitive loss of precision S1: l := new Cons p := l S2: t := new Cons *p := t p := t l t S1 p S2 l t S1 p S2 l t S1 p S2 l t S1 p S2 Flow-sensitive Subset-based Flow-insensitive Subset-based l t S1 p S2 l S1,S2 tp Flow-insensitive Unification- based

43
43 Fall 2011 “Advanced Compiler Techniques” bar() { i := &a; j := &b; foo(&i); foo(&j); // i pnts to what? *i :=...; } void foo(int* p) { printf(“%d”,*p); } 1 2 3 4 Another example

44
44 Fall 2011 “Advanced Compiler Techniques” bar() { i := &a; j := &b; foo(&i); foo(&j); // i pnts to what? *i :=...; } void foo(int* p) { printf(“%d”,*p); } i a j b p i a i a j b i a j b p i,j a,b p 1 2 3 4 12 Another example 4 3

45
45 Fall 2011 “Advanced Compiler Techniques” Steensgard vs. Anderson Consider assignment p = q, i.e., only p is modified, not q Subset-based Algorithms Anderson’s algorithm is an example Add a constraint: Targets of q must be subset of targets of p Graph of such constraints is also called “inclusion constraint graphs” Enforces unidirectional flow from q to p Unification-based Algorithms Steensgard is an example Merge equivalence classes: Targets of p and q must be identical Assumes bidirectional flow from q to p and vice-versa

46
46 Fall 2011 “Advanced Compiler Techniques” Steensgaard & beyond A well engineered implementation of Steensgaard ran on Word97 (2.1 MLOC) in 1 minute. A well engineered implementation of Steensgaard ran on Word97 (2.1 MLOC) in 1 minute. One Level Flow (Das PLDI 00) is an extension to Steensgaard that gets more precision and runs in 2 minutes on Word97. One Level Flow (Das PLDI 00) is an extension to Steensgaard that gets more precision and runs in 2 minutes on Word97.

47
47 Fall 2011 “Advanced Compiler Techniques” Analysis Sensitivity Flow-insensitive Flow-insensitive What may happen (on at least one path) What may happen (on at least one path) Linear-time Linear-time Flow-sensitive Flow-sensitive Consider control flow (what must happen) Consider control flow (what must happen) Iterative data-flow: possibly exponential Iterative data-flow: possibly exponential Context-insensitive Context-insensitive Call treated the same regardless of caller Call treated the same regardless of caller “Monovariant” analysis “Monovariant” analysis Context-sensitive Context-sensitive Reanalyze callee for each caller Reanalyze callee for each caller “Polyvariant” analysis “Polyvariant” analysis More sensitivity ) more accuracy, but more expense More sensitivity ) more accuracy, but more expense

48
48 Fall 2011 “Advanced Compiler Techniques” Which Pointer Analysis Should I Use? Hind & Pioli, ISSTA, Aug. 2000 Compared 5 algorithms (4 flow-insensitive, 1 flow-sensitive): Any address (single points-to set) Steensgard Anderson Burke (like Anderson, but separate solution per procedure) Choi et al. (flow-sensitive)

49
49 Fall 2011 “Advanced Compiler Techniques” Which Pointer Analysis Should I Use? (cont’d) Metrics 1. Precision: number of alias pairs 2. Precision of important optimizations: MOD/REF, REACH, LIVE, flow dependences, constant prop. 3. Efficiency: analysis time/memory, optimization time/memory Benchmarks 23 C programs, including some from SPEC benchmarks

50
50 Fall 2011 “Advanced Compiler Techniques” Summary of Results Hind & Pioli, ISSTA, Aug. 2000 1. Precision: Table 2 Steensgard much better than Any-Address (6x on average) Anderson/Burke significantly better than Steensgard (about 2x) Choi negligibly better than Anderson/Burke 2. MOD/REF precision: Table 2 Steensgard much better than Any-Address (2.5x on average) Anderson/Burke significantly better than Steensgard (15%) Choi very slightly better than Anderson/Burke (1%)

51
51 Fall 2011 “Advanced Compiler Techniques” Summary of Results (cont’d) 3. Analysis cost: Any-Address, Steensgard extremely fast Anderson/Burke about 30x slower Choi about 2.5x slower than Anderson/Burke 4. Total cost (analysis + optimizations): Steensgard, Burke are 15% faster than Any-Address! Anderson is as fast as Any-Address! Choi only about 9% slower

52
52 Fall 2011 “Advanced Compiler Techniques” Haven’t We Solved This Problem Yet? From [Hind, 2001]: Past 21 years: at least 75 papers and nine Ph.D. theses published on pointer analysis Past 21 years: at least 75 papers and nine Ph.D. theses published on pointer analysis

53
53 Fall 2011 “Advanced Compiler Techniques” Many Publications…

54
54 Fall 2011 “Advanced Compiler Techniques” So Which Pointer Analysis is Best? Comparisons between algorithms difficult Comparisons between algorithms difficult Size of points-to sets inadequate Size of points-to sets inadequate Model heap as one blob = one object for all heap pointers! Model heap as one blob = one object for all heap pointers! Trade-offs unclear Trade-offs unclear Faster pointer analysis can mean more objects = more time for client analysis Faster pointer analysis can mean more objects = more time for client analysis More precise analysis can reduce client analysis time! More precise analysis can reduce client analysis time! Idea: use client to drive pointer analyzer… Idea: use client to drive pointer analyzer…

55
55 Fall 2011 “Advanced Compiler Techniques” New Approaches Speculative Pointer Analysis Speculative Pointer Analysis Traditional analysis is conservative, to guarantee correctness. Traditional analysis is conservative, to guarantee correctness. Applications: program transformation, program optimization Applications: program transformation, program optimization Some application does not require 100% correctness. Some application does not require 100% correctness. Most important: applicability and usability Most important: applicability and usability

56
56 Fall 2011 “Advanced Compiler Techniques” Speculative Pointer Analysis (SPA) – An Example int a,b; int *p; p = &a; for (i=0…1000){ *p = 5; p = &b; } pa pa pb pb a b p pb

57
57 Fall 2011 “Advanced Compiler Techniques” Purpose of SPA Optimize pointer location set widths in loop bodies speculatively Optimize pointer location set widths in loop bodies speculatively Remove unlikely or infrequent location sets Remove unlikely or infrequent location sets Improves ability to manage access statically in our context Improves ability to manage access statically in our context Improves precision for the typical case Improves precision for the typical case

58
58 Fall 2011 “Advanced Compiler Techniques” Summary of SPA Traditional pointer analysis Traditional pointer analysis Based on compile time provable information Based on compile time provable information Stops analysis if that cannot be guaranteed Stops analysis if that cannot be guaranteed Used in many performance optimization techniques Used in many performance optimization techniques Speculative pointer and distance analysis Speculative pointer and distance analysis Always completes analysis without restrictions Always completes analysis without restrictions Extracts precise information for our purposes Extracts precise information for our purposes Targets compiler-enabled memory systems Targets compiler-enabled memory systems

59
59 Fall 2011 “Advanced Compiler Techniques” Probability-based Pointer Analysis (ASPLOS’06) Silvia & Steffan, U Toronto Silvia & Steffan, U Toronto Define a probability for a points-to relation Define a probability for a points-to relation Use matrix calculation to compute the resulting probability for each pointer Use matrix calculation to compute the resulting probability for each pointer

60
60 Fall 2011 “Advanced Compiler Techniques” Conventional Pointer Analysis Do pointers a and b point to the same location? Do pointers a and b point to the same location? Do this for every pair of pointers at every program point Do this for every pair of pointers at every program point *a = ~ ~ = *b *a = ~~ = *b Definitely Not Definitely Maybe Pointer Analysis optimize Probabilistic Pointer Analysis (PPA) PPA p p = 0.0 p p = 1.0 p 0.0 < p < 1.0 With what probability p, do pointers a and b point to the same location? With what probability p, do pointers a and b point to the same location? Do this for every pair of pointers at every program point Do this for every pair of pointers at every program point optimize

61
61 Fall 2011 “Advanced Compiler Techniques” PPA Research Objectives Accurate points-to probability information Accurate points-to probability information at every static pointer dereference at every static pointer dereference Scalable analysis Scalable analysis Goal: The entire SPEC integer benchmark suite Goal: The entire SPEC integer benchmark suite Understand scalability/accuracy tradeoff Understand scalability/accuracy tradeoff through flexible static memory model through flexible static memory model Improve our understanding of programs Improve our understanding of programs

62
62 Fall 2011 “Advanced Compiler Techniques” Algorithm Design Choices Fixed Fixed Bottom Up / Top Down Approach Bottom Up / Top Down Approach Linear transfer functions (for scalability) Linear transfer functions (for scalability) One-level context and flow sensitive One-level context and flow sensitive Flexible Flexible Edge profiling (or static prediction) Edge profiling (or static prediction) Safe (or unsafe) Safe (or unsafe) Field sensitive (or field insensitive) Field sensitive (or field insensitive)

63
63 Fall 2011 “Advanced Compiler Techniques” Traditional Points-To Graph int x, y, z, *b = &x; void foo(int *a) { if(…) b = &y; if(…) a = &z; else(…) a = b; while(…) { x = *a; … } y UND a z b x = pointer = pointed at Definitely Maybe = = Results are inconclusive

64 64 Fall 2011 “Advanced Compiler Techniques” Probabilistic Points-To Graph int x, y, z, *b = &x; void foo(int *a) { if(…) b = &y; if(…) a = &z; else(…) a = b; while(…) { x = *a; … } y UND a z b x 0.1 taken (edge profile) 0.2 taken (edge profile) = pointer = pointed at p = 1.0 0.0

{ "@context": "http://schema.org", "@type": "ImageObject", "contentUrl": "http://images.slideplayer.com/12/3408077/slides/slide_64.jpg", "name": "64 Fall 2011 Advanced Compiler Techniques Probabilistic Points-To Graph int x, y, z, *b = &x; void foo(int *a) { if(…) b = &y; if(…) a = &z; else(…) a = b; while(…) { x = *a; … } y UND a z b x 0.1 taken (edge profile) 0.2 taken (edge profile) = pointer = pointed at p = 1.0 0.0

65
65 Fall 2011 “Advanced Compiler Techniques” Summary Pointer Analysis Pointer Analysis Overview Overview Andersen’s Algorithm Andersen’s Algorithm Steensgard’s Algorithm Steensgard’s Algorithm New Directions New Directions Next Time Next Time Locality Analysis Locality Analysis

Similar presentations

OK

U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Advanced Compilers CMPSCI 710.

U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Advanced Compilers CMPSCI 710.

© 2017 SlidePlayer.com Inc.

All rights reserved.

Ads by Google

Ppt on advanced energy conversion systems Ppt on power line communication Ppt on nitrogen cycle and nitrogen fixation process Ppt on indian textile industries in uganda Head mounted display ppt on tv Ppt on wpi and cpi Ppt on synthesis and degradation of purines and pyrimidines are Ppt on nitrogen cycle and nitrogen fixation by legumes Procedure text how to make ppt online Download ppt on mind controlled robotic arms