It appears to be a recent regression. $ clang-trunk -v clang version 14.0.0 (https://github.com/llvm/llvm-project.git 4f5ba46e162eec32a9f9e2a725e6422281913043) $ clang-trunk abc.c ; ./a.out 0 $ clang-trunk -O2 abc.c ; ./a.out $ cat abc.c int a, c, d; char e, f; char(g)(char h, char i) { return i == 0 || h == -128 && i == 1 ? h : h % i; } char k() { int j; d = 3; for (;; d--) for (;;) { short b = g(d, e | d); j = !b + 1; f = (1 == b) * j; c = b; if (d) break; return 1; } } int main() { k(); printf("%X\n", a); }
My bisection points to commit 9934a5b2ed5aa6e6bbb2e55c3cd98839722c226e Author: Jun Ma <JunMa@linux.alibaba.com> Date: Thu Jul 15 18:37:40 2021 +0800 [CVP] processSwitch: Remove default case when switch cover all possible values. Differential Revision: https://reviews.llvm.org/D106056 llvm/include/llvm/Transforms/Utils/Local.h | 5 +++ .../Scalar/CorrelatedValuePropagation.cpp | 27 ++++++++++++++- llvm/lib/Transforms/Utils/Local.cpp | 24 ++++++++++++++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 23 ------------- .../Transforms/CorrelatedValuePropagation/basic.ll | 38 +++++++++++++++++++++- 5 files changed, 92 insertions(+), 25 deletions(-)
https://godbolt.org/z/qn4Enffoc, I can not reproduce. Also this patch only handle switchinst, this testcase has no swtichinst.
(In reply to JunMa from comment #2) > https://godbolt.org/z/qn4Enffoc, I can not reproduce. Also this patch only > handle switchinst, this testcase has no swtichinst. The C source is irrelevant; the IR has a switch, and https://reviews.llvm.org/D106056 appears to be at fault or exposing a bug somewhere else. Here's a reduced test for "opt -correlated-propagation" (it can probably be reduced further): define i8 @src(i8 %t0) { g.exit: %conv3 = or i8 %t0, 3 %rem.rhs.trunc.i = sext i8 %conv3 to i16 %rem16.i = srem i16 3, %rem.rhs.trunc.i %rem.sext.i = trunc i16 %rem16.i to i8 switch i8 %rem.sext.i, label %g.exit.1 [ i8 0, label %g.exit.1 i8 1, label %g.exit.1 ] g.exit.1:; preds = %g.exit, %g.exit, %g.exit %conv3.1 = or i8 %t0, 2 %rem.rhs.trunc.i.1 = sext i8 %conv3.1 to i16 %rem16.i.1 = srem i16 2, %rem.rhs.trunc.i.1 %rem.sext.i.1 = trunc i16 %rem16.i.1 to i8 switch i8 %rem.sext.i.1, label %g.exit.2 [ i8 0, label %g.exit.2 i8 1, label %g.exit.2 ] g.exit.2:; preds = %g.exit.1, %g.exit.1, %g.exit.1 %conv3.2 = or i8 %t0, 1 %rem.rhs.trunc.i.2 = sext i8 %conv3.2 to i16 %rem16.i.2 = srem i16 1, %rem.rhs.trunc.i.2 %rem.sext.i.2 = trunc i16 %rem16.i.2 to i8 switch i8 %rem.sext.i.2, label %.thread.2 [ i8 0, label %.thread.2 i8 1, label %.thread.2 ] .thread.2:; preds = %g.exit.2, %g.exit.2, %g.exit.2 %cmp.i.3 = icmp eq i8 %t0, 0 br i1 %cmp.i.3, label %.thread.3, label %.thread.3 .thread.3:; preds = %.thread.2, %.thread.2 ret i8 0 }
Alive2 appears to confirm that the switch transform is at fault: https://alive2.llvm.org/ce/z/artAVo
I reverted the original patch, so we are not blocking anyone while investigating. Here's a further reduction that seems to make the problem obvious - if the default block is the same as any of the case blocks, we can't make it unreachable? https://alive2.llvm.org/ce/z/ur28cN
I think it's safe to resolve this report. I reverted the offending patch with: https://reviews.llvm.org/rGec54e275f56cc042eb9c25acd And added a minimal test based on this example: https://reviews.llvm.org/rG00a50f2617849d0f374d8771f ...so we should not fail in the same way. There's still an open question about another potential bug discussed in: https://reviews.llvm.org/D106056