mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
fe3275edf3
Summary: There is currently a correctness issue when unrolling loops containing callbr's where their indirect targets are being updated correctly to the newly created labels, but their operands are not. This manifests in unrolled loops where the second and subsequent copies of callbr instructions have blockaddresses of the label from the first instance of the unrolled loop, which would result in nonsensical runtime control flow. For now, conservatively do not unroll the loop. In the future, I think we can pursue unrolling such loops provided we transform the cloned callbr's operands correctly. Such a transform and its legalities are being discussed in: https://reviews.llvm.org/D64101 Link: https://bugs.llvm.org/show_bug.cgi?id=42489 Link: https://groups.google.com/forum/#!topic/clang-built-linux/z-hRWP9KqPI Reviewers: fhahn, hfinkel, efriedma Reviewed By: fhahn, hfinkel, efriedma Subscribers: efriedma, hiraditya, zzheng, dmgreen, llvm-commits, pirama, kees, nathanchance, E5ten, craig.topper, chandlerc, glider, void, srhines Tags: #llvm Differential Revision: https://reviews.llvm.org/D64368 llvm-svn: 366130
67 lines
2.4 KiB
LLVM
67 lines
2.4 KiB
LLVM
; RUN: opt -loop-unswitch %s -S | FileCheck %s
|
|
|
|
; We want to check that the loop does not get split (so only 2 callbr's not 4).
|
|
; It's ok to modify this test in the future should we allow the loop containing
|
|
; callbr to be unswitched and are able to do so correctly.
|
|
|
|
; CHECK: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10))
|
|
; CHECK: to label %7 [label %10]
|
|
; CHECK: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10))
|
|
; CHECK: to label %9 [label %10]
|
|
|
|
; CHECK-NOT: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10))
|
|
; CHECK-NOT: to label %7 [label %10]
|
|
; CHECK-NOT: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10))
|
|
; CHECK-NOT: to label %9 [label %10]
|
|
; CHECK-NOT: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %19))
|
|
; CHECK-NOT: to label %16 [label %19]
|
|
; CHECK-NOT: callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %19))
|
|
; CHECK-NOT: to label %18 [label %19]
|
|
|
|
; This test is essentially:
|
|
; void foo(int n) {
|
|
; for (int i = 0; i < 1000; ++i)
|
|
; if (n) {
|
|
; asm goto("# %l0"::::bar);
|
|
; bar:;
|
|
; } else {
|
|
; asm goto("# %l0"::::baz);
|
|
; baz:;
|
|
; }
|
|
;}
|
|
|
|
define dso_local void @foo(i32) #0 {
|
|
br label %2
|
|
|
|
2: ; preds = %10, %1
|
|
%.0 = phi i32 [ 0, %1 ], [ %11, %10 ]
|
|
%3 = icmp ult i32 %.0, 1000
|
|
br i1 %3, label %4, label %12
|
|
|
|
4: ; preds = %2
|
|
%5 = icmp eq i32 %0, 0
|
|
br i1 %5, label %8, label %6
|
|
|
|
6: ; preds = %4
|
|
callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10)) #0
|
|
to label %7 [label %10]
|
|
|
|
7: ; preds = %6
|
|
br label %10
|
|
|
|
8: ; preds = %4
|
|
callbr void asm sideeffect "# ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %10)) #0
|
|
to label %9 [label %10]
|
|
|
|
9: ; preds = %8
|
|
br label %10
|
|
|
|
10: ; preds = %7, %6, %9, %8
|
|
%11 = add nuw nsw i32 %.0, 1
|
|
br label %2
|
|
|
|
12: ; preds = %2
|
|
ret void
|
|
}
|
|
|