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;
}
- A*b is an integer, so hoisting would reduce its precision
- Ba and b might point to the same location, so writing a[i] could change *b
- 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.