[llvm-bugs] [Bug 51529] New: Truncation to i1 generates invalid value

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Aug 18 19:22:20 PDT 2021


            Bug ID: 51529
           Summary: Truncation to i1 generates invalid value
           Product: libraries
           Version: 12.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: robin at voetter.nl
                CC: craig.topper at gmail.com, llvm-bugs at lists.llvm.org,
                    llvm-dev at redking.me.uk, pengfei.wang at intel.com,
                    spatel+llvm at rotateright.com

Created attachment 25166
  --> https://bugs.llvm.org/attachment.cgi?id=25166&action=edit
Test case

In order to load a value from a packed struct of 8 bools, the Zig compiler
generates code as follows:

%1 = load i8, i8* %ptr_to_packed_struct, align 1
%2 = lshr i8 %1, %target_bit_offset
%3 = trunc i8 %2 to i1

This seems to cause LLVM to not actually perform the truncation in very
esoteric cases, and the upper bits of %3 are not cleared. This would be fine of
course, i expect those to be allowed to be undefined, though when the resulting
value is compared with another i1 with the same truthiness (but a differing
backing bit value), an incorrect result is generated. See the attached test
case, which prints "error" when this case is detected. The incorrect value is
generated in %14 in function @b, and is later compared for equality with 1 in
function @a to produce `false` in %17 in @a.

This only seems to manifest itself when two components are available: the
original packed struct needs to be part of a union, and the resulting bit value
(after the pointer load) needs to be passed on the stack.

The related Zig issue is https://github.com/ziglang/zig/pull/9584. Note that
the attached test case was made by creating a similar case in C, and rewriting
it a bit to trigger the incorrect behavior. For this kind of code, clang
generates an additional and operation between the lshr and trunc, though
according to the semantics of trunc i would expect that to be included.

In Zig, this case is only triggered in debug mode. When I tested that with the
attached test case, clang crashed (see below). The test case is to be compiled
simply with `clang -otest test.ll` to create the incorrect code described
above, and adding `-O2` yields the segmentation fault below. 

Stack dump:
0.      Program arguments: /usr/bin/clang-12 -cc1 -triple
x86_64-unknown-linux-gnu -emit-obj --mrelax-relocations -disable-free
-disable-llvm-verifier -discard-value-names -main-file-name test.ll
-mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math
-mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic
-fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir
/usr/lib/clang/12.0.0 -O2 -fdebug-compilation-dir
/home/robin/programming/zooi/llvm-bug -ferror-limit 19 -fgnuc-version=4.2.1
-vectorize-loops -vectorize-slp -faddrsig -o /tmp/test-cbb751.o -x ir test.ll
1.      Code generation
2.      Running pass 'Function Pass Manager' on module 'test.ll'.
3.      Running pass 'Simple Register Coalescing' on function '@a'
 #0 0x00007f69eb76db4d llvm::sys::PrintStackTrace(llvm::raw_ostream&, int)
 #1 0x00007f69eb76b824 llvm::sys::RunSignalHandlers()
 #2 0x00007f69eb76b99b (/usr/bin/../lib/libLLVM-12.so+0xbdb99b)
 #3 0x00007f69ea79e000 __restore_rt (/usr/bin/../lib/libc.so.6+0x3d000)
 #4 0x00007f69ebc18897 (/usr/bin/../lib/libLLVM-12.so+0x1088897)
 #5 0x00007f69ebcdb914 (/usr/bin/../lib/libLLVM-12.so+0x114b914)
 #6 0x00007f69ebcdbaa1 (/usr/bin/../lib/libLLVM-12.so+0x114baa1)
 #7 0x00007f69ebce165a (/usr/bin/../lib/libLLVM-12.so+0x115165a)
 #8 0x00007f69ebce268e (/usr/bin/../lib/libLLVM-12.so+0x115268e)
 #9 0x00007f69ebce4c66 (/usr/bin/../lib/libLLVM-12.so+0x1154c66)
#10 0x00007f69ebce7196 (/usr/bin/../lib/libLLVM-12.so+0x1157196)
#11 0x00007f69ebb584e4
#12 0x00007f69eb8c4310 llvm::FPPassManager::runOnFunction(llvm::Function&)
#13 0x00007f69eb8c58fc llvm::FPPassManager::runOnModule(llvm::Module&)
#14 0x00007f69eb8c3c28 llvm::legacy::PassManagerImpl::run(llvm::Module&)
#15 0x00007f69f2804209 clang::EmitBackendOutput(clang::DiagnosticsEngine&,
clang::HeaderSearchOptions const&, clang::CodeGenOptions const&,
clang::TargetOptions const&, clang::LangOptions const&, llvm::DataLayout
const&, llvm::Module*, clang::BackendAction,
std::default_delete<llvm::raw_pwrite_stream> >)
#16 0x00007f69f2b7550a clang::CodeGenAction::ExecuteAction()
#17 0x00007f69f32eca89 clang::FrontendAction::Execute()
#18 0x00007f69f3282b0b
#19 0x00007f69f3367498
#20 0x0000564529d65479 cc1_main(llvm::ArrayRef<char const*>, char const*,
void*) (/usr/bin/clang-12+0x14479)
#21 0x0000564529d629e7 (/usr/bin/clang-12+0x119e7)
#22 0x0000564529d5f0ac main (/usr/bin/clang-12+0xe0ac)
#23 0x00007f69ea788e0a __libc_start_main
#24 0x0000564529d6238a _start (/usr/bin/clang-12+0x1138a)
clang-12: error: unable to execute command: Segmentation fault
clang-12: error: clang frontend command failed due to signal (use -v to see
clang version 12.0.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
clang-12: note: diagnostic msg: Error generating preprocessed source(s) - no
preprocessable inputs.

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210819/cea42650/attachment-0001.html>

More information about the llvm-bugs mailing list