Compiler Design

105601
Back to Compiler Design

Module 4: Intermediate Code Generation, Code Improvement (optimization)

  1. Q1d. Three-address code involves (i) Exactly 3 address (ii) At most 3 addresses (iii) No unary operator (iv) None20232m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    Three-address code involves
    (i) Exactly 3 address
    (ii) At most 3 addresses
    (iii) No unary operator
    (iv) None

    View this question on its own page →
    Worked Solution

    Answer: (ii) At most 3 addresses

    Explanation

    A three-address code is an intermediate-code statement of the general form:

    result=arg1 op arg2\mathrm{result} = \mathrm{arg}_1\ \text{op}\ \mathrm{arg}_2

    Each statement contains at most three operands/addresses: the destination plus at most two source operands. The name comes from the fact that a single 3-address statement involves at most three addresses.

    • It is not exactly 3 addresses — a statement like t = a or t = -a has fewer than three addresses.
    • It can contain a unary operation (e.g. t = -x), so saying "no unary operator" is wrong.
    • Therefore "Exactly 3 address" (i), "No unary operator" (iii), and "None" (iv) are incorrect.

    The correct statement is:

    (ii) At most 3 addresses\boxed{\text{(ii) At most 3 addresses}}

  2. Q1g. Which optimization eliminates repeated computation of the same expression? (i) Loop interchange (ii) Dead-code elimination only (iii) Common subexpression elimination (iv) Register allocation20262m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    Which optimization eliminates repeated computation of the same expression?
    (i) Loop interchange
    (ii) Dead-code elimination only
    (iii) Common subexpression elimination
    (iv) Register allocation

    View this question on its own page →
    Worked Solution

    Answer: (iii) Common subexpression elimination

    Explanation

    Common subexpression elimination (CSE) detects an expression that was already computed and whose operands have not changed since, and reuses the earlier result instead of recomputing it.

    Before:

    x = a * b + c
    y = a * b + d
    

    After CSE:

    t = a * b
    x = t + c
    y = t + d
    

    The other options: loop interchange changes loop order (cache behaviour); dead-code elimination removes useless code; register allocation maps variables to registers.

    (iii) Common subexpression elimination\boxed{\text{(iii) Common subexpression elimination}}

  3. Q1i. The method which merges the bodies of two loops is (i) Loop rolling (ii) Loop Jamming (iii) Constant folding (iv) None of the above20232m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    The method which merges the bodies of two loops is
    (i) Loop rolling
    (ii) Loop Jamming
    (iii) Constant folding
    (iv) None of the above

    View this question on its own page →
    Worked Solution

    Answer: (ii) Loop Jamming (loop jamming)

    Explanation

    • Loop jamming / loop fusion (jamming) is the compiler optimization that merges the bodies of two adjacent loops that have the same range of traversal, into a single loop, so the loop control overhead runs only once.
    • Loop rolling is not a standard optimization.
    • Constant folding folds expressions with only constants at compile time, evaluating them at compile time (e.g. x = 3+4 → x = 7), unrelated to merging loops.
    • "None of the above" is therefore wrong.

    Hence the method which merges the bodies of two loops is:

    (ii)Loop jamming (loop fusion)\boxed{\text{(ii)Loop jamming (loop fusion)}}

  4. Q6a. Generate the three-address code for the following expression. Then represent the generated code using quadruple, triple, and indirect-triple representations. x = a * (b + c) - d / e20267m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    Generate the three-address code for the following expression. Then represent the generated code using quadruple, triple, and indirect-triple representations.
    x=a∗(b+c)−d/ex = a * (b + c) - d / e

    View this question on its own page →
    Worked Solution

    Expression: x=a∗(b+c)−d/ex = a * (b + c) - d / e

    Operator precedence and parentheses give the evaluation order: (b+c)(b+c) first, then a∗(… )a * (\dots), then d/ed/e, then the subtraction, then the assignment.

    Three-address code

    t1 = b + c
    t2 = a * t1
    t3 = d / e
    t4 = t2 - t3
    x  = t4
    

    Syntax tree of the expression (each internal node becomes one three-address instruction, bottom-up)

    MermaidDiagram
    Rendering diagram…

    (i) Quadruples (op, arg1, arg2, result)

    # op arg1 arg2 result
    0 + b c t1
    1 * a t1 t2
    2 / d e t3
    3 - t2 t3 t4
    4 = t4 x

    (ii) Triples (op, arg1, arg2): there is no result field; a result is referred to by the number of the triple that computed it.

    # op arg1 arg2
    (0) + b c
    (1) * a (0)
    (2) / d e
    (3) - (1) (2)
    (4) = x (3)

    (iii) Indirect triples: the triples are the same as above, but a separate instruction list holds pointers to them. The order of execution can then be changed by reordering the pointers without touching the triples.

    Instruction list Points to
    100 (0)
    101 (1)
    102 (2)
    103 (3)
    104 (4)
    Triple # op arg1 arg2
    (0) + b c
    (1) * a (0)
    (2) / d e
    (3) - (1) (2)
    (4) = x (3)

    Comparison

    Form Temporaries in symbol table Easy to reorder for optimization
    Quadruples Yes (explicit result names) Yes
    Triples No No (numbers refer to positions)
    Indirect triples No Yes (reorder the pointer list)
  5. Q6b. Explain the construction of basic blocks and control-flow graphs (CFGs) in compiler design using a suitable three-address code example.20267m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    Explain the construction of basic blocks and control-flow graphs (CFGs) in compiler design using a suitable three-address code example.

    View this question on its own page →
    Worked Solution

    Basic block

    A basic block is a maximal sequence of consecutive three-address instructions with one entry point (only the first instruction can be reached from outside) and one exit point (control leaves only at the last instruction, with no jumps into or out of the middle).

    Algorithm to find basic blocks

    1. Find the leaders (first instructions of blocks):
      • the first instruction of the program;
      • the target of any conditional or unconditional jump;
      • the instruction immediately after a jump (conditional or unconditional).
    2. For each leader, the basic block consists of the leader and all instructions up to (but not including) the next leader or the end of the program.

    Example three-address code

    1  sum = 0
    2  i = 1
    3  if i > 10 goto 8
    4  t1 = i * 2
    5  sum = sum + t1
    6  i = i + 1
    7  goto 3
    8  print sum
    

    Leaders: instruction 1 (first), 3 (target of the jump at 7), 4 (follows the conditional jump at 3), 8 (target of the jump at 3 and follows the jump at 7). So the leaders are {1,3,4,8}\{1, 3, 4, 8\}.

    Block Instructions
    B1B_1 1-2
    B2B_2 3
    B3B_3 4-7
    B4B_4 8

    Control-flow graph (CFG)

    A CFG has the basic blocks as nodes. There is an edge Bi→BjB_i \to B_j if control can pass from the end of BiB_i to the start of BjB_j: either by a jump from the last instruction of BiB_i to the leader of BjB_j, or because BjB_j follows BiB_i in program order and BiB_i does not end in an unconditional jump.

    MermaidDiagram
    Rendering diagram…

    Uses: the CFG exposes loops (here B2→B3→B2B_2 \to B_3 \to B_2), and is the basis for data-flow analysis, local optimizations inside a block, and global optimizations such as code motion and dead-code elimination.

  6. Q8b. Translate the expression a = (a + b) * (c + d) + (a + b + c) into (i) Quadruple (ii) Triple (iii) Indirect triple20239m

    Module 4: Intermediate Code Generation, Code Improvement (optimization)

    Translate the expression a=(a+b)∗(c+d)+(a+b+c)a = (a + b) * (c + d) + (a + b + c) into
    (i) Quadruple
    (ii) Triple
    (iii) Indirect triple

    View this question on its own page →
    Worked Solution

    Three-address code for a=(a+b)∗(c+d)+(a+b+c)a=(a+b)*(c+d)+(a+b+c)

    Start from the natural statement sequence:

    t1 = a + b
    t2 = c + d
    t3 = t1 * t2
    t4 = a + b         (or reuse t1)
    t5 = t4 + c        → computes (a+b) + c
    t6 = t3 + t5
    a  = t6
    

    (i) Quadruples

    Form (op, arg1, arg2, result):

    No op arg1 arg2 result
    1 + a b t1
    2 + c d t2
    3 * t1 t2 t3
    4 + a b t4
    5 + t4 c t5
    6 + t3 t5 t6
    7 = t6 (empty) a

    (ii) Triples

    Three fields (op, arg1, arg2); a result value is referenced by its triple index (k).

    # op arg1 arg2
    1 + a b
    2 + c d
    3 * (1) (2)
    4 + a b
    5 + (4) c
    6 + (3) (5)
    7 = (6) a

    (iii) Indirect triples

    List of triples plus a separate indirect table that holds the execution-order pointers to the triples; changing an instruction (e.g. removing a common subexpression) is done by redirecting a pointer, no renumbering needed.

    Triples:

    # op arg1 arg2
    1 + a b
    2 + c d
    3 * (1) (2)
    4 + (1) c
    5 + (3) (4)
    6 = (5) a

    Indirect table (execution order):

    (1) → triple 1
    (2) → triple 2
    (3) → triple 3
    (4) → triple 4
    (5) → triple 5
    (6) → triple 6   → assigns into a
    

    Since triple 4 reuses triple 1 (a+b), the (a+b) subexpression appears once; that is exactly how the indirection layer makes common-subexpression elimination and code motion easy.

    Summary

    • Quadruple: explicit result names — easiest to manipulate, most commonly used in optimizers.
    • Triple: compact (no temporaries), but moving/deleting statements requires renumbering.
    • Indirect triple: triples + index vector — easy CSE/code motion at the price of one extra level of indirection.