 started looking at, and whenever you find, and the slide you do is normally of size 2 to 4, and this result has been obtained empirically that window size of 2 to 4 is sufficient. And whenever you find a shorter course sequence for the same operation, then you try to replace it. You have to design various standards. This technique was developed sometime in the first, actually paper appeared sometime in the 80s, and then it has been continuously improved, and it went on to do work like say, why just have a physical window, why not have a logical window. For example, if you will have branch instruction, then the actual jump will then or else make it physically far separated. Then I mean why can't you have a window which will have two instructions of branch just prior to branch, and the next instruction in the window could be of the part where the control actually jumped. So branch prediction also can be done using that. So basically what we are doing here is that we are looking at the target port which contains all the redundancies and suboptimal constructs, and we want to replace them by a shorter sequence of target instruction, and that is what the people is, and replace it by a faster sequence, and this is a small movement of the target system. So let's look at what we are trying to look at. So what we have is, for example, this is the first example we saw that suppose I have this template which says remove redundant loads and stores, and you see this template and instruction prove, we know that irrespective of what the application is, this can always be removed, unless you have an explicit jump coming to the second instruction. In that case, if you remove it, it could be dangerous. So instruction prove can always be removed if it does not happen here. So this is one optimization line as possible. Let's look at yet another example. So suppose we have this port sequence, and what we are dealing with is unreachable port. So suppose I have this hash defined debug being initialized to zero, and then I have this loop, this conditional it says if debug, and then it can remove any information. And you have already seen this kind of port, and one that many people very frequently use it in their application. But if you recall, we discussed at some point of time that when you have lags in the application, they internally define some kind of debug switches, and you can turn them on and off by just editing y dot by proxy or lags of y y dot c, and change this from zero to one, and then it gives you complete information how it is going to finite state machine or how the parser is going to a stack. It gives you the complete stack information while parsing. So suppose I get into a situation like this, and I know that this debug is switched. Now what can be done here is something very interesting. Now this says that if debug, what it actually means is something when it gets translated into three address code, maybe something like if debug is one, then I jump to well one where I am printing all the debugging information, otherwise I am going to well two. In L2 is the normal execution sequence, and I can eliminate this jump over jump because there is a jump from here to here and here to here. I can remove it by changing this condition, and then code may look something like if debug is not equal to one when I straight away go to L2, otherwise I print this information. So this is how my three address code may look like. Now if I try to optimize it using the people optimization, what may happen is that I will do something called constant propagation. A constant propagation says we won't have time to go into formal details of how the constant propagation is done, but what it means is that if I have a variable whose value is known at compile time and the value is constant, then I can replace the variable by the value itself, and then after this propagation I will have a condition like it will say that if 0 is not equal to 1, then go to L2. Now I know that this Boolean expression can be evaluated at compile time, and you know that this condition will always be, condition will always be 0 not equal to 1 is false, 0 not equal to 1 will always be true, could be. So condition that whenever we see a Boolean condition we say 2 are false, and look at Boolean expression. So this condition will always be true, and therefore I can replace the whole thing by saying just go to L2 because that condition itself is not required, and once I say I have this jump, all this elimination can get eliminated, and even this go to can get eliminated by just a Boolean window. So then I can say that this code will never get executed, so print statement is now inaccessible, and therefore the code becomes just a jump to L2, because I may be jumping to L2 from many other places, but definitely this jump is redundant, because from here I am just jumping if I eliminate this will just fall through. So this is one optimization, so there are many such templates which are possible, so I can have flow of control where I say that I am having a sequence of jumps, so if I say go to L1, and L1 comes here it says go to L2, then I know straight away that this place can be replaced by straight away going to L2, and then this L1 going to L2, can I eliminate this? I cannot because it is possible that I am coming to L1 not only from here, but from some other places. I need not replace this, this is where I was talking about a logical build-up rather than just a physical build-up. And similarly when we talk about a layer-like expression I can immediately see that these kind of expressions can easily be put as part of the template and can be removed at the time of people optimization. So whenever I say that I have addition with 0 or multiplication with 1, I know that these are basically operations and therefore I am just going to tell you that they are not going to contribute anything. Similarly I can do what we know as strength reduction, because normally you will find that there are operators which will accomplish the same thing but some operators are going to be costlier than others. So for example I can say that if I am trying to find a square, exponentiation may not be an operation which is available in the hardware and I have to actually make a function call but if I know that this is only a square then I can always replace it by a multiplication. Similarly if I say that if it is a multiplication by a power of 2 or a division by a number which is power of 2, then I can handle that by relation of a right shape. So these again are templates. Similarly another template which may be possible is that if I say add 1 to a register then I can replace this by an increment. Now who designed these templates? Normally the compiler writers who are familiar with the machine instruction set for which they are writing a compiler they will design these templates and use them. So there is some work which says that you can also automatically generate these templates but it is not always possible. There is some work which has been done on that of generating template automatically. But normally if you design these templates then a pattern map is sufficient to do the optimization. Now another thing we started looking at yesterday was when we were saying that we can either generate free address code and from free address code I can convert that into machine code by you can get next user information I can do all the optimization on registers and so on. But I can also generate code by tree relight. And we also looked at a DAG or a tree representation of some kind of code sequence where we did not have explicit libraries. Now what we want to do here is if you say that I am trying to do tree rewriting basically the issue is what the technique is something like this that if I take a tree suppose this is the tree I have and I will not go I will assume that recursively I can expand all the sub-trees of this if I can say that I generate some code sequence for this or I need a template so suppose take something like this if I say that I am trying to add a register to register suppose I have an instruction say add to register now there is only a template depending upon actual registers this could be any two registers from the register now suppose I find this template that my template in the tree may look something like this that I may have an addition and I may have some value let's say value one and I have value two there so what I can do is I can find that this template actually something similar to this provided these value one and value two are registers now I know that there are instructions which will take value one and load that into register so what I can do is I can have a rewriting rule which says that if you find a template and you know that this template can be replaced by something and the corresponding action has to be executed now this looks something very similar to what you actually did yeah you had a template and then you said this template can be replaced by it's left and right so when I had a template like saying e goes to e of p what I am saying here is that e of p is a template I am replacing it by e as I am going through the process of parsing and what was the corresponding action here corresponding action could be that I was either building an action like stream or I was editing some code or I was doing computation or something like that so depending upon the application I was able to write some action so this looks very similar to that it says that I have a template which I can replace by something and at the same time I can take an action here so suppose now I have an instruction of this form which says that I want to move content of a register into memory location so what this template is saying is that left hand side is an address right hand side is a register which contains a value this assignment is being done and the target of this is actually a memory location so this is a template which is saying that this instruction in general which says move contents of a register into a location whose address is given in this register can be described by this three kind of template and then action could be one of the actions could be that I made this instruction when I will find this template and replace this subtree by amp so I will take an example of how this is done but this is one possibility now similarly I can look at other instructions so for example if I look at this instruction which says add a constant to a register what this is saying is that I am looking at a template plus constant register and then I can replace the whole template by just a register by amuting this instruction of course I have to do bookkeeping to say that actually which is this physical register so R is only a template but actual bookkeeping A and this is what the template part is this is what the action part is going to be which will say emit this instruction with proper bookkeeping similarly I may have another instruction where I say that add two registers and put value into a register so I can have this template which says add R and R prime these are two different registers and put the register into R so this is one possibility now what we need to do is that if I have an intermediate representation in which I am representing my code as an xx and x3 then you just need to find these templates and how long will you go on you can keep on finding this template till the tree reduces to a single node then you say that I am done because how long template can match a single node and I can just move from that point on so let's look at few more instructions for which I will have a template and then actually look at the way we do code generation so here is another template which says I want to move contents of a memory location into a register and they are saying that address of that memory location is given in the register are done so I can take this address from that and then I can move that into content of that into a register so this basically is the template this is what the replacement is and this is the action which says that generate this instruction with software register on this another possible template could be that I now say that move contents of a register into a location whose address is given by this indirect which says that the address will have to be completed by looking at contents of the register a small offset or some offset which is a possible or I can say that I have a template which says take contents of a location whose address is given by r prime with an offset of d so this d and r prime addition of that gives me an address and when I d reference that that gives me content of a memory location and then I am adding that to r and I am moving this into r again so this is saying that add contents of a memory location into a register and slow with that into a register or I can have a template which says move contents of a memory location into a register so now I can say that look at contents of r prime add d to that add the 2 that gives me an address then I do a d reference and that takes me to r so this is another possible example so this way I can design a template of each of these instructions so this is yet another template which says that move a constant into a register so it is point clear that at least I can take machine instructions and write them in a form which looks like a tree and once I have done this now what I can do is I can take an abstract syntax tree and I can then start with matching of this template and we will see how to do this so first let's look at an abstract syntax tree for an expression like a is being assigned d plus c plus 9 and I have made certain assumptions here one assumption is that they all occur in the same scope and therefore they are all have a location which is at an offset with respect to certain base register since they are in the same scope the base register is going to be the same so what I have assumed is that and lower case a, lower case b and lower case c are the offsets of the storage of a, b and c with respect to the base register since this scope is same I don't have to worry about and now what I need to do is in this particular tree so let's see what this is doing this is saying that b plus r0 is going to give me address of b and this b reference is going to give me contents of that location so that will give me the value of b this will give me the value of c I am going to add 9 to c then I am going to add b to c plus 9 and then I am going to store this into an address and address is given by the left hand side which is r0 plus a and r0 is the base register so first let's do a template pattern matching and then you will see how to actually so now what are the kind of things I can do on this now I can match several templates and the templates I am going to use are one of these templates now depending on the machine instruction you have the templates could be different so what we can do is we start from here and first we say is that I look at this a and this a is an offset and it matches now I am going totally arbitrary traversal order I am just looking at randomly some template traversal order has not been fixed we look at how to fix the traversal order but if I just look at this road this says that it is matching a template and this move a constant to r so what I can do now is I can now say that the first register I am going to use is r1 because r0 is already blocked with an offset and now I can generate this instruction which says move a to r1 and this node is this b is replaced by r1 because now this content has been moved and I have replaced this template by itself so I can generate this instruction and now again I try to do pattern match and say that now this part of the tree matches a template which says add contents of to the register and if this part is matched then I just have to make sure that r1 is mapped on to r prime and r0 is mapped on to r in my generation of the instruction so I now can say that generate an instruction which says add r0 to r1 now you know that r0 can now be overwritten because r0 has future uses here so I just cannot use that so what I am doing here is I am adding r0 to r1 and then what do I do? I am going to replace this particular node by saying that this gets replaced by r1 so this is how my tree looks after this look at it now I can find more templates here and here is one possible template which says that I am adding this particular locations I am adding this particular location into r1 so what do I do now I just say that generate this instruction which says that there is something wrong here should not be add there is nothing like r2 here should be actually move so I think this is another here there should be a move instruction saying that I am moving contents of this into r2 and this is how it should look this is incorrect and then what we can do is we can go further and we can say that what did I do this is again the move same as here this actually should have been a move and not an add so again what we are doing here is that we are moving now contents of this and so I am looking at indirect r0 with c I am adding r2 and I am moving that into r3 there is nothing like r3 and r2 have not even been initialized so actually it is a move instruction please note these directions so this then becomes r3 and this is how my 3 is after this code sequence generation and then what may happen is that I may now match another template which says now add a constant to r so this constant is being added to this register this is the template and what may happen here is that I can now generate this instruction which says that add v at 9 to r3 and once I do that then this whole thing will get replaced by r3 itself and once I have done this what will happen now it will match maybe a template which says add two registers and store value into another target register so basically it is now matching r2 and r3 and then it may generate something like add r3 to r2 and then this whole thing gets replaced by r2 and once I have done this this is now going to match a template which says that add r prime to r indirect and this says move r2 this should have been an add not a move so now I am saying that actually this template this is incorrect but this move is correct because I am not adding anything I am just moving this r2 into r1 indirect so I generate this instruction and this is the instruction sequence I generate and what do I replace it with if you replace it now the target of this instruction is m and this whole thing gets reduced to m and that is where I say that this whole thing is in memory and therefore I can stop because there is nothing to match and there is the kind of code sequence I have there but there are certain issues there one issue as I said what is my implementation for this because we have not looked at how do I go feedback in 19 and the second issue is even more dangerous and that is when I say that I am adding two registers you can see so let us look at this sequence now the way I could have written look at this sequence I have a register on the left hand side and a constant on the right hand side now this operator is commutative that means I can also which will say that constant is on the left hand side and register is on the right hand side and that will also be valid so if I go back to the templates I had so let us go back to this which where I had templates and see what we actually wrote what we actually wrote was something like this that I am adding a constant and the pattern I matched was where constant is on the right hand side so first issue you have to be immediately aware of this that if your operator is commutative then I can write the same pattern in multiple ways that means I can write either D on the left or D on the right and both are valid now I do not know how the user code is going to be how user has written the code user can write A is the sign to B plus 9 or user can write A is sign to B and both are correct and I should be able to generate an efficient code of the same code for both the instructions it should not really matter in which way user has written and therefore I should make sure that when I have an instruction like this I also either have a template which matches plus RD or I have a way of saying this is an operator which is commutative and therefore both should match and now if you look at these templates it becomes worse because now I have a way from this particular instruction R so I can take and I can swap on this and I can swap on this both are possible so you can see that from each instruction I can generate multiple templates but then there are ways of handling how do I match multiple templates I can always look at how possible combinations and see if one of the template matches and if your instruction P is not too large then that match is not going to take too much of a pattern but the question remains how do I implement it so are you aware of some T-pattern match alternatives you know something like T-pattern matching have you seen any T-pattern matching alternatives so far what is gap does gap do a T-pattern match suppose I do now a traversal of this pattern say pre-order traversal or in-order traversal and just flatten it one of the forms which says pre-order traversal so can I say it's something like this and is assigned can I flatten it like this or can I take the second instruction and say R is assigned so this now becomes like 1x3 gamma and then whatever T I had for A being assigned B plus B plus 9 that can also be traversal in pre-order traversal and flatten and then what do I do can I use yak then to just match it is that pre-pattern matching so pre-pattern matching need not be only in this way you can use even tools like yak or bison to actually do code revolution so once you have generated to be a representation I can write my machine instructions now like a grammar, a complex tree grammar and then can do a pattern like using just yak and then get the code for this and what is the action I write here I already know the action I am going to write here is some bookkeeping for register and generate some instruction and I can write this kind of action and then yak and bison will be able to handle this situation only problem is going to be once again that different traversal orders and therefore different ways of flattening this particular tree are going to be giving different code sequences so for example the code sequence we looked at for this intermediate representation which was this code sequence which these two errors instead of add this should have a move I can take the same machine instruction and generate a different code sequence for that if I start doing my matching from the right hand side so suppose now I start matching my template from the right hand side and I say that this matches template which says constant to register and then I generate this instruction which says move 9 to register and the next pattern could be something like this where I actually match this whole thing and this is saying that now add this value into register r prime and r prime is now in this case r1 and then I can generate an instruction which says add r0 in direct c to r1 that gives me c plus 9 and then I can replace this whole thing by r1 and then the same pattern actually matches here and what I can do here is I can say that now this particular template matches this instruction template and what I can generate is add r0 b to r1 and then this whole thing can be replaced by r1 and then this whole thing matches the template which is saying that move r into a location whose address is given by r prime in direct d and here d is constant a and what I can generate is move r1 to r0 in direct a and then this whole thing reduces so instead of those seven instructions I generated I can just generate four instructions and I am done so traversal order is going to matter a lot and what immediately one has to think about is how do we address this issue of traversal so there are lot of techniques people have done work on this saying that irrespective of whether your operator is communicative or not and how do you do pattern match and how do you really do something about reducing the traversal order and generate at least ensure that you generate one instruction sequence which is that so there are lot of research work which is available on this and people have used different techniques in fact this is one of the pattern matching remains one of the most powerful techniques as far as code generation is concerned so many compilers actually instead of using three address code do this kind of template matching and you can see that this technique also is very amenable to retargetable code generation because all I need to do is write these templates for a different machine and once I have these templates for a different machine then I can take the same intermediate representation I can take the same code generation algorithm and then I can just traverse over this particular intermediate representation and then generate code by doing a pattern match with respect to a new machine template so you can do retargetable code generation so this is where I want to stop on code generation and I want to move on to a new topic which obviously we will not be able to cover in detail we just have about 20 minutes but I will give you a glimpse at least into what happens in optimization which is fairly formal stuff so let's look at something at least I mean you will get an idea of what optimization is all about so we talked about this problem called data flow analysis I mean I mentioned this term for data flow analysis and then let me say that we do optimization now what is data flow analysis first let's look at conceptually then I can throw in some symbols because without symbols nothing works so what we are trying to do is we are looking at a program and we are trying to find whether certain properties hold for this program irrespective of what is my input data and what are the paths which are taken during execution phase of this particular program so for example if you recall in the previous one of the files there is debug hash being defined to 0 so I had this hash defined debug now it doesn't matter which path is taken if this variable is defined only once then at all the places irrespective of your input at all the places debug can be replaced immediately by 0 how do I know this I have to do certain analysis over the program to say that at the statement which says if debug there is there are multiple paths which are reaching here but doesn't matter which path you follow during execution the value of debug which you will reach here is always going to be 0 if I can assert that at compile time that this property is independent of what happens at execution time so what we do in data flow analysis is we try to find out certain properties of the program during compile time and see that whether these properties can be used now for program optimization that is what data flow analysis is so global optimizations and remember that only optimization we have done so far is looking at the local basic block and using the next use information and saying that I can minimize my number of resources by looking at next use information but suppose I want to go beyond basic blocks then I need to worry about multiple paths which may reach each of these basic blocks so global optimizations are all based on what we know as data flow algorithms and what these algorithms do they gather certain data about the program and then what this data is going to tell us that we are looking for certain property that must hold every time this instruction gets executed so this property must always go this property that debug will always be 0 this must always go irrespective of how your program gets executed and that is what data flow analysis will be able to tell me and for different properties I want to compute the analysis may differ so if I look at one situation where I say that I want to do constant propagation so constant propagation was where I said debug is defined is initialized to 0 and then I was saying if debug and so on so what we want to do now is for constant propagation we want to find out for every point in my program now what is point in a program point in a program is nothing but one of the basic blocks we constructed and instruction which is getting executed so you remember the control flow graph of the program by saying that I find headers then I convert that three instruction sequence into a set of basic blocks and then I have control flow so during execution I will be either before some instruction or either after some instruction these are my program points so if you recall when I was doing this next use instruction computation I had these instruction saying i2, i3 and so on and I was doing computation of this property at this point of time at this point of time whether the variable is live or dead so there is the information I was computing so now we say that for each point in the program and for each variable which is being used in the program whether variable has a unique constant value at that point and if this condition is true if this property is true then I can replace variable that is by a constant value so for example if I can say that if I look at the basic block which contains this instruction it says if debug and then do something and there are multiple paths which are coming into this basic block in my control program if I can assert by analysis of this program that does not matter which path is taken irrespective of that at this program point value of debug will always be 0 and when I say does not matter which path is taken I must check this property on all the paths before I can do this assertion if I can check that and this debug always turns out to be 0 then I can always replace this value by 0 so this is what we do normally in constant propagation that I check this property at every program point saying that look at all possible paths and find out what is the value of this debug and if it is a unique value which is the same then I can always do this replacement another thing we saw was this live variable now live variable we were looking only within a basic block only but suppose I have to do control flow that means I must be able to check that if I go out on multiple paths from this whether this variable debug so there is some variable which is available here this is being used again what I need to do here is that for every program point I want to find out whether value of variable is sure to be overrated before this is going to be read again and if yes then there is no need to preserve that value so if I say that if I have a variable x here and if I know that doesn't matter which path I take then this value is always going to be overwritten on one of these paths on all of these paths before next use happens then I know that whatever value has been assigned to x here is of no use and I think that just remove it so what I was doing in next use information was assuming that there is only one control flow path and that was the basic property of a basic block saying you have a single entry and a single exit but when I go into data flow analysis I say there are multiple entries and multiple exits and this property must now be checked for all possible paths all combinations now you can see that immediately one problem that comes is when I talk about a closed form solution the reason is there could be infinitely many paths and also if you have a loop I mean for example if I say that there is a node where I enter the control there is a node where I exit the control and this is going to be unique for every program then I can count number of paths in that and this path may be number of paths may be finite if I don't have a loop but if I have a loop I can have infinite path because I cannot assert anything about whether loop will terminate or not okay now what do I do do I exhaustively check just for all possible paths or I can say I can do some clubbing and say that if I check this property for some of the paths then I can be sure about this property for all the paths right because somewhere you have to say that whatever form of your solution is it is in closed form I mean I just cannot go on saying that I have infinite paths and I keep on checking this property for all possible paths that's not doable and even if I have a large number of paths computationally it may be so costly that I may not be able to do that so I have to do this kind of analysis so again since I am just giving you a glimpse into what happens here let me skip some of these property materials and straight away come to some definition which will actually tell you something about that how do I model these solutions saying that although I have infinite paths but I can talk only about finite properties over these paths so what we say is that we find something called the reaching definition so what I may do here is that suppose I have a control flow graph and in this control flow graph so this is what my control flow graph is and this is a program point t and this is some entry into control flow graph now I want to find out something like saying that there is a definition d so what is my definition if you recall again we gave a definition like saying that if in general I have an instruction like this x is being assigned y of z this is given an a this is an instruction i or we call it definition of x we say that definition d reaches a point p if there is a path from d to p and d is not killed on this path that means this value is not overwritten suppose on this path so I have at this program point definition d which is defining let's say x and here I want to say is d reaching p this is the question I want to ask okay how do I know that this d will be p now suppose there is only one path okay from d to p and on this path I overwrite x I say x is assigned so I have let's say this is d1 and this is d2 and I say x is assigned certain some are with the expression then d1 will never reach p okay d1 will never reach p because on this path it is always going to be overwritten so this is one set of information I collect when I am trying to do data flow analysis whether I have a path from any definition to a point in the p program p and there are formal methods of doing that I mean it's just not you don't trace your program and then start doing this collecting this information similarly I may say that these are available to me suppose I am saying that at this point so now let me change my formalism and I say that a is assigned x plus y and suppose there are multiple paths coming here can I now look for a property which will say that is x plus y always computed on all these paths because if I have say a computation of x plus y on this path a computation of x plus y on this path a computation of x plus y on this path then I know for sure that doesn't matter which path comes here x plus y has been computed now it may not have the same value okay on this path it may have a different value on this path it may have a different value but that doesn't bother as long as we know that x plus y has been computed on all the paths okay then I know that I don't have to compute x plus y again so I can eliminate this second computation of x plus y because I know that irrespective of which path is taken during institution I will have some value of x plus y already computed okay so again I can do this kind of replacement and we say that an expression x of y is available at point p if every path to p evaluates one last such evaluation I do not make an assignment to either x or y because imagine that I am computing x plus y on this path and immediately after this I say that I am making an assignment to x now as soon as I make an assignment to x this x plus y becomes in value because the value I will be computing here will not be this value but it will be something else okay so again this is a property I think check by looking at my program okay another property may be I want to check whether the variable is live at a point p and we can say that if value of x can be used along some path oh so what may happen is that suppose I do this computation okay and I say that I want to reuse this computation and at runtime suppose this path is taken okay then I cannot reuse this value because this value has already been changed by assignment to x suppose this path was taken okay then I can use this value but I do not know at compile time which path will be taken this path could be taken or this path could be taken so I want to assert this property over all the paths so I should not have any assignment to either x or y on after last such computation okay but if you have an assignment then you must have one more computation for you similarly I can have something about like variable I can say variable is live some point p so I can say that if I have my control flow graph okay and I want to say is x live here at this point p okay then what will I say if it can be used along some path okay so suppose I have multiple paths going out okay and if it is used on one of the paths okay then I know that this is surely live okay now you can see something very interesting in these three definitions first definition if you see this take if something happens on one of the paths okay because there are multiple paths here so what what is happening here when you say reaching definition if there is a path from here and this is not here okay not is possible that on other paths okay I may not even have a definition of x okay but at least I know since I do not know which path is going to be taken here okay since I don't know which path is going to be taken here okay this path could be taken with equal probability as a path okay then I know that at least as far as this point is concerned there is a reaching definition okay but in this case I am asserting that something must happen on all the paths that if x plus y is available here then it must be computed on all the paths because if it is computed only on one of the paths okay and is not computed say on this path and actually control flows through this path at runtime then I know that x plus y will not be available to me okay this has not been completed already so for this to be available here it must be computed on all the paths but for this to be reaching definition it is sufficient to say that it is available on one of the paths okay similarly when I say whether this variable is live I don't care about all the paths if I say this variable is live even if one of the paths uses it then I know that this variable is live so this is now what I am computing here is that suppose I say x is used on this path and I assert that x is live here but actually at runtime this path is taken then I know that this x will never be used here but I am looking for certain properties which will always hold okay so I am looking at I am trying to simulate runtime behavior at compile time okay and I am only interested in properties which will always hold which will not hold some of the times so I can do runtime optimization but what I am trying to do first is compile time optimization and I am looking for certain properties which is always hold okay what are we doing here so let's look at the kind of things which we do here okay so I may write something very interesting okay I may say that each basic block can generate a set of instructions each basic block can kill a set of instructions each basic block so let's just write some basic block so suppose I have a basic block like this in which I have two instructions let's say d1 is instruction which says x is signed y plus 3 I have instruction d2 it is saying that y is assigned now z plus 2 and then I have d3 in which I say a is assigned d okay so for that these three instructions in a basic block now I know that when control comes in here okay and control goes out there basic block there is a single and single language okay what I know for sure is that irrespective of which parts which are taken at the end of this suppose this basic block contains only these three instructions at the end of this I will have a definition of x which will be d1 I will have a definition of y which will be d2 and I will have a definition of a which will be d3 this is definitely sure that d1, d2 and d3 but it is also going to kill certain definitions so for example prior to this suppose I had a basic block okay which let's say has d0 which was saying x is being assigned 7 okay now I also know that if control flows through this and since I don't know whether control will flow through this or not I have to assume with equal probability even if there is a path from there to here that if control flows from there then this d0 will not be available to me because x is being reassigned so this definition will always be clear so what I can do is I can compute now set of definitions which are generated by a basic law I can compute the set of definitions which are always going to be created by a basic law okay so for example now I can say that if my universal set of definitions of x is dx then what are the definitions which are going to be killed by this basic law of x everything except d1 okay so it is going to kill all definitions which are dx in dx-d1 okay so no matter how control flows if any definition comes that will get eliminated and only a definition which will be available to me will be a definition d1 okay so I can compute now my sets of variables which are generated by sets of definitions which are generated and sets of definitions which are killed in a basic law and then I can write equations like saying that the definitions which are coming in and what are the definitions which will come out the definitions which will come out are either it is generated in the block or it comes into the block and is not given okay so I can write such equations for each basic law so for example for reaching definition if I am trying to say with my reaching definitions then I can write an equation which will be of the form which will say that what comes out of a basic block is nothing but what gets generated here or what comes in and is not killed by this okay and this equation is actually capturing my reaching definition which are coming out of a basic law so what we try to do is we try to assert these kind of properties over the program and then using these properties we try to optimize this over the program okay so this is just to give you a glimpse into what actually happens in optimization so optimization is a really very formal mathematical structure is not just template based pattern matching saying that do something okay because that something will never work or may not work okay and what you do is you set up these kind of equations and then try to solve the equations okay now you can see that if I have one more equation okay one more equation could be that what is my insect if I compute my insect what will be insect so insect and reaching definition could be that I take union of out of all the predecessors basic law where p is so I can say that if my insect is I just take union of all the outs and my out is defined as whatever is generated union what is coming in and is not killed okay and this way for each basic law I can set up these equations and solve these equations which will tell me that what are the properties that always go like this okay okay so let's close our discussion here today