diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2456,10 +2456,11 @@ so operations which modify memory or may have undefined behavior can be hoisted past a volatile operation. -IR-level volatile loads and stores cannot safely be optimized into -llvm.memcpy or llvm.memmove intrinsics even when those intrinsics are -flagged volatile. Likewise, the backend should never split or merge -target-legal volatile load/store instructions. +IR-level volatile loads and stores cannot safely be optimized into llvm.memcpy +or llvm.memmove intrinsics even when those intrinsics are flagged volatile. +Likewise, the backend should never split or merge target-legal volatile +load/store instructions. Similarly, IR-level volatile loads and stores cannot +change from integer to floating-point or vice versa. .. admonition:: Rationale diff --git a/llvm/test/Transforms/InstCombine/volatile_load_cast.ll b/llvm/test/Transforms/InstCombine/volatile_load_cast.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/volatile_load_cast.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @float_load(i32* %addr) { +; CHECK-LABEL: @float_load( +; CHECK: %int = load volatile i32, i32* %addr, align 4 +; CHECK-NEXT: %float = bitcast i32 %int to float +; CHECK-NEXT: ret float %float + %int = load volatile i32, i32* %addr, align 4 + %float = bitcast i32 %int to float + ret float %float +} + +define i32 @int_load(float* %addr) { +; CHECK-LABEL: @int_load( +; CHECK: %float = load volatile float, float* %addr, align 4 +; CHECK-NEXT: %int = bitcast float %float to i32 +; CHECK-NEXT: ret i32 %int + %float = load volatile float, float* %addr, align 4 + %int = bitcast float %float to i32 + ret i32 %int +}