llvm.org GIT mirror llvm / 05485d7
[PostDom] document the current handling of infinite loops and unreachables Summary: As we are in the process of changing the behavior of how the post-dominator tree is computed, make sure we have some more test coverage in this area. Current inconsistencies: - Newly unreachable nodes are not added as new roots, in case the PDT is updated but not rebuilt. - Newly unreachable loops are not added to the CFG at all (neither when building from scratch nor when updating the CFG). This is inconsistent with the fact that unreachables are added to the PDT, but unreachable loops not. On the other side, PDT relationships are not loosened at the moment in cases where new unreachable loops are built. This commit is providing additional test coverage for https://reviews.llvm.org/D35851 Reviewers: dberlin, kuhar Reviewed By: kuhar Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D36107 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309684 91177308-0d34-0410-b5e6-96231b3b80d8 Tobias Grosser 2 years ago
1 changed file(s) with 268 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
325325 });
326326 }
327327
328 // Verify that the PDT is correctly updated in case an edge removal results
329 // in a new unreachable CFG node.
330 //
331 // For the following input code and initial PDT:
332 //
333 // CFG PDT
334 //
335 // A Exit
336 // | |
337 // _B D
338 // / | \ |
339 // ^ v \ B
340 // \ / D / \
341 // C \ C A
342 // v
343 // Exit
344 //
345 // we verify that CFG' and PDT-updated is obtained after removal of edge C -> B.
346 //
347 // CFG' PDT-updated
348 //
349 // A Exit
350 // | |
351 // B D
352 // | \ |
353 // v \ B
354 // / D \
355 // C \ A
356 // | v
357 // unreachable Exit
358 //
359 // WARNING: PDT-updated is inconsistent with PDT-recalculated, which is
360 // constructed from CFG' when recalculating the PDT from scratch.
361 //
362 // PDT-recalculated
363 //
364 // Exit
365 // / | \
366 // C B D
367 // |
368 // A
369 //
370 // TODO: document the wanted behavior after resolving this inconsistency.
371 TEST(DominatorTree, DeletingEdgesIntroducesUnreachables) {
372 StringRef ModuleString =
373 "define void @f() {\n"
374 "A:\n"
375 " br label %B\n"
376 "B:\n"
377 " br i1 undef, label %D, label %C\n"
378 "C:\n"
379 " br label %B\n"
380 "D:\n"
381 " ret void\n"
382 "}\n";
383
384 // Parse the module.
385 LLVMContext Context;
386 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
387
388 runWithDomTree(
389 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
390 Function::iterator FI = F.begin();
391
392 FI++;
393 BasicBlock *B = &*FI++;
394 BasicBlock *C = &*FI++;
395 BasicBlock *D = &*FI++;
396
397 assert(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
398
399 C->getTerminator()->eraseFromParent();
400 new UnreachableInst(C->getContext(), C);
401
402 DT->deleteEdge(C, B);
403 PDT->deleteEdge(C, B);
404
405 EXPECT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
406 EXPECT_EQ(PDT->getNode(C), nullptr);
407
408 PDT->recalculate(F);
409
410 EXPECT_FALSE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
411 EXPECT_NE(PDT->getNode(C), nullptr);
412 });
413 }
414
415 // Verify that the PDT is correctly updated in case an edge removal results
416 // in an infinite loop.
417 //
418 // Test case:
419 //
420 // CFG PDT
421 //
422 // A Exit
423 // | |
424 // _B D
425 // / | \ |
426 // ^ v \ B
427 // \ / D / \
428 // C \ C A
429 // / \ v
430 // ^ v Exit
431 // \_/
432 //
433 // After deleting the edge C->B, C is part of an infinite reverse-unreachable
434 // loop:
435 //
436 // CFG' PDT'
437 //
438 // A Exit
439 // | |
440 // B D
441 // | \ |
442 // v \ B
443 // / D \
444 // C \ A
445 // / \ v
446 // ^ v Exit
447 // \_/
448 //
449 // In PDT, D post-dominates B. We verify that this post-dominance
450 // relation is preserved _after_ deleting the edge C->B from CFG.
451 //
452 // As C now becomes reverse-unreachable, it is not anymore part of the
453 // PDT. We also verify this property.
454 //
455 // TODO: Can we change the PDT definition such that C remains part of the
456 // CFG, at best without loosing the dominance relation D postdom B.
457 TEST(DominatorTree, DeletingEdgesIntroducesInfiniteLoop) {
458 StringRef ModuleString =
459 "define void @f() {\n"
460 "A:\n"
461 " br label %B\n"
462 "B:\n"
463 " br i1 undef, label %D, label %C\n"
464 "C:\n"
465 " switch i32 undef, label %C [\n"
466 " i32 0, label %B\n"
467 " ]\n"
468 "D:\n"
469 " ret void\n"
470 "}\n";
471
472 // Parse the module.
473 LLVMContext Context;
474 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
475
476 runWithDomTree(
477 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
478 Function::iterator FI = F.begin();
479
480 FI++;
481 BasicBlock *B = &*FI++;
482 BasicBlock *C = &*FI++;
483 BasicBlock *D = &*FI++;
484
485 assert(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
486
487 auto SwitchC = cast(C->getTerminator());
488 SwitchC->removeCase(SwitchC->case_begin());
489 DT->deleteEdge(C, B);
490 PDT->deleteEdge(C, B);
491
492 EXPECT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
493 EXPECT_EQ(PDT->getNode(C), nullptr);
494
495 PDT->recalculate(F);
496
497 EXPECT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
498 EXPECT_EQ(PDT->getNode(C), nullptr);
499 });
500 }
501
502 // Verify that the PDT is correctly updated in case an edge removal results
503 // in an infinite loop.
504 //
505 // Test case:
506 //
507 // CFG PDT
508 //
509 // A Exit
510 // | / | \
511 // B-- C B D
512 // | \ |
513 // v \ A
514 // / D
515 // C--C2 \
516 // / \ \ v
517 // ^ v --Exit
518 // \_/
519 //
520 // After deleting the edge C->E, C is part of an infinite reverse-unreachable
521 // loop:
522 //
523 // CFG' PDT'
524 //
525 // A Exit
526 // | |
527 // B D
528 // | \ |
529 // v \ B
530 // / D \
531 // C \ A
532 // / \ v
533 // ^ v Exit
534 // \_/
535 //
536 // In PDT, D does not post-dominate B. After the edge C->E is removed, a new
537 // post-dominance relation is introduced.
538 //
539 // As C now becomes reverse-unreachable, it is not anymore part of the
540 // PDT. We also verify this property.
541 //
542 // TODO: Can we change the PDT definition such that C remains part of the
543 // CFG, at best without loosing the dominance relation D postdom B.
544 TEST(DominatorTree, DeletingEdgesIntroducesInfiniteLoop2) {
545 StringRef ModuleString =
546 "define void @f() {\n"
547 "A:\n"
548 " br label %B\n"
549 "B:\n"
550 " br i1 undef, label %D, label %C\n"
551 "C:\n"
552 " switch i32 undef, label %C [\n"
553 " i32 0, label %C2\n"
554 " ]\n"
555 "C2:\n"
556 " ret void\n"
557 "D:\n"
558 " ret void\n"
559 "}\n";
560
561 // Parse the module.
562 LLVMContext Context;
563 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
564
565 runWithDomTree(
566 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
567 Function::iterator FI = F.begin();
568
569 FI++;
570 BasicBlock *B = &*FI++;
571 BasicBlock *C = &*FI++;
572 BasicBlock *C2 = &*FI++;
573 BasicBlock *D = &*FI++;
574
575 auto SwitchC = cast(C->getTerminator());
576 SwitchC->removeCase(SwitchC->case_begin());
577 DT->deleteEdge(C, C2);
578 PDT->deleteEdge(C, C2);
579 C2->eraseFromParent();
580
581 EXPECT_EQ(DT->getNode(C2), nullptr);
582 PDT->eraseNode(C2);
583
584 EXPECT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
585 EXPECT_EQ(PDT->getNode(C), nullptr);
586 EXPECT_EQ(PDT->getNode(C2), nullptr);
587
588 PDT->recalculate(F);
589
590 EXPECT_TRUE(PDT->dominates(PDT->getNode(D), PDT->getNode(B)));
591 EXPECT_EQ(PDT->getNode(C), nullptr);
592 EXPECT_EQ(PDT->getNode(C2), nullptr);
593 });
594 }
595
328596 namespace {
329597 const auto Insert = CFGBuilder::ActionKind::Insert;
330598 const auto Delete = CFGBuilder::ActionKind::Delete;