[llvm] 534b924 - [LoopInfo] Allow cloning of callbr
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 19 00:57:36 PDT 2022
Author: Nikita Popov
Date: 2022-07-19T09:57:28+02:00
New Revision: 534b9246a20498e2cd4d2b9a512e7c5e75c83bc7
URL: https://github.com/llvm/llvm-project/commit/534b9246a20498e2cd4d2b9a512e7c5e75c83bc7
DIFF: https://github.com/llvm/llvm-project/commit/534b9246a20498e2cd4d2b9a512e7c5e75c83bc7.diff
LOG: [LoopInfo] Allow cloning of callbr
After D129288, callbr is safe to clone without special handling.
This permits optimizations like loop unroll and loop unswitch on
loops containing callbrs.
Fixes https://github.com/llvm/llvm-project/issues/41834.
Differential Revision: https://reviews.llvm.org/D129993
Added:
Modified:
llvm/lib/Analysis/LoopInfo.cpp
llvm/test/Transforms/LoopUnroll/callbr.ll
llvm/test/Transforms/SimpleLoopUnswitch/callbr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp
index 751005f675d9b..693b9ebd450a8 100644
--- a/llvm/lib/Analysis/LoopInfo.cpp
+++ b/llvm/lib/Analysis/LoopInfo.cpp
@@ -482,11 +482,8 @@ bool Loop::isLoopSimplifyForm() const {
bool Loop::isSafeToClone() const {
// Return false if any loop blocks contain indirectbrs, or there are any calls
// to noduplicate functions.
- // FIXME: it should be ok to clone CallBrInst's if we correctly update the
- // operand list to reflect the newly cloned labels.
for (BasicBlock *BB : this->blocks()) {
- if (isa<IndirectBrInst>(BB->getTerminator()) ||
- isa<CallBrInst>(BB->getTerminator()))
+ if (isa<IndirectBrInst>(BB->getTerminator()))
return false;
for (Instruction &I : *BB)
diff --git a/llvm/test/Transforms/LoopUnroll/callbr.ll b/llvm/test/Transforms/LoopUnroll/callbr.ll
index 723fd36ce16f1..80c4d4c47ad27 100644
--- a/llvm/test/Transforms/LoopUnroll/callbr.ll
+++ b/llvm/test/Transforms/LoopUnroll/callbr.ll
@@ -1,19 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -loop-unroll -S %s | FileCheck %s
-; Check that the loop body does not get unrolled. We could modify this test in
-; the future to support loop unrolling callbr's IFF we checked that the callbr
-; operands were unrolled/updated correctly, as today they are not.
+; Check that the loop body containing callbr is correctly unrolled.
define dso_local void @d() {
; CHECK-LABEL: @d(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
-; CHECK: for.cond.cleanup:
-; CHECK-NEXT: ret void
; CHECK: for.body:
-; CHECK-NEXT: [[E_04:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
-; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[E_04]], 0
-; CHECK-NEXT: br i1 [[TOBOOL]], label [[FOR_INC]], label [[IF_THEN:%.*]]
+; CHECK-NEXT: br i1 true, label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
; CHECK-NEXT: to label [[ASM_FALLTHROUGH:%.*]] [label %l_yes]
@@ -23,9 +17,27 @@ define dso_local void @d() {
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 (...) @g()
; CHECK-NEXT: br label [[FOR_INC]]
; CHECK: for.inc:
-; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[E_04]], 1
-; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3
-; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
+; CHECK-NEXT: br i1 false, label [[FOR_INC_1:%.*]], label [[IF_THEN_1:%.*]]
+; CHECK: if.then.1:
+; CHECK-NEXT: callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
+; CHECK-NEXT: to label [[ASM_FALLTHROUGH_1:%.*]] [label %l_yes.1]
+; CHECK: asm.fallthrough.1:
+; CHECK-NEXT: br label [[L_YES_1:%.*]]
+; CHECK: l_yes.1:
+; CHECK-NEXT: [[CALL_1:%.*]] = tail call i32 (...) @g()
+; CHECK-NEXT: br label [[FOR_INC_1]]
+; CHECK: for.inc.1:
+; CHECK-NEXT: br i1 false, label [[FOR_INC_2:%.*]], label [[IF_THEN_2:%.*]]
+; CHECK: if.then.2:
+; CHECK-NEXT: callbr void asm sideeffect "1: nop\0A\09.quad b, ${0:l}, $$5\0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
+; CHECK-NEXT: to label [[ASM_FALLTHROUGH_2:%.*]] [label %l_yes.2]
+; CHECK: asm.fallthrough.2:
+; CHECK-NEXT: br label [[L_YES_2:%.*]]
+; CHECK: l_yes.2:
+; CHECK-NEXT: [[CALL_2:%.*]] = tail call i32 (...) @g()
+; CHECK-NEXT: br label [[FOR_INC_2]]
+; CHECK: for.inc.2:
+; CHECK-NEXT: ret void
;
entry:
br label %for.body
diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/callbr.ll b/llvm/test/Transforms/SimpleLoopUnswitch/callbr.ll
index baba8eded741b..98bf3edc6b8d5 100644
--- a/llvm/test/Transforms/SimpleLoopUnswitch/callbr.ll
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/callbr.ll
@@ -6,12 +6,20 @@ declare i1 @foo()
define i32 @mem_cgroup_node_nr_lru_pages(i1 %tree) {
; CHECK-LABEL: @mem_cgroup_node_nr_lru_pages(
; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[TREE:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
+; CHECK: entry.split.us:
+; CHECK-NEXT: br label [[FOR_COND_US:%.*]]
+; CHECK: for.cond.us:
+; CHECK-NEXT: br label [[IF_END8_US:%.*]]
+; CHECK: if.end8.us:
+; CHECK-NEXT: br label [[FOR_COND_US]]
+; CHECK: entry.split:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
-; CHECK-NEXT: br i1 [[TREE:%.*]], label [[IF_END8:%.*]], label [[IF_ELSE:%.*]]
+; CHECK-NEXT: br label [[IF_ELSE:%.*]]
; CHECK: if.else:
; CHECK-NEXT: callbr void asm sideeffect ".pushsection __jump_table, \22aw\22 \0A\09.popsection \0A\09", "!i,~{dirflag},~{fpsr},~{flags}"()
-; CHECK-NEXT: to label [[IF_END8]] [label %for.cond5.preheader]
+; CHECK-NEXT: to label [[IF_END8:%.*]] [label %for.cond5.preheader]
; CHECK: for.cond5.preheader:
; CHECK-NEXT: br label [[FOR_COND5:%.*]]
; CHECK: for.cond5:
More information about the llvm-commits
mailing list