Volatile

The volatile type qualifier can be used to declare objects that may be modified in ways unknown to the compiler or have other unknown side effects (e.g. modification via a signal interrupt, hardware register, or memory mapped I/O). Subject to the implementation-defined abstract machine, volatile objects inhibit some optimizations such as keeping the objects in registers and some types of code motion.

These NULLSTONE tests isolate defects in the optimizer associated with incorrect optimization of volatile objects.

Example:

In the function below, the expression (x + y) appears to be loop invariant. However, x and y are declared with type qualifier volatile, and their values may change during the execution of the loop.

volatile int x, y;
int a[SIZE];

void f (void)
{
  int i;

  for (i = 0; i < SIZE; i++)
    a[i] = x + y;
}
  

Some compilers will hoist the expression (x + y) out of the loop as shown below, which is an incorrect optimization.

volatile int x, y;
int a[SIZE];

void f (void)
{
  int i;
  int temp;

  temp = x + y;                  /* incorrect code motion */
  for (i = 0; i < SIZE; i++)
    a[i] = temp;
}
  

Notes:

Empirical data suggests that incorrect optimization of volatile objects is one of the most common defects in C optimizers. In particular, eleven out of twelve commercially-available C compilers failed one or more NULLSTONE volatile conformance tests in a study performed in the spring of 1995. Hoisting volatile objects out of loops was the most common defect observed.

Const volatile objects are particularly problematic for many compilers, which often treat const volatile objects like const objects.