"매 control + data dependence를 매 한 그래프로". Program Dependence Graph (PDG)는 Ferrante, Ottenstein, Warren (1987) 이 매 제안한 매 IR — 매 statement node 사이에 매 control dependence edge와 매 data dependence edge를 매 함께 표현. Program slicing, parallelization, change impact analysis의 매 backbone.
매 핵심
매 두 종류 edge
매 Data dependence: 매 statement A가 매 정의한 var를 매 B가 매 사용 → A → B (def-use).
매 Control dependence: 매 A의 매 결과가 매 B의 매 실행 여부를 매 결정 → A → B.
매 Region node: 매 unconditional block 매 그룹화 (선택적).
매 CDG vs DDG vs PDG
CDG: control dependence만 (post-dominator frontier 기반).
Program slicing (Weiser 1981 + Horwitz et al. 1990).
Change impact analysis.
Loop parallelization (data dep 없으면 매 parallel-safe).
Code clone detection (subgraph isomorphism).
Differential testing / fuzzing.
💻 패턴
PDG 구축 sketch (Python AST)
importastfromcollectionsimportdefaultdictclassPDGBuilder(ast.NodeVisitor):def__init__(self):self.defs=defaultdict(list)# var -> [stmt_id]self.data_edges=[]self.ctrl_edges=[]defvisit_Assign(self,node):sid=id(node)forninast.walk(node.value):ifisinstance(n,ast.Name):forprevinself.defs[n.id]:self.data_edges.append((prev,sid))fortgtinnode.targets:ifisinstance(tgt,ast.Name):self.defs[tgt.id].append(sid)self.generic_visit(node)defvisit_If(self,node):sid=id(node)forsinnode.body+node.orelse:self.ctrl_edges.append((sid,id(s)))self.generic_visit(node)
Backward slicing
defbackward_slice(pdg,criterion:int)->set[int]:# criterion = stmt_id; 매 reachable predecessors via data + ctrl edgesreverse=defaultdict(list)foru,vinpdg.data_edges+pdg.ctrl_edges:reverse[v].append(u)seen,stack=set(),[criterion]whilestack:n=stack.pop()ifninseen:continueseen.add(n)stack.extend(reverse[n])returnseen
Loop parallelization check
defis_parallelizable(loop_pdg)->bool:# 매 No loop-carried data dependenceforu,vinloop_pdg.data_edges:ifloop_pdg.iter_distance(u,v)>0:returnFalsereturnTrue
LLVM via opt pass
# LLVM 18+ — print PDG of a function
opt -passes='print<dependence-analysis>' -disable-output input.ll
opt -passes='print<scalar-evolution>' -disable-output input.ll
Tree-sitter + custom analyzer (modern stack)
importtree_sitter_pythonastspfromtree_sitterimportLanguage,ParserLANG=Language(tsp.language())parser=Parser(LANG)tree=parser.parse(b"x = 1\ny = x + 2")# 매 walk tree, 매 build PDG with same edges as above