-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[LoopUnroll] Do not copy !llvm.loop from latch to non-latch #165635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
When LoopUnroll copies the original loop's latch to the corresponding non-latch branch in an unrolled iteration, any `!llvm.loop` is copied along with it, but `!llvm.loop` is useless and misleading there. This patch discards it. e06831a did the same for LoopPeel.
|
@llvm/pr-subscribers-llvm-transforms Author: Joel E. Denny (jdenny-ornl) ChangesWhen LoopUnroll copies the original loop's latch to the corresponding non-latch branch in an unrolled iteration, any e06831a did the same for LoopPeel. Full diff: https://github.com/llvm/llvm-project/pull/165635.diff 6 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
index 4fe736ac29b0a..8bbc857715d27 100644
--- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp
@@ -919,6 +919,12 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
Latches[i]->getTerminator()->replaceSuccessorWith(Headers[i], Headers[j]);
}
+ // Remove loop metadata copied from the original loop latch to branches that
+ // are no longer latches.
+ for (unsigned I = 0, E = Latches.size() - (CompletelyUnroll ? 0 : 1); I < E;
+ ++I)
+ Latches[I]->getTerminator()->setMetadata(LLVMContext::MD_loop, nullptr);
+
// Update dominators of blocks we might reach through exits.
// Immediate dominator of such block might change, because we add more
// routes which can lead to the exit: we can now reach it from the copied
diff --git a/llvm/test/Transforms/LoopUnroll/convergent.controlled.ll b/llvm/test/Transforms/LoopUnroll/convergent.controlled.ll
index 6e600d2a659da..5dc613e733f00 100644
--- a/llvm/test/Transforms/LoopUnroll/convergent.controlled.ll
+++ b/llvm/test/Transforms/LoopUnroll/convergent.controlled.ll
@@ -491,41 +491,41 @@ define i32 @unroll_nest(i32 %n, i1 %cond) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[L3:%.*]]
; CHECK: l3:
-; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br label [[L2:%.*]]
; CHECK: l2:
; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ]
-; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2_1:%.*]], label [[LATCH:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2_1:%.*]], label [[LATCH:%.*]]
; CHECK: l2.1:
; CHECK-NEXT: [[TOK_L2_1:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ]
; CHECK-NEXT: br i1 [[COND]], label [[L2]], label [[LATCH]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK: latch:
-; CHECK-NEXT: br label [[L2_12:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br label [[L2_12:%.*]]
; CHECK: l2.12:
; CHECK-NEXT: [[TOK_L2_11:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_11]]) ]
-; CHECK-NEXT: br i1 [[COND]], label [[L2_1_1:%.*]], label [[LATCH_1:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br i1 [[COND]], label [[L2_1_1:%.*]], label [[LATCH_1:%.*]]
; CHECK: l2.1.1:
; CHECK-NEXT: [[TOK_L2_1_1:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_1]]) ]
; CHECK-NEXT: br i1 [[COND]], label [[L2_12]], label [[LATCH_1]], !llvm.loop [[LOOP9]]
; CHECK: latch.1:
-; CHECK-NEXT: br label [[L2_2:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br label [[L2_2:%.*]]
; CHECK: l2.2:
; CHECK-NEXT: [[TOK_L2_2:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ]
-; CHECK-NEXT: br i1 [[COND]], label [[L2_1_2:%.*]], label [[LATCH_2:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br i1 [[COND]], label [[L2_1_2:%.*]], label [[LATCH_2:%.*]]
; CHECK: l2.1.2:
; CHECK-NEXT: [[TOK_L2_1_2:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_2]]) ]
; CHECK-NEXT: br i1 [[COND]], label [[L2_2]], label [[LATCH_2]], !llvm.loop [[LOOP9]]
; CHECK: latch.2:
-; CHECK-NEXT: br label [[L2_3:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br label [[L2_3:%.*]]
; CHECK: l2.3:
; CHECK-NEXT: [[TOK_L2_3:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ]
-; CHECK-NEXT: br i1 [[COND]], label [[L2_1_3:%.*]], label [[LATCH_3:%.*]], !llvm.loop [[LOOP4]]
+; CHECK-NEXT: br i1 [[COND]], label [[L2_1_3:%.*]], label [[LATCH_3:%.*]]
; CHECK: l2.1.3:
; CHECK-NEXT: [[TOK_L2_1_3:%.*]] = call token @llvm.experimental.convergence.anchor()
; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_3]]) ]
@@ -541,7 +541,7 @@ l3:
%tok.loop = call token @llvm.experimental.convergence.anchor()
%inc = add nsw i32 %x.0, 1
%exitcond = icmp eq i32 %inc, 4
- br label %l2, !llvm.loop !1
+ br label %l2
l2:
%tok.l2 = call token @llvm.experimental.convergence.anchor()
diff --git a/llvm/test/Transforms/LoopUnroll/followup.ll b/llvm/test/Transforms/LoopUnroll/followup.ll
index 051e43d52b3be..b6561781d29ca 100644
--- a/llvm/test/Transforms/LoopUnroll/followup.ll
+++ b/llvm/test/Transforms/LoopUnroll/followup.ll
@@ -36,11 +36,11 @@ for.end: ; preds = %for.body, %entry
; COMMON-LABEL: @test(
-; COUNT: br i1 %exitcond.1, label %for.end.loopexit, label %for.body, !llvm.loop ![[LOOP:[0-9]+]]
+; COUNT: br i1 %exitcond.1, label %for.end.loopexit, label %for.body, !llvm.loop ![[#LOOP:]]
-; COUNT: ![[FOLLOWUP_ALL:[0-9]+]] = !{!"FollowupAll"}
-; COUNT: ![[FOLLOWUP_UNROLLED:[0-9]+]] = !{!"FollowupUnrolled"}
-; COUNT: ![[LOOP]] = distinct !{![[LOOP]], ![[FOLLOWUP_ALL]], ![[FOLLOWUP_UNROLLED]]}
+; COUNT: ![[#LOOP]] = distinct !{![[#LOOP]], ![[#FOLLOWUP_ALL:]], ![[#FOLLOWUP_UNROLLED:]]}
+; COUNT: ![[#FOLLOWUP_ALL]] = !{!"FollowupAll"}
+; COUNT: ![[#FOLLOWUP_UNROLLED]] = !{!"FollowupUnrolled"}
; EPILOG: br i1 %niter.ncmp.7, label %for.end.loopexit.unr-lcssa, label %for.body, !llvm.loop ![[LOOP_0:[0-9]+]]
diff --git a/llvm/test/Transforms/LoopUnroll/pr131465.ll b/llvm/test/Transforms/LoopUnroll/pr131465.ll
index 643b020c6c110..60bea6a4d9043 100644
--- a/llvm/test/Transforms/LoopUnroll/pr131465.ll
+++ b/llvm/test/Transforms/LoopUnroll/pr131465.ll
@@ -11,11 +11,11 @@ define i32 @pr131465(i1 %x) mustprogress {
; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ 2, %[[ENTRY]] ], [ [[NEXT_1:%.*]], %[[FOR_BODY_1:.*]] ]
; CHECK-NEXT: [[NEXT:%.*]] = add nsw i32 [[INDVAR]], [[INC]]
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[NEXT]], 2
-; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_END:.*]], label %[[FOR_BODY_1]], !llvm.loop [[LOOP0:![0-9]+]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_END:.*]], label %[[FOR_BODY_1]]
; CHECK: [[FOR_BODY_1]]:
; CHECK-NEXT: [[NEXT_1]] = add nsw i32 [[NEXT]], [[INC]]
; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[NEXT_1]], 2
-; CHECK-NEXT: br i1 [[EXITCOND_1]], label %[[FOR_END]], label %[[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
+; CHECK-NEXT: br i1 [[EXITCOND_1]], label %[[FOR_END]], label %[[FOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: [[FOR_END]]:
; CHECK-NEXT: ret i32 0
;
@@ -37,7 +37,5 @@ for.end:
!0 = !{!0, !{!"llvm.loop.unroll.count", i32 2}}
;.
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]]}
-; CHECK: [[META1]] = !{!"llvm.loop.unroll.count", i32 2}
-; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
-; CHECK: [[META3]] = !{!"llvm.loop.unroll.disable"}
+; CHECK: [[META1]] = !{!"llvm.loop.unroll.disable"}
;.
diff --git a/llvm/test/Transforms/LoopUnroll/unroll-dont-copy-latch-loop-id.ll b/llvm/test/Transforms/LoopUnroll/unroll-dont-copy-latch-loop-id.ll
new file mode 100644
index 0000000000000..191ebb023b7c1
--- /dev/null
+++ b/llvm/test/Transforms/LoopUnroll/unroll-dont-copy-latch-loop-id.ll
@@ -0,0 +1,90 @@
+; Check that !llvm.loop is not copied from the original loop's latch to the
+; corresponding non-latch branch in any unrolled iteration.
+
+; The -implicit-check-not options make sure that no additional label or
+; !llvm.loop shows up.
+; DEFINE: %{unroll} = opt < %s -passes=loop-unroll -S
+; DEFINE: %{fc} = FileCheck %s \
+; DEFINE: -implicit-check-not='{{^[^ ;]*:}}' \
+; DEFINE: -implicit-check-not='!llvm.loop' \
+; DEFINE: -check-prefixes
+
+; Check partial unroll: only the unrolled loop's latch has !llvm.loop.
+; RUN: %{unroll} -unroll-count=3 | %{fc} ALL,UR,UR3
+
+; Check complete unroll: no !llvm.loop remains because no loop remains.
+; RUN: %{unroll} -unroll-count=4 | %{fc} ALL,UR,UR4
+
+; Check remainder: both loops have a !llvm.loop.
+; DEFINE: %{rt} = %{unroll} -unroll-count=3 -unroll-runtime
+; RUN: %{rt} -unroll-runtime-epilog=true | %{fc} ALL,RT,EPILOG
+; RUN: %{rt} -unroll-runtime-epilog=false | %{fc} ALL,RT,PROLOG
+
+; ALL: define void @test(i32 %n) {
+; ALL: entry:
+; UR: br label %body
+; EPILOG: br i1 %{{.*}}, label %body.epil.preheader, label %entry.new
+; PROLOG: br i1 %{{.*}}, label %body.prol.preheader, label %body.prol.loopexit
+; PROLOG: body.prol.preheader:
+; PROLOG: br label %body.prol
+; PROLOG: body.prol:
+; PROLOG: br i1 %{{.*}}, label %body.prol, label %body.prol.loopexit.unr-lcssa, !llvm.loop !0
+; PROLOG: body.prol.loopexit.unr-lcssa:
+; PROLOG: br label %body.prol.loopexit
+; PROLOG: body.prol.loopexit:
+; PROLOG: br i1 %{{.*}}, label %exit, label %entry.new
+; RT: entry.new:
+; RT: br label %body
+; ALL: body:
+; UR: br i1 %c, label %body.1, label %exit
+; EPILOG: br i1 %{{.*}}, label %body, label %exit.unr-lcssa, !llvm.loop !0
+; PROLOG: br i1 %{{.*}}, label %body, label %exit.unr-lcssa, !llvm.loop !2
+; UR: body.1:
+; UR: br i1 %c.1, label %body.2, label %exit
+; UR: body.2:
+; UR3: br i1 %c.2, label %body, label %exit, !llvm.loop !0
+; UR4: br i1 %c.2, label %body.3, label %exit
+; UR4: body.3:
+; UR4: br label %exit
+; RT: exit.unr-lcssa:
+; EPILOG: br i1 {{.*}}, label %body.epil.preheader, label %exit
+; PROLOG: br label %exit
+; EPILOG: body.epil.preheader:
+; EPILOG: br label %body.epil
+; EPILOG: body.epil:
+; EPILOG: br i1 {{.*}}, label %body.epil, label %exit.epilog-lcssa, !llvm.loop !3
+; EPILOG: exit.epilog-lcssa:
+; EPILOG: br label %exit
+; ALL: exit:
+; ALL: ret void
+; ALL: }
+define void @test(i32 %n) {
+entry:
+ %max = call i32 @llvm.umin.i32(i32 %n, i32 3)
+ br label %body
+
+body:
+ %i = phi i32 [ 0, %entry ], [ %inc, %body ]
+ %inc = add i32 %i, 1
+ %c = icmp ult i32 %i, %max
+ br i1 %c, label %body, label %exit, !llvm.loop !0
+
+exit:
+ ret void
+}
+
+; UR3: !0 = distinct !{!0, !1, !2}
+; UR3: !1 = !{!"copied"}
+; UR3: !2 = !{!"llvm.loop.unroll.disable"}
+;
+; EPILOG: !0 = distinct !{!0, !1, !2}
+; EPILOG: !1 = !{!"copied"}
+; EPILOG: !2 = !{!"llvm.loop.unroll.disable"}
+; EPILOG: !3 = distinct !{!3, !2}
+;
+; PROLOG: !0 = distinct !{!0, !1}
+; PROLOG: !1 = !{!"llvm.loop.unroll.disable"}
+; PROLOG: !2 = distinct !{!2, !3, !1}
+; PROLOG: !3 = !{!"copied"}
+!0 = distinct !{!0, !1}
+!1 = !{!"copied"}
diff --git a/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll b/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
index f85aac75539c6..77dd3429b684e 100644
--- a/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
+++ b/llvm/test/Transforms/LoopUnroll/unroll-loads-cse.ll
@@ -419,7 +419,7 @@ define void @loop_body_with_dead_blocks(ptr %src) {
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: [[L_2:%.*]] = load i32, ptr [[SRC]], align 8
; CHECK-NEXT: [[C_2:%.*]] = icmp eq i32 [[L_2]], 1
-; CHECK-NEXT: br i1 [[C_2]], label [[EXIT:%.*]], label [[LOOP_HEADER_1:%.*]], !llvm.loop [[LOOP7:![0-9]+]]
+; CHECK-NEXT: br i1 [[C_2]], label [[EXIT:%.*]], label [[LOOP_HEADER_1:%.*]]
; CHECK: loop.header.1:
; CHECK-NEXT: br label [[LOOP_BB_1:%.*]]
; CHECK: loop.bb.1:
@@ -429,7 +429,7 @@ define void @loop_body_with_dead_blocks(ptr %src) {
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: [[L_2_1:%.*]] = load i32, ptr [[SRC]], align 8
; CHECK-NEXT: [[C_2_1:%.*]] = icmp eq i32 [[L_2_1]], 1
-; CHECK-NEXT: br i1 [[C_2_1]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP9:![0-9]+]]
+; CHECK-NEXT: br i1 [[C_2_1]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP7:![0-9]+]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -471,7 +471,5 @@ exit:
; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]], [[META2]]}
; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]]}
-; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]], [[META8:![0-9]+]]}
-; CHECK: [[META8]] = !{!"llvm.loop.unroll.count", i32 2}
-; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META1]], [[META2]]}
+; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META1]], [[META2]]}
;.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like the kind of test that is going to really piss me off if I ever have to update it. Either de-magic and reduce the scope of this test, or add a UTC flag that adds {{$}} to the end of lines so absence of metadata can be verified.
When LoopUnroll copies the original loop's latch to the corresponding non-latch branch in an unrolled iteration, any
!llvm.loopis copied along with it, but!llvm.loopis useless and misleading there. This patch discards it.e06831a did the same for LoopPeel.