leaningtech/cheerp-meta

Another compilation timeout

zyz9740 opened this issue · 4 comments

emi_compile_timeout.zip

We found a case which causes timeout in O2 and O3. You can try to reproduce it.

I do reproduce.

For -O2, the timeout happens inside CFGStackifier::runOpt with this somehow degenerate CFG (note BasicBlock af.i.i):

; Function Attrs: nofree norecurse nounwind
define internal fastcc void @main() unnamed_addr #0 section "asmjs" {
entry:
  store i32* @b, i32** @d, align 4, !tbaa !5
  %0 = load volatile i32**, i32*** undef, align 4, !tbaa !5
  %1 = load i32*, i32** %0, align 4, !tbaa !5
  %2 = bitcast i32* %1 to i64*
  %3 = load i64, i64* %2, align 8
  %4 = load i32, i32* @b, align 4, !tbaa !9
  %cmp1.i.i.i = icmp sgt i32 %4, 0
  %5 = shl i64 %3, 32
  %cmp.i.i.i = icmp sgt i64 %5, 0
  %or.cond.i.i.i = and i1 %cmp.i.i.i, %cmp1.i.i.i
  %conv2.i.i = sext i32 %4 to i64
  %sub.i.i.i = sub nsw i64 9223372036854775807, %conv2.i.i
  %conv1.i.i = ashr exact i64 %5, 32
  %cmp3.i.i.i = icmp slt i64 %sub.i.i.i, %conv1.i.i
  %or.cond10.i.i.i = select i1 %or.cond.i.i.i, i1 %cmp3.i.i.i, i1 false
  br i1 %or.cond10.i.i.i, label %if.then.i.i, label %safe_add_func_int64_t_s_s.exit.i.i

safe_add_func_int64_t_s_s.exit.i.i:               ; preds = %entry
  %6 = and i64 %conv1.i.i, %conv2.i.i
  %7 = icmp slt i64 %6, 0
  %sub8.i.i.i = sub nsw i64 -9223372036854775808, %conv2.i.i
  %cmp9.i.i.i = icmp sgt i64 %sub8.i.i.i, %conv1.i.i
  %or.cond12.i.i.i = select i1 %7, i1 %cmp9.i.i.i, i1 false
  %add.i.i.i = select i1 %or.cond12.i.i.i, i64 0, i64 %conv2.i.i
  %spec.select.i.i.i = sub nsw i64 0, %conv1.i.i
  %tobool.not.i.i = icmp eq i64 %add.i.i.i, %spec.select.i.i.i
  br i1 %tobool.not.i.i, label %af.preheader.i.i, label %if.then.i.i

af.preheader.i.i:                                 ; preds = %safe_add_func_int64_t_s_s.exit.i.i
  %.b = load i1, i1* @g, align 1
  br i1 %.b, label %af.i.i, label %if.end.i.i

if.then.i.i:                                      ; preds = %safe_add_func_int64_t_s_s.exit.i.i, %entry
  store i1 true, i1* @g, align 1
  br label %j.exit

af.i.i:                                           ; preds = %af.preheader.i.i, %af.i.i
  br label %af.i.i

if.end.i.i:                                       ; preds = %af.preheader.i.i
  %8 = load volatile i32**, i32*** @f, align 4, !tbaa !5
  br label %j.exit

j.exit:                                           ; preds = %if.end.i.i, %if.then.i.i
  ret void
}

Thanks for reporting this.

This is indeed due to slightly different handling between clang and clang++ for the mustprogress attribute (and this in turn reflects the fact that such an infinite loop in C++ is UB while in C is valid).

In general /opt/cheerp/bin/clang++ is more seriously tested and the main target for us, and this might not be the only case where we assume that degenerates CFG such as this ones have to be optimized out by a previous compilation stage.

Thanks for the test case, we have a solution, will be merged with the next batch.

Fixed + merged.
Thanks!