Compilers

In the function above, why can the compiler not simply hoist the load of *b out of the loop?

void add(int *a, int *b, int n) {
    for (int i = 0; i < n; i++)
        a[i] += *b;
}
  1. A*b is an integer, so hoisting would reduce its precision
  2. Ba and b might point to the same location, so writing a[i] could change *b
  3. CCompilers are forbidden from optimizing any function that takes pointer arguments
Show answer and explanation

Answer: B. a and b might point to the same location, so writing a[i] could change *b

At first glance *b does not change inside the loop, so reading it once seems enough. But if the caller passes something like add(x, &x[3], n), b points into a, and writing a[3] changes *b. Because the compiler cannot rule out this aliasing, it generates code that rereads *b every iteration. In C, marking the pointers restrict promises they do not overlap and permits the optimization. It is neither a precision issue nor a ban on optimization.

  • A. Moving an integer load does not change precision.
  • B. Correct. a and b might overlap (aliasing).
  • C. Functions with pointers are optimized too.
Practice this topic Back to topic

More Compilers questions

  1. In register allocation by coloring an interference graph, what do the nodes and edges represent?
  2. What happens to generated code when register allocation causes a "spill"?
  3. What is the main purpose of instruction scheduling in a compiler?
  4. What is the effect of applying tail-call optimization to the final recursive call in the function above?
  5. Which correctly distinguishes a compiler from an interpreter?