-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Closed
Labels
Description
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!
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.