[llvm] r355564 - [LoopRotate] fix crash encountered with callbr

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 6 15:04:40 PST 2019


Author: nickdesaulniers
Date: Wed Mar  6 15:04:40 2019
New Revision: 355564

URL: http://llvm.org/viewvc/llvm-project?rev=355564&view=rev
Log:
[LoopRotate] fix crash encountered with callbr

Summary:
While implementing inlining support for callbr
(https://bugs.llvm.org/show_bug.cgi?id=40722), I hit a crash in Loop
Rotation when trying to build the entire x86 Linux kernel
(drivers/char/random.c). This is a small fix up to r353563.

Test case is drivers/char/random.c (with callbr's inlined), then ran
through creduce, then `opt -opt-bisect-limit=<limit>`, then bugpoint.

Thanks to Craig Topper for immediately spotting the fix, and teaching me
how to fish.

Reviewers: craig.topper, jyknight

Reviewed By: craig.topper

Subscribers: hiraditya, llvm-commits, srhines

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D58929

Added:
    llvm/trunk/test/Transforms/LoopRotate/callbr.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp

Modified: llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp?rev=355564&r1=355563&r2=355564&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopRotationUtils.cpp Wed Mar  6 15:04:40 2019
@@ -462,9 +462,8 @@ bool LoopRotate::rotateLoop(Loop *L, boo
     for (BasicBlock *ExitPred : ExitPreds) {
       // We only need to split loop exit edges.
       Loop *PredLoop = LI->getLoopFor(ExitPred);
-      if (!PredLoop || PredLoop->contains(Exit))
-        continue;
-      if (isa<IndirectBrInst>(ExitPred->getTerminator()))
+      if (!PredLoop || PredLoop->contains(Exit) ||
+          ExitPred->getTerminator()->isIndirectTerminator())
         continue;
       SplitLatchEdge |= L->getLoopLatch() == ExitPred;
       BasicBlock *ExitSplit = SplitCriticalEdge(

Added: llvm/trunk/test/Transforms/LoopRotate/callbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopRotate/callbr.ll?rev=355564&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopRotate/callbr.ll (added)
+++ llvm/trunk/test/Transforms/LoopRotate/callbr.ll Wed Mar  6 15:04:40 2019
@@ -0,0 +1,103 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -loop-rotate -o - -verify-loop-info -verify-dom-info | FileCheck %s
+; RUN: opt < %s -S -loop-rotate -o - -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true | FileCheck %s
+
+ at d = external global i64, align 8
+ at f = external global i32, align 4
+ at g = external global i32, align 4
+ at i = external global i32, align 4
+ at h = external global i32, align 4
+
+define i32 @o() #0 {
+; CHECK-LABEL: @o(
+; CHECK-NEXT:    [[TMP1:%.*]] = alloca [1 x i32], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = load i8*, i8** bitcast (i64* @d to i8**), align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* @f, align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[TMP17:%.*]], label [[DOTLR_PH2:%.*]]
+; CHECK:       .lr.ph2:
+; CHECK-NEXT:    br label [[TMP5:%.*]]
+; CHECK:         [[TMP6:%.*]] = phi i32 [ [[TMP3]], [[DOTLR_PH2]] ], [ [[TMP15:%.*]], [[M_EXIT:%.*]] ]
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i32 [[TMP6]], 4
+; CHECK-NEXT:    [[TMP8:%.*]] = zext i1 [[TMP7]] to i32
+; CHECK-NEXT:    store i32 [[TMP8]], i32* @g, align 4
+; CHECK-NEXT:    [[TMP9:%.*]] = bitcast [1 x i32]* [[TMP1]] to i8*
+; CHECK-NEXT:    [[TMP10:%.*]] = call i32 @n(i8* nonnull [[TMP9]], i8* [[TMP2]])
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    br i1 [[TMP11]], label [[THREAD_PRE_SPLIT:%.*]], label [[DOT_CRIT_EDGE:%.*]]
+; CHECK:       thread-pre-split:
+; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, i32* @i, align 4
+; CHECK-NEXT:    [[TMP12:%.*]] = icmp eq i32 [[DOTPR]], 0
+; CHECK-NEXT:    br i1 [[TMP12]], label [[M_EXIT]], label [[DOTLR_PH:%.*]]
+; CHECK:       .lr.ph:
+; CHECK-NEXT:    br label [[TMP13:%.*]]
+; CHECK:         [[DOT11:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP14:%.*]], [[J_EXIT_I:%.*]] ]
+; CHECK-NEXT:    callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, [[M_EXIT]])) #1
+; CHECK-NEXT:    to label [[J_EXIT_I]] [label %m.exit]
+; CHECK:       j.exit.i:
+; CHECK-NEXT:    [[TMP14]] = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
+; CHECK-NEXT:    br i1 [[TMP12]], label [[DOTM_EXIT_CRIT_EDGE:%.*]], label [[TMP13]]
+; CHECK:       .m.exit_crit_edge:
+; CHECK-NEXT:    [[SPLIT:%.*]] = phi i32 [ [[TMP14]], [[J_EXIT_I]] ]
+; CHECK-NEXT:    br label [[M_EXIT]]
+; CHECK:       m.exit:
+; CHECK-NEXT:    [[DOT1_LCSSA:%.*]] = phi i32 [ [[DOT11]], [[TMP13]] ], [ [[SPLIT]], [[DOTM_EXIT_CRIT_EDGE]] ], [ undef, [[THREAD_PRE_SPLIT]] ]
+; CHECK-NEXT:    store i32 [[DOT1_LCSSA]], i32* @h, align 4
+; CHECK-NEXT:    [[TMP15]] = load i32, i32* @f, align 4
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
+; CHECK-NEXT:    br i1 [[TMP16]], label [[DOT_CRIT_EDGE3:%.*]], label [[TMP5]]
+; CHECK:       ._crit_edge:
+; CHECK-NEXT:    br label [[TMP17]]
+; CHECK:       ._crit_edge3:
+; CHECK-NEXT:    br label [[TMP17]]
+; CHECK:         ret i32 undef
+;
+  %1 = alloca [1 x i32], align 4
+  %2 = load i8*, i8** bitcast (i64* @d to i8**), align 8
+  br label %3
+
+; <label>:3:                                      ; preds = %m.exit, %0
+  %4 = load i32, i32* @f, align 4
+  %5 = icmp eq i32 %4, 0
+  br i1 %5, label %16, label %6
+
+; <label>:6:                                      ; preds = %3
+  %7 = icmp ult i32 %4, 4
+  %8 = zext i1 %7 to i32
+  store i32 %8, i32* @g, align 4
+  %9 = bitcast [1 x i32]* %1 to i8*
+  %10 = call i32 @n(i8* nonnull %9, i8* %2)
+  %11 = icmp eq i32 %10, 0
+  br i1 %11, label %thread-pre-split, label %16
+
+thread-pre-split:                                 ; preds = %6
+  %.pr = load i32, i32* @i, align 4
+  br label %12
+
+; <label>:12:                                     ; preds = %j.exit.i, %thread-pre-split
+  %.1 = phi i32 [ %15, %j.exit.i ], [ undef, %thread-pre-split ]
+  %13 = icmp eq i32 %.pr, 0
+  br i1 %13, label %m.exit, label %14
+
+; <label>:14:                                     ; preds = %12
+  callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, %m.exit)) #1
+  to label %j.exit.i [label %m.exit]
+
+j.exit.i:                                         ; preds = %14
+  %15 = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
+  br label %12
+
+m.exit:                                           ; preds = %14, %12
+  %.1.lcssa = phi i32 [ %.1, %14 ], [ %.1, %12 ]
+  store i32 %.1.lcssa, i32* @h, align 4
+  br label %3
+
+; <label>:16:                                     ; preds = %6, %3
+  ret i32 undef
+}
+
+declare i32 @n(i8*, i8*)  #0
+
+attributes #0 = { "use-soft-float"="false" }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readnone }




More information about the llvm-commits mailing list