@@ -810,7 +810,8 @@ let parallel_renaming params args continuation queue =
810
810
px
811
811
(instrs @ [ J. Variable_statement [ J. V y, Some (cx, J. N ) ], J. N ])
812
812
in
813
- st @ continuation queue)
813
+ let never, code = continuation queue in
814
+ never, st @ code)
814
815
~init: continuation
815
816
queue
816
817
@@ -1359,7 +1360,9 @@ and translate_instrs ctx expr_queue loc instr =
1359
1360
and compile_block st queue (pc : Addr.t ) frontier interm =
1360
1361
if (not (List. is_empty queue))
1361
1362
&& (Addr.Set. mem pc st.loops || not (Config.Flag. inline () ))
1362
- then flush_all queue (compile_block st [] pc frontier interm)
1363
+ then
1364
+ let never, code = compile_block st [] pc frontier interm in
1365
+ never, flush_all queue code
1363
1366
else
1364
1367
match Addr.Set. mem pc st.loops with
1365
1368
| false -> compile_block_no_loop st queue pc frontier interm
@@ -1371,7 +1374,7 @@ and compile_block st queue (pc : Addr.t) frontier interm =
1371
1374
| [] -> J.Label. zero
1372
1375
in
1373
1376
st.loop_stack < - (pc, (lab, ref false )) :: st.loop_stack;
1374
- let body = compile_block_no_loop st queue pc frontier interm in
1377
+ let never_body, body = compile_block_no_loop st queue pc frontier interm in
1375
1378
let body =
1376
1379
let rec remove_tailing_continue acc = function
1377
1380
| [] -> body
@@ -1386,13 +1389,13 @@ and compile_block st queue (pc : Addr.t) frontier interm =
1386
1389
, None
1387
1390
, None
1388
1391
, Js_simpl. block
1389
- (if Addr.Set. cardinal frontier > 0
1392
+ (if never_body
1390
1393
then (
1391
- if debug () then Format. eprintf " @ break; }@]" ;
1392
- body @ [ J. Break_statement None , J. N ])
1393
- else (
1394
1394
if debug () then Format. eprintf " }@]" ;
1395
- body)) )
1395
+ body)
1396
+ else (
1397
+ if debug () then Format. eprintf " @ break; }@]" ;
1398
+ body @ [ J. Break_statement None , J. N ])) )
1396
1399
, source_location st.ctx pc )
1397
1400
in
1398
1401
let label =
@@ -1403,8 +1406,8 @@ and compile_block st queue (pc : Addr.t) frontier interm =
1403
1406
| [] -> assert false
1404
1407
in
1405
1408
match label with
1406
- | None -> [ for_loop ]
1407
- | Some label -> [ J. Labelled_statement (label, for_loop), J. N ])
1409
+ | None -> never_body, [ for_loop ]
1410
+ | Some label -> never_body, [ J. Labelled_statement (label, for_loop), J. N ])
1408
1411
1409
1412
and compile_block_no_loop st queue (pc : Addr.t ) frontier interm =
1410
1413
if pc > = 0
@@ -1436,8 +1439,6 @@ and compile_block_no_loop st queue (pc : Addr.t) frontier interm =
1436
1439
let new_frontier = resolve_nodes interm grey in
1437
1440
let block = Addr.Map. find pc st.blocks in
1438
1441
let seq, queue = translate_instrs st.ctx queue (source_location st.ctx pc) block.body in
1439
- seq
1440
- @
1441
1442
match block.branch with
1442
1443
| Code. Pushtrap ((pc1 , args1 ), x , (pc2 , args2 ), pc3s ) ->
1443
1444
(* FIX: document this *)
@@ -1469,17 +1470,18 @@ and compile_block_no_loop st queue (pc : Addr.t) frontier interm =
1469
1470
let try_catch_frontier = Addr.Set. union new_frontier handler_frontier_cont in
1470
1471
if debug () then Format. eprintf " @[<2>try {@," ;
1471
1472
if Addr.Map. mem pc1 handler_interm then decr_preds st pc1;
1472
- let body =
1473
- prefix @ compile_branch st [] (pc1, args1) backs try_catch_frontier handler_interm
1473
+ let never_body, body =
1474
+ compile_branch st [] (pc1, args1) backs try_catch_frontier handler_interm
1474
1475
in
1476
+ let body = prefix @ body in
1475
1477
if debug () then Format. eprintf " } catch {@," ;
1476
1478
let x =
1477
1479
let block2 = Addr.Map. find pc2 st.blocks in
1478
1480
let m = Subst. build_mapping args2 block2.params in
1479
1481
try Var.Map. find x m with Not_found -> x
1480
1482
in
1481
1483
if Addr.Map. mem pc2 handler_interm then decr_preds st pc2;
1482
- let handler =
1484
+ let never_handler, handler =
1483
1485
compile_branch st [] (pc2, args2) backs try_catch_frontier handler_interm
1484
1486
in
1485
1487
if debug () then Format. eprintf " }@]@ " ;
@@ -1509,12 +1511,12 @@ and compile_block_no_loop st queue (pc : Addr.t) frontier interm =
1509
1511
None
1510
1512
with Escape -> Some (Var. fork x))
1511
1513
in
1512
- let after =
1514
+ let never_after, after =
1513
1515
match Addr.Set. choose handler_frontier_cont with
1514
- | exception Not_found -> []
1516
+ | exception Not_found -> false , []
1515
1517
| pc ->
1516
1518
if Addr.Set. mem pc frontier
1517
- then []
1519
+ then false , []
1518
1520
else compile_block st [] pc frontier interm
1519
1521
in
1520
1522
let wrap_exn x =
@@ -1540,27 +1542,31 @@ and compile_block_no_loop st queue (pc : Addr.t) frontier interm =
1540
1542
:: handler
1541
1543
| false , None -> handler
1542
1544
in
1543
- flush_all
1544
- queue
1545
- (( J. Try_statement (body, Some (J. V handler_var, handler), None )
1546
- , source_location st.ctx pc )
1547
- :: after)
1548
- | _ -> (
1545
+ ( (never_body && never_handler) || never_after
1546
+ , seq
1547
+ @ flush_all
1548
+ queue
1549
+ (( J. Try_statement (body, Some (J. V handler_var, handler), None )
1550
+ , source_location st.ctx pc )
1551
+ :: after) )
1552
+ | _ ->
1549
1553
let prefix, frontier_cont, new_interm = colapse_frontier st new_frontier interm in
1550
1554
assert (Addr.Set. cardinal frontier_cont < = 1 );
1551
1555
List. iter succs ~f: (fun (pc , _ ) ->
1552
1556
if Addr.Map. mem pc new_interm then decr_preds st pc);
1553
1557
(* Beware evaluation order! *)
1554
- let cond =
1555
- compile_conditional st queue pc block.branch backs frontier_cont new_interm succs
1558
+ let never_cond, cond =
1559
+ compile_conditional st queue pc block.branch backs frontier_cont new_interm
1556
1560
in
1557
- prefix
1558
- @ cond
1559
- @
1560
- match Addr.Set. choose frontier_cont with
1561
- | exception Not_found -> []
1562
- | pc ->
1563
- if Addr.Set. mem pc frontier then [] else compile_block st [] pc frontier interm)
1561
+ let never_after, after =
1562
+ match Addr.Set. choose frontier_cont with
1563
+ | exception Not_found -> false , []
1564
+ | pc ->
1565
+ if Addr.Set. mem pc frontier
1566
+ then false , []
1567
+ else compile_block st [] pc frontier interm
1568
+ in
1569
+ never_cond || never_after, seq @ prefix @ cond @ after
1564
1570
1565
1571
and colapse_frontier st new_frontier interm =
1566
1572
if Addr.Set. cardinal new_frontier > 1
@@ -1606,21 +1612,12 @@ and colapse_frontier st new_frontier interm =
1606
1612
Addr.Map. add pc (idx, (x, i, default = i)) interm) ))
1607
1613
else [] , new_frontier, interm
1608
1614
1609
- and compile_decision_tree st _queue backs frontier interm succs loc cx dtree =
1615
+ and compile_decision_tree st backs frontier interm loc cx dtree =
1610
1616
(* Some changes here may require corresponding changes
1611
1617
in function [DTree.fold_cont] above. *)
1612
- let rec loop cx = function
1618
+ let rec loop cx : _ -> bool * _ = function
1613
1619
| DTree. Empty -> assert false
1614
- | DTree. Branch ((pc , _ ) as cont ) ->
1615
- (* Block of code that never continues (either returns, throws an exception
1616
- or loops back) *)
1617
- (* If not found in successors, this is a backward edge *)
1618
- let never =
1619
- let d = try List. assoc pc succs with Not_found -> Addr.Set. empty in
1620
- (not (Addr.Set. mem pc frontier || Addr.Map. mem pc interm))
1621
- && Addr.Set. is_empty d
1622
- in
1623
- never, compile_branch st [] cont backs frontier interm
1620
+ | DTree. Branch cont -> compile_branch st [] cont backs frontier interm
1624
1621
| DTree. If (cond , cont1 , cont2 ) ->
1625
1622
let never1, iftrue = loop cx cont1 in
1626
1623
let never2, iffalse = loop cx cont2 in
@@ -1670,9 +1667,10 @@ and compile_decision_tree st _queue backs frontier interm succs loc cx dtree =
1670
1667
let v = J. V (Code.Var. fresh () ) in
1671
1668
J. EVar v, [ J. Variable_statement [ v, Some (cx, J. N ) ], J. N ]
1672
1669
in
1673
- binds @ snd (loop cx dtree)
1670
+ let never, code = loop cx dtree in
1671
+ never, binds @ code
1674
1672
1675
- and compile_conditional st queue pc last backs frontier interm succs =
1673
+ and compile_conditional st queue pc last backs frontier interm =
1676
1674
(if debug ()
1677
1675
then
1678
1676
match last with
@@ -1687,86 +1685,64 @@ and compile_conditional st queue pc last backs frontier interm succs =
1687
1685
match last with
1688
1686
| Return x ->
1689
1687
let (_px, cx), queue = access_queue queue x in
1690
- flush_all queue [ J. Return_statement (Some cx), loc ]
1688
+ true , flush_all queue [ J. Return_statement (Some cx), loc ]
1691
1689
| Raise (x , k ) ->
1692
1690
let (_px, cx), queue = access_queue queue x in
1693
- flush_all queue (throw_statement st.ctx cx k loc)
1691
+ true , flush_all queue (throw_statement st.ctx cx k loc)
1694
1692
| Stop ->
1695
1693
let e_opt =
1696
1694
if st.ctx.Ctx. should_export then Some (s_var Constant. exports) else None
1697
1695
in
1698
- flush_all queue [ J. Return_statement e_opt, loc ]
1696
+ true , flush_all queue [ J. Return_statement e_opt, loc ]
1699
1697
| Branch cont -> compile_branch st queue cont backs frontier interm
1700
1698
| Pushtrap _ -> assert false
1701
- | Poptrap cont -> flush_all queue (compile_branch st [] cont backs frontier interm)
1699
+ | Poptrap cont ->
1700
+ let never, code = compile_branch st [] cont backs frontier interm in
1701
+ never, flush_all queue code
1702
1702
| Cond (x , c1 , c2 ) ->
1703
1703
let (_px, cx), queue = access_queue queue x in
1704
- let b =
1705
- compile_decision_tree
1706
- st
1707
- queue
1708
- backs
1709
- frontier
1710
- interm
1711
- succs
1712
- loc
1713
- cx
1714
- (DTree. build_if c1 c2)
1704
+ let never, b =
1705
+ compile_decision_tree st backs frontier interm loc cx (DTree. build_if c1 c2)
1715
1706
in
1716
- flush_all queue b
1707
+ never, flush_all queue b
1717
1708
| Switch (x , [||], a2 ) ->
1718
1709
let (_px, cx), queue = access_queue queue x in
1719
- let code =
1710
+ let never, code =
1720
1711
compile_decision_tree
1721
1712
st
1722
- queue
1723
1713
backs
1724
1714
frontier
1725
1715
interm
1726
- succs
1727
1716
loc
1728
1717
(Mlvalue.Block. tag cx)
1729
1718
(DTree. build_switch a2)
1730
1719
in
1731
- flush_all queue code
1720
+ never, flush_all queue code
1732
1721
| Switch (x , a1 , [||]) ->
1733
1722
let (_px, cx), queue = access_queue queue x in
1734
- let code =
1735
- compile_decision_tree
1736
- st
1737
- queue
1738
- backs
1739
- frontier
1740
- interm
1741
- succs
1742
- loc
1743
- cx
1744
- (DTree. build_switch a1)
1723
+ let never, code =
1724
+ compile_decision_tree st backs frontier interm loc cx (DTree. build_switch a1)
1745
1725
in
1746
- flush_all queue code
1726
+ never, flush_all queue code
1747
1727
| Switch (x , a1 , a2 ) ->
1748
1728
(* The variable x is accessed several times, so we can directly
1749
1729
refer to it *)
1750
- let b1 =
1730
+ let never1, b1 =
1751
1731
compile_decision_tree
1752
1732
st
1753
- queue
1754
1733
backs
1755
1734
frontier
1756
1735
interm
1757
- succs
1758
1736
loc
1759
1737
(var x)
1760
1738
(DTree. build_switch a1)
1761
1739
in
1762
- let b2 =
1740
+ let never2, b2 =
1763
1741
compile_decision_tree
1764
1742
st
1765
- queue
1766
1743
backs
1767
1744
frontier
1768
1745
interm
1769
- succs
1770
1746
loc
1771
1747
(Mlvalue.Block. tag (var x))
1772
1748
(DTree. build_switch a2)
@@ -1776,11 +1752,11 @@ and compile_conditional st queue pc last backs frontier interm succs =
1776
1752
(Mlvalue. is_immediate (var x))
1777
1753
loc
1778
1754
(Js_simpl. block b1)
1779
- false
1755
+ never1
1780
1756
(Js_simpl. block b2)
1781
- false
1757
+ never2
1782
1758
in
1783
- flush_all queue code
1759
+ never1 && never2, flush_all queue code
1784
1760
in
1785
1761
(if debug ()
1786
1762
then
@@ -1796,7 +1772,7 @@ and compile_argument_passing ctx queue (pc, args) _backs continuation =
1796
1772
let block = Addr.Map. find pc ctx.Ctx. blocks in
1797
1773
parallel_renaming block.params args continuation queue
1798
1774
1799
- and compile_branch st queue ((pc , _ ) as cont ) backs frontier interm =
1775
+ and compile_branch st queue ((pc , _ ) as cont ) backs frontier interm : bool * _ =
1800
1776
compile_argument_passing st.ctx queue cont backs (fun queue ->
1801
1777
if Addr.Set. mem pc backs
1802
1778
then (
@@ -1816,11 +1792,11 @@ and compile_branch st queue ((pc, _) as cont) backs frontier interm =
1816
1792
if Option. is_none label
1817
1793
then Format. eprintf " continue;@ "
1818
1794
else Format. eprintf " continue (%d);@ " pc;
1819
- flush_all queue [ J. Continue_statement label, J. N ])
1795
+ true , flush_all queue [ J. Continue_statement label, J. N ])
1820
1796
else if Addr.Set. mem pc frontier || Addr.Map. mem pc interm
1821
1797
then (
1822
1798
if debug () then Format. eprintf " (br %d)@ " pc;
1823
- flush_all queue (compile_branch_selection pc interm))
1799
+ false , flush_all queue (compile_branch_selection pc interm))
1824
1800
else compile_block st queue pc frontier interm)
1825
1801
1826
1802
and compile_branch_selection pc interm =
@@ -1838,7 +1814,7 @@ and compile_closure ctx (pc, args) =
1838
1814
let current_blocks = st.visited_blocks in
1839
1815
st.visited_blocks < - Addr.Set. empty;
1840
1816
if debug () then Format. eprintf " @[<hov 2>closure{@," ;
1841
- let res =
1817
+ let _never, res =
1842
1818
compile_branch st [] (pc, args) Addr.Set. empty Addr.Set. empty Addr.Map. empty
1843
1819
in
1844
1820
if Addr.Set. cardinal st.visited_blocks <> Addr.Set. cardinal current_blocks
0 commit comments