Callbr is no longer an indirect terminator in the sense that is relevant here (that it's successors cannot be updated). The primary effect of this change is that callbr no longer prevents formation of loop simplify form. I decided to drop the isIndirectTerminator() method entirely and replace it with isa<IndirectBrInst>() checks. I assume this method was added to abstract over indirectbr and callbr, but it never really caught on, and there is nothing left to abstract anymore at this point. Differential Revision: https://reviews.llvm.org/D129849
109 lines
4.6 KiB
LLVM
109 lines
4.6 KiB
LLVM
; 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
|
|
|
|
@d = external global i64, align 8
|
|
@f = external global i32, align 4
|
|
@g = external global i32, align 4
|
|
@i = external global i32, align 4
|
|
@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_PH4:%.*]]
|
|
; CHECK: .lr.ph4:
|
|
; CHECK-NEXT: br label [[TMP5:%.*]]
|
|
; CHECK: 5:
|
|
; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP3]], [[DOTLR_PH4]] ], [ [[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: 13:
|
|
; CHECK-NEXT: [[DOT11:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP14:%.*]], [[J_EXIT_I:%.*]] ]
|
|
; CHECK-NEXT: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
|
|
; CHECK-NEXT: to label [[J_EXIT_I]] [label %.m.exit_crit_edge]
|
|
; CHECK: j.exit.i:
|
|
; CHECK-NEXT: [[TMP14]] = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #[[ATTR2:[0-9]+]]
|
|
; CHECK-NEXT: br i1 [[TMP12]], label [[DOTM_EXIT_CRIT_EDGE2:%.*]], label [[TMP13]]
|
|
; CHECK: .m.exit_crit_edge:
|
|
; CHECK-NEXT: [[SPLIT:%.*]] = phi i32 [ [[DOT11]], [[TMP13]] ]
|
|
; CHECK-NEXT: br label [[M_EXIT]]
|
|
; CHECK: .m.exit_crit_edge2:
|
|
; CHECK-NEXT: [[SPLIT3:%.*]] = phi i32 [ [[TMP14]], [[J_EXIT_I]] ]
|
|
; CHECK-NEXT: br label [[M_EXIT]]
|
|
; CHECK: m.exit:
|
|
; CHECK-NEXT: [[DOT1_LCSSA:%.*]] = phi i32 [ [[SPLIT]], [[DOTM_EXIT_CRIT_EDGE:%.*]] ], [ [[SPLIT3]], [[DOTM_EXIT_CRIT_EDGE2]] ], [ 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_EDGE5:%.*]], label [[TMP5]]
|
|
; CHECK: ._crit_edge:
|
|
; CHECK-NEXT: br label [[TMP17]]
|
|
; CHECK: ._crit_edge5:
|
|
; CHECK-NEXT: br label [[TMP17]]
|
|
; CHECK: 17:
|
|
; CHECK-NEXT: 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 "", "!i,~{dirflag},~{fpsr},~{flags}"() #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 }
|