Functions with cycles are removed for two primary reasons:
* as a simplifying assumption for register allocation which occurs down
the line, and;
* if a function contains cycles post-optimization neither unrolling or
loop vectorization were beneficial, and the function _might_ be
better suited as a helper anyway.
Cycles are detected by iterating over Strongly Connected Components
(SCCs) which imply the existence of cycles if:
- a SCC contains more than one node, or;
- it has a self-edge.
Signed-off-by: Anton Johansson <anjo@rev.ng>
---
.../PrepareForTcgPass/PrepareForTcgPass.cpp | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/subprojects/helper-to-tcg/passes/PrepareForTcgPass/PrepareForTcgPass.cpp b/subprojects/helper-to-tcg/passes/PrepareForTcgPass/PrepareForTcgPass.cpp
index f0ef1abd17..ccbe3820a0 100644
--- a/subprojects/helper-to-tcg/passes/PrepareForTcgPass/PrepareForTcgPass.cpp
+++ b/subprojects/helper-to-tcg/passes/PrepareForTcgPass/PrepareForTcgPass.cpp
@@ -16,10 +16,42 @@
//
#include <PrepareForTcgPass.h>
+#include <llvm/ADT/SCCIterator.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
using namespace llvm;
+static void removeFunctionsWithLoops(Module &M, ModuleAnalysisManager &MAM)
+{
+ // Iterate over all Strongly Connected Components (SCCs), a SCC implies
+ // the existence of loops if:
+ // - it has more than one node, or;
+ // - it has a self-edge.
+ SmallVector<Function *, 16> FunctionsToRemove;
+ for (Function &F : M) {
+ if (F.isDeclaration()) {
+ continue;
+ }
+ for (auto It = scc_begin(&F); !It.isAtEnd(); ++It) {
+#if LLVM_VERSION_MAJOR > 10
+ if (It.hasCycle()) {
+#else
+ if (It.hasLoop()) {
+#endif
+ FunctionsToRemove.push_back(&F);
+ break;
+ }
+ }
+ }
+
+ for (auto *F : FunctionsToRemove) {
+ F->deleteBody();
+ }
+}
+
PreservedAnalyses PrepareForTcgPass::run(Module &M, ModuleAnalysisManager &MAM)
{
+ removeFunctionsWithLoops(M, MAM);
return PreservedAnalyses::none();
}
--
2.45.2