You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
1
(9) |
2
(6) |
3
|
|
4
|
5
(3) |
6
(2) |
7
|
8
(6) |
9
(7) |
10
(1) |
|
11
(1) |
12
(2) |
13
(5) |
14
(3) |
15
(2) |
16
(8) |
17
(1) |
|
18
|
19
|
20
(2) |
21
(2) |
22
|
23
(1) |
24
|
|
25
(2) |
26
(2) |
27
(1) |
28
|
29
(1) |
30
|
|
|
From: <sv...@va...> - 2017-06-13 18:15:32
|
Author: iraisr
Date: Tue Jun 13 19:15:26 2017
New Revision: 16445
Log:
Announce fix for BZ#381162.
Related VEX commit r3392.
Modified:
trunk/NEWS
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Tue Jun 13 19:15:26 2017
@@ -36,6 +36,7 @@
where XXXXXX is the bug number as listed below.
380397 s390x: __GI_strcspn() replacemenet needed
+381162 possible array overrun in VEX register allocator
Release 3.13.0 (15 June 2017)
|
|
From: <sv...@va...> - 2017-06-13 18:14:36
|
Author: iraisr
Date: Tue Jun 13 19:14:28 2017
New Revision: 3392
Log:
Fix a possible array overrun in VEX register allocator.
Fixes BZ#381162.
Modified:
trunk/priv/host_generic_reg_alloc2.c
Modified: trunk/priv/host_generic_reg_alloc2.c
==============================================================================
--- trunk/priv/host_generic_reg_alloc2.c (original)
+++ trunk/priv/host_generic_reg_alloc2.c Tue Jun 13 19:14:28 2017
@@ -433,7 +433,7 @@
/* .. and the redundant backward map */
/* Each value is 0 .. n_rregs-1 or is INVALID_RREG_NO.
- This inplies n_rregs must be <= 32768. */
+ This implies n_rregs must be <= 32768. */
Short* vreg_state; /* [0 .. n_vregs-1] */
/* The vreg -> rreg map constructed and then applied to each
@@ -554,8 +554,7 @@
/* An array to hold the reg-usage info for the incoming
instructions. */
- reg_usage_arr
- = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->arr_used-1);
+ reg_usage_arr = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->arr_used);
/* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
|
|
From: <sv...@va...> - 2017-06-13 15:54:26
|
Author: iraisr
Date: Tue Jun 13 16:54:16 2017
New Revision: 3391
Log:
Introduce RegAllocState into the VEX register allocator.
Modified:
branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
branches/VEX_JIT_HACKS/priv/main_main.c
Modified: branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c Tue Jun 13 16:54:16 2017
@@ -142,8 +142,8 @@
#define INVALID_RREG_NO ((Short)(-1))
-#define IS_VALID_VREGNO(_zz) ((_zz) >= 0 && (_zz) < n_vregs)
-#define IS_VALID_RREGNO(_zz) ((_zz) >= 0 && (_zz) < n_rregs)
+#define IS_VALID_VREGNO(_zz) ((_zz) >= 0 && (_zz) < state->n_vregs)
+#define IS_VALID_RREGNO(_zz) ((_zz) >= 0 && (_zz) < state->n_rregs)
/* Search forward from some given point in the incoming instruction
@@ -338,10 +338,73 @@
# undef IS_4_ALIGNED
}
+#define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
+STATIC_ASSERT((LibVEX_N_SPILL_BYTES % LibVEX_GUEST_STATE_ALIGN) == 0);
+STATIC_ASSERT((N_SPILL64S % 2) == 0);
+
+/* Register allocator state. Keeps all vital information at one place. */
+typedef
+ struct {
+ /* Info on vregs. Computed once and remains unchanged. */
+ UInt n_vregs;
+ VRegLR* vreg_lrs; /* [0 .. n_vregs-1] */
+
+ /* Running state of the core allocation algorithm. */
+ RRegState* rreg_state; /* [0 .. n_rregs-1] */
+ UInt n_rregs;
+
+ /* .. and the redundant backward map */
+ /* Each value is 0 .. n_rregs-1 or is INVALID_RREG_NO.
+ This implies n_rregs must be <= 32768. */
+ Short* vreg_state; /* [0 .. n_vregs-1] */
+ }
+ RegAllocState;
+
+
+#define INVALID_INSTRNO (-2)
+
+static void initRegAllocState(
+ RegAllocState* state,
+ const RegAllocSettings* settings,
+ UInt n_vregs)
+{
+ state->n_vregs = n_vregs;
+
+ state->vreg_lrs = NULL;
+ if (state->n_vregs > 0)
+ state->vreg_lrs = LibVEX_Alloc_inline(sizeof(VRegLR) * state->n_vregs);
+ for (UInt j = 0; j < state->n_vregs; j++) {
+ state->vreg_lrs[j].live_after = INVALID_INSTRNO;
+ state->vreg_lrs[j].dead_before = INVALID_INSTRNO;
+ state->vreg_lrs[j].spill_offset = 0;
+ state->vreg_lrs[j].spill_size = 0;
+ state->vreg_lrs[j].reg_class = HRcINVALID;
+ }
+
+ /* n_rregs is no more than a short name for n_available_real_regs. */
+ state->n_rregs = settings->univ->allocable;
+ /* If this is not so, the universe we have is nonsensical. */
+ vassert(state->n_rregs > 0);
+
+ /* Initialise running state. */
+ state->rreg_state = LibVEX_Alloc_inline(state->n_rregs * sizeof(RRegState));
+
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ state->rreg_state[j].has_hlrs = False;
+ state->rreg_state[j].disp = Free;
+ state->rreg_state[j].vreg = INVALID_HREG;
+ state->rreg_state[j].is_spill_cand = False;
+ state->rreg_state[j].eq_spill_slot = False;
+ }
+
+ state->vreg_state = LibVEX_Alloc_inline(state->n_vregs * sizeof(Short));
+ for (UInt j = 0; j < state->n_vregs; j++)
+ state->vreg_state[j] = INVALID_RREG_NO;
+}
static inline void flush_rreg_lrs_la(
- RRegLR** rreg_lrs_la, UInt *rreg_lrs_size, UInt *rreg_lrs_used,
- HReg rreg, Int flush_la, Int flush_db, const HChar *debug_phase)
+ RRegLR** rreg_lrs_la, UInt *rreg_lrs_size, UInt *rreg_lrs_used,
+ HReg rreg, Int flush_la, Int flush_db, const HChar *debug_phase)
{
ensureRRLRspace(rreg_lrs_la, rreg_lrs_size, *rreg_lrs_used);
if (0) {
@@ -368,27 +431,20 @@
UInt ii_start,
UInt ii_length,
+ /* Register allocator state. */
+ RegAllocState* state,
+
/* Register allocator settings. */
const RegAllocSettings* settings,
- UInt n_vregs,
-
/* Outgoing code with real registers. */
HInstrVec* instrs_out
)
{
-# define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
- STATIC_ASSERT((LibVEX_N_SPILL_BYTES % LibVEX_GUEST_STATE_ALIGN) == 0);
- STATIC_ASSERT((N_SPILL64S % 2) == 0);
-
vassert(ii_start + ii_length <= instrs_in->insns_used);
const Bool eq_spill_opt = True;
- /* Info on vregs and rregs. Computed once and remains
- unchanged. */
- VRegLR* vreg_lrs; /* [0 .. n_vregs-1] */
-
/* We keep two copies of the real-reg live range info, one sorted
by .live_after and the other by .dead_before. First the
unsorted info is created in the _la variant is copied into the
@@ -415,19 +471,6 @@
Int* rreg_live_after;
Int* rreg_dead_before;
- /* Running state of the core allocation algorithm. */
- RRegState* rreg_state; /* [0 .. n_rregs-1] */
- Int n_rregs;
-
- /* .. and the redundant backward map */
- /* Each value is 0 .. n_rregs-1 or is INVALID_RREG_NO.
- This inplies n_rregs must be <= 32768. */
- Short* vreg_state; /* [0 .. n_vregs-1] */
-
- /* The vreg -> rreg map constructed and then applied to each
- instr. */
- HRegRemap remap;
-
/* Sanity checks are expensive. They are only done periodically,
not at each insn processed. */
Bool do_sanity_check;
@@ -437,8 +480,6 @@
overflowing 32k. */
vassert(ii_length <= 15000);
-# define INVALID_INSTRNO (-2)
-
# define EMIT_INSTR(_instr) \
do { \
HInstr* _tmp = (_instr); \
@@ -450,62 +491,35 @@
addHInstr(instrs_out, _tmp); \
} while (0)
-# define PRINT_STATE \
- do { \
- Int z, q; \
- for (z = 0; z < n_rregs; z++) { \
- vex_printf(" rreg_state[%2d] = ", z); \
- settings->ppReg(settings->univ->regs[z]); \
- vex_printf(" \t"); \
- switch (rreg_state[z].disp) { \
- case Free: vex_printf("Free\n"); break; \
- case Unavail: vex_printf("Unavail\n"); break; \
- case Bound: vex_printf("BoundTo "); \
- settings->ppReg(rreg_state[z].vreg); \
- vex_printf("\n"); break; \
- } \
- } \
- vex_printf("\n vreg_state[0 .. %d]:\n ", n_vregs-1); \
- q = 0; \
- for (z = 0; z < n_vregs; z++) { \
- if (vreg_state[z] == INVALID_RREG_NO) \
- continue; \
- vex_printf("[%d] -> %d ", z, vreg_state[z]); \
- q++; \
- if (q > 0 && (q % 6) == 0) \
- vex_printf("\n "); \
- } \
- vex_printf("\n"); \
+# define PRINT_STATE \
+ do { \
+ Int z, q; \
+ for (z = 0; z < state->n_rregs; z++) { \
+ vex_printf(" rreg_state[%2d] = ", z); \
+ settings->ppReg(settings->univ->regs[z]); \
+ vex_printf(" \t"); \
+ switch (state->rreg_state[z].disp) { \
+ case Free: vex_printf("Free\n"); break; \
+ case Unavail: vex_printf("Unavail\n"); break; \
+ case Bound: vex_printf("BoundTo "); \
+ settings->ppReg(state->rreg_state[z].vreg); \
+ vex_printf("\n"); break; \
+ } \
+ } \
+ vex_printf("\n vreg_state[0 .. %d]:\n ", state->n_vregs-1); \
+ q = 0; \
+ for (z = 0; z < state->n_vregs; z++) { \
+ if (state->vreg_state[z] == INVALID_RREG_NO) \
+ continue; \
+ vex_printf("[%d] -> %d ", z, state->vreg_state[z]); \
+ q++; \
+ if (q > 0 && (q % 6) == 0) \
+ vex_printf("\n "); \
+ } \
+ vex_printf("\n"); \
} while (0)
- /* --------- Stage 0: allocate/initialise running state. --------- */
-
- /* ... and initialise running state. */
- /* n_rregs is no more than a short name for n_available_real_regs. */
- n_rregs = settings->univ->allocable;
-
- /* If this is not so, vreg_state entries will overflow. */
- vassert(n_vregs < 32767);
-
- /* If this is not so, the universe we have is nonsensical. */
- vassert(n_rregs > 0);
-
- rreg_state = LibVEX_Alloc_inline(n_rregs * sizeof(RRegState));
- vreg_state = LibVEX_Alloc_inline(n_vregs * sizeof(Short));
-
- for (Int j = 0; j < n_rregs; j++) {
- rreg_state[j].has_hlrs = False;
- rreg_state[j].disp = Free;
- rreg_state[j].vreg = INVALID_HREG;
- rreg_state[j].is_spill_cand = False;
- rreg_state[j].eq_spill_slot = False;
- }
-
- for (Int j = 0; j < n_vregs; j++)
- vreg_state[j] = INVALID_RREG_NO;
-
-
/* --------- Stage 1: compute vreg live ranges. --------- */
/* --------- Stage 2: compute rreg live ranges. --------- */
@@ -517,21 +531,9 @@
0 .. n_vregs-1, so we can just dump the results
in a pre-allocated array. */
- vreg_lrs = NULL;
- if (n_vregs > 0)
- vreg_lrs = LibVEX_Alloc_inline(sizeof(VRegLR) * n_vregs);
-
- for (Int j = 0; j < n_vregs; j++) {
- vreg_lrs[j].live_after = INVALID_INSTRNO;
- vreg_lrs[j].dead_before = INVALID_INSTRNO;
- vreg_lrs[j].spill_offset = 0;
- vreg_lrs[j].spill_size = 0;
- vreg_lrs[j].reg_class = HRcINVALID;
- }
-
/* An array to hold the reg-usage info for the incoming
instructions. */
- reg_usage_arr = LibVEX_Alloc_inline(sizeof(HRegUsage) * ii_length - 1);
+ reg_usage_arr = LibVEX_Alloc_inline(sizeof(HRegUsage) * ii_length);
/* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
@@ -548,11 +550,10 @@
/* We'll need to track live range start/end points seperately for
each rreg. Sigh. */
- vassert(n_rregs > 0);
- rreg_live_after = LibVEX_Alloc_inline(n_rregs * sizeof(Int));
- rreg_dead_before = LibVEX_Alloc_inline(n_rregs * sizeof(Int));
+ rreg_live_after = LibVEX_Alloc_inline(state->n_rregs * sizeof(Int));
+ rreg_dead_before = LibVEX_Alloc_inline(state->n_rregs * sizeof(Int));
- for (Int j = 0; j < n_rregs; j++) {
+ for (UInt j = 0; j < state->n_rregs; j++) {
rreg_live_after[j] =
rreg_dead_before[j] = INVALID_INSTRNO;
}
@@ -582,46 +583,46 @@
vassert(hregIsVirtual(vreg));
Int k = hregIndex(vreg);
- if (k < 0 || k >= n_vregs) {
+ if (k < 0 || k >= state->n_vregs) {
vex_printf("\n");
settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n");
- vex_printf("vreg %d, n_vregs %d\n", k, n_vregs);
+ vex_printf("vreg %d, n_vregs %d\n", k, state->n_vregs);
vpanic("doRegisterAllocation: out-of-range vreg");
}
/* Take the opportunity to note its regclass. We'll need
that when allocating spill slots. */
- if (vreg_lrs[k].reg_class == HRcINVALID) {
+ if (state->vreg_lrs[k].reg_class == HRcINVALID) {
/* First mention of this vreg. */
- vreg_lrs[k].reg_class = hregClass(vreg);
+ state->vreg_lrs[k].reg_class = hregClass(vreg);
} else {
/* Seen it before, so check for consistency. */
- vassert(vreg_lrs[k].reg_class == hregClass(vreg));
+ vassert(state->vreg_lrs[k].reg_class == hregClass(vreg));
}
/* Now consider live ranges. */
switch (reg_usage_arr[ii].vMode[j]) {
case HRmRead:
- if (vreg_lrs[k].live_after == INVALID_INSTRNO) {
+ if (state->vreg_lrs[k].live_after == INVALID_INSTRNO) {
vex_printf("\n\nOFFENDING VREG = %d\n", k);
vpanic("doRegisterAllocation: "
"first event for vreg is Read");
}
- vreg_lrs[k].dead_before = toShort(ii + 1);
+ state->vreg_lrs[k].dead_before = toShort(ii + 1);
break;
case HRmWrite:
- if (vreg_lrs[k].live_after == INVALID_INSTRNO)
- vreg_lrs[k].live_after = toShort(ii);
- vreg_lrs[k].dead_before = toShort(ii + 1);
+ if (state->vreg_lrs[k].live_after == INVALID_INSTRNO)
+ state->vreg_lrs[k].live_after = toShort(ii);
+ state->vreg_lrs[k].dead_before = toShort(ii + 1);
break;
case HRmModify:
- if (vreg_lrs[k].live_after == INVALID_INSTRNO) {
+ if (state->vreg_lrs[k].live_after == INVALID_INSTRNO) {
vex_printf("\n\nOFFENDING VREG = %d\n", k);
vpanic("doRegisterAllocation: "
"first event for vreg is Modify");
}
- vreg_lrs[k].dead_before = toShort(ii + 1);
+ state->vreg_lrs[k].dead_before = toShort(ii + 1);
break;
default:
vpanic("doRegisterAllocation(1)");
@@ -655,8 +656,8 @@
/* Don't bother to look at registers which are not available
to the allocator. We asserted above that n_rregs > 0, so
n_rregs-1 is safe. */
- if (rReg_maxIndex >= n_rregs)
- rReg_maxIndex = n_rregs-1;
+ if (rReg_maxIndex >= state->n_rregs)
+ rReg_maxIndex = state->n_rregs - 1;
}
/* for each allocator-available real reg mentioned in the insn ... */
@@ -732,7 +733,7 @@
/* ------ start of FINALISE RREG LIVE RANGES ------ */
/* Now finish up any live ranges left over. */
- for (Int j = 0; j < n_rregs; j++) {
+ for (UInt j = 0; j < state->n_rregs; j++) {
if (0) {
vex_printf("residual %d: %d %d\n", j, rreg_live_after[j],
@@ -767,12 +768,12 @@
/* rreg is involved in a HLR. Record this info in the array, if
there is space. */
UInt ix = hregIndex(rreg);
- vassert(ix < n_rregs);
- rreg_state[ix].has_hlrs = True;
+ vassert(ix < state->n_rregs);
+ state->rreg_state[ix].has_hlrs = True;
}
if (0) {
- for (Int j = 0; j < n_rregs; j++) {
- if (!rreg_state[j].has_hlrs)
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ if (!state->rreg_state[j].has_hlrs)
continue;
settings->ppReg(settings->univ->regs[j]);
vex_printf(" hinted\n");
@@ -800,9 +801,9 @@
/* ------ end of FINALISE RREG LIVE RANGES ------ */
if (DEBUG_REGALLOC) {
- for (Int j = 0; j < n_vregs; j++) {
- vex_printf("vreg %d: la = %d, db = %d\n",
- j, vreg_lrs[j].live_after, vreg_lrs[j].dead_before );
+ for (Int j = 0; j < state->n_vregs; j++) {
+ vex_printf("vreg %d: la = %d, db = %d\n", j,
+ state->vreg_lrs[j].live_after, state->vreg_lrs[j].dead_before);
}
}
@@ -853,12 +854,12 @@
local_memset(ss_busy_until_before, 0, sizeof(ss_busy_until_before));
- for (Int j = 0; j < n_vregs; j++) {
+ for (Int j = 0; j < state->n_vregs; j++) {
/* True iff this vreg is unused. In which case we also expect
that the reg_class field for it has not been set. */
- if (vreg_lrs[j].live_after == INVALID_INSTRNO) {
- vassert(vreg_lrs[j].reg_class == HRcINVALID);
+ if (state->vreg_lrs[j].live_after == INVALID_INSTRNO) {
+ vassert(state->vreg_lrs[j].reg_class == HRcINVALID);
continue;
}
@@ -870,7 +871,7 @@
kept in sync with the size info on the definition of
HRegClass. */
Int ss_no = -1;
- switch (vreg_lrs[j].reg_class) {
+ switch (state->vreg_lrs[j].reg_class) {
case HRcVec128: case HRcFlt64:
/* Find two adjacent free slots in which between them
@@ -878,15 +879,15 @@
Since we are trying to find an even:odd pair, move
along in steps of 2 (slots). */
for (ss_no = 0; ss_no < N_SPILL64S-1; ss_no += 2)
- if (ss_busy_until_before[ss_no+0] <= vreg_lrs[j].live_after
- && ss_busy_until_before[ss_no+1] <= vreg_lrs[j].live_after)
+ if (ss_busy_until_before[ss_no+0] <= state->vreg_lrs[j].live_after
+ && ss_busy_until_before[ss_no+1] <= state->vreg_lrs[j].live_after)
break;
if (ss_no >= N_SPILL64S-1) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- ss_busy_until_before[ss_no+0] = vreg_lrs[j].dead_before;
- ss_busy_until_before[ss_no+1] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+0] = state->vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+1] = state->vreg_lrs[j].dead_before;
break;
default:
@@ -895,33 +896,34 @@
at the start point of this interval, and assign the
interval to it. */
for (ss_no = 0; ss_no < N_SPILL64S; ss_no++)
- if (ss_busy_until_before[ss_no] <= vreg_lrs[j].live_after)
+ if (ss_busy_until_before[ss_no] <= state->vreg_lrs[j].live_after)
break;
if (ss_no == N_SPILL64S) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- ss_busy_until_before[ss_no] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no] = state->vreg_lrs[j].dead_before;
break;
- } /* switch (vreg_lrs[j].reg_class) */
+ } /* switch (state->vreg_lrs[j].reg_class) */
/* This reflects LibVEX's hard-wired knowledge of the baseBlock
layout: the guest state, then two equal sized areas following
it for two sets of shadow state, and then the spill area. */
- vreg_lrs[j].spill_offset = toShort(settings->guest_sizeB * 3 + ss_no * 8);
+ state->vreg_lrs[j].spill_offset
+ = toShort(settings->guest_sizeB * 3 + ss_no * 8);
/* Independent check that we've made a sane choice of slot */
- sanity_check_spill_offset( &vreg_lrs[j] );
+ sanity_check_spill_offset(&state->vreg_lrs[j]);
/* if (j > max_ss_no) */
/* max_ss_no = j; */
}
if (0) {
vex_printf("\n\n");
- for (Int j = 0; j < n_vregs; j++)
+ for (Int j = 0; j < state->n_vregs; j++)
vex_printf("vreg %d --> spill offset %d\n",
- j, vreg_lrs[j].spill_offset);
+ j, state->vreg_lrs[j].spill_offset);
}
/* --------- Stage 4: establish rreg preferences --------- */
@@ -966,7 +968,8 @@
instruction. */
do_sanity_check
= toBool(
- False /* Set to True for sanity checking of all insns. */
+ /* TODO-JIT: Sanity checks unconditionally enabled. */
+ True /* Set to True for sanity checking of all insns. */
|| ii == ii_length - 1
|| (ii > 0 && (ii % 17) == 0)
);
@@ -993,7 +996,7 @@
/* assert that this rreg is marked as unavailable */
vassert(!hregIsVirtual(reg));
- vassert(rreg_state[hregIndex(reg)].disp == Unavail);
+ vassert(state->rreg_state[hregIndex(reg)].disp == Unavail);
}
}
@@ -1001,11 +1004,11 @@
unavailable in the running rreg_state must have a
corresponding hard live range entry in the rreg_lrs
array. */
- for (Int j = 0; j < n_rregs; j++) {
- vassert(rreg_state[j].disp == Bound
- || rreg_state[j].disp == Free
- || rreg_state[j].disp == Unavail);
- if (rreg_state[j].disp != Unavail)
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ vassert(state->rreg_state[j].disp == Bound
+ || state->rreg_state[j].disp == Free
+ || state->rreg_state[j].disp == Unavail);
+ if (state->rreg_state[j].disp != Unavail)
continue;
Int k;
for (k = 0; k < rreg_lrs_used; k++) {
@@ -1023,14 +1026,14 @@
/* Sanity check 3: all vreg-rreg bindings must bind registers
of the same class. */
- for (Int j = 0; j < n_rregs; j++) {
- if (rreg_state[j].disp != Bound) {
- vassert(rreg_state[j].eq_spill_slot == False);
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ if (state->rreg_state[j].disp != Bound) {
+ vassert(state->rreg_state[j].eq_spill_slot == False);
continue;
}
vassert(hregClass(settings->univ->regs[j])
- == hregClass(rreg_state[j].vreg));
- vassert( hregIsVirtual(rreg_state[j].vreg));
+ == hregClass(state->rreg_state[j].vreg));
+ vassert( hregIsVirtual(state->rreg_state[j].vreg));
}
/* Sanity check 4: the vreg_state and rreg_state
@@ -1038,20 +1041,20 @@
rreg_state[j].vreg points at some vreg_state entry then
that vreg_state entry should point back at
rreg_state[j]. */
- for (Int j = 0; j < n_rregs; j++) {
- if (rreg_state[j].disp != Bound)
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ if (state->rreg_state[j].disp != Bound)
continue;
- Int k = hregIndex(rreg_state[j].vreg);
+ Int k = hregIndex(state->rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(k));
- vassert(vreg_state[k] == j);
+ vassert(state->vreg_state[k] == j);
}
- for (Int j = 0; j < n_vregs; j++) {
- Int k = vreg_state[j];
+ for (Int j = 0; j < state->n_vregs; j++) {
+ Int k = state->vreg_state[j];
if (k == INVALID_RREG_NO)
continue;
vassert(IS_VALID_RREGNO(k));
- vassert(rreg_state[k].disp == Bound);
- vassert(hregIndex(rreg_state[k].vreg) == j);
+ vassert(state->rreg_state[k].disp == Bound);
+ vassert(hregIndex(state->rreg_state[k].vreg) == j);
}
} /* if (do_sanity_check) */
@@ -1077,8 +1080,8 @@
UInt m = hregIndex(vregD);
vassert(IS_VALID_VREGNO(k));
vassert(IS_VALID_VREGNO(m));
- if (vreg_lrs[k].dead_before != ii + 1) goto cannot_coalesce;
- if (vreg_lrs[m].live_after != ii) goto cannot_coalesce;
+ if (state->vreg_lrs[k].dead_before != ii + 1) goto cannot_coalesce;
+ if (state->vreg_lrs[m].live_after != ii) goto cannot_coalesce;
if (DEBUG_REGALLOC) {
vex_printf("COALESCE ");
settings->ppReg(vregS);
@@ -1087,7 +1090,7 @@
vex_printf("\n\n");
}
/* Find the state entry for vregS. */
- Int n = vreg_state[k]; /* k is the index of vregS */
+ Int n = state->vreg_state[k]; /* k is the index of vregS */
if (n == INVALID_RREG_NO) {
/* vregS is not currently in a real register. So we can't
do the coalescing. Give up. */
@@ -1097,15 +1100,15 @@
/* Finally, we can do the coalescing. It's trivial -- merely
claim vregS's register for vregD. */
- rreg_state[n].vreg = vregD;
+ state->rreg_state[n].vreg = vregD;
vassert(IS_VALID_VREGNO(hregIndex(vregD)));
vassert(IS_VALID_VREGNO(hregIndex(vregS)));
- vreg_state[hregIndex(vregD)] = toShort(n);
- vreg_state[hregIndex(vregS)] = INVALID_RREG_NO;
+ state->vreg_state[hregIndex(vregD)] = toShort(n);
+ state->vreg_state[hregIndex(vregS)] = INVALID_RREG_NO;
/* This rreg has become associated with a different vreg and
hence with a different spill slot. Play safe. */
- rreg_state[n].eq_spill_slot = False;
+ state->rreg_state[n].eq_spill_slot = False;
/* Move on to the next insn. We skip the post-insn stuff for
fixed registers, since this move should not interact with
@@ -1119,17 +1122,17 @@
/* Look for vregs whose live range has just ended, and
mark the associated rreg as free. */
- for (Int j = 0; j < n_rregs; j++) {
- if (rreg_state[j].disp != Bound)
+ for (UInt j = 0; j < state->n_rregs; j++) {
+ if (state->rreg_state[j].disp != Bound)
continue;
- UInt vregno = hregIndex(rreg_state[j].vreg);
+ UInt vregno = hregIndex(state->rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(vregno));
- if (vreg_lrs[vregno].dead_before <= ii) {
- rreg_state[j].disp = Free;
- rreg_state[j].eq_spill_slot = False;
- Int m = hregIndex(rreg_state[j].vreg);
+ if (state->vreg_lrs[vregno].dead_before <= ii) {
+ state->rreg_state[j].disp = Free;
+ state->rreg_state[j].eq_spill_slot = False;
+ Int m = hregIndex(state->rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(m));
- vreg_state[m] = INVALID_RREG_NO;
+ state->vreg_state[m] = INVALID_RREG_NO;
if (DEBUG_REGALLOC) {
vex_printf("free up ");
settings->ppReg(settings->univ->regs[j]);
@@ -1181,31 +1184,32 @@
/* If this fails, we don't have an entry for this rreg.
Which we should. */
vassert(IS_VALID_RREGNO(k));
- Int m = hregIndex(rreg_state[k].vreg);
- if (rreg_state[k].disp == Bound) {
+ Int m = hregIndex(state->rreg_state[k].vreg);
+ if (state->rreg_state[k].disp == Bound) {
/* Yes, there is an associated vreg. Spill it if it's
still live. */
vassert(IS_VALID_VREGNO(m));
- vreg_state[m] = INVALID_RREG_NO;
- if (vreg_lrs[m].dead_before > ii) {
- vassert(vreg_lrs[m].reg_class != HRcINVALID);
- if ((!eq_spill_opt) || !rreg_state[k].eq_spill_slot) {
+ state->vreg_state[m] = INVALID_RREG_NO;
+ if (state->vreg_lrs[m].dead_before > ii) {
+ vassert(state->vreg_lrs[m].reg_class != HRcINVALID);
+ if ((!eq_spill_opt) || !state->rreg_state[k].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
settings->genSpill(&spill1, &spill2, settings->univ->regs[k],
- vreg_lrs[m].spill_offset, settings->mode64);
+ state->vreg_lrs[m].spill_offset,
+ settings->mode64);
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
EMIT_INSTR(spill1);
if (spill2)
EMIT_INSTR(spill2);
}
- rreg_state[k].eq_spill_slot = True;
+ state->rreg_state[k].eq_spill_slot = True;
}
}
- rreg_state[k].disp = Unavail;
- rreg_state[k].vreg = INVALID_HREG;
- rreg_state[k].eq_spill_slot = False;
+ state->rreg_state[k].disp = Unavail;
+ state->rreg_state[k].vreg = INVALID_HREG;
+ state->rreg_state[k].eq_spill_slot = False;
/* check for further rregs entering HLRs at this point */
rreg_lrs_la_next++;
@@ -1226,6 +1230,8 @@
We also build up the final vreg->rreg mapping to be applied
to the insn. */
+ /* The vreg -> rreg map constructed and then applied to each instr. */
+ HRegRemap remap;
initHRegRemap(&remap);
/* ------------ BEGIN directReload optimisation ----------- */
@@ -1254,13 +1260,13 @@
nreads++;
Int m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- Int k = vreg_state[m];
+ Int k = state->vreg_state[m];
if (!IS_VALID_RREGNO(k)) {
/* ok, it is spilled. Now, is this its last use? */
- vassert(vreg_lrs[m].dead_before >= ii+1);
- if (vreg_lrs[m].dead_before == ii+1
+ vassert(state->vreg_lrs[m].dead_before >= ii+1);
+ if (state->vreg_lrs[m].dead_before == ii+1
&& hregIsInvalid(cand)) {
- spilloff = vreg_lrs[m].spill_offset;
+ spilloff = state->vreg_lrs[m].spill_offset;
cand = vreg;
}
}
@@ -1314,14 +1320,14 @@
anything more. Inspect the current state to find out. */
Int m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- Int n = vreg_state[m];
+ Int n = state->vreg_state[m];
if (IS_VALID_RREGNO(n)) {
- vassert(rreg_state[n].disp == Bound);
+ vassert(state->rreg_state[n].disp == Bound);
addToHRegRemap(&remap, vreg, settings->univ->regs[n]);
/* If this rreg is written or modified, mark it as different
from any spill slot value. */
if (reg_usage_arr[ii].vMode[j] != HRmRead)
- rreg_state[n].eq_spill_slot = False;
+ state->rreg_state[n].eq_spill_slot = False;
continue;
} else {
vassert(n == INVALID_RREG_NO);
@@ -1334,11 +1340,11 @@
as possible. */
Int k_suboptimal = -1;
Int k;
- for (k = 0; k < n_rregs; k++) {
- if (rreg_state[k].disp != Free
+ for (k = 0; k < state->n_rregs; k++) {
+ if (state->rreg_state[k].disp != Free
|| hregClass(settings->univ->regs[k]) != hregClass(vreg))
continue;
- if (rreg_state[k].has_hlrs) {
+ if (state->rreg_state[k].has_hlrs) {
/* Well, at least we can use k_suboptimal if we really
have to. Keep on looking for a better candidate. */
k_suboptimal = k;
@@ -1351,12 +1357,12 @@
if (k_suboptimal >= 0)
k = k_suboptimal;
- if (k < n_rregs) {
- rreg_state[k].disp = Bound;
- rreg_state[k].vreg = vreg;
+ if (k < state->n_rregs) {
+ state->rreg_state[k].disp = Bound;
+ state->rreg_state[k].vreg = vreg;
Int p = hregIndex(vreg);
vassert(IS_VALID_VREGNO(p));
- vreg_state[p] = toShort(k);
+ state->vreg_state[p] = toShort(k);
addToHRegRemap(&remap, vreg, settings->univ->regs[k]);
/* Generate a reload if needed. This only creates needed
reloads because the live range builder for vregs will
@@ -1365,11 +1371,12 @@
the first reference for this vreg, and so a reload is
indeed needed. */
if (reg_usage_arr[ii].vMode[j] != HRmWrite) {
- vassert(vreg_lrs[p].reg_class != HRcINVALID);
+ vassert(state->vreg_lrs[p].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
settings->genReload(&reload1, &reload2, settings->univ->regs[k],
- vreg_lrs[p].spill_offset, settings->mode64);
+ state->vreg_lrs[p].spill_offset,
+ settings->mode64);
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
EMIT_INSTR(reload1);
@@ -1379,13 +1386,13 @@
If it's merely read we can claim it now equals the
spill slot, but not so if it is modified. */
if (reg_usage_arr[ii].vMode[j] == HRmRead) {
- rreg_state[k].eq_spill_slot = True;
+ state->rreg_state[k].eq_spill_slot = True;
} else {
vassert(reg_usage_arr[ii].vMode[j] == HRmModify);
- rreg_state[k].eq_spill_slot = False;
+ state->rreg_state[k].eq_spill_slot = False;
}
} else {
- rreg_state[k].eq_spill_slot = False;
+ state->rreg_state[k].eq_spill_slot = False;
}
continue;
@@ -1399,18 +1406,19 @@
/* First, mark in the rreg_state, those rregs which are not spill
candidates, due to holding a vreg mentioned by this
instruction. Or being of the wrong class. */
- for (k = 0; k < n_rregs; k++) {
- rreg_state[k].is_spill_cand = False;
- if (rreg_state[k].disp != Bound)
+ for (k = 0; k < state->n_rregs; k++) {
+ state->rreg_state[k].is_spill_cand = False;
+ if (state->rreg_state[k].disp != Bound)
continue;
if (hregClass(settings->univ->regs[k]) != hregClass(vreg))
continue;
- rreg_state[k].is_spill_cand = True;
+ state->rreg_state[k].is_spill_cand = True;
/* Note, the following loop visits only the virtual regs
mentioned by the instruction. */
for (m = 0; m < reg_usage_arr[ii].n_vRegs; m++) {
- if (sameHReg(rreg_state[k].vreg, reg_usage_arr[ii].vRegs[m])) {
- rreg_state[k].is_spill_cand = False;
+ if (sameHReg(state->rreg_state[k].vreg,
+ reg_usage_arr[ii].vRegs[m])) {
+ state->rreg_state[k].is_spill_cand = False;
break;
}
}
@@ -1422,8 +1430,8 @@
possible, in the hope that this will minimise the number
of consequent reloads required. */
Int spillee
- = findMostDistantlyMentionedVReg (
- reg_usage_arr, ii+1, ii_length, rreg_state, n_rregs );
+ = findMostDistantlyMentionedVReg(reg_usage_arr, ii+1, ii_length,
+ state->rreg_state, state->n_rregs);
if (spillee == -1) {
/* Hmmmmm. There don't appear to be any spill candidates.
@@ -1436,25 +1444,26 @@
/* Right. So we're going to spill rreg_state[spillee]. */
vassert(IS_VALID_RREGNO(spillee));
- vassert(rreg_state[spillee].disp == Bound);
+ vassert(state->rreg_state[spillee].disp == Bound);
/* check it's the right class */
vassert(hregClass(settings->univ->regs[spillee]) == hregClass(vreg));
/* check we're not ejecting the vreg for which we are trying
to free up a register. */
- vassert(! sameHReg(rreg_state[spillee].vreg, vreg));
+ vassert(! sameHReg(state->rreg_state[spillee].vreg, vreg));
- m = hregIndex(rreg_state[spillee].vreg);
+ m = hregIndex(state->rreg_state[spillee].vreg);
vassert(IS_VALID_VREGNO(m));
/* So here's the spill store. Assert that we're spilling a
live vreg. */
- vassert(vreg_lrs[m].dead_before > ii);
- vassert(vreg_lrs[m].reg_class != HRcINVALID);
- if ((!eq_spill_opt) || !rreg_state[spillee].eq_spill_slot) {
+ vassert(state->vreg_lrs[m].dead_before > ii);
+ vassert(state->vreg_lrs[m].reg_class != HRcINVALID);
+ if ((!eq_spill_opt) || !state->rreg_state[spillee].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
settings->genSpill(&spill1, &spill2, settings->univ->regs[spillee],
- vreg_lrs[m].spill_offset, settings->mode64);
+ state->vreg_lrs[m].spill_offset,
+ settings->mode64);
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
EMIT_INSTR(spill1);
@@ -1464,24 +1473,25 @@
/* Update the rreg_state to reflect the new assignment for this
rreg. */
- rreg_state[spillee].vreg = vreg;
- vreg_state[m] = INVALID_RREG_NO;
+ state->rreg_state[spillee].vreg = vreg;
+ state->vreg_state[m] = INVALID_RREG_NO;
- rreg_state[spillee].eq_spill_slot = False; /* be safe */
+ state->rreg_state[spillee].eq_spill_slot = False; /* be safe */
m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- vreg_state[m] = toShort(spillee);
+ state->vreg_state[m] = toShort(spillee);
/* Now, if this vreg is being read or modified (as opposed to
written), we have to generate a reload for it. */
if (reg_usage_arr[ii].vMode[j] != HRmWrite) {
- vassert(vreg_lrs[m].reg_class != HRcINVALID);
+ vassert(state->vreg_lrs[m].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
settings->genReload(&reload1, &reload2,
settings->univ->regs[spillee],
- vreg_lrs[m].spill_offset, settings->mode64);
+ state->vreg_lrs[m].spill_offset,
+ settings->mode64);
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
EMIT_INSTR(reload1);
@@ -1491,10 +1501,10 @@
If it's merely read we can claim it now equals the
spill slot, but not so if it is modified. */
if (reg_usage_arr[ii].vMode[j] == HRmRead) {
- rreg_state[spillee].eq_spill_slot = True;
+ state->rreg_state[spillee].eq_spill_slot = True;
} else {
vassert(reg_usage_arr[ii].vMode[j] == HRmModify);
- rreg_state[spillee].eq_spill_slot = False;
+ state->rreg_state[spillee].eq_spill_slot = False;
}
}
@@ -1543,10 +1553,10 @@
vassert(!hregIsVirtual(reg));
Int k = hregIndex(reg);
vassert(IS_VALID_RREGNO(k));
- vassert(rreg_state[k].disp == Unavail);
- rreg_state[k].disp = Free;
- rreg_state[k].vreg = INVALID_HREG;
- rreg_state[k].eq_spill_slot = False;
+ vassert(state->rreg_state[k].disp == Unavail);
+ state->rreg_state[k].disp = Free;
+ state->rreg_state[k].vreg = INVALID_HREG;
+ state->rreg_state[k].eq_spill_slot = False;
/* check for further rregs leaving HLRs at this point */
rreg_lrs_db_next++;
@@ -1562,9 +1572,9 @@
/* ------ END: Process each insn in turn. ------ */
- /* free(rreg_state); */
+ /* free(state->rreg_state); */
/* free(rreg_lrs); */
- /* if (vreg_lrs) free(vreg_lrs); */
+ /* if (state->vreg_lrs) free(state->vreg_lrs); */
/* Paranoia */
vassert(rreg_lrs_la_next == rreg_lrs_used);
@@ -1580,6 +1590,10 @@
HInstrVec* insns_out)
{
UInt ii_start = 0, ii = 0;
+
+ RegAllocState state;
+ initRegAllocState(&state, settings, n_vregs);
+
for ( ; ii < insns_in->insns_used; ii++) {
HInstrIfThenElse* hite = settings->isIfThenElse(insns_in->insns[ii]);
@@ -1594,8 +1608,8 @@
}
if (ii - ii_start > 0) {
- regAlloc_HInstrVecChunk(insns_in, ii_start, ii - ii_start, settings,
- n_vregs, insns_out);
+ regAlloc_HInstrVecChunk(insns_in, ii_start, ii - ii_start, &state,
+ settings, insns_out);
}
}
@@ -1625,6 +1639,9 @@
{
vassert((settings->guest_sizeB % LibVEX_GUEST_STATE_ALIGN) == 0);
+ /* If this is not so, vreg_state entries will overflow. */
+ vassert(sb_in->n_vregs < 32767);
+
HInstrSB* sb_out = newHInstrSB();
doRegisterAllocation_HInstrVec(sb_in->insns, sb_in->n_vregs, settings,
Modified: branches/VEX_JIT_HACKS/priv/main_main.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/main_main.c (original)
+++ branches/VEX_JIT_HACKS/priv/main_main.c Tue Jun 13 16:54:16 2017
@@ -926,6 +926,7 @@
// the output of the front end, and iropt never screws up the IR by
// itself, unless it is being hacked on. So remove this post-iropt
// check in "production" use.
+ /* TODO-JIT: Remove sanity checking here and there. */
sanityCheckIRSB( irsb, "after initial iropt",
True/*must be flat*/, guest_word_type );
|
|
From: Carl E. L. <ce...@us...> - 2017-06-13 15:05:41
|
Julian:
I have tested the tar ball for RC2 on Power 6, Power 7, Power 8 LE,
Power 8 BE and Power 9. Looks good to go for the release.
Carl Love
|
|
From: <sv...@va...> - 2017-06-13 05:06:07
|
Author: iraisr
Date: Tue Jun 13 06:05:44 2017
New Revision: 3390
Log:
Work through incoming HInstrVec in terms of HInstr chunks delimited
by HInstrIfThenElse.
Modified:
branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
Modified: branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c Tue Jun 13 06:05:44 2017
@@ -354,36 +354,39 @@
(*rreg_lrs_used)++;
}
-/* A target-independent register allocator. Requires various
- functions which it uses to deal abstractly with instructions and
- registers, since it cannot have any target-specific knowledge.
-
- Returns a new list of instructions, which, as a result of the
- behaviour of mapRegs, will be in-place modifications of the
- original instructions.
+/* Register allocator for a chunk of instructions in an HInstrVec.
- Requires that the incoming code has been generated using
- vreg numbers 0, 1 .. n_vregs-1. Appearance of a vreg outside
- that range is a checked run-time error.
-
- Takes an expandable array of pointers to unallocated insns.
- Returns an expandable array of pointers to allocated insns.
+ Takes a chunk of unallocated insns present in HInstrVec, delimited
+ by 'ii_start' .. 'ii_start + ii_length' (exclusive).
+
+ Emits the allocated insns into insns_out.
*/
-HInstrSB* doRegisterAllocation (
+static void regAlloc_HInstrVecChunk (
/* Incoming virtual-registerised code. */
- HInstrSB* sb_in,
+ HInstrVec* instrs_in,
+
+ UInt ii_start,
+ UInt ii_length,
/* Register allocator settings. */
- const RegAllocSettings* settings
+ const RegAllocSettings* settings,
+
+ UInt n_vregs,
+
+ /* Outgoing code with real registers. */
+ HInstrVec* instrs_out
)
{
# define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
+ STATIC_ASSERT((LibVEX_N_SPILL_BYTES % LibVEX_GUEST_STATE_ALIGN) == 0);
+ STATIC_ASSERT((N_SPILL64S % 2) == 0);
+
+ vassert(ii_start + ii_length <= instrs_in->insns_used);
const Bool eq_spill_opt = True;
/* Info on vregs and rregs. Computed once and remains
unchanged. */
- Int n_vregs;
VRegLR* vreg_lrs; /* [0 .. n_vregs-1] */
/* We keep two copies of the real-reg live range info, one sorted
@@ -402,7 +405,7 @@
/* Info on register usage in the incoming instruction array.
Computed once and remains unchanged, more or less; updated
sometimes by the direct-reload optimisation. */
- HRegUsage* reg_usage_arr; /* [0 .. instrs_in->insns_used-1] */
+ HRegUsage* reg_usage_arr; /* [0 .. ii_length - 1] */
/* Used when constructing vreg_lrs (for allocating stack
slots). */
@@ -425,22 +428,14 @@
instr. */
HRegRemap remap;
- /* The output array of instructions. */
- HInstrSB* instrs_out;
- HInstrVec *instrs_in = sb_in->insns;
-
/* Sanity checks are expensive. They are only done periodically,
not at each insn processed. */
Bool do_sanity_check;
- vassert(0 == (settings->guest_sizeB % LibVEX_GUEST_STATE_ALIGN));
- vassert(0 == (LibVEX_N_SPILL_BYTES % LibVEX_GUEST_STATE_ALIGN));
- vassert(0 == (N_SPILL64S % 2));
-
/* The live range numbers are signed shorts, and so limiting the
number of insns to 15000 comfortably guards against them
overflowing 32k. */
- vassert(instrs_in->insns_used <= 15000);
+ vassert(ii_length <= 15000);
# define INVALID_INSTRNO (-2)
@@ -452,7 +447,7 @@
settings->ppInstr(_tmp, settings->mode64); \
vex_printf("\n\n"); \
} \
- addHInstr(instrs_out->insns, _tmp); \
+ addHInstr(instrs_out, _tmp); \
} while (0)
# define PRINT_STATE \
@@ -484,15 +479,11 @@
} while (0)
- /* --------- Stage 0: set up output array --------- */
- /* --------- and allocate/initialise running state. --------- */
-
- instrs_out = newHInstrSB();
+ /* --------- Stage 0: allocate/initialise running state. --------- */
/* ... and initialise running state. */
/* n_rregs is no more than a short name for n_available_real_regs. */
n_rregs = settings->univ->allocable;
- n_vregs = sb_in->n_vregs;
/* If this is not so, vreg_state entries will overflow. */
vassert(n_vregs < 32767);
@@ -540,8 +531,7 @@
/* An array to hold the reg-usage info for the incoming
instructions. */
- reg_usage_arr
- = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->insns_used-1);
+ reg_usage_arr = LibVEX_Alloc_inline(sizeof(HRegUsage) * ii_length - 1);
/* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
@@ -571,14 +561,14 @@
/* ------ start of ITERATE OVER INSNS ------ */
- for (Int ii = 0; ii < instrs_in->insns_used; ii++) {
+ for (UInt ii = 0; ii < ii_length; ii++) {
+ const HInstr* instr_in = instrs_in->insns[ii_start + ii];
- settings->getRegUsage(®_usage_arr[ii], instrs_in->insns[ii],
- settings->mode64);
+ settings->getRegUsage(®_usage_arr[ii], instr_in, settings->mode64);
if (0) {
vex_printf("\n%d stage1: ", ii);
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n");
ppHRegUsage(settings->univ, ®_usage_arr[ii]);
}
@@ -594,7 +584,7 @@
Int k = hregIndex(vreg);
if (k < 0 || k >= n_vregs) {
vex_printf("\n");
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n");
vex_printf("vreg %d, n_vregs %d\n", k, n_vregs);
vpanic("doRegisterAllocation: out-of-range vreg");
@@ -702,7 +692,7 @@
settings->ppReg(settings->univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n");
vpanic("doRegisterAllocation: "
"first event for rreg is Read");
@@ -715,7 +705,7 @@
settings->ppReg(settings->univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n");
vpanic("doRegisterAllocation: "
"first event for rreg is Modify");
@@ -957,12 +947,13 @@
/* ------ BEGIN: Process each insn in turn. ------ */
- for (Int ii = 0; ii < instrs_in->insns_used; ii++) {
+ for (UInt ii = 0; ii < ii_length; ii++) {
+ HInstr* instr_in = instrs_in->insns[ii_start + ii];
if (DEBUG_REGALLOC) {
vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
vex_printf("---- ");
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
vex_printf("\n\nInitial state:\n");
PRINT_STATE;
vex_printf("\n");
@@ -976,7 +967,7 @@
do_sanity_check
= toBool(
False /* Set to True for sanity checking of all insns. */
- || ii == instrs_in->insns_used-1
+ || ii == ii_length - 1
|| (ii > 0 && (ii % 17) == 0)
);
@@ -1077,7 +1068,7 @@
the dst to the src's rreg, and that's all. */
HReg vregS = INVALID_HREG;
HReg vregD = INVALID_HREG;
- if (settings->isMove(instrs_in->insns[ii], &vregS, &vregD)) {
+ if (settings->isMove(instr_in, &vregS, &vregD)) {
if (!hregIsVirtual(vregS)) goto cannot_coalesce;
if (!hregIsVirtual(vregD)) goto cannot_coalesce;
/* Check that *isMove is not telling us a bunch of lies ... */
@@ -1244,10 +1235,9 @@
can convert the instruction into one that reads directly from
the spill slot. This is clearly only possible for x86 and
amd64 targets, since ppc and arm are load-store
- architectures. If successful, replace instrs_in->arr[ii]
- with this new instruction, and recompute its reg usage, so
- that the change is invisible to the standard-case handling
- that follows. */
+ architectures. If successful, replace instrs_in->insns[ii_start + ii]
+ with this new instruction, and recompute its reg usage, so that
+ the change is invisible to the standard-case handling that follows. */
if (settings->directReload != NULL && reg_usage_arr[ii].n_vRegs <= 2) {
Bool debug_direct_reload = False;
@@ -1283,17 +1273,17 @@
vassert(! sameHReg(reg_usage_arr[ii].vRegs[0],
reg_usage_arr[ii].vRegs[1]));
- reloaded = settings->directReload(instrs_in->insns[ii], cand,
- spilloff);
+ reloaded = settings->directReload(instr_in, cand, spilloff);
if (debug_direct_reload && !reloaded) {
vex_printf("[%3d] ", spilloff); ppHReg(cand); vex_printf(" ");
- settings->ppInstr(instrs_in->insns[ii], settings->mode64);
+ settings->ppInstr(instr_in, settings->mode64);
}
if (reloaded) {
/* Update info about the insn, so it looks as if it had
been in this form all along. */
- instrs_in->insns[ii] = reloaded;
- settings->getRegUsage(®_usage_arr[ii], instrs_in->insns[ii],
+ instr_in = reloaded;
+ instrs_in->insns[ii_start + ii] = reloaded;
+ settings->getRegUsage(®_usage_arr[ii], instr_in,
settings->mode64);
if (debug_direct_reload && !reloaded) {
vex_printf(" --> ");
@@ -1433,7 +1423,7 @@
of consequent reloads required. */
Int spillee
= findMostDistantlyMentionedVReg (
- reg_usage_arr, ii+1, instrs_in->insns_used, rreg_state, n_rregs );
+ reg_usage_arr, ii+1, ii_length, rreg_state, n_rregs );
if (spillee == -1) {
/* Hmmmmm. There don't appear to be any spill candidates.
@@ -1525,9 +1515,9 @@
and emit that.
*/
- /* NOTE, DESTRUCTIVELY MODIFIES instrs_in->insns[ii]. */
- settings->mapRegs(&remap, instrs_in->insns[ii], settings->mode64);
- EMIT_INSTR(instrs_in->insns[ii]);
+ /* NOTE, DESTRUCTIVELY MODIFIES instrs_in->insns[ii_start + ii]. */
+ settings->mapRegs(&remap, instr_in, settings->mode64);
+ EMIT_INSTR(instr_in);
if (DEBUG_REGALLOC) {
vex_printf("After dealing with current insn:\n");
@@ -1580,14 +1570,68 @@
vassert(rreg_lrs_la_next == rreg_lrs_used);
vassert(rreg_lrs_db_next == rreg_lrs_used);
- return instrs_out;
-
# undef INVALID_INSTRNO
# undef EMIT_INSTR
# undef PRINT_STATE
}
+static void doRegisterAllocation_HInstrVec(
+ HInstrVec* insns_in, UInt n_vregs, const RegAllocSettings* settings,
+ HInstrVec* insns_out)
+{
+ UInt ii_start = 0, ii = 0;
+ for ( ; ii < insns_in->insns_used; ii++) {
+ HInstrIfThenElse* hite = settings->isIfThenElse(insns_in->insns[ii]);
+
+ if (UNLIKELY(hite != NULL)) {
+ vpanic("HInstrIfThenElse not supported yet in reg alloc");
+ // Pass the previous insn chunk to regAlloc_HInstrVecChunk
+ // Save the snapshot of the register allocator state
+ // Work on fallThrough
+ // Work on outOfLine
+ // Merge the states and emit HInstrIfThenElse
+ }
+ }
+ if (ii - ii_start > 0) {
+ regAlloc_HInstrVecChunk(insns_in, ii_start, ii - ii_start, settings,
+ n_vregs, insns_out);
+ }
+}
+
+/* A target-independent register allocator. Requires various
+ functions which it uses to deal abstractly with instructions and
+ registers, since it cannot have any target-specific knowledge.
+ They are all stashed in 'settings'.
+
+ Returns a new list of instructions, which, as a result of the
+ behaviour of mapRegs, will be in-place modifications of the
+ original instructions.
+
+ Requires that the incoming code has been generated using
+ vreg numbers 0, 1 .. n_vregs-1. Appearance of a vreg outside
+ that range is a checked run-time error.
+
+ Takes an HInstrSB with unallocated insns.
+ Returns an HInstrSB with allocated insns.
+*/
+HInstrSB* doRegisterAllocation(
+ /* Incoming virtual-registerised code. */
+ HInstrSB* sb_in,
+
+ /* Register allocator settings. */
+ const RegAllocSettings* settings
+)
+{
+ vassert((settings->guest_sizeB % LibVEX_GUEST_STATE_ALIGN) == 0);
+
+ HInstrSB* sb_out = newHInstrSB();
+
+ doRegisterAllocation_HInstrVec(sb_in->insns, sb_in->n_vregs, settings,
+ sb_out->insns);
+
+ return sb_out;
+}
/*---------------------------------------------------------------*/
/*--- host_reg_alloc2.c ---*/
|