@@ -1345,19 +1345,21 @@ bb3:
1345
1345
return %result : $()
1346
1346
}
1347
1347
1348
- // Do not consolidate this local borrowscope because it has a PointerEscape.
1348
+ // Consolidate this local borrowscope even though it has a
1349
+ // PointerEscape. The escaping value can be assumed not to be used
1350
+ // outside the borrow scope.
1349
1351
//
1350
1352
// CHECK-LABEL: sil [ossa] @testBorrowEscape : $@convention(thin) (@guaranteed C) -> () {
1351
1353
// CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C
1352
- // CHECK: [[COPY:%.*]] = copy_value [[BORROW]] : $C
1353
- // CHECK-NEXT : end_borrow %1 : $C
1354
+ // CHECK-NOT : copy_value
1355
+ // CHECK: end_borrow [[BORROW]] : $C
1354
1356
// CHECK-NEXT: cond_br undef, bb1, bb2
1355
1357
// CHECK: bb1:
1358
+ // CHECK: [[COPY:%.*]] = copy_value %0 : $C
1356
1359
// CHECK: apply %{{.*}}([[COPY]]) : $@convention(thin) (@owned C) -> ()
1357
1360
// CHECK: br bb3
1358
1361
// CHECK: bb2:
1359
- // CHECK-NEXT: destroy_value [[COPY]] : $C
1360
- // CHECK: br bb3
1362
+ // CHECK-NEXT: br bb3
1361
1363
// CHECK: bb3:
1362
1364
// CHECK-NOT: destroy
1363
1365
// CHECK-LABEL: } // end sil function 'testBorrowEscape'
@@ -1447,3 +1449,182 @@ bb3:
1447
1449
destroy_value %2 : $C
1448
1450
return %0 : $C
1449
1451
}
1452
+
1453
+ // =============================================================================
1454
+ // Test reborrows
1455
+ // =============================================================================
1456
+
1457
+ // Extend the lifetime of an owned value through a nested borrow scope
1458
+ // with cross-block reborrows. Its lifetime must be extended past the
1459
+ // end_borrow of the phi.
1460
+ //
1461
+ // CHECK-LABEL: sil [ossa] @testSubReborrowExtension : $@convention(thin) () -> () {
1462
+ // CHECK: bb0:
1463
+ // CHECK: [[ALLOC:%.*]] = alloc_ref $C
1464
+ // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C
1465
+ // CHECK: cond_br undef, bb1, bb2
1466
+ // CHECK: bb1:
1467
+ // CHECK: [[CP1:%.*]] = copy_value %0 : $C
1468
+ // CHECK: br bb3([[CP1]] : $C, [[BORROW]] : $C)
1469
+ // CHECK: bb2:
1470
+ // CHECK: [[CP2:%.*]] = copy_value %0 : $C
1471
+ // CHECK: br bb3([[CP2]] : $C, [[BORROW]] : $C)
1472
+ // CHECK: bb3([[OWNEDPHI:%.*]] : @owned $C, [[BORROWPHI:%.*]] @guaranteed $C
1473
+ // CHECK: end_borrow [[BORROWPHI]]
1474
+ // CHECK: destroy_value [[OWNEDPHI]] : $C
1475
+ // CHECK: destroy_value %0 : $C
1476
+ // CHECK-LABEL: } // end sil function 'testSubReborrowExtension'
1477
+ sil [ossa] @testSubReborrowExtension : $@convention(thin) () -> () {
1478
+ bb0:
1479
+ %alloc = alloc_ref $C
1480
+ %copy = copy_value %alloc : $C
1481
+ %borrow = begin_borrow %alloc : $C
1482
+ cond_br undef, bb1, bb2
1483
+ bb1:
1484
+ br bb3(%copy : $C, %borrow: $C)
1485
+ bb2:
1486
+ br bb3(%copy : $C, %borrow: $C)
1487
+ bb3(%phi : @owned $C, %borrowphi : @guaranteed $C):
1488
+ end_borrow %borrowphi : $C
1489
+ destroy_value %phi : $C
1490
+ destroy_value %alloc : $C
1491
+ %99 = tuple ()
1492
+ return %99 : $()
1493
+ }
1494
+
1495
+ // Test a cross-block reborrow and a live nested copy of the reborrow:
1496
+ // def: borrow
1497
+ // use: phi reborrow (in the same block as the borrow)
1498
+ // copy reborrowed phi
1499
+ // end reborrow
1500
+ // copy outside borrow scope.
1501
+ //
1502
+ // consolidateBorrow only processes the SSA borrow scope, not the
1503
+ // extended borrow scope, and it does not process the borrow scope
1504
+ // introduced by the phi. Therefore, it should leave the in-scope copy
1505
+ // alone-- it will be treated like the definition of a separate OSSA
1506
+ // lifetime. The inner copy's lifetime will be canonicalized, removing
1507
+ // outercopy.
1508
+ //
1509
+ // CHECK-LABEL: sil [ossa] @testLiveCopyAfterReborrow : $@convention(thin) () -> () {
1510
+ // CHECK: [[ALLOC:%.*]] = alloc_ref $C
1511
+ // CHECK: bb3([[BORROWPHI:%.*]] : @guaranteed $C):
1512
+ // CHECK: [[COPY:%.*]] = copy_value [[BORROWPHI]]
1513
+ // CHECK: end_borrow [[BORROWPHI]] : $C
1514
+ // CHECK-NOT: copy_value
1515
+ // CHECK-NOT: destroy_value
1516
+ // CHECK: apply
1517
+ // CHECK: destroy_value [[COPY]]
1518
+ // CHECK: destroy_value [[ALLOC]] : $C
1519
+ // CHECK-LABEL: } // end sil function 'testLiveCopyAfterReborrow'
1520
+ sil [ossa] @testLiveCopyAfterReborrow : $@convention(thin) () -> () {
1521
+ bb0:
1522
+ %alloc = alloc_ref $C
1523
+ cond_br undef, bb1, bb2
1524
+ bb1:
1525
+ %borrow1 = begin_borrow %alloc : $C
1526
+ br bb3(%borrow1: $C)
1527
+ bb2:
1528
+ %borrow2 = begin_borrow %alloc : $C
1529
+ br bb3(%borrow2: $C)
1530
+ bb3(%borrowphi : @guaranteed $C):
1531
+ %innercopy = copy_value %borrowphi : $C
1532
+ end_borrow %borrowphi : $C
1533
+ %outercopy = copy_value %innercopy : $C
1534
+ destroy_value %innercopy : $C
1535
+ %f = function_ref @takeGuaranteedC : $@convention(thin) (@guaranteed C) -> ()
1536
+ apply %f(%outercopy) : $@convention(thin) (@guaranteed C) -> ()
1537
+ destroy_value %outercopy : $C
1538
+ destroy_value %alloc : $C
1539
+ %99 = tuple ()
1540
+ return %99 : $()
1541
+ }
1542
+
1543
+ // Test a cross-block reborrow and a dead nested copy of the reborrow:
1544
+ // def: borrow
1545
+ // use: phi reborrow (in the same block as the borrow)
1546
+ // copy reborrowed phi
1547
+ // end reborrow
1548
+ // use of copied reborrow outside borrow scope.
1549
+ //
1550
+ // consolidateBorrow only processes the SSA borrow scope, not the
1551
+ // extended borrow scope, and it does not process the borrow scope
1552
+ // introduced by the phi. Therefore, it should leave the in-scope copy alone--
1553
+ // it will be treated like the definition of a separate OSSA lifetime.
1554
+ // The inner copy's lifetime will be canonicalized, removing
1555
+ // outercopy.
1556
+ //
1557
+ // CHECK-LABEL: sil [ossa] @testDeadCopyAfterReborrow : $@convention(thin) () -> () {
1558
+ // CHECK: [[ALLOC:%.*]] = alloc_ref $C
1559
+ // CHECK: bb3([[BORROWPHI:%.*]] : @guaranteed $C):
1560
+ // CHECK-NOT: copy_value
1561
+ // CHECK: end_borrow [[BORROWPHI]] : $C
1562
+ // CHECK-NOT: copy_value
1563
+ // CHECK: destroy_value [[ALLOC]] : $C
1564
+ // CHECK-LABEL: } // end sil function 'testDeadCopyAfterReborrow'
1565
+ sil [ossa] @testDeadCopyAfterReborrow : $@convention(thin) () -> () {
1566
+ bb0:
1567
+ %alloc = alloc_ref $C
1568
+ cond_br undef, bb1, bb2
1569
+ bb1:
1570
+ %borrow1 = begin_borrow %alloc : $C
1571
+ br bb3(%borrow1: $C)
1572
+ bb2:
1573
+ %borrow2 = begin_borrow %alloc : $C
1574
+ br bb3(%borrow2: $C)
1575
+ bb3(%borrowphi : @guaranteed $C):
1576
+ %innercopy = copy_value %borrowphi : $C
1577
+ end_borrow %borrowphi : $C
1578
+ %outercopy = copy_value %innercopy : $C
1579
+ destroy_value %innercopy : $C
1580
+ destroy_value %outercopy : $C
1581
+ destroy_value %alloc : $C
1582
+ %99 = tuple ()
1583
+ return %99 : $()
1584
+ }
1585
+
1586
+ // Test a reborrow with a nested borrow with an outside use
1587
+ // def: borrowphi
1588
+ // nested borrow -- consolidated borrow scope
1589
+ // inner copy -- removed when rewriting nested borrow
1590
+ // end nested borrow
1591
+ // middle copy -- when consolidating borrow scope,
1592
+ // its operand is replace with a copy of borrowphi
1593
+ // then removeed when borrowphi's copy is canonicalized
1594
+ // end borrowphi
1595
+ // outer copy -- removeed when borrowphi's copy is canonicalized
1596
+ //
1597
+ // CHECK-LABEL: sil [ossa] @testNestedReborrowOutsideUse : $@convention(thin) () -> () {
1598
+ // CHECK: [[ALLOC:%.*]] = alloc_ref $C
1599
+ // CHECK: bb3([[BORROWPHI:%.*]] : @guaranteed $C):
1600
+ // CHECK-NEXT: [[COPY:%.*]] = copy_value [[BORROWPHI]] : $C
1601
+ // CHECK-NEXT: begin_borrow [[BORROWPHI]] : $C
1602
+ // CHECK-NEXT: end_borrow
1603
+ // CHECK-NEXT: end_borrow
1604
+ // CHECK-NEXT: destroy_value [[COPY]] : $C
1605
+ // CHECK-NEXT: destroy_value [[ALLOC]] : $C
1606
+ // CHECK-LABEL: } // end sil function 'testNestedReborrowOutsideUse'
1607
+ sil [ossa] @testNestedReborrowOutsideUse : $@convention(thin) () -> () {
1608
+ bb0:
1609
+ %alloc = alloc_ref $C
1610
+ cond_br undef, bb1, bb2
1611
+ bb1:
1612
+ %borrow1 = begin_borrow %alloc : $C
1613
+ br bb3(%borrow1: $C)
1614
+ bb2:
1615
+ %borrow2 = begin_borrow %alloc : $C
1616
+ br bb3(%borrow2: $C)
1617
+ bb3(%borrowphi : @guaranteed $C):
1618
+ %nestedborrow = begin_borrow %borrowphi : $C
1619
+ %innercopy = copy_value %nestedborrow : $C
1620
+ end_borrow %nestedborrow : $C
1621
+ %middlecopy = copy_value %innercopy : $C
1622
+ end_borrow %borrowphi : $C
1623
+ %outercopy = copy_value %middlecopy : $C
1624
+ destroy_value %innercopy : $C
1625
+ destroy_value %middlecopy : $C
1626
+ destroy_value %outercopy : $C
1627
+ destroy_value %alloc : $C
1628
+ %99 = tuple ()
1629
+ return %99 : $()
1630
+ }
0 commit comments