Skip to content

[clang] __builtin_bit_cast / std::bit_cast drop volatile from load #160336

@a2flo

Description

@a2flo

I'm not sure if this is intended behavior, but it is certainly unexpected.
Given a load from a volatile pointer that is then bitcasted to a different type, clang currently drops the "volatile" part of the load.

With the following code, clang does not emit a volatile load from "volatile_ptr":

#include <bit>
extern volatile float* volatile_ptr;
int main(int, char**) {
    return std::bit_cast<int>(volatile_ptr[0]); // alternatively: return __builtin_bit_cast(int, volatile_ptr[0]);
}

results in:

define dso_local noundef i32 @main(i32 noundef %0, ptr noundef readnone captures(none) %1) local_unnamed_addr #0 !dbg !12 {
  %3 = load ptr, ptr @volatile_ptr, align 8, !dbg !23
  %4 = load i32, ptr %3, align 4, !dbg !45
  ret i32 %4, !dbg !47
}

I would expect the bitcast code to be (more or less) semantically equivalent to this:

extern volatile float* volatile_ptr;
int main(int, char**) {
    return *(volatile int*)&volatile_ptr[0];
}

which of course results in a volatile load:

define dso_local noundef i32 @main(i32 noundef %0, ptr noundef readnone captures(none) %1) local_unnamed_addr #0 !dbg !14 {
  %3 = load ptr, ptr @volatile_ptr, align 8, !dbg !25
  %4 = load volatile i32, ptr %3, align 4, !dbg !31
  ret i32 %4, !dbg !34
}

Looking at the code, shouldn't the emitted memcpy here not be volatile if the source address is volatile?

Builder.CreateMemCpy(DestAddress, SourceAddress, SizeVal);


For testing: https://godbolt.org/z/zvf64761T

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:codegenIR generation bugs: mangling, exceptions, etc.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions