diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -2910,6 +2910,10 @@ if (L.getHeader()->getParent()->hasOptSize()) return false; + // Skip non-trivial unswitching for loops that cannot be cloned. + if (!L.isSafeToClone()) + return false; + // For non-trivial unswitching, because it often creates new loops, we rely on // the pass manager to iterate on the loops rather than trying to immediately // reach a fixed point. There is no substantial advantage to iterating diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll b/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimpleLoopUnswitch/not-safe-to-clone.ll @@ -0,0 +1,27 @@ +; RUN: opt -passes='unswitch' %s -S | FileCheck %s + +declare i1 @foo() + +; CHECK: define {{.*}} @mem_cgroup_node_nr_lru_pages +define i32 @mem_cgroup_node_nr_lru_pages(i1 %tree) { +entry: + br label %for.cond + +for.cond: ; preds = %if.end8, %entry + br i1 %tree, label %if.end8, label %if.else + +if.else: ; preds = %for.cond + callbr void asm sideeffect ".pushsection __jump_table, \22aw\22 \0A\09.popsection \0A\09", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@mem_cgroup_node_nr_lru_pages, %for.cond5)) + to label %if.end8 [label %for.cond5] + +for.cond5: ; preds = %if.else, %for.cond5 + %call6 = call i1 @foo() + br i1 %call6, label %if.end8.loopexit, label %for.cond5 + +if.end8.loopexit: ; preds = %for.cond5 + br label %if.end8 + +if.end8: ; preds = %if.end8.loopexit, %if.else, %for.cond + br label %for.cond +} +