Compiler ARMCLAN 6.21 optimization problem

In the following functions, I count the amount of allocated memory.

Getting the alloc size fails with compiler optimization -Os balanced. The variable allocSize keeps always the init value 42. Doing the same access in 2 steps returns the correct value!

And the same 1 step statement works in the osFreeMemTest() function!?

Do I have missed something in the C-syntax or is this a compiler bug?

#include <stdlib.h>
static volatile uint32_t allocCount     = 0;
static volatile uint32_t freeCount      = 0;
static volatile uint32_t allocFreeDiff  = 0;

static volatile uint32_t allocTotal     = 0;
static volatile uint32_t allocTotal2    = 0;

void * osAllocMemTest(size_t size)
{
   volatile uint32_t  allocSize         = 42;
   
   volatile uint32_t * pAllocSize       = 0;
   volatile uint32_t  allocSize2        = 0;

   volatile void *p = 0;

   p = malloc(size);
   if (p == NULL) {       
       //System reset as ultimate fault handling
       NVIC_SystemReset();
   }

   allocCount++;
   allocFreeDiff = allocCount - freeCount;

   // code returns 42 with optimizing level -Os balanced, works only for -O0 and -O1  
   // because statement is skipped when optimized
   allocSize = *(((uint32_t *) p) - 1); 
   
   // replacement with 2 steps works with optimization
   pAllocSize = ((uint32_t *) p) - 1;
   allocSize2 = *pAllocSize;
   
   allocTotal += allocSize;
   allocTotal2 += allocSize2;

   //Return a pointer to the newly allocated memory block
   return (void *) p;
}

/**
 * @brief Release a previously allocated memory block
 * @param[in] p Previously allocated memory block to be freed
 **/

void osFreeMemTest(void *p)
{
   volatile uint32_t allocSize = 0;

   //Make sure the pointer is valid
   if(p != NULL)
   {

      freeCount++;
      allocFreeDiff = allocCount - freeCount;

      // works here with optimization -Os balanced
      allocSize = *(((uint32_t *) p) - 1);
      allocTotal -= allocSize;

      //Free memory block
      free(p);
   }
}