Bug 107196

Summary: [13 Regression] llvm-14.0.6 is miscompiles by gcc-13 in -O3: hangs llvm testsuite (inliner seems to break it)
Product: gcc Reporter: Sergei Trofimovich <slyfox>
Component: ipaAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: marxin
Priority: P3 Keywords: wrong-code
Version: 13.0   
Target Milestone: 13.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2022-10-09 00:00:00

Description Sergei Trofimovich 2022-10-09 18:32:14 UTC
It's not a self-contained bug and requires full llvm build to trigger it. My apologies. In my defense I have a few small clues to share!

The heavyweight reproducer: download llvm, build it with this week's gcc and run one test that hangs. The bug started happening about 2 weeks ago.

The reproducer steps:

$ export CC=gcc-13
$ export CXX=g++-13

$ wget -c https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.6/llvm-project-14.0.6.src.tar.xz
$ tar xf llvm-project-14.0.6.src.tar.xz
$ mkdir build
$ cd build

# We will build only 'llc' and run only one minimal haning test.

$ cmake ../llvm-project-14.0.6.src/llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=RISCV -DLLVM_ENABLE_PROJECTS='llvm'
$ make -j $(nproc) llc

$ cat >bug.ll <<EOF
    ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
    ; RUN: llc -mtriple=riscv32 -target-abi=ilp32d -mattr=+v,+zfh,+experimental-zvfh,+f,+d -riscv-v-vector-bits-min=128 -riscv-v-fixed-length-vector-lmul-max=1 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,LMULMAX1

    define void @ui2fp_v8i64_v8f16(<8 x i64>* %x, <8 x half>* %y) {
    ; LMULMAX1-LABEL: ui2fp_v8i64_v8f16:
    ; LMULMAX1:       # %bb.0:
      %a = load <8 x i64>, <8 x i64>* %x
      %d = uitofp <8 x i64> %a to <8 x half>
      store <8 x half> %d, <8 x half>* %y
      ret void
    }
EOF

$ timeout 10 bin/llc -mtriple=riscv32 -target-abi=ilp32d -mattr=+v,+zfh,+experimental-zvfh,+f,+d -riscv-v-vector-bits-min=128 -riscv-v-fixed-length-vector-lmul-max=1 -verify-machineinstrs ./bug.ll && echo FINISHED || echo TIMED OUT

'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
TIMED OUT

$ LANG=C $CC -v |& unnix
Using built-in specs.
COLLECT_GCC=/<<NIX>>/gcc-13.0.0/bin/gcc
COLLECT_LTO_WRAPPER=/<<NIX>>/gcc-13.0.0/libexec/gcc/x86_64-unknown-linux-gnu/13.0.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with:
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.0.0 20221002 (experimental) (GCC)
Comment 1 Andrew Pinski 2022-10-09 18:34:06 UTC
We definitely needs more information than this. It could very well be a bug in LLVM too.
Have you tried compiling LLVM with -fsanitize=address ?
Comment 2 Andrew Pinski 2022-10-09 18:34:18 UTC
How about -fwrapv ?
Comment 3 Sergei Trofimovich 2022-10-09 18:38:22 UTC
The clues:

1. I bisected gcc down to

  commit 2460f7cdef7ef9c971de79271afc0db73687a272
  Author: Aldy Hernandez <aldyh@redhat.com>
  Date:   Fri Sep 23 19:47:33 2022 +0200

    Set ranges from unreachable edges for all known ranges.

But I suspect it's not the culprit and only a trigger in inliner behaviour change.

2. The bug is probably somewhere in mis-compilation of llvm/lib/Target/RISCV/RISCVISelLowering.cpp. The following workaround repairs the test:

--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1,3 +1,4 @@
+#pragma GCC optimize(0)
 //===-- RISCVISelLowering.cpp - RISCV DAG Lowering Implementation  --------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.

$ timeout 10 bin/llc -mtriple=riscv32 -target-abi=ilp32d -mattr=+v,+zfh,+experimental-zvfh,+f,+d -riscv-v-vector-bits-min=128 -riscv-v-fixed-length-vector-lmul-max=1 -verify-machineinstrs ./bug.ll && echo FINISHED || echo TIMED OUT
'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
'+experimental-zvfh' is not a recognized feature for this target (ignoring feature)
FINISHED

3. It looks like using '-O2 --param=max-inline-insns-single=116' (instead of -O3) against llvm/lib/Target/RISCV/RISCVISelLowering.cpp is enough to trigger the bug. '-O2 --param=max-inline-insns-single=115' sees to work.
Comment 4 Andrew Pinski 2022-10-09 18:47:05 UTC
llvm/lib/Target/RISCV/RISCVISelLowering.cpp is huge source and it might have undefined code in it.
Maybe narrow down which function is going wrong.

