@@ -1003,6 +1003,7 @@ static int zend_jit_add_range(zend_lifetime_interval **intervals, int var, uint3
1003
1003
ival -> range .end = to ;
1004
1004
ival -> range .next = NULL ;
1005
1005
ival -> hint = NULL ;
1006
+ ival -> used_as_hint = NULL ;
1006
1007
intervals [var ] = ival ;
1007
1008
} else if (ival -> range .start > to + 1 ) {
1008
1009
zend_life_range * range = zend_arena_alloc (& CG (arena ), sizeof (zend_life_range ));
@@ -1526,6 +1527,17 @@ static int zend_jit_compute_liveness(zend_op_array *op_array, zend_ssa *ssa, zen
1526
1527
}
1527
1528
1528
1529
* list = zend_jit_sort_intervals (intervals , ssa -> vars_count );
1530
+
1531
+ if (* list ) {
1532
+ zend_lifetime_interval * ival = * list ;
1533
+ while (ival ) {
1534
+ if (ival -> hint ) {
1535
+ ival -> hint -> used_as_hint = ival ;
1536
+ }
1537
+ ival = ival -> list_next ;
1538
+ }
1539
+ }
1540
+
1529
1541
free_alloca (intervals , use_heap );
1530
1542
return SUCCESS ;
1531
1543
@@ -1581,13 +1593,14 @@ static uint32_t zend_interval_intersection(zend_lifetime_interval *ival1, zend_l
1581
1593
1582
1594
/* See "Optimized Interval Splitting in a Linear Scan Register Allocator",
1583
1595
Christian Wimmer VEE'05 (2005), Figure 4. Allocation without spilling */
1584
- static int zend_jit_try_allocate_free_reg (zend_op_array * op_array , zend_ssa * ssa , zend_lifetime_interval * current , zend_regset available , zend_lifetime_interval * active , zend_lifetime_interval * inactive , zend_lifetime_interval * * list , zend_lifetime_interval * * free )
1596
+ static int zend_jit_try_allocate_free_reg (zend_op_array * op_array , zend_ssa * ssa , zend_lifetime_interval * current , zend_regset available , zend_regset * hints , zend_lifetime_interval * active , zend_lifetime_interval * inactive , zend_lifetime_interval * * list , zend_lifetime_interval * * free )
1585
1597
{
1586
1598
zend_lifetime_interval * it ;
1587
1599
uint32_t freeUntilPos [ZREG_NUM ];
1588
- uint32_t pos ;
1589
- zend_reg i , reg ;
1600
+ uint32_t pos , pos2 ;
1601
+ zend_reg i , reg , reg2 ;
1590
1602
zend_reg hint = ZREG_NONE ;
1603
+ zend_regset low_priority_regs ;
1591
1604
zend_life_range * range ;
1592
1605
1593
1606
if ((ssa -> var_info [current -> ssa_var ].type & MAY_BE_ANY ) == MAY_BE_DOUBLE ) {
@@ -1618,7 +1631,12 @@ static int zend_jit_try_allocate_free_reg(zend_op_array *op_array, zend_ssa *ssa
1618
1631
if (current -> range .start != zend_interval_end (it )) {
1619
1632
freeUntilPos [it -> reg ] = 0 ;
1620
1633
} else if (zend_jit_may_reuse_reg (op_array , ssa , current -> range .start , current -> ssa_var , it -> ssa_var )) {
1621
- hint = it -> reg ;
1634
+ if (!ZEND_REGSET_IN (* hints , it -> reg ) &&
1635
+ /* TODO: Avoid most often scratch registers. Find a better way ??? */
1636
+ (!current -> used_as_hint ||
1637
+ (it -> reg != ZREG_R0 && it -> reg != ZREG_R1 && it -> reg != ZREG_XMM0 && it -> reg != ZREG_XMM1 ))) {
1638
+ hint = it -> reg ;
1639
+ }
1622
1640
} else {
1623
1641
freeUntilPos [it -> reg ] = 0 ;
1624
1642
}
@@ -1629,8 +1647,11 @@ static int zend_jit_try_allocate_free_reg(zend_op_array *op_array, zend_ssa *ssa
1629
1647
freeUntilPos [it -> reg ] = 0 ;
1630
1648
it = it -> list_next ;
1631
1649
}
1632
- if (current -> hint ) {
1633
- hint = current -> hint -> reg ;
1650
+ }
1651
+ if (current -> hint ) {
1652
+ hint = current -> hint -> reg ;
1653
+ if (current -> hint -> used_as_hint == current ) {
1654
+ ZEND_REGSET_EXCL (* hints , hint );
1634
1655
}
1635
1656
}
1636
1657
@@ -1712,14 +1733,40 @@ static int zend_jit_try_allocate_free_reg(zend_op_array *op_array, zend_ssa *ssa
1712
1733
1713
1734
if (hint != ZREG_NONE && freeUntilPos [hint ] > zend_interval_end (current )) {
1714
1735
current -> reg = hint ;
1736
+ if (current -> used_as_hint ) {
1737
+ ZEND_REGSET_INCL (* hints , hint );
1738
+ }
1715
1739
return 1 ;
1716
1740
}
1717
1741
1718
1742
pos = 0 ; reg = ZREG_NONE ;
1743
+ pos2 = 0 ; reg2 = ZREG_NONE ;
1744
+ low_priority_regs = * hints ;
1745
+ if (current -> used_as_hint ) {
1746
+ /* TODO: Avoid most often scratch registers. Find a better way ??? */
1747
+ ZEND_REGSET_INCL (low_priority_regs , ZREG_R0 );
1748
+ ZEND_REGSET_INCL (low_priority_regs , ZREG_R1 );
1749
+ ZEND_REGSET_INCL (low_priority_regs , ZREG_XMM0 );
1750
+ ZEND_REGSET_INCL (low_priority_regs , ZREG_XMM1 );
1751
+ }
1719
1752
for (i = 0 ; i < ZREG_NUM ; i ++ ) {
1720
- if (ZEND_REGSET_IN (available , i ) && freeUntilPos [i ] > pos ) {
1721
- reg = i ;
1722
- pos = freeUntilPos [i ];
1753
+ if (ZEND_REGSET_IN (available , i )) {
1754
+ if (ZEND_REGSET_IN (low_priority_regs , i )) {
1755
+ if (freeUntilPos [i ] > pos2 ) {
1756
+ reg2 = i ;
1757
+ pos2 = freeUntilPos [i ];
1758
+ }
1759
+ } else if (freeUntilPos [i ] > pos ) {
1760
+ reg = i ;
1761
+ pos = freeUntilPos [i ];
1762
+ }
1763
+ }
1764
+ }
1765
+
1766
+ if (reg == ZREG_NONE ) {
1767
+ if (reg2 != ZREG_NONE ) {
1768
+ reg = reg2 ;
1769
+ pos = pos2 ;
1723
1770
}
1724
1771
}
1725
1772
@@ -1729,6 +1776,9 @@ static int zend_jit_try_allocate_free_reg(zend_op_array *op_array, zend_ssa *ssa
1729
1776
} else if (zend_interval_end (current ) < pos ) {
1730
1777
/* register available for the whole interval */
1731
1778
current -> reg = reg ;
1779
+ if (current -> used_as_hint ) {
1780
+ ZEND_REGSET_INCL (* hints , reg );
1781
+ }
1732
1782
return 1 ;
1733
1783
} else {
1734
1784
/* TODO: enable interval splitting ??? */
@@ -1737,6 +1787,9 @@ static int zend_jit_try_allocate_free_reg(zend_op_array *op_array, zend_ssa *ssa
1737
1787
return 0 ;
1738
1788
}
1739
1789
current -> reg = reg ;
1790
+ if (current -> used_as_hint ) {
1791
+ ZEND_REGSET_INCL (* hints , reg );
1792
+ }
1740
1793
return 1 ;
1741
1794
}
1742
1795
}
@@ -1759,6 +1812,7 @@ static zend_lifetime_interval* zend_jit_linear_scan(zend_op_array *op_array, zen
1759
1812
zend_lifetime_interval * current , * * p , * q ;
1760
1813
uint32_t position ;
1761
1814
zend_regset available = ZEND_REGSET_UNION (ZEND_REGSET_GP , ZEND_REGSET_FP );
1815
+ zend_regset hints = ZEND_REGSET_EMPTY ;
1762
1816
1763
1817
unhandled = list ;
1764
1818
/* active = inactive = handled = free = {} */
@@ -1811,7 +1865,7 @@ static zend_lifetime_interval* zend_jit_linear_scan(zend_op_array *op_array, zen
1811
1865
}
1812
1866
}
1813
1867
1814
- if (zend_jit_try_allocate_free_reg (op_array , ssa , current , available , active , inactive , & unhandled , & free ) ||
1868
+ if (zend_jit_try_allocate_free_reg (op_array , ssa , current , available , & hints , active , inactive , & unhandled , & free ) ||
1815
1869
zend_jit_allocate_blocked_reg ()) {
1816
1870
ZEND_REGSET_EXCL (available , current -> reg );
1817
1871
current -> list_next = active ;
0 commit comments