SPLASH/ISSTA 2026 Tool Demonstrations

FlowLog: Re-thinking Datalog forFast and Extensible Static Analysis

Zhenghong Yu1 Hangdong Zhao2 Wanzhu Hou1 Paraschos Koutris1
1University of Wisconsin–Madison
2Microsoft Gray Systems Lab

ArecursiveDatalogruleA simple Datalog program: Reachability

A declarative logic programming language

Input facts Apply rules Derived facts
R0 Head
:-
R1, R2, …, Rn Body
abcdesource
Reach(y):-Source(y). Reach(y):-Reach(x), Edge(x, y).
Head
Body

Reach = {a}{a, b, c}{a, b, c, d}{a, b, c, d, e}

Challenges in Building Datalog Engines

Building from scratch

  • Fine-grained control over evaluation
  • Datalog-specific optimizations
  • New features require
    invasive changes
  • Incrementality and scale-out
    require major engineering
Soufflé Flix Ascent

Building on an existing engine

  • Reuse mature execution primitives
  • Inherit parallelism or incrementality
  • Datalog-aware optimization
    becomes difficult
  • Runtime costs are dictated
    by the substrate
RecStepDDlog
FlowLog combines both.
Mature Differential Dataflow[1] primitives
Fine-grained, Datalog-aware optimization

[1] McSherry et al. “Differential Dataflow.” CIDR 2013.

FlowLog architecture

FlowLog architecture from the demo paper: a front end with parser and syntax checker; a compiler with stratifier, planner and code generator; a Rust executable; and a back end with input reader, Differential Dataflow runtime and profiler, producing results.

Demo 1 · One-shot mode

Efficient and scalable
static analysis

DOOP · Context-insensitive points-to analysis

ArealDatalogprogram in FlowLog

DOOP* uses Datalog rules to compute points-to information for Java programs. Here we use its context-insensitive analysis.

// Input (EDB) facts extracted from Java bytecode
.decl MainClass(class: string)
.input MainClass
// ... other input relations omitted

// Derived (IDB) relations used by the analysis
.decl Reachable(method: string)
.decl LoadInstanceField(base: string, sig: string, to: string, inmethod: string)
// Variable var may point to object heap
.decl VarPointsTo(heap: string, var: string)
// Field sig of object baseHeap may point to object heap
.decl InstanceFieldPointsTo(heap: string, sig: string, baseHeap: string)// Propagate points-to information through a field load
VarPointsTo(heap, to) :-
  Reachable(inmethod),
  LoadInstanceField(base, sig, to, inmethod),
  VarPointsTo(baseheap, base),
  InstanceFieldPointsTo(heap, sig, baseheap).// Output: variable-to-object points-to information
.output VarPointsTo

Soufflé-style syntax

.decl Relation(...)Declare a relation schema
.input RelationLoad input facts
Head :- Body.Derive tuples with a rule
.output RelationEmit a relation as program output
QR code for the FlowLog port of DOOP FlowLog port of DOOP

*DOOP Framework 101, plast-lab.github.io/doop-pldi15-tutorial/

Run DOOP with FlowLog

OptionDescription
-D <dir>output result directory
-F <dir>input fact directory
-o <path>output binary
-Penable profiling
# Compile the DOOP analysis
$ flowlog context-insensitive.dl -o doop-one-shot -F ./facts -D ./out

# Run in parallel with 32 workers
$ ./doop-one-shot -w 32

FlowLogis faston real analyses

Median runtime speedup over Soufflé 5.9×Polonius 3.9×DOOP
Runtime and peak-memory comparison of FlowLog, Soufflé, DDlog, and Ascent on Polonius Rust borrow-checking and DOOP Java points-to workloads at 32 threads; lower is better.

Figure from the SPLASH/ISSTA 2026 tool-demo paper · 32 threads · log scale · lower is better

FlowLogscaleson real analyses

Speedup as thread count grows for FlowLog, Soufflé, DDlog, and Ascent on Polonius Rust borrow-checking and DOOP Java points-to workloads.

Figure from the SPLASH/ISSTA 2026 tool-demo paper · speedup relative to one thread

Demo 2 · Incremental mode

Maintain analysis results
as inputs change

DOOP · Context-insensitive points-to analysis

Run DOOP in incremental mode

# Compile the same analysis in incremental mode
$ flowlog context-insensitive.dl -o doop-inc -F ./facts -D ./out --mode datalog-inc

# Launch the interactive shell with 32 workers
$ ./doop-inc -w 32
Shell commandPurpose
beginBegin an update round
put <rel> <tuple> <diff>Stage one tuple: +1 inserts, −1 retracts
file <rel> <path> <diff>Stage a fact file: +1 inserts, −1 retracts
commitApply all staged updates together

Update DOOP as input changes

DOOP · Tomcat · Retract one LoadInstanceField fact

Full recomputation ≈ 4.9 s
Incremental update 28.45 ms

≈ 172× faster

Measured on the current demo machine · context-insensitive analysis

Demo 3 · Profiler

Diagnose and fix
performance bottlenecks

DOOP · Context-insensitive points-to analysis

Profiler-guided diagnosis

Revisit the field-load rule with a deliberately poor join order:

VarPointsTo(heap, to) :-
  Reachable(inmethod),
  LoadInstanceField(base, signature, to, inmethod),
  VarPointsTo(baseheap, base),
  InstanceFieldPointsTo(heap, signature, baseheap).
// Pin a poor join order for this demo
.plan (1,3,4,2)
# Enable per-operator profiling with -P
$ flowlog context-insensitive.dl -o doop-prof -F ./facts -D ./out -P
$ ./doop-prof -w 32

Demo 4 · Extended semantics

Extensible recursive
semantics

K-core decomposition · Non-monotonic recursion

Control recursive evaluation

Recursive controls

fixpoint { ... }
Repeat until stable
.iterative R
R may gain or lose tuples across iterations
loop while { @it <= N } { ... }
Bound the number of iterations
loop until { Done } { ... }
Stop when Done becomes non-empty

K-core decomposition k = 3

fixpoint {
  .iterative active_edge
  .iterative degree

  active_edge(x, y) :-
    edge(x, y), !removed(x), !removed(y).
  degree(x, count(y)) :- active_edge(x, y).
  removed(x) :- degree(x, d), d < 3.
}

Repeatedly remove vertices with fewer than 3 neighbors.

Real-world Applications

DOOP integration

In progress with the DOOP team
to support their analyses in FlowLog.

Agent verification

Developing FlowLog support
for agent verification.

…and more.

QR code for preliminary DOOP benchmark results DOOP benchmarksPreliminary results →
FlowLog

Efficient

  • Scalable static analysis
  • Profiler-guided optimization

Extensible

  • Incremental updates
  • Extended recursive semantics

Four Datalog systems in practice

Soufflé 1

Mature one-shot toolchain

B-tree indexes limit join parallelism to the outer loop

Ascent 2

Lightweight, embedded in Rust macros

Features require engineering

Performance needs tuning

DDlog 3

Incremental execution

High memory use from duplicated stateful intermediates

FlowLog

Datalog-aware optimization

Fine-grained join parallelism

Incremental execution & richer semantics

1 https://souffle-lang.github.io/2 https://github.com/s-arash/ascent3 https://github.com/vmware-archive/differential-datalog