Maybe fire up gdb and see where the infinite loop is located too.
Comment 5 Sergei Trofimovich 2022-10-09 19:25:33 UTC
(In reply to Andrew Pinski from comment #1)
> We definitely needs more information than this. It could very well be a bug
> in LLVM too.
> Have you tried compiling LLVM with -fsanitize=address ?

(In reply to Andrew Pinski from comment #2)
> How about -fwrapv ?

Tried the following:
- -fwrapv: no change, hangup still happens
- -fsanitize=address: hangup disappears, no reports on stderr
- -fwrapv -fsanitize=address: hangup disappears, no reports on stderr
- -fsanitize=undefined: hangup disappears, no reports on stderr
Comment 6 Sergei Trofimovich 2022-10-09 20:02:06 UTC
(In reply to Andrew Pinski from comment #4)
> llvm/lib/Target/RISCV/RISCVISelLowering.cpp is huge source and it might have
> undefined code in it.
> Maybe narrow down which function is going wrong.

What would be the best way to do it? I initially tried '#pragma GCC push_options/#pragma GCC optimize(0)/#pragma GCC pop_options', but the final result still requires a few headers and RISCVISelLowering.cpp functions to be outside optimize(0).

I'm afraid I spent on in a few days and filed the bug in hopes there is a nicer technique to nail down the specific transformation that changes the behaviour.

If there is no better way to do it I'll start sprinkling __attribute__((noinline, noipa)) around to get broken and working variants closer.

> Maybe fire up gdb and see where the infinite loop is located too.

Looking at gdb the problem is not very clear: generic (not RISCV-specific code) at '#8  Run () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1538' implements some instruction selection logic to pick better instructions (DAGCombiner). Normally it stabilizes, but in this case it does not finish. Heavy use of STL-like data structures do not make it easier to trace through in gdb to see where first deviation bet ween good/bad happens. llvm has debugging mode to dump the transformations applied but enabling it at build time make the bug to go away.

Full backtrace:

llvm::DenseMapBase<llvm::DenseMap<llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >, llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >::LookupBucketFor<llvm::SDNode*> () at llvm/include/llvm/ADT/DenseMap.h:632
632           if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
(gdb) bt
#0  llvm::DenseMapBase<llvm::DenseMap<llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >, llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >::LookupBucketFor<llvm::SDNode*> ()
    at llvm/include/llvm/ADT/DenseMap.h:632
#1  llvm::DenseMapBase<llvm::DenseMap<llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >, llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >::LookupBucketFor<llvm::SDNode*> ()
    at llvm/include/llvm/ADT/DenseMap.h:663
#2  llvm::DenseMapBase<llvm::DenseMap<llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >, llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >::try_emplace<unsigned int> ()
    at llvm/include/llvm/ADT/DenseMap.h:225
#3  llvm::DenseMapBase<llvm::DenseMap<llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >, llvm::SDNode*, unsigned int, llvm::DenseMapInfo<llvm::SDNode*, void>, llvm::detail::DenseMapPair<llvm::SDNode*, unsigned int> >::insert ()
    at llvm/include/llvm/ADT/DenseMap.h:216
#4  AddToWorklist () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:273
#5  0x00000000014f12e8 in AddToWorklist () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:268
#6  AddUsersToWorklist () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:195
#7  AddToWorklistWithUsers () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:200
#8  Run () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1538
#9  llvm::SelectionDAG::Combine () at llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:24210
#10 0x00000000015ea7bf in llvm::SelectionDAGISel::CodeGenAndEmitDAG ()
    at llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:958
#11 0x00000000015ed2c5 in llvm::SelectionDAGISel::SelectAllBasicBlocks ()
    at llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1634
#12 0x00000000015efd8b in llvm::SelectionDAGISel::runOnMachineFunction ()
    at llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:515
#13 0x0000000000ba4f34 in llvm::MachineFunctionPass::runOnFunction () at llvm/lib/CodeGen/MachineFunctionPass.cpp:72
#14 llvm::MachineFunctionPass::runOnFunction () at llvm/lib/CodeGen/MachineFunctionPass.cpp:37
#15 0x0000000000ff87b0 in llvm::FPPassManager::runOnFunction () at llvm/lib/IR/LegacyPassManager.cpp:1434
#16 0x0000000000ff8b3c in llvm::FPPassManager::runOnModule () at llvm/lib/IR/LegacyPassManager.cpp:1480
#17 0x0000000000ffa39e in runOnModule () at llvm/lib/IR/LegacyPassManager.cpp:1549
#18 llvm::legacy::PassManagerImpl::run () at llvm/lib/IR/LegacyPassManager.cpp:539
#19 0x000000000065a38a in compileModule () at llvm/tools/llc/llc.cpp:719
#20 main () at llvm/tools/llc/llc.cpp:417
Comment 7 Andrew Pinski 2022-10-20 17:28:34 UTC
This might be fixed already.
Comment 8 Sergei Trofimovich 2022-10-21 06:26:01 UTC
I confirm that today's master does not exhibit the failure. Bisecting to the fix ends up at this fix:

  commit c9b840db504d15db01f06fe1fec38282dbafee07
  Author: Aldy Hernandez <aldyh@redhat.com>
  Date:   Mon Oct 17 18:56:24 2022 +0200

    Make sure exported range for SSA post-dominates the DEF in set_global_ranges_from_unreachable_edges.

    The problem here is that we're exporting a range for an SSA range that
    happens on the other side of a __builtin_unreachable, but the SSA does
    not post-dominate the definition point.  This is causing ivcanon to
    unroll things incorrectly.

    This was a snafu when converting the code from evrp.

            PR tree-optimization/107293

Looks plausible?
Comment 9 Andrew Pinski 2022-10-21 06:28:42 UTC
(In reply to Sergei Trofimovich from comment #8)
> I confirm that today's master does not exhibit the failure. Bisecting to the
> fix ends up at this fix:
> 
>   commit c9b840db504d15db01f06fe1fec38282dbafee07
>   Author: Aldy Hernandez <aldyh@redhat.com>
>   Date:   Mon Oct 17 18:56:24 2022 +0200
> 
>     Make sure exported range for SSA post-dominates the DEF in
> set_global_ranges_from_unreachable_edges.
> 
>     The problem here is that we're exporting a range for an SSA range that
>     happens on the other side of a __builtin_unreachable, but the SSA does
>     not post-dominate the definition point.  This is causing ivcanon to
>     unroll things incorrectly.
> 
>     This was a snafu when converting the code from evrp.
> 
>             PR tree-optimization/107293
> 
> Looks plausible?

Yes because that patch fixes the problem from the patch which you had originally bisect the issue down to.

So just closing as a dup of bug 107293.

*** This bug has been marked as a duplicate of bug 107293 ***