(volatile uint32_t*) へのポインタ キャストを介して割り込みステータス レジスタを読み取ると、この式 (指定されたアドレスの変数) を読み取ると副作用が生じるため、常にこの式を評価する必要があることがコンパイラに伝えられます。
tmp 変数は揮発性ではないため、コンパイラーはレジスターの値を変数に格納することを自由に最適化できます。
C標準の5.1.2.3章(ここを参照)は十分に関連していると思います。
さらに、第 6.7.3 章では次のように説明しています。
volatile 修飾された型を持つオブジェクトは、実装に不明な方法で変更されたり、その他の未知の副作用を持つ可能性があります。したがって、そのようなオブジェクトを参照する式は、5.1.2.3 で説明されているように、抽象マシンの規則に従って厳密に評価されます。さらに、すべてのシーケンス ポイントで、オブジェクトに最後に格納された値は、前述の未知の要因によって変更された場合を除き、抽象マシンによって規定された値と一致するものとします。116) volatile 修飾された型を持つオブジェクトへのアクセスを構成するものは実装定義です。
実際には tmp を省略して、次のように書くことができます:
*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;
これは、INTERRUPT_STATUS_REG_ADDRESS にある uint32_t レジスタを読み取るだけです。