2222#include " mlir/Interfaces/ControlFlowInterfaces.h"
2323#include " mlir/Support/LLVM.h"
2424#include " llvm/Support/Casting.h"
25+ #include " llvm/Support/Debug.h"
2526#include < cassert>
2627#include < optional>
2728
29+ #define DEBUG_TYPE " dead-code-analysis"
30+ #define DBGS () (llvm::dbgs() << ' [' << DEBUG_TYPE << " ] " )
31+ #define LDBG (X ) LLVM_DEBUG(DBGS() << X << " \n " )
32+
2833using namespace mlir ;
2934using namespace mlir ::dataflow;
3035
@@ -122,13 +127,15 @@ DeadCodeAnalysis::DeadCodeAnalysis(DataFlowSolver &solver)
122127}
123128
124129LogicalResult DeadCodeAnalysis::initialize (Operation *top) {
130+ LDBG (" Initializing DeadCodeAnalysis for top-level op: " << top->getName ());
125131 // Mark the top-level blocks as executable.
126132 for (Region ®ion : top->getRegions ()) {
127133 if (region.empty ())
128134 continue ;
129135 auto *state =
130136 getOrCreate<Executable>(getProgramPointBefore (®ion.front ()));
131137 propagateIfChanged (state, state->setToLive ());
138+ LDBG (" Marked entry block live for region in op: " << top->getName ());
132139 }
133140
134141 // Mark as overdefined the predecessors of symbol callables with potentially
@@ -139,13 +146,18 @@ LogicalResult DeadCodeAnalysis::initialize(Operation *top) {
139146}
140147
141148void DeadCodeAnalysis::initializeSymbolCallables (Operation *top) {
149+ LDBG (" [init] Entering initializeSymbolCallables for top-level op: "
150+ << top->getName ());
142151 analysisScope = top;
143152 auto walkFn = [&](Operation *symTable, bool allUsesVisible) {
153+ LDBG (" [init] Processing symbol table op: " << symTable->getName ());
144154 Region &symbolTableRegion = symTable->getRegion (0 );
145155 Block *symbolTableBlock = &symbolTableRegion.front ();
146156
147157 bool foundSymbolCallable = false ;
148158 for (auto callable : symbolTableBlock->getOps <CallableOpInterface>()) {
159+ LDBG (" [init] Found CallableOpInterface: "
160+ << callable.getOperation ()->getName ());
149161 Region *callableRegion = callable.getCallableRegion ();
150162 if (!callableRegion)
151163 continue ;
@@ -159,6 +171,8 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
159171 auto *state =
160172 getOrCreate<PredecessorState>(getProgramPointAfter (callable));
161173 propagateIfChanged (state, state->setHasUnknownPredecessors ());
174+ LDBG (" [init] Marked callable as having unknown predecessors: "
175+ << callable.getOperation ()->getName ());
162176 }
163177 foundSymbolCallable = true ;
164178 }
@@ -173,10 +187,15 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
173187 if (!uses) {
174188 // If we couldn't gather the symbol uses, conservatively assume that
175189 // we can't track information for any nested symbols.
190+ LDBG (" [init] Could not gather symbol uses, conservatively marking "
191+ " all nested callables as having unknown predecessors" );
176192 return top->walk ([&](CallableOpInterface callable) {
177193 auto *state =
178194 getOrCreate<PredecessorState>(getProgramPointAfter (callable));
179195 propagateIfChanged (state, state->setHasUnknownPredecessors ());
196+ LDBG (" [init] Marked nested callable as "
197+ " having unknown predecessors: "
198+ << callable.getOperation ()->getName ());
180199 });
181200 }
182201
@@ -190,10 +209,15 @@ void DeadCodeAnalysis::initializeSymbolCallables(Operation *top) {
190209 continue ;
191210 auto *state = getOrCreate<PredecessorState>(getProgramPointAfter (symbol));
192211 propagateIfChanged (state, state->setHasUnknownPredecessors ());
212+ LDBG (" [init] Found non-call use for symbol, "
213+ " marked as having unknown predecessors: "
214+ << symbol->getName ());
193215 }
194216 };
195217 SymbolTable::walkSymbolTables (top, /* allSymUsesVisible=*/ !top->getBlock (),
196218 walkFn);
219+ LDBG (" [init] Finished initializeSymbolCallables for top-level op: "
220+ << top->getName ());
197221}
198222
199223// / Returns true if the operation is a returning terminator in region
@@ -205,9 +229,12 @@ static bool isRegionOrCallableReturn(Operation *op) {
205229}
206230
207231LogicalResult DeadCodeAnalysis::initializeRecursively (Operation *op) {
232+ LDBG (" [init] Entering initializeRecursively for op: " << op->getName ()
233+ << " at " << op);
208234 // Initialize the analysis by visiting every op with control-flow semantics.
209235 if (op->getNumRegions () || op->getNumSuccessors () ||
210236 isRegionOrCallableReturn (op) || isa<CallOpInterface>(op)) {
237+ LDBG (" [init] Visiting op with control-flow semantics: " << *op);
211238 // When the liveness of the parent block changes, make sure to re-invoke the
212239 // analysis on the op.
213240 if (op->getBlock ())
@@ -218,14 +245,22 @@ LogicalResult DeadCodeAnalysis::initializeRecursively(Operation *op) {
218245 return failure ();
219246 }
220247 // Recurse on nested operations.
221- for (Region ®ion : op->getRegions ())
222- for (Operation &op : region.getOps ())
223- if (failed (initializeRecursively (&op)))
248+ for (Region ®ion : op->getRegions ()) {
249+ LDBG (" [init] Recursing into region of op: " << op->getName ());
250+ for (Operation &nestedOp : region.getOps ()) {
251+ LDBG (" [init] Recursing into nested op: " << nestedOp.getName () << " at "
252+ << &nestedOp);
253+ if (failed (initializeRecursively (&nestedOp)))
224254 return failure ();
255+ }
256+ }
257+ LDBG (" [init] Finished initializeRecursively for op: " << op->getName ()
258+ << " at " << op);
225259 return success ();
226260}
227261
228262void DeadCodeAnalysis::markEdgeLive (Block *from, Block *to) {
263+ LDBG (" Marking edge live from block " << from << " to block " << to);
229264 auto *state = getOrCreate<Executable>(getProgramPointBefore (to));
230265 propagateIfChanged (state, state->setToLive ());
231266 auto *edgeState =
@@ -234,37 +269,48 @@ void DeadCodeAnalysis::markEdgeLive(Block *from, Block *to) {
234269}
235270
236271void DeadCodeAnalysis::markEntryBlocksLive (Operation *op) {
272+ LDBG (" Marking entry blocks live for op: " << op->getName ());
237273 for (Region ®ion : op->getRegions ()) {
238274 if (region.empty ())
239275 continue ;
240276 auto *state =
241277 getOrCreate<Executable>(getProgramPointBefore (®ion.front ()));
242278 propagateIfChanged (state, state->setToLive ());
279+ LDBG (" Marked entry block live for region in op: " << op->getName ());
243280 }
244281}
245282
246283LogicalResult DeadCodeAnalysis::visit (ProgramPoint *point) {
284+ LDBG (" Visiting program point: " << point << " " << *point);
247285 if (point->isBlockStart ())
248286 return success ();
249287 Operation *op = point->getPrevOp ();
288+ LDBG (" Visiting operation: " << *op);
250289
251290 // If the parent block is not executable, there is nothing to do.
252291 if (op->getBlock () != nullptr &&
253- !getOrCreate<Executable>(getProgramPointBefore (op->getBlock ()))->isLive ())
292+ !getOrCreate<Executable>(getProgramPointBefore (op->getBlock ()))
293+ ->isLive ()) {
294+ LDBG (" Parent block not live, skipping op: " << *op);
254295 return success ();
296+ }
255297
256298 // We have a live call op. Add this as a live predecessor of the callee.
257- if (auto call = dyn_cast<CallOpInterface>(op))
299+ if (auto call = dyn_cast<CallOpInterface>(op)) {
300+ LDBG (" Visiting call operation: " << *op);
258301 visitCallOperation (call);
302+ }
259303
260304 // Visit the regions.
261305 if (op->getNumRegions ()) {
262306 // Check if we can reason about the region control-flow.
263307 if (auto branch = dyn_cast<RegionBranchOpInterface>(op)) {
308+ LDBG (" Visiting region branch operation: " << *op);
264309 visitRegionBranchOperation (branch);
265310
266311 // Check if this is a callable operation.
267312 } else if (auto callable = dyn_cast<CallableOpInterface>(op)) {
313+ LDBG (" Visiting callable operation: " << *op);
268314 const auto *callsites = getOrCreateFor<PredecessorState>(
269315 getProgramPointAfter (op), getProgramPointAfter (callable));
270316
@@ -276,16 +322,19 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
276322
277323 // Otherwise, conservatively mark all entry blocks as executable.
278324 } else {
325+ LDBG (" Marking all entry blocks live for op: " << *op);
279326 markEntryBlocksLive (op);
280327 }
281328 }
282329
283330 if (isRegionOrCallableReturn (op)) {
284331 if (auto branch = dyn_cast<RegionBranchOpInterface>(op->getParentOp ())) {
332+ LDBG (" Visiting region terminator: " << *op);
285333 // Visit the exiting terminator of a region.
286334 visitRegionTerminator (op, branch);
287335 } else if (auto callable =
288336 dyn_cast<CallableOpInterface>(op->getParentOp ())) {
337+ LDBG (" Visiting callable terminator: " << *op);
289338 // Visit the exiting terminator of a callable.
290339 visitCallableTerminator (op, callable);
291340 }
@@ -294,10 +343,12 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
294343 if (op->getNumSuccessors ()) {
295344 // Check if we can reason about the control-flow.
296345 if (auto branch = dyn_cast<BranchOpInterface>(op)) {
346+ LDBG (" Visiting branch operation: " << *op);
297347 visitBranchOperation (branch);
298348
299349 // Otherwise, conservatively mark all successors as exectuable.
300350 } else {
351+ LDBG (" Marking all successors live for op: " << *op);
301352 for (Block *successor : op->getSuccessors ())
302353 markEdgeLive (op->getBlock (), successor);
303354 }
@@ -307,6 +358,7 @@ LogicalResult DeadCodeAnalysis::visit(ProgramPoint *point) {
307358}
308359
309360void DeadCodeAnalysis::visitCallOperation (CallOpInterface call) {
361+ LDBG (" visitCallOperation: " << call.getOperation ()->getName ());
310362 Operation *callableOp = call.resolveCallableInTable (&symbolTable);
311363
312364 // A call to a externally-defined callable has unknown predecessors.
@@ -329,11 +381,15 @@ void DeadCodeAnalysis::visitCallOperation(CallOpInterface call) {
329381 auto *callsites =
330382 getOrCreate<PredecessorState>(getProgramPointAfter (callableOp));
331383 propagateIfChanged (callsites, callsites->join (call));
384+ LDBG (" Added callsite as predecessor for callable: "
385+ << callableOp->getName ());
332386 } else {
333387 // Mark this call op's predecessors as overdefined.
334388 auto *predecessors =
335389 getOrCreate<PredecessorState>(getProgramPointAfter (call));
336390 propagateIfChanged (predecessors, predecessors->setHasUnknownPredecessors ());
391+ LDBG (" Marked call op's predecessors as unknown for: "
392+ << call.getOperation ()->getName ());
337393 }
338394}
339395
@@ -365,22 +421,26 @@ DeadCodeAnalysis::getOperandValues(Operation *op) {
365421}
366422
367423void DeadCodeAnalysis::visitBranchOperation (BranchOpInterface branch) {
424+ LDBG (" visitBranchOperation: " << branch.getOperation ()->getName ());
368425 // Try to deduce a single successor for the branch.
369426 std::optional<SmallVector<Attribute>> operands = getOperandValues (branch);
370427 if (!operands)
371428 return ;
372429
373430 if (Block *successor = branch.getSuccessorForOperands (*operands)) {
374431 markEdgeLive (branch->getBlock (), successor);
432+ LDBG (" Branch has single successor: " << successor);
375433 } else {
376434 // Otherwise, mark all successors as executable and outgoing edges.
377435 for (Block *successor : branch->getSuccessors ())
378436 markEdgeLive (branch->getBlock (), successor);
437+ LDBG (" Branch has multiple/all successors live" );
379438 }
380439}
381440
382441void DeadCodeAnalysis::visitRegionBranchOperation (
383442 RegionBranchOpInterface branch) {
443+ LDBG (" visitRegionBranchOperation: " << branch.getOperation ()->getName ());
384444 // Try to deduce which regions are executable.
385445 std::optional<SmallVector<Attribute>> operands = getOperandValues (branch);
386446 if (!operands)
@@ -397,16 +457,19 @@ void DeadCodeAnalysis::visitRegionBranchOperation(
397457 // Mark the entry block as executable.
398458 auto *state = getOrCreate<Executable>(point);
399459 propagateIfChanged (state, state->setToLive ());
460+ LDBG (" Marked region successor live: " << point);
400461 // Add the parent op as a predecessor.
401462 auto *predecessors = getOrCreate<PredecessorState>(point);
402463 propagateIfChanged (
403464 predecessors,
404465 predecessors->join (branch, successor.getSuccessorInputs ()));
466+ LDBG (" Added region branch as predecessor for successor: " << point);
405467 }
406468}
407469
408470void DeadCodeAnalysis::visitRegionTerminator (Operation *op,
409471 RegionBranchOpInterface branch) {
472+ LDBG (" visitRegionTerminator: " << *op);
410473 std::optional<SmallVector<Attribute>> operands = getOperandValues (op);
411474 if (!operands)
412475 return ;
@@ -425,6 +488,7 @@ void DeadCodeAnalysis::visitRegionTerminator(Operation *op,
425488 auto *state =
426489 getOrCreate<Executable>(getProgramPointBefore (®ion->front ()));
427490 propagateIfChanged (state, state->setToLive ());
491+ LDBG (" Marked region entry block live for region: " << region);
428492 predecessors = getOrCreate<PredecessorState>(
429493 getProgramPointBefore (®ion->front ()));
430494 } else {
@@ -434,11 +498,14 @@ void DeadCodeAnalysis::visitRegionTerminator(Operation *op,
434498 }
435499 propagateIfChanged (predecessors,
436500 predecessors->join (op, successor.getSuccessorInputs ()));
501+ LDBG (" Added region terminator as predecessor for successor: "
502+ << (successor.getSuccessor () ? " region entry" : " parent op" ));
437503 }
438504}
439505
440506void DeadCodeAnalysis::visitCallableTerminator (Operation *op,
441507 CallableOpInterface callable) {
508+ LDBG (" visitCallableTerminator: " << *op);
442509 // Add as predecessors to all callsites this return op.
443510 auto *callsites = getOrCreateFor<PredecessorState>(
444511 getProgramPointAfter (op), getProgramPointAfter (callable));
@@ -449,11 +516,15 @@ void DeadCodeAnalysis::visitCallableTerminator(Operation *op,
449516 getOrCreate<PredecessorState>(getProgramPointAfter (predecessor));
450517 if (canResolve) {
451518 propagateIfChanged (predecessors, predecessors->join (op));
519+ LDBG (" Added callable terminator as predecessor for callsite: "
520+ << predecessor->getName ());
452521 } else {
453522 // If the terminator is not a return-like, then conservatively assume we
454523 // can't resolve the predecessor.
455524 propagateIfChanged (predecessors,
456525 predecessors->setHasUnknownPredecessors ());
526+ LDBG (" Could not resolve callable terminator for callsite: "
527+ << predecessor->getName ());
457528 }
458529 }
459530}
0 commit comments