Skip to content

Pragma clang loop unroll(full) and UBSAN causes hangs attempting to unroll INT_MAX+1 times #77842

@modiking

Description

@modiking

Pseudo-code example:

#pragma clang loop unroll(full)
    for (const auto b : std::array<int, 4> arr)
      //some work inside loop

Couldn't quite get a C++ example but the reduced IR repro:

# cat repro.ll
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-redhat-linux-gnu"

define void @foo(i64 %end) {
entry:
  br label %loopheader

loopheader:
  %iv = phi i64 [ 0, %entry ], [ %iv_new, %backedge ]
  %exit = icmp eq i64 %iv, %end
  br i1 %exit, label %for.cond.cleanup.loopexit, label %cont23

for.cond.cleanup.loopexit:                        
  ret void

cont23:                                           
  %exitcond241 = icmp eq i64 %iv, 2147483647
  br i1 %exitcond241, label %handler.add_overflow, label %backedge

handler.add_overflow:                        
  unreachable

backedge: ; preds = %cont23
  %iv_new = add i64 %iv, 1
  br label %loopheader, !llvm.loop !0
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.full"}

# ~/llvm-project/build-rel/bin/opt --version
LLVM (http://llvm.org/):
  LLVM version 18.0.0git
  Optimized build with assertions.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: skylake-avx512
  
# git log
commit 9a2df55f47e4ec02a1efbf8efa776cfeed527df2 (HEAD, origin/main, origin/HEAD)

 # ~/llvm-project/build-rel/bin/opt -passes=loop-unroll -debug-only=loop-unroll repro.ll --disable-output
Loop Unroll: F[foo] Loop %loopheader
  Loop Size = 6
  Exiting block %loopheader: TripCount=0, TripMultiple=
1, BreakoutTrip=1
  Exiting block %cont23: TripCount=2147483648, TripMultiple=0, BreakoutTrip=0
COMPLETELY UNROLLING loop %loopheader with trip count 2147483648!

CFG:
foo

UBSAN introduces an add_overflow handler to the loop. When analyzing for unrolling, every other exit block's Trip Count is unknown but because of the constant compare SCEV identifies the Trip Count as 2147483648 and attempts to unroll as such. This ends up effectively hanging the compiler as it tries to perform the transformation.

Metadata

Metadata

Assignees

Labels

hangCompiler hang (infinite loop)loopoptim

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions