[clang] 9824ec8 - [clang][dataflow] Refactor `DataflowWorklist` types and add a WTO version.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 4 16:30:01 PDT 2023
Author: Yitzhak Mandelbaum
Date: 2023-08-04T23:29:08Z
New Revision: 9824ec875cecc533d55c1f11c0c0440520c34464
URL: https://github.com/llvm/llvm-project/commit/9824ec875cecc533d55c1f11c0c0440520c34464
DIFF: https://github.com/llvm/llvm-project/commit/9824ec875cecc533d55c1f11c0c0440520c34464.diff
LOG: [clang][dataflow] Refactor `DataflowWorklist` types and add a WTO version.
Removes dependency of the DataflowWorklistBase type on the PostOrderCFGView. The
base had no particular connection to this order -- looks like it was included as
a convenience to the two derived classes rather than because it belonged there
conceptually. Removing it cleans up the base class a bit and makes it suitable
to extension with the new WTODataflowWorklist class.
Differential Revision: https://reviews.llvm.org/D153071
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
clang/unittests/Analysis/CFGTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h b/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
index e926adf6f0b2a9..f1d05743bf7f12 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowWorklist.h
@@ -12,6 +12,7 @@
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWWORKLIST_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWWORKLIST_H
+#include "clang/Analysis/Analyses/IntervalPartition.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/PriorityQueue.h"
@@ -21,16 +22,13 @@ namespace clang {
/// on the order defined by 'Comp'.
template <typename Comp, unsigned QueueSize> class DataflowWorklistBase {
llvm::BitVector EnqueuedBlocks;
- PostOrderCFGView *POV;
llvm::PriorityQueue<const CFGBlock *,
SmallVector<const CFGBlock *, QueueSize>, Comp>
WorkList;
public:
- DataflowWorklistBase(const CFG &Cfg, PostOrderCFGView *POV, Comp C)
- : EnqueuedBlocks(Cfg.getNumBlockIDs()), POV(POV), WorkList(C) {}
-
- const PostOrderCFGView *getCFGView() const { return POV; }
+ DataflowWorklistBase(const CFG &Cfg, Comp C)
+ : EnqueuedBlocks(Cfg.getNumBlockIDs()), WorkList(C) {}
void enqueueBlock(const CFGBlock *Block) {
if (Block && !EnqueuedBlocks[Block->getBlockID()]) {
@@ -62,7 +60,7 @@ struct ReversePostOrderCompare {
struct ForwardDataflowWorklist
: DataflowWorklistBase<ReversePostOrderCompare, 20> {
ForwardDataflowWorklist(const CFG &Cfg, PostOrderCFGView *POV)
- : DataflowWorklistBase(Cfg, POV,
+ : DataflowWorklistBase(Cfg,
ReversePostOrderCompare{POV->getComparator()}) {}
ForwardDataflowWorklist(const CFG &Cfg, AnalysisDeclContext &Ctx)
@@ -74,6 +72,19 @@ struct ForwardDataflowWorklist
}
};
+/// A worklist implementation for forward dataflow analysis based on a weak
+/// topological ordering of the nodes. The worklist cannot contain the same
+/// block multiple times at once.
+struct WTODataflowWorklist : DataflowWorklistBase<WTOCompare, 20> {
+ WTODataflowWorklist(const CFG &Cfg, const WTOCompare &Cmp)
+ : DataflowWorklistBase(Cfg, Cmp) {}
+
+ void enqueueSuccessors(const CFGBlock *Block) {
+ for (auto B : Block->succs())
+ enqueueBlock(B);
+ }
+};
+
/// A worklist implementation for backward dataflow analysis. The enqueued
/// block will be dequeued in post order. The worklist cannot contain the same
/// block multiple times at once.
@@ -81,8 +92,7 @@ struct BackwardDataflowWorklist
: DataflowWorklistBase<PostOrderCFGView::BlockOrderCompare, 20> {
BackwardDataflowWorklist(const CFG &Cfg, AnalysisDeclContext &Ctx)
: DataflowWorklistBase(
- Cfg, Ctx.getAnalysis<PostOrderCFGView>(),
- Ctx.getAnalysis<PostOrderCFGView>()->getComparator()) {}
+ Cfg, Ctx.getAnalysis<PostOrderCFGView>()->getComparator()) {}
void enqueuePredecessors(const CFGBlock *Block) {
for (auto B : Block->preds())
diff --git a/clang/unittests/Analysis/CFGTest.cpp b/clang/unittests/Analysis/CFGTest.cpp
index 7ce35e3fe4a4f4..9fa034a0e472e9 100644
--- a/clang/unittests/Analysis/CFGTest.cpp
+++ b/clang/unittests/Analysis/CFGTest.cpp
@@ -6,13 +6,15 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/CFG.h"
#include "CFGBuildResult.h"
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/Analyses/IntervalPartition.h"
#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
#include "clang/Tooling/Tooling.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
@@ -244,6 +246,8 @@ TEST(CFG, ElementRefIterator) {
TEST(CFG, Worklists) {
const char *Code = "int f(bool cond) {\n"
" int a = 5;\n"
+ " while (a < 6)\n"
+ " ++a;\n"
" if (cond)\n"
" a += 1;\n"
" return a;\n"
@@ -272,6 +276,30 @@ TEST(CFG, Worklists) {
ForwardNodes.begin()));
}
+ // RPO: 876321054
+ // WTO: 876534210
+ // So, we construct the WTO order accordingly from the reference order.
+ std::vector<const CFGBlock *> WTOOrder = {
+ ReferenceOrder[0], ReferenceOrder[1], ReferenceOrder[2],
+ ReferenceOrder[7], ReferenceOrder[3], ReferenceOrder[8],
+ ReferenceOrder[4], ReferenceOrder[5], ReferenceOrder[6]};
+
+ {
+ using ::testing::ElementsAreArray;
+ std::optional<WeakTopologicalOrdering> WTO = getIntervalWTO(*CFG);
+ ASSERT_TRUE(WTO);
+ WTOCompare WCmp(*WTO);
+ WTODataflowWorklist WTOWorklist(*CFG, WCmp);
+ for (const auto *B : *CFG)
+ WTOWorklist.enqueueBlock(B);
+
+ std::vector<const CFGBlock *> WTONodes;
+ while (const CFGBlock *B = WTOWorklist.dequeue())
+ WTONodes.push_back(B);
+
+ EXPECT_THAT(WTONodes, ElementsAreArray(WTOOrder));
+ }
+
std::reverse(ReferenceOrder.begin(), ReferenceOrder.end());
{
More information about the cfe-commits
mailing list