[PATCH] D149585: [clang][dataflow] Optimize case of degenerate `do-while` loops.
Yitzhak Mandelbaum via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon May 1 07:11:33 PDT 2023
ymandel created this revision.
ymandel added reviewers: xazax.hun, gribozavr2, sgatev.
Herald added subscribers: martong, rnkovacs.
Herald added a reviewer: NoQ.
Herald added a project: All.
ymandel requested review of this revision.
Herald added a project: clang.
In general, the iteration algorithm would be closer to optimal if it stabilized
loop bodies before visiting their successors. There is a special case of this
situation which is particularly problematic in practice: degenerate loops of the
form `do { ... } while(0)`, which are used in some macro definitions, for
syntactic reasons. When a series of these loops appear in sequence, as in uses
of logging or tracing macro, the resulting iteration can become exponential in
running time.
This patch is a short term fix for the particular degenerate case. Long-term, we
intend to implement an iteration order (like Bourdoncle's WTO) which takes loop
stabilization into account.
Issue #60273.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D149585
Files:
clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
Index: clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -20,6 +20,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/CFG.h"
@@ -34,6 +35,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "clang-dataflow"
@@ -50,6 +52,15 @@
return BlockPos - Pred.succ_begin();
}
+// Detects a degenerate `do-while` loop of the form `do { ... } while(0)`. This
+// form is sometimes used in macro definitions.
+static bool isDegenerateDoWhile(const CFGBlock &B) {
+ if (const auto *D = dyn_cast_or_null<DoStmt>(B.getTerminatorStmt()))
+ if (const auto *Cond = dyn_cast<IntegerLiteral>(D->getCond()))
+ return Cond->getValue().isZero();
+ return false;
+}
+
static bool isLoopHead(const CFGBlock &B) {
if (const auto *T = B.getTerminatorStmt())
switch (T->getStmtClass()) {
@@ -468,7 +479,15 @@
if (Block->hasNoReturnElement())
continue;
- Worklist.enqueueSuccessors(Block);
+ if (isDegenerateDoWhile(*Block) && Block->succ_size() == 2)
+ // Visit the loop body only. Avoid visiting the successor of the loop to
+ // ensure that the body is visited first. Otherwise, the successor will
+ // likely be revisited after the loop body. When a series of these loops
+ // appear in sequence (such as with the use of certain macros), the wasted
+ // work can result in exponential running times.
+ Worklist.enqueueBlock(*Block->succ_begin());
+ else
+ Worklist.enqueueSuccessors(Block);
}
// FIXME: Consider evaluating unreachable basic blocks (those that have a
// state set to `std::nullopt` at this point) to also analyze dead code.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149585.518435.patch
Type: text/x-patch
Size: 2114 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230501/410f795e/attachment.bin>
More information about the cfe-commits
mailing list