3

Suppose I have, in C99, for(int j=0; j < t->k; j++), t->k does not change throughout the loop iteration. Does the compiler optimize this line, or there will be one dereferencing operation per loop iteration?

In other words, would

tmpk = t->k;
for(int j = 0; j < tmpk; j++)

be better for a large number of iterations?

Dervin Thunk
  • 19,515
  • 28
  • 127
  • 217
  • 3
    The important thing is, if the compiler can deduce that `t->l` won't change. Related: [_What is the strict aliasing rule?_](http://stackoverflow.com/questions/98650) – mafso Aug 05 '14 at 02:41
  • I meant, there might be some `int` pointers used in the loop body, for which the compiler cannot know they don't alias `t->l` (although you may know that), if some writing to their pointees occurs, the compiler must assume that `t->l` may change. Depending on the whole code, this may also be a problem for readers of the code (who have to scan the loop body to see if that value can change, using a variable (as `tmpl` in your code) may make it clearer that the upper bound for `j` doesn't change through execution of the loop body). – mafso Aug 05 '14 at 02:50
  • The only correct answer is "it depends". Compilers are different, loops are different, there is a lot of reasons why a compiler might be unable to deduce that something is indeed an invariant. You have to look at your assembly output to know for sure. – n. m. could be an AI Aug 05 '14 at 02:52
  • @mafso: Ah, I see. And no, `t->l` is not written to at any point in the loop. I've added the `gcc` keyword to see if someone can crack the "depends" answer nm rightfully points at. – Dervin Thunk Aug 05 '14 at 02:53
  • Edited such that my comment about `t->k` is now a dangling pointer! :) – Jeffrey Hantin Aug 05 '14 at 02:54
  • @JeffreyHantin: Switched example to `t->k`. You happy now?! :) – Dervin Thunk Aug 05 '14 at 02:55
  • @mafso The strict aliasing rule only comes into play if different pointers alias the same memory under differently-typed interpretations; that is, simultaneously aliasing and type-punning. This is apt to happen if you cast a `char *` to a `struct foobar *`, populate the `foobar`, then use the `char *` to write what you think are the bytes of the `foobar`. – Jeffrey Hantin Aug 05 '14 at 02:59
  • @JeffreyHantin; I didn't link to the strict aliasing rule because I think, here is a violation of it, but because the optimizations possible with that rule are related. Any `int` pointer or character pointer may alias `t->k` and this may prevent the optimization in question. – mafso Aug 05 '14 at 03:03
  • @Dervin, now you broke my first comment semantically since `t->k` now *is* part of the loop proper! I'll delete it. – Jeffrey Hantin Aug 05 '14 at 03:05

1 Answers1

4

In the general case this depends on whether t is declared restrict; in the absence of an explicit aliasing restriction the compiler cannot assume that no other pointer provides a path to modify k.

Of course, if the compiler can prove that t->k is invariant by inspection of the loop body, it may choose to move the dereference out of the loop body, or do so incorrectly if the optimizer is buggy.

Explicitly caching the value of t->k in a local variable would rather reliably force the issue. :-)

Jeffrey Hantin
  • 35,734
  • 7
  • 75
  • 94