Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misoptimization: EarlyCSEPass uses replaces powi.f16 with float result #98665

Closed
tgross35 opened this issue Jul 12, 2024 · 1 comment · Fixed by #98681
Closed

Misoptimization: EarlyCSEPass uses replaces powi.f16 with float result #98665

tgross35 opened this issue Jul 12, 2024 · 1 comment · Fixed by #98681

Comments

@tgross35
Copy link

tgross35 commented Jul 12, 2024

It looks like EarlyCSEPass is transformin the following:

  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  %0 = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1) ; 0xH3C00 = 1.0f16
  store half %0, ptr %_3, align 2
  %1 = load half, ptr %_3, align 2
  %_4 = fcmp oeq half %1, 0xH3C00
  br i1 %_4, label %bb1, label %bb2

Into this:

  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  store float 1.000000e+00, ptr %_3, align 2
  %0 = load half, ptr %_3, align 2
  %_4 = fcmp oeq half %0, 0xH3C00
  br i1 %_4, label %bb1, label %bb2

And later InstCombine folds further into:

  %_6 = alloca [48 x i8], align 8
  %_3 = alloca [2 x i8], align 2
  store float 1.000000e+00, ptr %_3, align 2
  br i1 false, label %bb1, label %bb2

EarlyCSE seems to be doing an incorrect transformation: the result of powi.f16(1.0, 1) should be half 1.0 (0x3c00), but it is returning float 1.0 (0x3f800000). This is incorrect and an OOB write.

This comes from the following rust code, which asserts only when optimizations are enabled:

#![feature(f16)]
#![allow(unused)]

#[inline(never)]
pub fn check_pow(a: f16) {
    assert_eq!(1.0f16.powi(1), 1.0);
}

pub fn main() {
    check_pow(1.0);
    println!("finished");
}

Link to compiler explorer: https://rust.godbolt.org/z/zsbzzxGvj

I'm not sure how to reduce to a llc example since the passes appear different. I have been testing on aarch64 since x86 has other f16 ABI bugs, but I don't think this is limited to aarch64.

@dtcxzyw
Copy link
Member

dtcxzyw commented Jul 12, 2024

Reproducer: https://godbolt.org/z/jhM834G3z

define half @test() {
    %x = call half @llvm.powi.f16.i32(half 0xH3C00, i32 1)
    ret half %x
}
opt: /root/llvm-project/llvm/lib/IR/Value.cpp:507: void llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=early-cse <source>
1.	Running pass "function(early-cse<>)" on module "<source>"
2.	Running pass "early-cse<>" on function "test"
 #0 0x0000000004e9b948 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4e9b948)
 #1 0x0000000004e990bc SignalHandler(int) Signals.cpp:0:0
 #2 0x000078ad4b442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x000078ad4b4969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x000078ad4b442476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x000078ad4b4287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x000078ad4b42871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x000078ad4b439e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x0000000004cce094 llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4cce094)
 #9 0x0000000003ae3b58 (anonymous namespace)::EarlyCSE::processNode(llvm::DomTreeNodeBase<llvm::BasicBlock>*) EarlyCSE.cpp:0:0
#10 0x0000000003ae5a85 (anonymous namespace)::EarlyCSE::run() EarlyCSE.cpp:0:0
#11 0x0000000003ae81f8 llvm::EarlyCSEPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3ae81f8)
#12 0x0000000002ac11be llvm::detail::PassModel<llvm::Function, llvm::EarlyCSEPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2ac11be)
#13 0x0000000004c9f2d8 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9f2d8)
#14 0x0000000000dc9bee llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdc9bee)
#15 0x0000000004c9dd46 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9dd46)
#16 0x0000000000dca1fe llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xdca1fe)
#17 0x0000000004c9bf10 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x4c9bf10)
#18 0x00000000008db1d2 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8db1d2)
#19 0x00000000008ce0fc optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8ce0fc)
#20 0x000078ad4b429d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#21 0x000078ad4b429e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#22 0x00000000008c556e _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x8c556e)
Program terminated with signal: SIGSEGV
Compiler returned: 139

There is a bug in constant folding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants