[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