Implement a priority queue datastructure based on Python's heapq.
Make function prologue print the function name.
Re-implement the whole register allocator using a new stratey.

The details of the new stratey for register allocation is as follows. The new
strategy makes some simplifying assumptions. This is to get the basic simple
allocator working. As we progress we improve the alloctor. But for now the
simplifying assumptions are:

1. One of the major simplifying assumption is that a variable that is spilled
   is always kept in memory. It is neither reloaded as we do in the case of
   Live Range splitting nor is it re-materialized.

2. No coalescing is implemented. Coalescing in SSA form graph is nothing but
   assigning all the phi-operands and registers to the same register. We do
   do not do it yet. This is the next first step.

3. The Live Range Analysis Algorithm has an inherent problem that I had
   realized a while back. While merging live ranges, conceptually I was
   thinking on unions and used to merge live ranges using the lower of the two
   live ranges as the start of the interval and the larger of the two value as
   the end of the interval. I knew that this was clearly wrong because when
   a live range ends in if-else blocks i.e. different branches of the Control
   Flow Graph, we just take the instruction that gets executed last among
   the two blocks. This is just so wrong. But I did not know any better way
   to fix this. Now I know, this is the next second step. Take the sets of
   instruction labels and compute their set unions! Stupid me! Why didn't I
   think about this before!

4. Every time an allocation fails, we completely rebuild the cost function
   priority queue, rebuild the whole graph. This is such a waste of time. We can
   do much better than this. This is one of the next steps too.

Here is how the allocator works for now.

1. Initially we build the interference graph just using the Live Range
   information we have. Reduce it to SAT and try to solve the SAT. If the SAT
   is solved we have our allocation, go to Step 5.

2. If the allocation fails, we will compute the spill costs. We use a cost
   function to determine the spill costs of each variable. The cost function
   used is the Chaitin's allocator style cost function that computes the
   execution frequency and uses a frequency multiplier of 10 to increase the
   frequency of execution of instructions for each level deep in the loop.
   We build a priority queue of spill costs and pick the one with the least
   spill cost.

4. Then we mark this virtual register as spilled, eliminate it from Live
   Range intervals completely, and we repeat from Step 1.

   Note, when we remove the virtual register from the Live Range intervals,
   when we rebuild everything again, it doesn't appear in the Interference
   graph or the Spill cost priority queue anymore.

5. Generate the register assignments from the SAT solution.

6. Deconstruct the SSA.
The formal parameters are equivalent to defining the variable, so give them the execution frequency of the start node.
If the register is a result of a load operation, it should never be spilled.

This makes sense because, if we want to spill the register, we can
as well directly reload from the memory location. It makes absolutely
no sense to spill that register. So give the spill cost of infinity to
such a register.
Fix whitespace issues.