[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
This commit is contained in:
Nikita Popov 2022-07-15 12:35:08 +02:00
parent d489b3807f
commit 534b9246a2
3 changed files with 34 additions and 17 deletions

View File

@ -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)

View File

@ -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

View File

@ -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: