llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.24k stars 11.66k forks source link

[SimplifyCFG] Hang/Assertion `IterCnt++ < 1000 && "Sanity: iterative simplification didn't converge!"' failed. #51632

Open llvmbot opened 2 years ago

llvmbot commented 2 years ago
Bugzilla Link 52290
Version trunk
OS Windows NT
Reporter LLVM Bugzilla Contributor
CC @dbakunevich

Extended Description

To reproduce: run "opt -simplifycfg -S" on the following test

; RUN: opt < %s -simplifycfg -S | FileCheck %s
; RUN: opt < %s -passes=simplifycfg -S | FileCheck %s

; FIXME: Fails due to infinite loop in iterativelySimplifyCFG.

define i32 @&#8203;test(float %arg) gc "statepoint-example" personality i32* ()* @&#8203;blam {
bb:
  %tmp = call i1 @&#8203;llvm.experimental.widenable.condition()
  br i1 %tmp, label %bb2, label %bb1

bb1:                                              ; preds = %bb
  br i1 undef, label %bb7, label %bb5

bb2:                                              ; preds = %bb
  %tmp3 = getelementptr inbounds i8, i8 addrspace(1)* undef, i64 16
  br i1 undef, label %bb6, label %bb4

bb4:                                              ; preds = %bb2
  call void @&#8203;snork() [ "deopt"() ]
  unreachable

bb5:                                              ; preds = %bb1
  ret i32 0

bb6:                                              ; preds = %bb2
  br label %bb7

bb7:                                              ; preds = %bb6, %bb1
  %tmp8 = call i32 (...) @&#8203;llvm.experimental.deoptimize.i32(i32 10) [ "deopt"() ]
  ret i32 %tmp8
}

declare i32* @&#8203;blam()

declare void @&#8203;snork()

declare i32 @&#8203;llvm.experimental.deoptimize.i32(...)

; Function Attrs: inaccessiblememonly nofree nosync nounwind speculatable willreturn
declare i1 @&#8203;llvm.experimental.widenable.condition() #&#8203;0

attributes #&#8203;0 = { inaccessiblememonly nofree nosync nounwind speculatable willreturn }

Originally result was hang (and it's same in product). I've added a sanity assert and it now is failing. It happens due to infinite execution of iterativelySimplifyCFG. The IR does not change between iterations, so maybe two transforms are undoing one another.

llvmbot commented 2 years ago

This one should be the fix: https://reviews.llvm.org/D112693

llvmbot commented 2 years ago

UPD: indeed, Phi appears there after it's created by

// Otherwise, if there are multiple predecessors, insert a PHI that merges
// in the constant and simplify the block result.  Subsequent passes of
// simplifycfg will thread the block.
if (BlockIsSimpleEnoughToThreadThrough(BB)) {

Looks like this one and the following one "tryWidenCondBranchToCondBranch" keep undoing one another.

llvmbot commented 2 years ago

I'm certain that FoldCondBranchOnPHI has nothing to do with this bug, at least because this test has no phis.

llvmbot commented 2 years ago

Dima, I am confused. What test are you referring?

dbakunevich commented 2 years ago

More information from my researc

dbakunevich commented 2 years ago

Summary: we removed one BB and after 1 iteration we created it.

dbakunevich commented 2 years ago

Investigated this bug and found out that there is a looping of the form: 1-st Iteration:

br i1 undef, label %zero.critedge, label %bci_89.us589.preheader.split ---> br i1 undef, label %zero, label %bci_89.us589.preheader.split

zero.critedge:  ---> remove
br label %zero

zero:    ; preds = %zero.critedge, %bci_89.us   --->    zero:    ; preds = %"static void FuzzerUtils.init(jobject, jfloat)541743.exit.split", %bci_89.us

2-nd Iteration:

bci_89.us:    ; preds = %"static jobject java.lang.invoke.Invokers$Holder.linkToTargetMethod(jobject)587833.exit" ---> bci_89.us:    ; preds = %"static void FuzzerUtils.init(jobject, jfloat)541743.exit.split", %"static jobject java.lang.invoke.Invokers$Holder.linkToTargetMethod(jobject)587833.exit"

br i1 undef, label %zero, label %bci_89.us589.preheader.split ---> br i1 undef, label %bci_89.us, label %bci_89.us589.preheader.split

zero:    ; preds = %"static void FuzzerUtils.init(jobject, jfloat)541743.exit.split", %bci_89.us ---> zero:    ; preds = %bci_89.us

3-d Iteration:

bci_89.us:    ; preds = %"static void FuzzerUtils.init(jobject, jfloat)541743.exit.split", %"static jobject java.lang.invoke.Invokers$Holder.linkToTargetMethod(jobject)587833.exit" ---> bci_89.us:    ; preds = %"static jobject java.lang.invoke.Invokers$Holder.linkToTargetMethod(jobject)587833.exit"

br i1 undef, label %bci_89.us, label %bci_89.us589.preheader.split ---> br i1 undef, label %zero.critedge, label %bci_89.us589.preheader.split

create new BB --->  zero.critedge:                                    ; preds = %"static void FuzzerUtils.init(jobject, jfloat)541743.exit.split"
                    br label %zero

zero:    ; preds = %bci_89.us ---> zero:    ; preds = %zero.critedge, %bci_89.us
JonPsson commented 2 years ago

testcase.tar.gz

clang -cc1 -triple s390x-ibm-linux -S -target-cpu arch13 -O3 -w -o /dev/null -x ir tc_crash2_aftercreduce.ll -mllvm -disable-licm-promotion -mllvm -unroll-allow-remainder=false -mllvm -unroll-count=4

_lib/Transforms/Scalar/SimplifyCFGPass.cpp:238: bool iterativelySimplifyCFG(llvm::Function&, const llvm::TargetTransformInfo&, llvm::DomTreeUpdater*, const llvm::SimplifyCFGOptions&): Assertion `IterCnt++ < 1000 && "Iterative simplification didn't converge!"' failed.