Elimination of const copy of variable

Viewed 92

I was reviewing some code. There I saw this:

int Obj::GetValue() const
{
   return m_val;
}

void SomeFunc(const Obj *obj1)
{
   // keep a copy in case obj1 is modified!
   const Obj o2 = *obj1;
   //... much more code
   // some which may modify data pointed to by obj1
   DoSomething(o2.GetValue());    // use original value!
}

can a compiler optimize this code such that o2.GetValue() will end up being replace by obj1->GetValue() or some cached value ?

Obj1 points to some memtable, the pointer remains valid through the function, but the memtable data can change synchronously due to some call within the function that operate on the memtable which incidentally is global! this is why the dev took a copy of Obj1, but because he was not planning on modifying it he decided to declare it const.

I think that because we point to a const object, and the copied object is const then the optimiser can decide to optimize out the copy

I've checked with godbolt.org using: gcc, clang & msvc as our code is multi platform, and all seems good. But of course if this code is UB, I will ask for it to be changed.

2 Answers

can a compiler optimize this code such that o2.GetValue() will end up being replace by obj->GetValue() or some cached value ?

If the compiler can guarantee that the optimization follows the as-if rule it can do such an optimization.

If it can do that assumption depends what is actually done in:

   //... much more code
   // some which may modify data pointed to by obj1

The compiler has to assume that *obj1 may alias another way of reaching the same object of type Obj. It can't eliminate the copy unless it can track the caller and understand where the pointer is coming from or otherwise prove that this can't happen.

The const on obj1 means you are not allowed to modify it via this name, but it cannot assume that it's not changed by some other name. C++ doesn't have the restrict modifier available in C, but there are compiler extensions that can be used to inform the compiler that there is no aliasing, and potentially enable such optimizations.

The passage in CppReference cited above explains (for C)

These rules control whether a function that receives two pointers must re-read one after writing through another

C++ has the same feature: pointers can alias values of the same type, but it is undefined behavior to modify an aliased location if the types don't match. C++ has a more complex meaning of "same type" in that a derived type contains a base class subobject.

Related