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: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 ---*/
|
|
From: Ivo R. <iv...@iv...> - 2017-06-12 16:31:44
|
2017-06-10 12:57 GMT+02:00 Julian Seward <js...@ac...>: > On 02/06/17 17:57, Julian Seward wrote: >> An RC1 tarball for 3.13.0 is now available at [..] > > Thank you to everybody who tried out the RC1 tarball. There's now > an RC2 available for testing at > > ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC2.tar.bz2 > (md5sum = 6f3c12c41036a59b0f49d597fbd59035) Tested successfully on x86+amd64/Solaris 11.3 and 12.0. I. |
|
From: Rhys K. <rhy...@gm...> - 2017-06-12 12:40:52
|
On 11 June 2017 at 10:55, Paul Floyd <pa...@fr...> wrote: > > On 10 Jun 2017, at 12:57, Julian Seward wrote: > > > On 02/06/17 17:57, Julian Seward wrote: > >> An RC1 tarball for 3.13.0 is now available at [..] > > > > Thank you to everybody who tried out the RC1 tarball. There's now > > an RC2 available for testing at > > > > ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC2.tar.bz2 > > (md5sum = 6f3c12c41036a59b0f49d597fbd59035) > > > Hi > > Here's what I see: > > Vanilla Solaris 11.3 amd64: > Build OK > regtest > == 677 tests, 36 stderr failures, 8 stdout failures, 0 stderrB failures, 0 > stdoutB failures, 0 post failures == > > Fedora 24 amd64 > Build OK > regtest > == 757 tests, 1 stderr failure, 0 stdout failures, 0 stderrB failures, 1 > stdoutB failure, 2 post failures == > > Mac OS 10.7.5 > Build OK > Can't get regtest to build (I'm not in the habit of running tegtest on > Mac). > > Tested the RC2 tarball on macOS: macOS 10.11.6 Build OK regtest == 619 tests, 233 stderr failures, 14 stdout failures, 0 stderrB failures, 0 stdoutB failures, 31 post failures == No new release blockers for this platform that would hold up a release. Regards, Rhys > A+ > Paul > > > ------------------------------------------------------------ > ------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, Slashdot.org! http://sdm.link/slashdot > _______________________________________________ > Valgrind-developers mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers > |
|
From: Paul F. <pa...@fr...> - 2017-06-11 15:26:04
|
On 10 Jun 2017, at 12:57, Julian Seward wrote: > On 02/06/17 17:57, Julian Seward wrote: >> An RC1 tarball for 3.13.0 is now available at [..] > > Thank you to everybody who tried out the RC1 tarball. There's now > an RC2 available for testing at > > ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC2.tar.bz2 > (md5sum = 6f3c12c41036a59b0f49d597fbd59035) Hi Here's what I see: Vanilla Solaris 11.3 amd64: Build OK regtest == 677 tests, 36 stderr failures, 8 stdout failures, 0 stderrB failures, 0 stdoutB failures, 0 post failures == Fedora 24 amd64 Build OK regtest == 757 tests, 1 stderr failure, 0 stdout failures, 0 stderrB failures, 1 stdoutB failure, 2 post failures == Mac OS 10.7.5 Build OK Can't get regtest to build (I'm not in the habit of running tegtest on Mac). A+ Paul |
|
From: Julian S. <js...@ac...> - 2017-06-10 10:57:51
|
On 02/06/17 17:57, Julian Seward wrote: > An RC1 tarball for 3.13.0 is now available at [..] Thank you to everybody who tried out the RC1 tarball. There's now an RC2 available for testing at ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC2.tar.bz2 (md5sum = 6f3c12c41036a59b0f49d597fbd59035) Relative to the RC1, the RC2 contains the following four fixes and is otherwise identical: * bug 380200: xtree generated callgrind files refer to files without directory name * bug 380397: Add a replacement for __GI_strcspn() required on s390x/Linux. * bug 380202: Assertion failure for cache line size (vg_assert(cls == 64)) on aarch64. * n-i-bz: Fix pub_tool_basics.h build issue with g++ 4.4.7. Unless some problem shows up with RC2, it will ship as 3.13.0 final on Thursday 15 June. J |
|
From: <sv...@va...> - 2017-06-09 19:28:12
|
Author: philippe
Date: Fri Jun 9 20:28:04 2017
New Revision: 16444
Log:
Fix a minor doc issue in cachegrind manual example
Modified:
trunk/cachegrind/docs/cg-manual.xml
Modified: trunk/cachegrind/docs/cg-manual.xml
==============================================================================
--- trunk/cachegrind/docs/cg-manual.xml (original)
+++ trunk/cachegrind/docs/cg-manual.xml Fri Jun 9 20:28:04 2017
@@ -1134,7 +1134,7 @@
<programlisting><![CDATA[
enum E { A, B, C };
enum E e;
-enum E table[] = { 1, 2, 3 };
+int table[] = { 1, 2, 3 };
int i;
...
i += table[e];
|
|
From: <sv...@va...> - 2017-06-09 13:53:32
|
Author: sewardj
Date: Fri Jun 9 14:53:25 2017
New Revision: 16443
Log:
-> 3.13.0.RC2
Modified:
branches/VALGRIND_3_13_BRANCH/NEWS
branches/VALGRIND_3_13_BRANCH/configure.ac
Modified: branches/VALGRIND_3_13_BRANCH/NEWS
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/NEWS (original)
+++ branches/VALGRIND_3_13_BRANCH/NEWS Fri Jun 9 14:53:25 2017
@@ -248,8 +248,12 @@
379925 PPC64, mtffs does not set the FPCC and C bits in the FPSCR correctly
379966 WARNING: unhandled amd64-linux syscall: 313 (finit_module)
380200 xtree generated callgrind files refer to files without directory name
+380202 Assertion failure for cache line size (cls == 64) on aarch64.
+380397 s390x: __GI_strcspn() replacement needed
+n-i-bz Fix pub_tool_basics.h build issue with g++ 4.4.7.
(3.13.0.RC1: 2 June 2017, vex r3386, valgrind r16434)
+(3.13.0.RC2: 9 June 2017, vex r3389, valgrind r16443)
Modified: branches/VALGRIND_3_13_BRANCH/configure.ac
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/configure.ac (original)
+++ branches/VALGRIND_3_13_BRANCH/configure.ac Fri Jun 9 14:53:25 2017
@@ -8,7 +8,7 @@
##------------------------------------------------------------##
# Process this file with autoconf to produce a configure script.
-AC_INIT([Valgrind],[3.13.0.RC1],[val...@li...])
+AC_INIT([Valgrind],[3.13.0.RC2],[val...@li...])
AC_CONFIG_SRCDIR(coregrind/m_main.c)
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
|
From: <sv...@va...> - 2017-06-09 13:35:20
|
Author: sewardj
Date: Fri Jun 9 14:35:11 2017
New Revision: 16442
Log:
Merge from trunk, r16438:
fix: Bug 380202 - Assertion failure for cache line size [..]
Modified:
branches/VALGRIND_3_13_BRANCH/ (props changed)
branches/VALGRIND_3_13_BRANCH/coregrind/m_libcproc.c
Modified: branches/VALGRIND_3_13_BRANCH/coregrind/m_libcproc.c
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/coregrind/m_libcproc.c (original)
+++ branches/VALGRIND_3_13_BRANCH/coregrind/m_libcproc.c Fri Jun 9 14:35:11 2017
@@ -1208,7 +1208,7 @@
cls = 4 * (1ULL << (0xF & (ctr_el0 >> 16)));
/* Stay sane .. */
- vg_assert(cls == 64);
+ vg_assert(cls == 64 || cls == 128);
startaddr &= ~(cls - 1);
for (addr = startaddr; addr < endaddr; addr += cls) {
|
|
From: <sv...@va...> - 2017-06-09 13:33:44
|
Author: sewardj
Date: Fri Jun 9 14:33:37 2017
New Revision: 16441
Log:
Merge from trunk, r16437:
Fix pub_tool_basics.h build issue with g++ 4.4.7.
Modified:
branches/VALGRIND_3_13_BRANCH/ (props changed)
branches/VALGRIND_3_13_BRANCH/include/pub_tool_basics.h
Modified: branches/VALGRIND_3_13_BRANCH/include/pub_tool_basics.h
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/include/pub_tool_basics.h (original)
+++ branches/VALGRIND_3_13_BRANCH/include/pub_tool_basics.h Fri Jun 9 14:33:37 2017
@@ -480,7 +480,8 @@
union { \
void *in; \
D out; \
- } var = {.in = (void *) (x)}; var.out; \
+ } var; \
+ var.in = (void *) (x); var.out; \
})
// Poor man's static assert
|
|
From: <sv...@va...> - 2017-06-09 13:31:07
|
Author: sewardj
Date: Fri Jun 9 14:31:00 2017
New Revision: 16440
Log:
Merge from trunk, r16436:
Add a replacement for __GI_strcspn() required on s390x/Linux.
Modified:
branches/VALGRIND_3_13_BRANCH/shared/ (props changed)
branches/VALGRIND_3_13_BRANCH/shared/vg_replace_strmem.c
Modified: branches/VALGRIND_3_13_BRANCH/shared/vg_replace_strmem.c
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/shared/vg_replace_strmem.c (original)
+++ branches/VALGRIND_3_13_BRANCH/shared/vg_replace_strmem.c Fri Jun 9 14:31:00 2017
@@ -1721,6 +1721,7 @@
#if defined(VGO_linux)
STRCSPN(VG_Z_LIBC_SONAME, strcspn)
+ STRCSPN(VG_Z_LIBC_SONAME, __GI_strcspn)
#elif defined(VGO_darwin)
|
|
From: <sv...@va...> - 2017-06-09 13:27:42
|
Author: sewardj
Date: Fri Jun 9 14:27:34 2017
New Revision: 16439
Log:
Merge from trunk, r16435:
Fix 380200 - xtree generated callgrind files [..]
Modified:
branches/VALGRIND_3_13_BRANCH/ (props changed)
branches/VALGRIND_3_13_BRANCH/NEWS (contents, props changed)
branches/VALGRIND_3_13_BRANCH/coregrind/m_xtree.c
Modified: branches/VALGRIND_3_13_BRANCH/NEWS
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/NEWS (original)
+++ branches/VALGRIND_3_13_BRANCH/NEWS Fri Jun 9 14:27:34 2017
@@ -247,6 +247,7 @@
379895 clock_gettime does not execute POST syscall wrapper
379925 PPC64, mtffs does not set the FPCC and C bits in the FPSCR correctly
379966 WARNING: unhandled amd64-linux syscall: 313 (finit_module)
+380200 xtree generated callgrind files refer to files without directory name
(3.13.0.RC1: 2 June 2017, vex r3386, valgrind r16434)
Modified: branches/VALGRIND_3_13_BRANCH/coregrind/m_xtree.c
==============================================================================
--- branches/VALGRIND_3_13_BRANCH/coregrind/m_xtree.c (original)
+++ branches/VALGRIND_3_13_BRANCH/coregrind/m_xtree.c Fri Jun 9 14:27:34 2017
@@ -433,6 +433,10 @@
VgFile* fp = xt_open(outfilename);
DedupPoolAlloc* fnname_ddpa;
DedupPoolAlloc* filename_ddpa;
+ HChar* filename_buf = NULL;
+ UInt filename_buf_size = 0;
+ const HChar* filename_dir;
+ const HChar* filename_name;
if (fp == NULL)
return;
@@ -489,23 +493,43 @@
const HChar* img = img_value(VG_(indexXA)(xt->data, xecu));
- // CALLED_FLF gets the Filename/Line number/Function name for ips[n]
+ // CALLED_FLF gets the Dir+Filename/Line number/Function name for ips[n]
+ // in the variables called_filename/called_linenum/called_fnname.
+ // The booleans called_filename_new/called_fnname_new are set to True
+ // the first time the called_filename/called_fnname are encountered.
+ // The called_filename_nr/called_fnname_nr are numbers identifying
+ // the strings called_filename/called_fnname.
#define CALLED_FLF(n) \
if ((n) < 0 \
|| !VG_(get_filename_linenum)(ips[(n)], \
- &called_filename, \
- NULL, \
+ &filename_name, \
+ &filename_dir, \
&called_linenum)) { \
- called_filename = "UnknownFile???"; \
+ filename_name = "UnknownFile???"; \
called_linenum = 0; \
} \
if ((n) < 0 \
|| !VG_(get_fnname)(ips[(n)], &called_fnname)) { \
called_fnname = "UnknownFn???"; \
} \
+ { \
+ UInt needed_size = VG_(strlen)(filename_dir) + 1 \
+ + VG_(strlen)(filename_name) + 1; \
+ if (filename_buf_size < needed_size) { \
+ filename_buf_size = needed_size; \
+ filename_buf = VG_(realloc)(xt->cc, filename_buf, \
+ filename_buf_size); \
+ } \
+ } \
+ VG_(strcpy)(filename_buf, filename_dir); \
+ if (filename_buf[0] != '\0') { \
+ VG_(strcat)(filename_buf, "/"); \
+ } \
+ VG_(strcat)(filename_buf, filename_name); \
called_filename_nr = VG_(allocStrDedupPA)(filename_ddpa, \
- called_filename, \
+ filename_buf, \
&called_filename_new); \
+ called_filename = filename_buf; \
called_fnname_nr = VG_(allocStrDedupPA)(fnname_ddpa, \
called_fnname, \
&called_fnname_new);
@@ -579,6 +603,7 @@
VG_(fclose)(fp);
VG_(deleteDedupPA)(fnname_ddpa);
VG_(deleteDedupPA)(filename_ddpa);
+ VG_(free)(filename_buf);
}
|
|
From: <sv...@va...> - 2017-06-09 13:13:56
|
Author: sewardj
Date: Fri Jun 9 14:13:48 2017
New Revision: 16438
Log:
fix: Bug 380202 - Assertion failure for cache line size (vg_assert(cls == 64)) on aarch64.
Modified:
trunk/coregrind/m_libcproc.c
Modified: trunk/coregrind/m_libcproc.c
==============================================================================
--- trunk/coregrind/m_libcproc.c (original)
+++ trunk/coregrind/m_libcproc.c Fri Jun 9 14:13:48 2017
@@ -1208,7 +1208,7 @@
cls = 4 * (1ULL << (0xF & (ctr_el0 >> 16)));
/* Stay sane .. */
- vg_assert(cls == 64);
+ vg_assert(cls == 64 || cls == 128);
startaddr &= ~(cls - 1);
for (addr = startaddr; addr < endaddr; addr += cls) {
|
|
From: Will S. <wil...@vn...> - 2017-06-08 19:01:57
|
On Thu, 2017-06-08 at 08:25 -0700, Carl E. Love wrote: > Julian: > > I have tested 3.13.0 RC1 on Power 7, Power 8 BE, Power 8 LE, Power 9 > internal development platforms. I did not find any regressions, I did > notice a couple of tests seem to run a little different on Power 9 then > expected. For example, memcheck/tests/ppc64/power_ISA2_07 gave > > --- power_ISA2_07.stderr.exp 2017-05-31 10:13:56.000000000 -0500 > +++ power_ISA2_07.stderr.out 2017-06-07 10:30:10.277404680 -0500 > @@ -2,7 +2,7 @@ > > HEAP SUMMARY: > in use at exit: 0 bytes in 0 blocks > - total heap usage: 0 allocs, 0 frees, 0 bytes allocated > + total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated > > > Seems a little strange that we see heap usage on Power 9 but not earlier > platforms. We will want to look into it but at this point. I don't see > it as an issue that need fixing for this release. I see this on older platforms with newer OS installs, (i.e. fedora 25 in a power8 guest). I suspect something glibc related. in any case, it's not a power9 specific thing. > > Carl Love > |
|
From: Petar J. <mip...@gm...> - 2017-06-08 17:08:21
|
On Fri, Jun 2, 2017 at 5:57 PM, Julian Seward <js...@ac...> wrote: > Please give it a try in configurations that are important for you and report > any problems you have, either on this mailing list, or (preferably) via our > bug tracker at https://bugs.kde.org/enter_bug.cgi?product=valgrind > Tested on different MIPS32/MIPS64 LE/BE platforms. No regressions. Good to go. Regards, Petar |
|
From: Carl E. L. <ce...@us...> - 2017-06-08 15:25:29
|
Julian:
I have tested 3.13.0 RC1 on Power 7, Power 8 BE, Power 8 LE, Power 9
internal development platforms. I did not find any regressions, I did
notice a couple of tests seem to run a little different on Power 9 then
expected. For example, memcheck/tests/ppc64/power_ISA2_07 gave
--- power_ISA2_07.stderr.exp 2017-05-31 10:13:56.000000000 -0500
+++ power_ISA2_07.stderr.out 2017-06-07 10:30:10.277404680 -0500
@@ -2,7 +2,7 @@
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
- total heap usage: 0 allocs, 0 frees, 0 bytes allocated
+ total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated
Seems a little strange that we see heap usage on Power 9 but not earlier
platforms. We will want to look into it but at this point. I don't see
it as an issue that need fixing for this release.
Carl Love
|
|
From: <sv...@va...> - 2017-06-08 12:30:48
|
Author: iraisr
Date: Thu Jun 8 13:30:41 2017
New Revision: 3389
Log:
Introduce flush_rreg_lrs_la()
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 Thu Jun 8 13:30:41 2017
@@ -207,9 +207,9 @@
/* Double the size of the real-reg live-range array, if needed. */
__attribute__((noinline))
-static void ensureRRLRspace_SLOW ( RRegLR** info, Int* size, Int used )
+static void ensureRRLRspace_SLOW ( RRegLR** info, UInt* size, UInt used )
{
- Int k;
+ UInt k;
RRegLR* arr2;
if (0)
vex_printf("ensureRRISpace: %d -> %d\n", *size, 2 * *size);
@@ -221,7 +221,7 @@
*info = arr2;
}
inline
-static void ensureRRLRspace ( RRegLR** info, Int* size, Int used )
+static void ensureRRLRspace ( RRegLR** info, UInt* size, UInt used )
{
if (LIKELY(used < *size)) return;
ensureRRLRspace_SLOW(info, size, used);
@@ -339,6 +339,21 @@
}
+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)
+{
+ ensureRRLRspace(rreg_lrs_la, rreg_lrs_size, *rreg_lrs_used);
+ if (0) {
+ vex_printf("%s (%d,%d)\n", debug_phase, flush_la, flush_db);
+ }
+
+ (*rreg_lrs_la)[*rreg_lrs_used].rreg = rreg;
+ (*rreg_lrs_la)[*rreg_lrs_used].live_after = toShort(flush_la);
+ (*rreg_lrs_la)[*rreg_lrs_used].dead_before = toShort(flush_db);
+ (*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.
@@ -379,8 +394,8 @@
location in the two arrays to consider. */
RRegLR* rreg_lrs_la;
RRegLR* rreg_lrs_db;
- Int rreg_lrs_size;
- Int rreg_lrs_used;
+ UInt rreg_lrs_size;
+ UInt rreg_lrs_used;
Int rreg_lrs_la_next;
Int rreg_lrs_db_next;
@@ -711,13 +726,9 @@
if (flush) {
vassert(flush_la != INVALID_INSTRNO);
vassert(flush_db != INVALID_INSTRNO);
- ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
- if (0)
- vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
- rreg_lrs_la[rreg_lrs_used].rreg = settings->univ->regs[j];
- rreg_lrs_la[rreg_lrs_used].live_after = toShort(flush_la);
- rreg_lrs_la[rreg_lrs_used].dead_before = toShort(flush_db);
- rreg_lrs_used++;
+ flush_rreg_lrs_la(&rreg_lrs_la, &rreg_lrs_size, &rreg_lrs_used,
+ settings->univ->regs[j], flush_la, flush_db,
+ "FLUSH 1");
}
} /* iterate over rregs in the instr */
@@ -747,14 +758,9 @@
if (rreg_live_after[j] == INVALID_INSTRNO)
continue;
- ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
- if (0)
- vex_printf("FLUSH 2 (%d,%d)\n",
- rreg_live_after[j], rreg_dead_before[j]);
- rreg_lrs_la[rreg_lrs_used].rreg = settings->univ->regs[j];
- rreg_lrs_la[rreg_lrs_used].live_after = toShort(rreg_live_after[j]);
- rreg_lrs_la[rreg_lrs_used].dead_before = toShort(rreg_dead_before[j]);
- rreg_lrs_used++;
+ flush_rreg_lrs_la(&rreg_lrs_la, &rreg_lrs_size, &rreg_lrs_used,
+ settings->univ->regs[j], rreg_live_after[j],
+ rreg_dead_before[j], "FLUSH 2");
}
/* Compute summary hints for choosing real regs. If a real reg is
|
|
From: <sv...@va...> - 2017-06-08 12:15:59
|
Author: iraisr
Date: Thu Jun 8 13:15:50 2017
New Revision: 3388
Log:
Introduce RegAllocSettings
Modified:
branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
branches/VEX_JIT_HACKS/priv/host_generic_regs.h
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 Thu Jun 8 13:15:50 2017
@@ -157,7 +157,7 @@
considered.
To do this we don't actually need to see the incoming instruction
- stream. Rather, what we need us the HRegUsage records for the
+ stream. Rather, what we need is the HRegUsage records for the
incoming instruction stream. Hence that is passed in.
Returns an index into the state array indicating the (v,r) pair to
@@ -354,44 +354,12 @@
Takes an expandable array of pointers to unallocated insns.
Returns an expandable array of pointers to allocated insns.
*/
-HInstrArray* doRegisterAllocation (
-
+HInstrSB* doRegisterAllocation (
/* Incoming virtual-registerised code. */
- HInstrArray* instrs_in,
-
- /* The real-register universe to use. This contains facts about
- real registers, one of which is the set of registers available
- for allocation. */
- const RRegUniverse* univ,
-
- /* Return True iff the given insn is a reg-reg move, in which
- case also return the src and dst regs. */
- Bool (*isMove) ( const HInstr*, HReg*, HReg* ),
-
- /* Get info about register usage in this insn. */
- void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool ),
-
- /* Apply a reg-reg mapping to an insn. */
- void (*mapRegs) ( HRegRemap*, HInstr*, Bool ),
-
- /* Return one, or, if we're unlucky, two insn(s) to spill/restore a
- real reg to a spill slot byte offset. The two leading HInstr**
- args are out parameters, through which the generated insns are
- returned. Also (optionally) a 'directReload' function, which
- attempts to replace a given instruction by one which reads
- directly from a specified spill slot. May be NULL, in which
- case the optimisation is not attempted. */
- void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ),
- void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
- HInstr* (*directReload) ( HInstr*, HReg, Short ),
- Int guest_sizeB,
-
- /* For debug printing only. */
- void (*ppInstr) ( const HInstr*, Bool ),
- void (*ppReg) ( HReg ),
+ HInstrSB* sb_in,
- /* 32/64bit mode */
- Bool mode64
+ /* Register allocator settings. */
+ const RegAllocSettings* settings
)
{
# define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
@@ -419,7 +387,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->arr_used-1] */
+ HRegUsage* reg_usage_arr; /* [0 .. instrs_in->insns_used-1] */
/* Used when constructing vreg_lrs (for allocating stack
slots). */
@@ -443,32 +411,33 @@
HRegRemap remap;
/* The output array of instructions. */
- HInstrArray* instrs_out;
+ 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 == (guest_sizeB % LibVEX_GUEST_STATE_ALIGN));
+ 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->arr_used <= 15000);
+ vassert(instrs_in->insns_used <= 15000);
# define INVALID_INSTRNO (-2)
-# define EMIT_INSTR(_instr) \
- do { \
- HInstr* _tmp = (_instr); \
- if (DEBUG_REGALLOC) { \
- vex_printf("** "); \
- (*ppInstr)(_tmp, mode64); \
- vex_printf("\n\n"); \
- } \
- addHInstr ( instrs_out, _tmp ); \
+# define EMIT_INSTR(_instr) \
+ do { \
+ HInstr* _tmp = (_instr); \
+ if (DEBUG_REGALLOC) { \
+ vex_printf("** "); \
+ settings->ppInstr(_tmp, settings->mode64); \
+ vex_printf("\n\n"); \
+ } \
+ addHInstr(instrs_out->insns, _tmp); \
} while (0)
# define PRINT_STATE \
@@ -476,13 +445,13 @@
Int z, q; \
for (z = 0; z < n_rregs; z++) { \
vex_printf(" rreg_state[%2d] = ", z); \
- (*ppReg)(univ->regs[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 "); \
- (*ppReg)(rreg_state[z].vreg); \
+ settings->ppReg(rreg_state[z].vreg); \
vex_printf("\n"); break; \
} \
} \
@@ -503,12 +472,12 @@
/* --------- Stage 0: set up output array --------- */
/* --------- and allocate/initialise running state. --------- */
- instrs_out = newHInstrArray();
+ instrs_out = newHInstrSB();
/* ... and initialise running state. */
/* n_rregs is no more than a short name for n_available_real_regs. */
- n_rregs = univ->allocable;
- n_vregs = instrs_in->n_vregs;
+ 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);
@@ -557,7 +526,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);
+ = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->insns_used-1);
/* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
@@ -587,15 +556,16 @@
/* ------ start of ITERATE OVER INSNS ------ */
- for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
+ for (Int ii = 0; ii < instrs_in->insns_used; ii++) {
- (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
+ settings->getRegUsage(®_usage_arr[ii], instrs_in->insns[ii],
+ settings->mode64);
if (0) {
vex_printf("\n%d stage1: ", ii);
- (*ppInstr)(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
vex_printf("\n");
- ppHRegUsage(univ, ®_usage_arr[ii]);
+ ppHRegUsage(settings->univ, ®_usage_arr[ii]);
}
/* ------ start of DEAL WITH VREG LIVE RANGES ------ */
@@ -609,7 +579,7 @@
Int k = hregIndex(vreg);
if (k < 0 || k >= n_vregs) {
vex_printf("\n");
- (*ppInstr)(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
vex_printf("\n");
vex_printf("vreg %d, n_vregs %d\n", k, n_vregs);
vpanic("doRegisterAllocation: out-of-range vreg");
@@ -714,10 +684,10 @@
} else if (!isW && isR) {
if (rreg_live_after[j] == INVALID_INSTRNO) {
vex_printf("\nOFFENDING RREG = ");
- (*ppReg)(univ->regs[j]);
+ settings->ppReg(settings->univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
vex_printf("\n");
vpanic("doRegisterAllocation: "
"first event for rreg is Read");
@@ -727,10 +697,10 @@
vassert(isR && isW);
if (rreg_live_after[j] == INVALID_INSTRNO) {
vex_printf("\nOFFENDING RREG = ");
- (*ppReg)(univ->regs[j]);
+ settings->ppReg(settings->univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
vex_printf("\n");
vpanic("doRegisterAllocation: "
"first event for rreg is Modify");
@@ -744,7 +714,7 @@
ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
if (0)
vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
- rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
+ rreg_lrs_la[rreg_lrs_used].rreg = settings->univ->regs[j];
rreg_lrs_la[rreg_lrs_used].live_after = toShort(flush_la);
rreg_lrs_la[rreg_lrs_used].dead_before = toShort(flush_db);
rreg_lrs_used++;
@@ -781,7 +751,7 @@
if (0)
vex_printf("FLUSH 2 (%d,%d)\n",
rreg_live_after[j], rreg_dead_before[j]);
- rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
+ rreg_lrs_la[rreg_lrs_used].rreg = settings->univ->regs[j];
rreg_lrs_la[rreg_lrs_used].live_after = toShort(rreg_live_after[j]);
rreg_lrs_la[rreg_lrs_used].dead_before = toShort(rreg_dead_before[j]);
rreg_lrs_used++;
@@ -808,7 +778,7 @@
for (Int j = 0; j < n_rregs; j++) {
if (!rreg_state[j].has_hlrs)
continue;
- ppReg(univ->regs[j]);
+ settings->ppReg(settings->univ->regs[j]);
vex_printf(" hinted\n");
}
}
@@ -844,14 +814,14 @@
vex_printf("RRegLRs by LA:\n");
for (Int j = 0; j < rreg_lrs_used; j++) {
vex_printf(" ");
- (*ppReg)(rreg_lrs_la[j].rreg);
+ settings->ppReg(rreg_lrs_la[j].rreg);
vex_printf(" la = %d, db = %d\n",
rreg_lrs_la[j].live_after, rreg_lrs_la[j].dead_before );
}
vex_printf("RRegLRs by DB:\n");
for (Int j = 0; j < rreg_lrs_used; j++) {
vex_printf(" ");
- (*ppReg)(rreg_lrs_db[j].rreg);
+ settings->ppReg(rreg_lrs_db[j].rreg);
vex_printf(" la = %d, db = %d\n",
rreg_lrs_db[j].live_after, rreg_lrs_db[j].dead_before );
}
@@ -943,7 +913,7 @@
/* 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(guest_sizeB * 3 + ss_no * 8);
+ 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] );
@@ -979,16 +949,14 @@
correctly set up our running state, which tracks the status of
each real register. */
- insn_count = original_insn_count;
-
/* ------ BEGIN: Process each insn in turn. ------ */
- for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
+ for (Int ii = 0; ii < instrs_in->insns_used; ii++) {
if (DEBUG_REGALLOC) {
vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
vex_printf("---- ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
vex_printf("\n\nInitial state:\n");
PRINT_STATE;
vex_printf("\n");
@@ -1002,7 +970,7 @@
do_sanity_check
= toBool(
False /* Set to True for sanity checking of all insns. */
- || ii == instrs_in->arr_used-1
+ || ii == instrs_in->insns_used-1
|| (ii > 0 && (ii % 17) == 0)
);
@@ -1022,7 +990,7 @@
vex_printf("considering la %d .. db %d reg = ",
rreg_lrs_la[j].live_after,
rreg_lrs_la[j].dead_before);
- (*ppReg)(reg);
+ settings->ppReg(reg);
vex_printf("\n");
}
@@ -1063,7 +1031,7 @@
vassert(rreg_state[j].eq_spill_slot == False);
continue;
}
- vassert(hregClass(univ->regs[j])
+ vassert(hregClass(settings->univ->regs[j])
== hregClass(rreg_state[j].vreg));
vassert( hregIsVirtual(rreg_state[j].vreg));
}
@@ -1103,7 +1071,7 @@
the dst to the src's rreg, and that's all. */
HReg vregS = INVALID_HREG;
HReg vregD = INVALID_HREG;
- if ( (*isMove)( instrs_in->arr[ii], &vregS, &vregD ) ) {
+ if (settings->isMove(instrs_in->insns[ii], &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 ... */
@@ -1116,9 +1084,9 @@
if (vreg_lrs[m].live_after != ii) goto cannot_coalesce;
if (DEBUG_REGALLOC) {
vex_printf("COALESCE ");
- (*ppReg)(vregS);
+ settings->ppReg(vregS);
vex_printf(" -> ");
- (*ppReg)(vregD);
+ settings->ppReg(vregD);
vex_printf("\n\n");
}
/* Find the state entry for vregS. */
@@ -1167,7 +1135,7 @@
vreg_state[m] = INVALID_RREG_NO;
if (DEBUG_REGALLOC) {
vex_printf("free up ");
- (*ppReg)(univ->regs[j]);
+ settings->ppReg(settings->univ->regs[j]);
vex_printf("\n");
}
}
@@ -1208,7 +1176,7 @@
than before it. */
if (DEBUG_REGALLOC) {
vex_printf("need to free up rreg: ");
- (*ppReg)(rreg_lrs_la[rreg_lrs_la_next].rreg);
+ settings->ppReg(rreg_lrs_la[rreg_lrs_la_next].rreg);
vex_printf("\n\n");
}
Int k = hregIndex(rreg_lrs_la[rreg_lrs_la_next].rreg);
@@ -1227,8 +1195,8 @@
if ((!eq_spill_opt) || !rreg_state[k].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
- (*genSpill)( &spill1, &spill2, univ->regs[k],
- vreg_lrs[m].spill_offset, mode64 );
+ settings->genSpill(&spill1, &spill2, settings->univ->regs[k],
+ vreg_lrs[m].spill_offset, settings->mode64);
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
EMIT_INSTR(spill1);
@@ -1275,7 +1243,7 @@
that the change is invisible to the standard-case handling
that follows. */
- if (directReload && reg_usage_arr[ii].n_vRegs <= 2) {
+ if (settings->directReload != NULL && reg_usage_arr[ii].n_vRegs <= 2) {
Bool debug_direct_reload = False;
HReg cand = INVALID_HREG;
Bool nreads = 0;
@@ -1309,19 +1277,21 @@
vassert(! sameHReg(reg_usage_arr[ii].vRegs[0],
reg_usage_arr[ii].vRegs[1]));
- reloaded = directReload ( instrs_in->arr[ii], cand, spilloff );
+ reloaded = settings->directReload(instrs_in->insns[ii], cand,
+ spilloff);
if (debug_direct_reload && !reloaded) {
vex_printf("[%3d] ", spilloff); ppHReg(cand); vex_printf(" ");
- ppInstr(instrs_in->arr[ii], mode64);
+ settings->ppInstr(instrs_in->insns[ii], settings->mode64);
}
if (reloaded) {
/* Update info about the insn, so it looks as if it had
been in this form all along. */
- instrs_in->arr[ii] = reloaded;
- (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
+ instrs_in->insns[ii] = reloaded;
+ settings->getRegUsage(®_usage_arr[ii], instrs_in->insns[ii],
+ settings->mode64);
if (debug_direct_reload && !reloaded) {
vex_printf(" --> ");
- ppInstr(reloaded, mode64);
+ settings->ppInstr(reloaded, settings->mode64);
}
}
@@ -1340,7 +1310,7 @@
vassert(hregIsVirtual(vreg));
if (0) {
- vex_printf("considering "); (*ppReg)(vreg); vex_printf("\n");
+ vex_printf("considering "); settings->ppReg(vreg); vex_printf("\n");
}
/* Now we're trying to find a rreg for "vreg". First of all,
@@ -1351,7 +1321,7 @@
Int n = vreg_state[m];
if (IS_VALID_RREGNO(n)) {
vassert(rreg_state[n].disp == Bound);
- addToHRegRemap(&remap, vreg, univ->regs[n]);
+ 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)
@@ -1370,7 +1340,7 @@
Int k;
for (k = 0; k < n_rregs; k++) {
if (rreg_state[k].disp != Free
- || hregClass(univ->regs[k]) != hregClass(vreg))
+ || hregClass(settings->univ->regs[k]) != hregClass(vreg))
continue;
if (rreg_state[k].has_hlrs) {
/* Well, at least we can use k_suboptimal if we really
@@ -1391,7 +1361,7 @@
Int p = hregIndex(vreg);
vassert(IS_VALID_VREGNO(p));
vreg_state[p] = toShort(k);
- addToHRegRemap(&remap, vreg, univ->regs[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
guarantee that the first event for a vreg is a write.
@@ -1402,8 +1372,8 @@
vassert(vreg_lrs[p].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
- (*genReload)( &reload1, &reload2, univ->regs[k],
- vreg_lrs[p].spill_offset, mode64 );
+ settings->genReload(&reload1, &reload2, settings->univ->regs[k],
+ vreg_lrs[p].spill_offset, settings->mode64);
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
EMIT_INSTR(reload1);
@@ -1437,7 +1407,7 @@
rreg_state[k].is_spill_cand = False;
if (rreg_state[k].disp != Bound)
continue;
- if (hregClass(univ->regs[k]) != hregClass(vreg))
+ if (hregClass(settings->univ->regs[k]) != hregClass(vreg))
continue;
rreg_state[k].is_spill_cand = True;
/* Note, the following loop visits only the virtual regs
@@ -1457,7 +1427,7 @@
of consequent reloads required. */
Int spillee
= findMostDistantlyMentionedVReg (
- reg_usage_arr, ii+1, instrs_in->arr_used, rreg_state, n_rregs );
+ reg_usage_arr, ii+1, instrs_in->insns_used, rreg_state, n_rregs );
if (spillee == -1) {
/* Hmmmmm. There don't appear to be any spill candidates.
@@ -1472,7 +1442,7 @@
vassert(IS_VALID_RREGNO(spillee));
vassert(rreg_state[spillee].disp == Bound);
/* check it's the right class */
- vassert(hregClass(univ->regs[spillee]) == hregClass(vreg));
+ 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));
@@ -1487,8 +1457,8 @@
if ((!eq_spill_opt) || !rreg_state[spillee].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
- (*genSpill)( &spill1, &spill2, univ->regs[spillee],
- vreg_lrs[m].spill_offset, mode64 );
+ settings->genSpill(&spill1, &spill2, settings->univ->regs[spillee],
+ vreg_lrs[m].spill_offset, settings->mode64);
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
EMIT_INSTR(spill1);
@@ -1513,8 +1483,9 @@
vassert(vreg_lrs[m].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
- (*genReload)( &reload1, &reload2, univ->regs[spillee],
- vreg_lrs[m].spill_offset, mode64 );
+ settings->genReload(&reload1, &reload2,
+ settings->univ->regs[spillee],
+ vreg_lrs[m].spill_offset, settings->mode64);
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
EMIT_INSTR(reload1);
@@ -1533,7 +1504,7 @@
/* So after much twisting and turning, we have vreg mapped to
rreg_state[spillee].rreg. Note that in the map. */
- addToHRegRemap(&remap, vreg, univ->regs[spillee]);
+ addToHRegRemap(&remap, vreg, settings->univ->regs[spillee]);
} /* iterate over virtual registers in this instruction. */
@@ -1548,9 +1519,9 @@
and emit that.
*/
- /* NOTE, DESTRUCTIVELY MODIFIES instrs_in->arr[ii]. */
- (*mapRegs)( &remap, instrs_in->arr[ii], mode64 );
- EMIT_INSTR( instrs_in->arr[ii] );
+ /* NOTE, DESTRUCTIVELY MODIFIES instrs_in->insns[ii]. */
+ settings->mapRegs(&remap, instrs_in->insns[ii], settings->mode64);
+ EMIT_INSTR(instrs_in->insns[ii]);
if (DEBUG_REGALLOC) {
vex_printf("After dealing with current insn:\n");
@@ -1610,10 +1581,6 @@
# undef PRINT_STATE
}
-static UInt count_longest_insn_seq(HInstrVec* insns,
- HInstrIfThenElse* (*isIfThenElse)(const HInstr*))
-{
- UInt longest_insn_count = 0;
/*---------------------------------------------------------------*/
Modified: branches/VEX_JIT_HACKS/priv/host_generic_regs.h
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_regs.h (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_regs.h Thu Jun 8 13:15:50 2017
@@ -486,45 +486,58 @@
/*--- Reg alloc: TODO: move somewhere else ---*/
/*---------------------------------------------------------*/
+/* Settings for the register allocator. Immutable (do not change at all). */
+typedef
+ struct {
+ /* The real-register universe to use. This contains facts about
+ real registers, one of which is the set of registers available
+ for allocation. */
+ const RRegUniverse* univ;
+
+ /* Return True iff the given insn is a reg-reg move, in which
+ case also return the src and dst regs. */
+ Bool (*isMove)(const HInstr*, HReg*, HReg*);
+
+ /* Get info about register usage in this insn. */
+ void (*getRegUsage)(HRegUsage*, const HInstr*, Bool);
+
+ /* Apply a reg-reg mapping to an insn. */
+ void (*mapRegs)(HRegRemap*, HInstr*, Bool);
+
+ /* Is this instruction actually HInstrIfThenElse? */
+ HInstrIfThenElse* (*isIfThenElse)(const HInstr*);
+
+ /* Return one, or, if we're unlucky, two insn(s) to spill/restore a
+ real reg to a spill slot byte offset. The two leading HInstr**
+ args are out parameters, through which the generated insns are
+ returned. Also (optionally) a 'directReload' function, which
+ attempts to replace a given instruction by one which reads
+ directly from a specified spill slot. May be NULL, in which
+ case the optimisation is not attempted. */
+ void (*genSpill)( HInstr**, HInstr**, HReg, Int, Bool);
+ void (*genReload)( HInstr**, HInstr**, HReg, Int, Bool);
+ HInstr* (*directReload)( HInstr*, HReg, Short);
+ UInt guest_sizeB;
+
+ /* For debug printing only. */
+ void (*ppInstr)(const HInstr*, Bool);
+ void (*ppCondCode)(HCondCode);
+ void (*ppReg)(HReg);
+
+ /* 32/64bit mode */
+ Bool mode64;
+ }
+ RegAllocSettings;
+
+
extern
HInstrSB* doRegisterAllocation (
/* Incoming virtual-registerised code. */
HInstrSB* sb_in,
- /* The real-register universe to use. This contains facts about
- real registers, one of which is the set of registers available
- for allocation. */
- const RRegUniverse* univ,
-
- /* Return True iff the given insn is a reg-reg move, in which
- case also return the src and dst regs. */
- Bool (*isMove) (const HInstr*, HReg*, HReg*),
-
- /* Get info about register usage in this insn. */
- void (*getRegUsage) (HRegUsage*, const HInstr*, Bool),
-
- /* Apply a reg-reg mapping to an insn. */
- void (*mapRegs) (HRegRemap*, HInstr*, Bool),
-
- /* Is this instruction actually HInstrIfThenElse? Returns pointer to
- HInstrIfThenElse if yes, NULL otherwise. */
- HInstrIfThenElse* (*isIfThenElse) (const HInstr*),
-
- /* Return insn(s) to spill/restore a real reg to a spill slot
- offset. And optionally a function to do direct reloads. */
- void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ),
- void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
- HInstr* (*directReload) ( HInstr*, HReg, Short ),
- Int guest_sizeB,
-
- /* For debug printing only. */
- void (*ppInstr) ( const HInstr*, Bool ),
- void (*ppCondCode)(HCondCode),
- void (*ppReg) ( HReg ),
-
- /* 32/64bit mode */
- Bool mode64
+ /* Register allocator settings. */
+ const RegAllocSettings* 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 Thu Jun 8 13:15:50 2017
@@ -1052,11 +1052,13 @@
}
/* Register allocate. */
- rcode = doRegisterAllocation ( vcode, rRegUniv,
- isMove, getRegUsage, mapRegs, isIfThenElse,
- genSpill, genReload, directReload,
- guest_sizeB,
- ppInstr, ppCondCode, ppReg, mode64 );
+ RegAllocSettings settings = {
+ .univ = rRegUniv, .isMove = isMove, .getRegUsage = getRegUsage,
+ .mapRegs = mapRegs, .isIfThenElse = isIfThenElse, .genSpill = genSpill,
+ .genReload = genReload, .directReload = directReload,
+ .guest_sizeB = guest_sizeB, .ppInstr = ppInstr, .ppCondCode = ppCondCode,
+ .ppReg = ppReg, .mode64 = mode64};
+ rcode = doRegisterAllocation(vcode, &settings);
vexAllocSanityCheck();
|
|
From: <sv...@va...> - 2017-06-08 11:02:56
|
Author: iraisr
Date: Thu Jun 8 12:02:44 2017
New Revision: 3387
Log:
Revert VEX register allocator back to the original state from r3309.\nI will introduce modifications in small steps rather than in a giant leap.
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 Thu Jun 8 12:02:44 2017
@@ -33,6 +33,8 @@
without prior written permission.
*/
+/* Copyright (C) 2017-2017 Ivo Raisr <iv...@iv...> */
+
#include "libvex_basictypes.h"
#include "libvex.h"
@@ -90,7 +92,7 @@
disposition of each allocatable real register is. The array gets
updated as the allocator processes instructions. The identity of
the register is not recorded here, because the index of this
- structure in doRegisterAllocation()'s |rreg_state| is the index
+ structure in RegAllocState's |rreg_state| is the index
number of the register, and the register itself can be extracted
from the RRegUniverse supplied to doRegisterAllocation(). */
typedef
@@ -109,7 +111,7 @@
vreg. Is safely left at False, and becomes True after a
spill store or reload for this rreg. */
Bool eq_spill_slot;
- /* What's it's current disposition? */
+ /* What's its current disposition? */
enum { Free, /* available for use */
Unavail, /* in a real-reg live range */
Bound /* in use (holding value of some vreg) */
@@ -140,8 +142,8 @@
#define INVALID_RREG_NO ((Short)(-1))
-#define IS_VALID_VREGNO(_zz) ((_zz) >= 0 && (_zz) < state->n_vregs)
-#define IS_VALID_RREGNO(_zz) ((_zz) >= 0 && (_zz) < state->n_rregs)
+#define IS_VALID_VREGNO(_zz) ((_zz) >= 0 && (_zz) < n_vregs)
+#define IS_VALID_RREGNO(_zz) ((_zz) >= 0 && (_zz) < n_rregs)
/* Search forward from some given point in the incoming instruction
@@ -155,7 +157,7 @@
considered.
To do this we don't actually need to see the incoming instruction
- stream. Rather, what we need is the HRegUsage records for the
+ stream. Rather, what we need us the HRegUsage records for the
incoming instruction stream. Hence that is passed in.
Returns an index into the state array indicating the (v,r) pair to
@@ -205,20 +207,21 @@
/* Double the size of the real-reg live-range array, if needed. */
__attribute__((noinline))
-static void ensureRRLRspace_SLOW(RRegLR** info, UInt* size, UInt used)
+static void ensureRRLRspace_SLOW ( RRegLR** info, Int* size, Int used )
{
+ Int k;
RRegLR* arr2;
if (0)
- vex_printf("ensureRRLRspace: %u -> %u\n", *size, 2 * *size);
+ vex_printf("ensureRRISpace: %d -> %d\n", *size, 2 * *size);
vassert(used == *size);
arr2 = LibVEX_Alloc_inline(2 * *size * sizeof(RRegLR));
- for (UInt k = 0; k < *size; k++)
+ for (k = 0; k < *size; k++)
arr2[k] = (*info)[k];
*size *= 2;
*info = arr2;
}
inline
-static void ensureRRLRspace(RRegLR** info, UInt* size, UInt used)
+static void ensureRRLRspace ( RRegLR** info, Int* size, Int used )
{
if (LIKELY(used < *size)) return;
ensureRRLRspace_SLOW(info, size, used);
@@ -228,7 +231,7 @@
/* Sort an array of RRegLR entries by either the .live_after or
.dead_before fields. This is performance-critical. */
static void sortRRLRarray ( RRegLR* arr,
- UInt size, Bool by_live_after )
+ Int size, Bool by_live_after )
{
Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
9841, 29524, 88573, 265720,
@@ -335,330 +338,318 @@
# undef IS_4_ALIGNED
}
-#define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
-STATIC_ASSERT((N_SPILL64S % 2) == 0);
-/* Register allocator state. Keeps all vital information at one place. */
-typedef
- struct {
- /* The real-register universe to use. This contains facts about
- real registers, one of which is the set of registers available
- for allocation. */
- const RRegUniverse* univ;
-
- /* Info on vregs. Computed once and remains unchanged. */
- UInt n_vregs;
- VRegLR* vreg_lrs; /* [0 .. n_vregs-1] */
-
- /* Used when constructing vreg_lrs (for allocating stack slots). */
- Short ss_busy_until_before[N_SPILL64S];
-
- /* 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 _db variant. Once
- that's done both of them are sorted. We also need two integer cursors
- which record the next location in the two arrays to consider. */
- RRegLR* rreg_lrs_la;
- RRegLR* rreg_lrs_db;
- UInt rreg_lrs_size;
- UInt rreg_lrs_used;
- UInt rreg_lrs_la_next;
- UInt rreg_lrs_db_next;
-
- /* Info on register usage in the incoming HInstrVec.
- 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] */
-
- /* Used when constructing rreg_lrs. */
- UInt* rreg_live_after;
- UInt* rreg_dead_before;
-
- /* 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 inplies n_rregs must be <= 32768. */
- Short* vreg_state; /* [0 .. n_vregs-1] */
-
- /* Return True iff the given insn is a reg-reg move, in which
- case also return the src and dst regs. */
- Bool (*isMove)(const HInstr*, HReg*, HReg*);
-
- /* Get info about register usage in this insn. */
- void (*getRegUsage)(HRegUsage*, const HInstr*, Bool);
-
- /* Apply a reg-reg mapping to an insn. */
- void (*mapRegs)(HRegRemap*, HInstr*, Bool);
-
- /* Is this instruction actually HInstrIfThenElse? */
- HInstrIfThenElse* (*isIfThenElse)(const HInstr*);
-
- /* Return one, or, if we're unlucky, two insn(s) to spill/restore a
- real reg to a spill slot byte offset. The two leading HInstr**
- args are out parameters, through which the generated insns are
- returned. Also (optionally) a 'directReload' function, which
- attempts to replace a given instruction by one which reads
- directly from a specified spill slot. May be NULL, in which
- case the optimisation is not attempted. */
- void (*genSpill)( HInstr**, HInstr**, HReg, Int, Bool);
- void (*genReload)( HInstr**, HInstr**, HReg, Int, Bool);
- HInstr* (*directReload)( HInstr*, HReg, Short);
- UInt guest_sizeB;
-
- /* For debug printing only. */
- void (*ppInstr)(const HInstr*, Bool);
- void (*ppCondCode)(HCondCode);
- void (*ppReg)(HReg);
-
- /* 32/64bit mode */
- Bool mode64;
- }
- RegAllocState;
-
-#define INVALID_INSTRNO (-2)
-
-static void initRegAllocState(RegAllocState* state, const RRegUniverse* univ,
- Bool (*isMove)(const HInstr*, HReg*, HReg*),
- void (*getRegUsage)(HRegUsage*, const HInstr*, Bool),
- void (*mapRegs)(HRegRemap*, HInstr*, Bool),
- HInstrIfThenElse* (*isIfThenElse)(const HInstr*),
- void (*genSpill)( HInstr**, HInstr**, HReg, Int, Bool),
- void (*genReload)( HInstr**, HInstr**, HReg, Int, Bool),
- HInstr* (*directReload)( HInstr*, HReg, Short),
- UInt guest_sizeB,
- void (*ppInstr)(const HInstr*, Bool), void (*ppCondCode)(HCondCode),
- void (*ppReg)(HReg), Bool mode64, const HInstrVec* instrs_in, UInt n_vregs)
+/* 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.
+
+ 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.
+*/
+HInstrArray* doRegisterAllocation (
+
+ /* Incoming virtual-registerised code. */
+ HInstrArray* instrs_in,
+
+ /* The real-register universe to use. This contains facts about
+ real registers, one of which is the set of registers available
+ for allocation. */
+ const RRegUniverse* univ,
+
+ /* Return True iff the given insn is a reg-reg move, in which
+ case also return the src and dst regs. */
+ Bool (*isMove) ( const HInstr*, HReg*, HReg* ),
+
+ /* Get info about register usage in this insn. */
+ void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool ),
+
+ /* Apply a reg-reg mapping to an insn. */
+ void (*mapRegs) ( HRegRemap*, HInstr*, Bool ),
+
+ /* Return one, or, if we're unlucky, two insn(s) to spill/restore a
+ real reg to a spill slot byte offset. The two leading HInstr**
+ args are out parameters, through which the generated insns are
+ returned. Also (optionally) a 'directReload' function, which
+ attempts to replace a given instruction by one which reads
+ directly from a specified spill slot. May be NULL, in which
+ case the optimisation is not attempted. */
+ void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ),
+ void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
+ HInstr* (*directReload) ( HInstr*, HReg, Short ),
+ Int guest_sizeB,
+
+ /* For debug printing only. */
+ void (*ppInstr) ( const HInstr*, Bool ),
+ void (*ppReg) ( HReg ),
+
+ /* 32/64bit mode */
+ Bool mode64
+)
{
- /* Initialize Register Allocator state. */
- state->univ = univ;
- state->isMove = isMove;
- state->getRegUsage = getRegUsage;
- state->mapRegs = mapRegs;
- state->isIfThenElse = isIfThenElse;
- state->genSpill = genSpill;
- state->genReload = genReload;
- state->directReload = directReload;
- state->guest_sizeB = guest_sizeB;
- state->ppInstr = ppInstr;
- state->ppCondCode = ppCondCode;
- state->ppReg = ppReg;
- state->mode64 = mode64;
+# define N_SPILL64S (LibVEX_N_SPILL_BYTES / 8)
- /* n_rregs is no more than a short name for n_available_real_regs. */
- state->n_rregs = univ->allocable;
- state->n_vregs = n_vregs;
+ const Bool eq_spill_opt = True;
- /* If this is not so, vreg_state entries will overflow. */
- vassert(state->n_vregs < 32767);
+ /* 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
+ by .live_after and the other by .dead_before. First the
+ unsorted info is created in the _la variant is copied into the
+ _db variant. Once that's done both of them are sorted.
+ We also need two integer cursors which record the next
+ location in the two arrays to consider. */
+ RRegLR* rreg_lrs_la;
+ RRegLR* rreg_lrs_db;
+ Int rreg_lrs_size;
+ Int rreg_lrs_used;
+ Int rreg_lrs_la_next;
+ Int rreg_lrs_db_next;
+
+ /* 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->arr_used-1] */
+
+ /* Used when constructing vreg_lrs (for allocating stack
+ slots). */
+ Short ss_busy_until_before[N_SPILL64S];
+
+ /* Used when constructing rreg_lrs. */
+ 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;
- /* If this is not so, the universe we have is nonsensical. */
- vassert(state->n_rregs > 0);
+ /* The output array of instructions. */
+ HInstrArray* instrs_out;
- state->rreg_state = LibVEX_Alloc_inline(state->n_rregs * sizeof(RRegState));
- state->vreg_state = LibVEX_Alloc_inline(state->n_vregs * sizeof(Short));
+ /* Sanity checks are expensive. They are only done periodically,
+ not at each insn processed. */
+ Bool do_sanity_check;
- for (UInt i = 0; i < state->n_rregs; i++) {
- state->rreg_state[i].has_hlrs = False;
- state->rreg_state[i].disp = Free;
- state->rreg_state[i].vreg = INVALID_HREG;
- state->rreg_state[i].is_spill_cand = False;
- state->rreg_state[i].eq_spill_slot = False;
- }
+ vassert(0 == (guest_sizeB % LibVEX_GUEST_STATE_ALIGN));
+ vassert(0 == (LibVEX_N_SPILL_BYTES % LibVEX_GUEST_STATE_ALIGN));
+ vassert(0 == (N_SPILL64S % 2));
- for (UInt i = 0; i < n_vregs; i++)
- state->vreg_state[i] = INVALID_RREG_NO;
+ /* 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->arr_used <= 15000);
+# define INVALID_INSTRNO (-2)
- /* Initialize vreg live ranges. */
+# define EMIT_INSTR(_instr) \
+ do { \
+ HInstr* _tmp = (_instr); \
+ if (DEBUG_REGALLOC) { \
+ vex_printf("** "); \
+ (*ppInstr)(_tmp, mode64); \
+ vex_printf("\n\n"); \
+ } \
+ addHInstr ( instrs_out, _tmp ); \
+ } while (0)
- /* This is relatively simple, because (1) we only seek the complete
- end-to-end live range of each vreg, and are not interested in
- any holes in it, and (2) the vregs are conveniently numbered 0
- .. n_vregs-1, so we can just dump the results in a
- pre-allocated array. */
+# define PRINT_STATE \
+ do { \
+ Int z, q; \
+ for (z = 0; z < n_rregs; z++) { \
+ vex_printf(" rreg_state[%2d] = ", z); \
+ (*ppReg)(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 "); \
+ (*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"); \
+ } while (0)
- state->vreg_lrs = NULL;
- if (state->n_vregs > 0)
- state->vreg_lrs = LibVEX_Alloc_inline(sizeof(VRegLR) * state->n_vregs);
- for (UInt i = 0; i < state->n_vregs; i++) {
- state->vreg_lrs[i].live_after = INVALID_INSTRNO;
- state->vreg_lrs[i].dead_before = INVALID_INSTRNO;
- state->vreg_lrs[i].spill_offset = 0;
- state->vreg_lrs[i].spill_size = 0;
- state->vreg_lrs[i].reg_class = HRcINVALID;
- }
+ /* --------- Stage 0: set up output array --------- */
+ /* --------- and allocate/initialise running state. --------- */
- /* An array to hold the reg-usage info for the incoming instructions. */
- state->reg_usage_arr
- = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->insns_used-1);
+ instrs_out = newHInstrArray();
+ /* ... and initialise running state. */
+ /* n_rregs is no more than a short name for n_available_real_regs. */
+ n_rregs = univ->allocable;
+ n_vregs = instrs_in->n_vregs;
- /* Initialize rreg live ranges. */
+ /* If this is not so, vreg_state entries will overflow. */
+ vassert(n_vregs < 32767);
- /* This is more complex than previous step, because we need to compute
- exactly all the live ranges of all the allocatable real regs,
- and we don't know in advance how many there will be. */
+ /* If this is not so, the universe we have is nonsensical. */
+ vassert(n_rregs > 0);
- state->rreg_lrs_used = 0;
- state->rreg_lrs_size = 4;
- state->rreg_lrs_la
- = LibVEX_Alloc_inline(state->rreg_lrs_size * sizeof(RRegLR));
- state->rreg_lrs_db = NULL; /* Will be created later. */
-
- /* Track live range start/end points seperately for each rreg. Sigh. */
- vassert(state->n_rregs > 0);
- state->rreg_live_after = LibVEX_Alloc_inline(state->n_rregs * sizeof(UInt));
- state->rreg_dead_before = LibVEX_Alloc_inline(state->n_rregs * sizeof(UInt));
+ rreg_state = LibVEX_Alloc_inline(n_rregs * sizeof(RRegState));
+ vreg_state = LibVEX_Alloc_inline(n_vregs * sizeof(Short));
- for (UInt i = 0; i < state->n_rregs; i++) {
- state->rreg_live_after[i] = state->rreg_dead_before[i] = INVALID_INSTRNO;
+ 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;
}
- local_memset(state->ss_busy_until_before, 0,
- sizeof(state->ss_busy_until_before));
-}
+ for (Int j = 0; j < n_vregs; j++)
+ vreg_state[j] = INVALID_RREG_NO;
-static void print_state(const RegAllocState* state)
-{
- for (UInt i = 0; i < state->n_rregs; i++) {
- vex_printf(" rreg_state[%2d] = ", i);
- state->ppReg(state->univ->regs[i]);
- vex_printf(" \t");
-
- switch (state->rreg_state[i].disp) {
- case Free: vex_printf("Free\n"); break;
- case Unavail: vex_printf("Unavail\n"); break;
- case Bound: vex_printf("BoundTo ");
- state->ppReg(state->rreg_state[i].vreg);
- vex_printf("\n"); break;
- }
- }
- vex_printf("\n vreg_state[0 .. %u]:\n ", state->n_vregs - 1);
- UInt j = 0;
- for (UInt i = 0; i < state->n_vregs; i++) {
- if (state->vreg_state[i] == INVALID_RREG_NO)
- continue;
- vex_printf("[%u] -> %d ", i, state->vreg_state[i]);
- j++;
- if (j > 0 && (j % 6) == 0)
- vex_printf("\n ");
- }
+ /* --------- Stage 1: compute vreg live ranges. --------- */
+ /* --------- Stage 2: compute rreg live ranges. --------- */
- vex_printf("\n");
-}
+ /* ------ start of SET UP TO COMPUTE VREG LIVE RANGES ------ */
-/* 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.
+ /* This is relatively simple, because (1) we only seek the complete
+ end-to-end live range of each vreg, and are not interested in
+ any holes in it, and (2) the vregs are conveniently numbered
+ 0 .. n_vregs-1, so we can just dump the results
+ in a pre-allocated array. */
- Returns a new vector of instructions, which, as a result of the
- behaviour of mapRegs, will be in-place modifications of the
- original instructions.
+ vreg_lrs = NULL;
+ if (n_vregs > 0)
+ vreg_lrs = LibVEX_Alloc_inline(sizeof(VRegLR) * n_vregs);
- Takes a vector of unallocated insns. Returns a vector of allocated insns.
- Both vectors have the same structure, including any HInstrIfThenElse.
-*/
-static HInstrVec* regAlloc_HInstrVec(RegAllocState* state,
- const HInstrVec* instrs_in)
-{
- const Bool eq_spill_opt = True;
+ 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;
+ }
- /* The live range numbers are signed shorts, and so limiting the
- number of insns to 15000 comfortably guards against them
- overflowing 32k. */
- /* TODO-JIT: this is incorrect w.r.t. IfThenElse */
- vassert(instrs_in->insns_used <= 15000);
+ /* 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);
-# define EMIT_INSTR(_instr) \
- do { \
- HInstr* _tmp = (_instr); \
- if (DEBUG_REGALLOC) { \
- vex_printf("** "); \
- state->ppInstr(_tmp, state->mode64); \
- vex_printf("\n\n"); \
- } \
- addHInstr(instrs_out, _tmp); \
- } while (0)
+ /* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
+
+ /* ------ start of SET UP TO COMPUTE RREG LIVE RANGES ------ */
- /* --------- Stage 0: set up --------- */
- HInstrVec* instrs_out = newHInstrVec();
+ /* This is more complex than Stage 1, because we need to compute
+ exactly all the live ranges of all the allocatable real regs,
+ and we don't know in advance how many there will be. */
+ rreg_lrs_used = 0;
+ rreg_lrs_size = 4;
+ rreg_lrs_la = LibVEX_Alloc_inline(rreg_lrs_size * sizeof(RRegLR));
+ rreg_lrs_db = NULL; /* we'll create this later */
+
+ /* 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));
+
+ for (Int j = 0; j < n_rregs; j++) {
+ rreg_live_after[j] =
+ rreg_dead_before[j] = INVALID_INSTRNO;
+ }
- /* --------- Stage 1: iterate over instructins --------- */
+ /* ------ end of SET UP TO COMPUTE RREG LIVE RANGES ------ */
/* ------ start of ITERATE OVER INSNS ------ */
- for (UInt ii = 0; ii < instrs_in->insns_used; ii++) {
- const HInstr* instr = instrs_in->insns[ii];
-
- if (state->isIfThenElse(instr) != NULL) {
- vpanic("regAlloc_HInstrVec: IfThenElse unimplemented");
- }
+ for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
- state->getRegUsage(&state->reg_usage_arr[ii], instr, state->mode64);
+ (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
if (0) {
- vex_printf("\n%u stage1: ", ii);
- state->ppInstr(instr, state->mode64);
+ vex_printf("\n%d stage1: ", ii);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
vex_printf("\n");
- ppHRegUsage(state->univ, &state->reg_usage_arr[ii]);
+ ppHRegUsage(univ, ®_usage_arr[ii]);
}
/* ------ start of DEAL WITH VREG LIVE RANGES ------ */
/* for each virtual reg mentioned in the insn ... */
- for (UInt j = 0; j < state->reg_usage_arr[ii].n_vRegs; j++) {
+ for (Int j = 0; j < reg_usage_arr[ii].n_vRegs; j++) {
- HReg vreg = state->reg_usage_arr[ii].vRegs[j];
+ HReg vreg = reg_usage_arr[ii].vRegs[j];
vassert(hregIsVirtual(vreg));
Int k = hregIndex(vreg);
- if (k < 0 || k >= state->n_vregs) {
+ if (k < 0 || k >= n_vregs) {
vex_printf("\n");
- state->ppInstr(instr, state->mode64);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
vex_printf("\n");
- vex_printf("vreg %d, n_vregs %u\n", k, state->n_vregs);
- vpanic("regAlloc_HInstrVec: out-of-range vreg");
+ vex_printf("vreg %d, n_vregs %d\n", k, n_vregs);
+ vpanic("doRegisterAllocation: out-of-range vreg");
}
/* Take the opportunity to note its regclass. We'll need
that when allocating spill slots. */
- if (state->vreg_lrs[k].reg_class == HRcINVALID) {
+ if (vreg_lrs[k].reg_class == HRcINVALID) {
/* First mention of this vreg. */
- state->vreg_lrs[k].reg_class = hregClass(vreg);
+ vreg_lrs[k].reg_class = hregClass(vreg);
} else {
/* Seen it before, so check for consistency. */
- vassert(state->vreg_lrs[k].reg_class == hregClass(vreg));
+ vassert(vreg_lrs[k].reg_class == hregClass(vreg));
}
/* Now consider live ranges. */
- switch (state->reg_usage_arr[ii].vMode[j]) {
+ switch (reg_usage_arr[ii].vMode[j]) {
case HRmRead:
- if (state->vreg_lrs[k].live_after == INVALID_INSTRNO) {
+ if (vreg_lrs[k].live_after == INVALID_INSTRNO) {
vex_printf("\n\nOFFENDING VREG = %d\n", k);
- vpanic("regAlloc_HInstrVec: first event for vreg is Read");
+ vpanic("doRegisterAllocation: "
+ "first event for vreg is Read");
}
- state->vreg_lrs[k].dead_before = toShort(ii + 1);
+ vreg_lrs[k].dead_before = toShort(ii + 1);
break;
case HRmWrite:
- 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);
+ if (vreg_lrs[k].live_after == INVALID_INSTRNO)
+ vreg_lrs[k].live_after = toShort(ii);
+ vreg_lrs[k].dead_before = toShort(ii + 1);
break;
case HRmModify:
- if (state->vreg_lrs[k].live_after == INVALID_INSTRNO) {
+ if (vreg_lrs[k].live_after == INVALID_INSTRNO) {
vex_printf("\n\nOFFENDING VREG = %d\n", k);
- vpanic("regAlloc_HInstrVec: first event for vreg is Modify");
+ vpanic("doRegisterAllocation: "
+ "first event for vreg is Modify");
}
- state->vreg_lrs[k].dead_before = toShort(ii + 1);
+ vreg_lrs[k].dead_before = toShort(ii + 1);
break;
default:
- vpanic("regAlloc_HInstrVec(1)");
+ vpanic("doRegisterAllocation(1)");
} /* switch */
} /* iterate over virtual registers */
@@ -669,10 +660,10 @@
/* If this doesn't hold, the following iteration over real registers
will fail miserably. */
- STATIC_ASSERT(N_RREGUNIVERSE_REGS == 64);
+ vassert(N_RREGUNIVERSE_REGS == 64);
- const ULong rRead = state->reg_usage_arr[ii].rRead;
- const ULong rWritten = state->reg_usage_arr[ii].rWritten;
+ const ULong rRead = reg_usage_arr[ii].rRead;
+ const ULong rWritten = reg_usage_arr[ii].rWritten;
const ULong rMentioned = rRead | rWritten;
UInt rReg_minIndex;
@@ -689,8 +680,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 >= state->n_rregs)
- rReg_maxIndex = state->n_rregs-1;
+ if (rReg_maxIndex >= n_rregs)
+ rReg_maxIndex = n_rregs-1;
}
/* for each allocator-available real reg mentioned in the insn ... */
@@ -714,48 +705,49 @@
Bool flush = False;
if (isW && !isR) {
- flush_la = state->rreg_live_after[j];
- flush_db = state->rreg_dead_before[j];
+ flush_la = rreg_live_after[j];
+ flush_db = rreg_dead_before[j];
if (flush_la != INVALID_INSTRNO && flush_db != INVALID_INSTRNO)
flush = True;
- state->rreg_live_after[j] = ii;
- state->rreg_dead_before[j] = ii+1;
+ rreg_live_after[j] = ii;
+ rreg_dead_before[j] = ii+1;
} else if (!isW && isR) {
- if (state->rreg_live_after[j] == INVALID_INSTRNO) {
+ if (rreg_live_after[j] == INVALID_INSTRNO) {
vex_printf("\nOFFENDING RREG = ");
- state->ppReg(state->univ->regs[j]);
+ (*ppReg)(univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- state->ppInstr(instr, state->mode64);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
vex_printf("\n");
- vpanic("regAlloc_HInstrVec: first event for rreg is Read");
+ vpanic("doRegisterAllocation: "
+ "first event for rreg is Read");
}
- state->rreg_dead_before[j] = ii+1;
+ rreg_dead_before[j] = ii+1;
} else {
vassert(isR && isW);
- if (state->rreg_live_after[j] == INVALID_INSTRNO) {
+ if (rreg_live_after[j] == INVALID_INSTRNO) {
vex_printf("\nOFFENDING RREG = ");
- state->ppReg(state->univ->regs[j]);
+ (*ppReg)(univ->regs[j]);
vex_printf("\n");
vex_printf("\nOFFENDING instr = ");
- state->ppInstr(instr, state->mode64);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
vex_printf("\n");
- vpanic("regAlloc_HInstrVec: first event for rreg is Modify");
+ vpanic("doRegisterAllocation: "
+ "first event for rreg is Modify");
}
- state->rreg_dead_before[j] = ii+1;
+ rreg_dead_before[j] = ii+1;
}
if (flush) {
vassert(flush_la != INVALID_INSTRNO);
vassert(flush_db != INVALID_INSTRNO);
- UInt used = state->rreg_lrs_used;
- ensureRRLRspace(&state->rreg_lrs_la, &state->rreg_lrs_size, used);
+ ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
if (0)
vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
- state->rreg_lrs_la[used].rreg = state->univ->regs[j];
- state->rreg_lrs_la[used].live_after = toShort(flush_la);
- state->rreg_lrs_la[used].dead_before = toShort(flush_db);
- state->rreg_lrs_used++;
+ rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
+ rreg_lrs_la[rreg_lrs_used].live_after = toShort(flush_la);
+ rreg_lrs_la[rreg_lrs_used].dead_before = toShort(flush_db);
+ rreg_lrs_used++;
}
} /* iterate over rregs in the instr */
@@ -769,32 +761,30 @@
/* ------ start of FINALISE RREG LIVE RANGES ------ */
/* Now finish up any live ranges left over. */
- for (UInt j = 0; j < state->n_rregs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
if (0) {
- vex_printf("residual %u: %u %u\n", j, state->rreg_live_after[j],
- state->rreg_dead_before[j]);
+ vex_printf("residual %d: %d %d\n", j, rreg_live_after[j],
+ rreg_dead_before[j]);
}
- vassert( (state->rreg_live_after[j] == INVALID_INSTRNO
- && state->rreg_dead_before[j] == INVALID_INSTRNO)
+ vassert( (rreg_live_after[j] == INVALID_INSTRNO
+ && rreg_dead_before[j] == INVALID_INSTRNO)
||
- (state->rreg_live_after[j] != INVALID_INSTRNO
- && state->rreg_dead_before[j] != INVALID_INSTRNO)
+ (rreg_live_after[j] != INVALID_INSTRNO
+ && rreg_dead_before[j] != INVALID_INSTRNO)
);
- if (state->rreg_live_after[j] == INVALID_INSTRNO)
+ if (rreg_live_after[j] == INVALID_INSTRNO)
continue;
- ensureRRLRspace(&state->rreg_lrs_la, &state->rreg_lrs_size,
- state->rreg_lrs_used);
+ ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
if (0)
vex_printf("FLUSH 2 (%d,%d)\n",
- state->rreg_live_after[j], state->rreg_dead_before[j]);
- UInt used = state->rreg_lrs_used;
- state->rreg_lrs_la[used].rreg = state->univ->regs[j];
- state->rreg_lrs_la[used].live_after = toShort(state->rreg_live_after[j]);
- state->rreg_lrs_la[used].dead_before = toShort(state->rreg_dead_before[j]);
- state->rreg_lrs_used++;
+ rreg_live_after[j], rreg_dead_before[j]);
+ rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
+ rreg_lrs_la[rreg_lrs_used].live_after = toShort(rreg_live_after[j]);
+ rreg_lrs_la[rreg_lrs_used].dead_before = toShort(rreg_dead_before[j]);
+ rreg_lrs_used++;
}
/* Compute summary hints for choosing real regs. If a real reg is
@@ -805,73 +795,65 @@
their HLRs. Correctness of final assignment is unaffected by
this mechanism -- it is only an optimisation. */
- for (UInt j = 0; j < state->rreg_lrs_used; j++) {
- HReg rreg = state->rreg_lrs_la[j].rreg;
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ HReg rreg = rreg_lrs_la[j].rreg;
vassert(!hregIsVirtual(rreg));
/* rreg is involved in a HLR. Record this info in the array, if
there is space. */
UInt ix = hregIndex(rreg);
- vassert(ix < state->n_rregs);
- state->rreg_state[ix].has_hlrs = True;
+ vassert(ix < n_rregs);
+ rreg_state[ix].has_hlrs = True;
}
if (0) {
- for (UInt j = 0; j < state->n_rregs; j++) {
- if (!state->rreg_state[j].has_hlrs)
+ for (Int j = 0; j < n_rregs; j++) {
+ if (!rreg_state[j].has_hlrs)
continue;
- state->ppReg(state->univ->regs[j]);
+ ppReg(univ->regs[j]);
vex_printf(" hinted\n");
}
}
/* Finally, copy the _la variant into the _db variant and
sort both by their respective fields. */
- state->rreg_lrs_db
- = LibVEX_Alloc_inline(state->rreg_lrs_used * sizeof(RRegLR));
- for (UInt j = 0; j < state->rreg_lrs_used; j++)
- state->rreg_lrs_db[j] = state->rreg_lrs_la[j];
-
- sortRRLRarray(state->rreg_lrs_la, state->rreg_lrs_used,
- True /* by .live_after*/ );
- sortRRLRarray(state->rreg_lrs_db, state->rreg_lrs_used,
- False/* by .dead_before*/ );
+ rreg_lrs_db = LibVEX_Alloc_inline(rreg_lrs_used * sizeof(RRegLR));
+ for (Int j = 0; j < rreg_lrs_used; j++)
+ rreg_lrs_db[j] = rreg_lrs_la[j];
+
+ sortRRLRarray( rreg_lrs_la, rreg_lrs_used, True /* by .live_after*/ );
+ sortRRLRarray( rreg_lrs_db, rreg_lrs_used, False/* by .dead_before*/ );
/* And set up the cursors. */
- state->rreg_lrs_la_next = 0;
- state->rreg_lrs_db_next = 0;
+ rreg_lrs_la_next = 0;
+ rreg_lrs_db_next = 0;
- const RRegLR* lrs_la = state->rreg_lrs_la;
- const RRegLR* lrs_db = state->rreg_lrs_db;
- for (UInt j = 1; j < state->rreg_lrs_used; j++) {
- vassert(lrs_la[j-1].live_after <= lrs_la[j].live_after);
- vassert(lrs_db[j-1].dead_before <= lrs_db[j].dead_before);
+ for (Int j = 1; j < rreg_lrs_used; j++) {
+ vassert(rreg_lrs_la[j-1].live_after <= rreg_lrs_la[j].live_after);
+ vassert(rreg_lrs_db[j-1].dead_before <= rreg_lrs_db[j].dead_before);
}
/* ------ end of FINALISE RREG LIVE RANGES ------ */
if (DEBUG_REGALLOC) {
- for (UInt 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 );
+ 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 );
}
}
if (DEBUG_REGALLOC) {
vex_printf("RRegLRs by LA:\n");
- for (UInt j = 0; j < state->rreg_lrs_used; j++) {
+ for (Int j = 0; j < rreg_lrs_used; j++) {
vex_printf(" ");
- state->ppReg(state->rreg_lrs_la[j].rreg);
+ (*ppReg)(rreg_lrs_la[j].rreg);
vex_printf(" la = %d, db = %d\n",
- state->rreg_lrs_la[j].live_after,
- state->rreg_lrs_la[j].dead_before );
+ rreg_lrs_la[j].live_after, rreg_lrs_la[j].dead_before );
}
vex_printf("RRegLRs by DB:\n");
- for (UInt j = 0; j < state->rreg_lrs_used; j++) {
+ for (Int j = 0; j < rreg_lrs_used; j++) {
vex_printf(" ");
- state->ppReg(state->rreg_lrs_db[j].rreg);
+ (*ppReg)(rreg_lrs_db[j].rreg);
vex_printf(" la = %d, db = %d\n",
- state->rreg_lrs_db[j].live_after,
- state->rreg_lrs_db[j].dead_before );
+ rreg_lrs_db[j].live_after, rreg_lrs_db[j].dead_before );
}
}
@@ -903,12 +885,14 @@
*/
/* Int max_ss_no = -1; */
- for (UInt j = 0; j < state->n_vregs; j++) {
+ local_memset(ss_busy_until_before, 0, sizeof(ss_busy_until_before));
+
+ for (Int j = 0; j < 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 (state->vreg_lrs[j].live_after == INVALID_INSTRNO) {
- vassert(state->vreg_lrs[j].reg_class == HRcINVALID);
+ if (vreg_lrs[j].live_after == INVALID_INSTRNO) {
+ vassert(vreg_lrs[j].reg_class == HRcINVALID);
continue;
}
@@ -920,7 +904,7 @@
kept in sync with the size info on the definition of
HRegClass. */
Int ss_no = -1;
- switch (state->vreg_lrs[j].reg_class) {
+ switch (vreg_lrs[j].reg_class) {
case HRcVec128: case HRcFlt64:
/* Find two adjacent free slots in which between them
@@ -928,19 +912,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 (state->ss_busy_until_before[ss_no+0]
- <= state->vreg_lrs[j].live_after
- && state->ss_busy_until_before[ss_no+1]
- <= state->vreg_lrs[j].live_after)
+ 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)
break;
if (ss_no >= N_SPILL64S-1) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- state->ss_busy_until_before[ss_no+0]
- = state->vreg_lrs[j].dead_before;
- state->ss_busy_until_before[ss_no+1]
- = state->vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+0] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+1] = vreg_lrs[j].dead_before;
break;
default:
@@ -949,35 +929,33 @@
at the start point of this interval, and assign the
interval to it. */
for (ss_no = 0; ss_no < N_SPILL64S; ss_no++)
- if (state->ss_busy_until_before[ss_no]
- <= state->vreg_lrs[j].live_after)
+ if (ss_busy_until_before[ss_no] <= vreg_lrs[j].live_after)
break;
if (ss_no == N_SPILL64S) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- state->ss_busy_until_before[ss_no] = state->vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no] = vreg_lrs[j].dead_before;
break;
- } /* switch (state->vreg_lrs[j].reg_class) */
+ } /* switch (vreg_lrs[j].reg_class) */
- /* This reflects LibVEX's hard-wired knowledge of the guest state
+ /* 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. */
- state->vreg_lrs[j].spill_offset
- = toShort(state->guest_sizeB * 3 + ss_no * 8);
+ vreg_lrs[j].spill_offset = toShort(guest_sizeB * 3 + ss_no * 8);
/* Independent check that we've made a sane choice of slot */
- sanity_check_spill_offset(&state->vreg_lrs[j]);
+ sanity_check_spill_offset( &vreg_lrs[j] );
/* if (j > max_ss_no) */
/* max_ss_no = j; */
}
if (0) {
vex_printf("\n\n");
- for (UInt j = 0; j < state->n_vregs; j++)
+ for (Int j = 0; j < n_vregs; j++)
vex_printf("vreg %d --> spill offset %d\n",
- j, state->vreg_lrs[j].spill_offset);
+ j, vreg_lrs[j].spill_offset);
}
/* --------- Stage 4: establish rreg preferences --------- */
@@ -1001,18 +979,18 @@
correctly set up our running state, which tracks the status of
each real register. */
+ insn_count = original_insn_count;
+
/* ------ BEGIN: Process each insn in turn. ------ */
- for (UInt ii = 0; ii < instrs_in->insns_used; ii++) {
- HInstr* instr = instrs_in->insns[ii];
- vassert(!state->isIfThenElse(instr));
+ for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
if (DEBUG_REGALLOC) {
- vex_printf("\n====----====---- Insn %u ----====----====\n", ii);
+ vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
vex_printf("---- ");
- state->ppInstr(instr, state->mode64);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
vex_printf("\n\nInitial state:\n");
- print_state(state);
+ PRINT_STATE;
vex_printf("\n");
}
@@ -1021,10 +999,10 @@
/* Sanity checks are expensive. So they are done only once
every 17 instructions, and just before the last
instruction. */
- Bool do_sanity_check
+ do_sanity_check
= toBool(
False /* Set to True for sanity checking of all insns. */
- || ii == instrs_in->insns_used-1
+ || ii == instrs_in->arr_used-1
|| (ii > 0 && (ii % 17) == 0)
);
@@ -1033,25 +1011,24 @@
/* Sanity check 1: all rregs with a hard live range crossing
this insn must be marked as unavailable in the running
state. */
- for (UInt j = 0; j < state->rreg_lrs_used; j++) {
- if (state->rreg_lrs_la[j].live_after < ii
- && ii < state->rreg_lrs_la[j].dead_before) {
- /* ii is the middle of a hard live range for some real
- reg. Check it's marked as such in the running
- state. */
- HReg reg = state->rreg_lrs_la[j].rreg;
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ if (rreg_lrs_la[j].live_after < ii
+ && ii < rreg_lrs_la[j].dead_before) {
+ /* ii is in the middle of a hard live range for some real
+ reg. Check it's marked as such in the running state. */
+ HReg reg = rreg_lrs_la[j].rreg;
if (0) {
vex_printf("considering la %d .. db %d reg = ",
- state->rreg_lrs_la[j].live_after,
- state->rreg_lrs_la[j].dead_before);
- state->ppReg(reg);
+ rreg_lrs_la[j].live_after,
+ rreg_lrs_la[j].dead_before);
+ (*ppReg)(reg);
vex_printf("\n");
}
/* assert that this rreg is marked as unavailable */
vassert(!hregIsVirtual(reg));
- vassert(state->rreg_state[hregIndex(reg)].disp == Unavail);
+ vassert(rreg_state[hregIndex(reg)].disp == Unavail);
}
}
@@ -1059,36 +1036,36 @@
unavailable in the running rreg_state must have a
corresponding hard live range entry in the rreg_lrs
array. */
- 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)
+ 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)
continue;
- UInt k;
- for (k = 0; k < state->rreg_lrs_used; k++) {
- HReg reg = state->rreg_lrs_la[k].rreg;
+ Int k;
+ for (k = 0; k < rreg_lrs_used; k++) {
+ HReg reg = rreg_lrs_la[k].rreg;
vassert(!hregIsVirtual(reg));
if (hregIndex(reg) == j
- && state->rreg_lrs_la[k].live_after < ii
- && ii < state->rreg_lrs_la[k].dead_before)
+ && rreg_lrs_la[k].live_after < ii
+ && ii < rreg_lrs_la[k].dead_before)
break;
}
/* If this vassertion fails, we couldn't find a
corresponding HLR. */
- vassert(k < state->rreg_lrs_used);
+ vassert(k < rreg_lrs_used);
}
/* Sanity check 3: all vreg-rreg bindings must bind registers
of the same class. */
- 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);
+ for (Int j = 0; j < n_rregs; j++) {
+ if (rreg_state[j].disp != Bound) {
+ vassert(rreg_state[j].eq_spill_slot == False);
continue;
}
- vassert(hregClass(state->univ->regs[j])
- == hregClass(state->rreg_state[j].vreg));
- vassert(hregIsVirtual(state->rreg_state[j].vreg));
+ vassert(hregClass(univ->regs[j])
+ == hregClass(rreg_state[j].vreg));
+ vassert( hregIsVirtual(rreg_state[j].vreg));
}
/* Sanity check 4: the vreg_state and rreg_state
@@ -1096,20 +1073,20 @@
rreg_state[j].vreg points at some vreg_state entry then
that vreg_state entry should point back at
rreg_state[j]. */
- for (UInt j = 0; j < state->n_rregs; j++) {
- if (state->rreg_state[j].disp != Bound)
+ for (Int j = 0; j < n_rregs; j++) {
+ if (rreg_state[j].disp != Bound)
continue;
- Int k = hregIndex(state->rreg_state[j].vreg);
+ Int k = hregIndex(rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(k));
- vassert(state->vreg_state[k] == j);
+ vassert(vreg_state[k] == j);
}
- for (UInt j = 0; j < state->n_vregs; j++) {
- Int k = state->vreg_state[j];
+ for (Int j = 0; j < n_vregs; j++) {
+ Int k = vreg_state[j];
if (k == INVALID_RREG_NO)
continue;
vassert(IS_VALID_RREGNO(k));
- vassert(state->rreg_state[k].disp == Bound);
- vassert(hregIndex(state->rreg_state[k].vreg) == j);
+ vassert(rreg_state[k].disp == Bound);
+ vassert(hregIndex(rreg_state[k].vreg) == j);
}
} /* if (do_sanity_check) */
@@ -1126,26 +1103,26 @@
the dst to the src's rreg, and that's all. */
HReg vregS = INVALID_HREG;
HReg vregD = INVALID_HREG;
- if (state->isMove(instr, &vregS, &vregD)) {
+ if ( (*isMove)( instrs_in->arr[ii], &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 ... */
vassert(hregClass(vregS) == hregClass(vregD));
- Int k = hregIndex(vregS);
- Int m = hregIndex(vregD);
+ UInt k = hregIndex(vregS);
+ UInt m = hregIndex(vregD);
vassert(IS_VALID_VREGNO(k));
vassert(IS_VALID_VREGNO(m));
- if (state->vreg_lrs[k].dead_before != ii + 1) goto cannot_coalesce;
- if (state->vreg_lrs[m].live_after != ii) goto cannot_coalesce;
+ if (vreg_lrs[k].dead_before != ii + 1) goto cannot_coalesce;
+ if (vreg_lrs[m].live_after != ii) goto cannot_coalesce;
if (DEBUG_REGALLOC) {
vex_printf("COALESCE ");
- state->ppReg(vregS);
+ (*ppReg)(vregS);
vex_printf(" -> ");
- state->ppReg(vregD);
+ (*ppReg)(vregD);
vex_printf("\n\n");
}
/* Find the state entry for vregS. */
- Int n = state->vreg_state[k]; /* k is the index of vregS */
+ Int n = 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. */
@@ -1155,15 +1132,15 @@
/* Finally, we can do the coalescing. It's trivial -- merely
claim vregS's register for vregD. */
- state->rreg_state[n].vreg = vregD;
+ rreg_state[n].vreg = vregD;
vassert(IS_VALID_VREGNO(hregIndex(vregD)));
vassert(IS_VALID_VREGNO(hregIndex(vregS)));
- state->vreg_state[hregIndex(vregD)] = toShort(n);
- state->vreg_state[hregIndex(vregS)] = INVALID_RREG_NO;
+ vreg_state[hregIndex(vregD)] = toShort(n);
+ 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. */
- state->rreg_state[n].eq_spill_slot = False;
+ 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
@@ -1177,20 +1154,20 @@
/* Look for vregs whose live range has just ended, and
mark the associated rreg as free. */
- for (UInt j = 0; j < state->n_rregs; j++) {
- if (state->rreg_state[j].disp != Bound)
+ for (Int j = 0; j < n_rregs; j++) {
+ if (rreg_state[j].disp != Bound)
continue;
- UInt vregno = hregIndex(state->rreg_state[j].vreg);
+ UInt vregno = hregIndex(rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(vregno));
- 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);
+ 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);
vassert(IS_VALID_VREGNO(m));
- state->vreg_state[m] = INVALID_RREG_NO;
+ vreg_state[m] = INVALID_RREG_NO;
if (DEBUG_REGALLOC) {
vex_printf("free up ");
- state->ppReg(state->univ->regs[j]);
+ (*ppReg)(univ->regs[j]);
vex_printf("\n");
}
}
@@ -1212,16 +1189,16 @@
(their .live_after field).
*/
while (True) {
- vassert(state->rreg_lrs_la_next >= 0);
- vassert(state->rreg_lrs_la_next <= state->rreg_lrs_used);
- if (state->rreg_lrs_la_next == state->rreg_lrs_used)
+ vassert(rreg_lrs_la_next >= 0);
+ vassert(rreg_lrs_la_next <= rreg_lrs_used);
+ if (rreg_lrs_la_next == rreg_lrs_used)
break; /* no more real reg live ranges to consider */
- if (ii < state->rreg_lrs_la[state->rreg_lrs_la_next].live_after)
+ if (ii < rreg_lrs_la[rreg_lrs_la_next].live_after)
break; /* next live range does not yet start */
- vassert(ii == state->rreg_lrs_la[state->rreg_lrs_la_next].live_after);
+ vassert(ii == rreg_lrs_la[rreg_lrs_la_next].live_after);
/* rreg_lrs_la[rreg_lrs_la_next].rreg needs to be freed up.
Find the associated rreg_state entry. */
- /* Note, re ii == state->rreg_lrs_la[rreg_lrs_la_next].live_after.
+ /* Note, re ii == rreg_lrs_la[rreg_lrs_la_next].live_after.
Real register live ranges are guaranteed to be well-formed
in that they start with a write to the register -- Stage 2
rejects any code not satisfying this. So the correct
@@ -1231,48 +1208,47 @@
than before it. */
if (DEBUG_REGALLOC) {
vex_printf("need to free up rreg: ");
- state->ppReg(state->rreg_lrs_la[state->rreg_lrs_la_next].rreg);
+ (*ppReg)(rreg_lrs_la[rreg_lrs_la_next].rreg);
vex_printf("\n\n");
}
- Int k = hregIndex(state->rreg_lrs_la[state->rreg_lrs_la_next].rreg);
+ Int k = hregIndex(rreg_lrs_la[rreg_lrs_la_next].rreg);
/* If this fails, we don't have an entry for this rreg.
Which we should. */
vassert(IS_VALID_RREGNO(k));
- Int m = hregIndex(state->rreg_state[k].vreg);
- if (state->rreg_state[k].disp == Bound) {
+ Int m = hregIndex(rreg_state[k].vreg);
+ if (rreg_state[k].disp == Bound) {
/* Yes, there is an associated vreg. Spill it if it's
still live. */
vassert(IS_VALID_VREGNO(m));
- 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) {
+ 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) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
- state->genSpill(&spill1, &spill2, state->univ->regs[k],
- state->vreg_lrs[m].spill_offset,
- state->mode64);
+ (*genSpill)( &spill1, &spill2, univ->regs[k],
+ vreg_lrs[m].spill_offset, mode64 );
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
EMIT_INSTR(spill1);
if (spill2)
EMIT_INSTR(spill2);
}
- state->rreg_state[k].eq_spill_slot = True;
+ rreg_state[k].eq_spill_slot = True;
}
}
- state->rreg_state[k].disp = Unavail;
- state->rreg_state[k].vreg = INVALID_HREG;
- state->rreg_state[k].eq_spill_slot = False;
+ rreg_state[k].disp = Unavail;
+ rreg_state[k].vreg = INVALID_HREG;
+ rreg_state[k].eq_spill_slot = False;
/* check for further rregs entering HLRs at this point */
- state->rreg_lrs_la_next++;
+ rreg_lrs_la_next++;
}
if (DEBUG_REGALLOC) {
vex_printf("After pre-insn actions for fixed regs:\n");
- print_state(state);
+ PRINT_STATE;
vex_printf("\n");
}
@@ -1285,7 +1261,6 @@
We also build up the final vreg->rreg mapping to be applied
to the insn. */
- HRegRemap remap;
initHRegRemap(&remap);
/* ------------ BEGIN directReload optimisation ----------- */
@@ -1300,29 +1275,28 @@
that the change is invisible to the standard-case handling
that follows. */
- if (state->directReload != NULL
- && state->reg_usage_arr[ii].n_vRegs <= 2) {
+ if (directReload && reg_usage_arr[ii].n_vRegs <= 2) {
Bool debug_direct_reload = False;
HReg cand = INVALID_HREG;
Bool nreads = 0;
Short spilloff = 0;
- for (UInt j = 0; j < state->reg_usage_arr[ii].n_vRegs; j++) {
+ for (Int j = 0; j < reg_usage_arr[ii].n_vRegs; j++) {
- HReg vreg = state->reg_usage_arr[ii].vRegs[j];
+ HReg vreg = reg_usage_arr[ii].vRegs[j];
vassert(hregIsVirtual(vreg));
- if (state->reg_usage_arr[ii].vMode[j] == HRmRead) {
+ if (reg_usage_arr[ii].vMode[j] == HRmRead) {
nreads++;
Int m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- Int k = state->vreg_state[m];
+ Int k = vreg_state[m];
if (!IS_VALID_RREGNO(k)) {
/* ok, it is spilled. Now, is this its last use? */
- vassert(state->vreg_lrs[m].dead_before >= ii+1);
- if (state->vreg_lrs[m].dead_before == ii+1
+ vassert(vreg_lrs[m].dead_before >= ii+1);
+ if (vreg_lrs[m].dead_before == ii+1
&& hregIsInvalid(cand)) {
- spilloff = state->vreg_lrs[m].spill_offset;
+ spilloff = vreg_lrs[m].spill_offset;
cand = vreg;
}
}
@@ -1330,25 +1304,24 @@
}
if (nreads == 1 && ! hregIsInvalid(cand)) {
- if (state->reg_usage_arr[ii].n_vRegs == 2)
- vassert(! sameHReg(state->reg_usage_arr[ii].vRegs[0],
- state->reg_usage_arr[ii].vRegs[1]));
+ HInstr* reloaded;
+ if (reg_usage_arr[ii].n_vRegs == 2)
+ vassert(! sameHReg(reg_usage_arr[ii].vRegs[0],
+ reg_usage_arr[ii].vRegs[1]));
- HInstr* reloaded = state->directReload(instr, cand, spilloff);
- if (debug_direct_reload && reloaded == NULL) {
+ reloaded = directReload ( instrs_in->arr[ii], cand, spilloff );
+ if (debug_direct_reload && !reloaded) {
vex_printf("[%3d] ", spilloff); ppHReg(cand); vex_printf(" ");
- state->ppInstr(instr, state->mode64);
+ ppInstr(instrs_in->arr[ii], mode64);
}
- if (reloaded != NULL) {
+ if (reloaded) {
/* Update info about the insn, so it looks as if it had
been in this form all along. */
- instr = reloaded;
- instrs_in->insns[ii] = reloaded;
- state->getRegUsage(&state->reg_usage_arr[ii], instr,
- state->mode64);
- if (debug_direct_reload && reloaded == NULL) {
+ instrs_in->arr[ii] = reloaded;
+ (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
+ if (debug_direct_reload && !reloaded) {
vex_printf(" --> ");
- state->ppInstr(reloaded, state->mode64);
+ ppInstr(reloaded, mode64);
}
}
@@ -1361,13 +1334,13 @@
/* ------------ END directReload optimisation ------------ */
/* for each virtual reg mentioned i...
[truncated message content] |
|
From: Mark W. <ma...@kl...> - 2017-06-06 13:22:02
|
On Fri, 2017-06-02 at 17:57 +0200, Julian Seward wrote: > An RC1 tarball for 3.13.0 is now available at > ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC1.tar.bz2 > (md5sum = a94957849869f1e50a16d60737cfcc29) > > Please give it a try in configurations that are important for you and report > any problems you have, either on this mailing list, or (preferably) via our > bug tracker at https://bugs.kde.org/enter_bug.cgi?product=valgrind I packaged this for fedora rawhide: https://koji.fedoraproject.org/koji/buildinfo?buildID=903933 There are also copr builds for Fedora 25, EPEL 6/7 (i386, x86_64 and ppc64le): https://copr.fedorainfracloud.org/coprs/mjw/valgrind-3.13.0/ These include some patches that might make it into the final 3.13.0: - KDE#380397 s390x: __GI_strcspn() replacemenet needed - valgrind svn 16437 Fix pub_tool_basics.h build issue with g++ 4.4.7. - KDE#380200 xtree generated callgrind files refer to files without directory - KDE#380202 Assertion failure for cache line size on aarch64 |
|
From: <sv...@va...> - 2017-06-06 09:03:14
|
Author: mjw
Date: Tue Jun 6 10:03:03 2017
New Revision: 16437
Log:
Fix pub_tool_basics.h build issue with g++ 4.4.7.
g++ 4.4.7 doesn't accept union field initializers:
In file included from ../../include/pub_tool_vki.h:50,
from valgrind_cpp_test.cpp:13:
../../include/vki/vki-linux.h: In function ‘vki_cmsghdr* __vki_cmsg_nxthdr(void*, __vki_kernel_size_t, vki_cmsghdr*)’:
../../include/vki/vki-linux.h:673: error: expected primary-expression before ‘.’ token
Assign value after declaration which works for any g++ version.
Modified:
trunk/include/pub_tool_basics.h
Modified: trunk/include/pub_tool_basics.h
==============================================================================
--- trunk/include/pub_tool_basics.h (original)
+++ trunk/include/pub_tool_basics.h Tue Jun 6 10:03:03 2017
@@ -480,7 +480,8 @@
union { \
void *in; \
D out; \
- } var = {.in = (void *) (x)}; var.out; \
+ } var; \
+ var.in = (void *) (x); var.out; \
})
// Poor man's static assert
|
|
From: <sv...@va...> - 2017-06-05 21:09:16
|
Author: iraisr
Date: Mon Jun 5 22:09:06 2017
New Revision: 16436
Log:
Add a replacement for __GI_strcspn() required on s390x/Linux.
Fixes BZ#380397.
Patch by: Andreas Arnez <ar...@li...>
Modified:
trunk/NEWS
trunk/shared/vg_replace_strmem.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Mon Jun 5 22:09:06 2017
@@ -1,3 +1,43 @@
+Release 3.14.0 (?? ????????? 201?)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--
+Release 3.14.0 is under development, not yet released.
+
+3.14.0 is a feature release with many improvements and the usual collection of
+bug fixes.
+
+This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux,
+PPC32/Linux, PPC64BE/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux,
+MIPS64/Linux, ARM/Android, ARM64/Android, MIPS32/Android, X86/Android,
+X86/Solaris, AMD64/Solaris and AMD64/MacOSX 10.12.
+
+* ==================== CORE CHANGES ===================
+
+
+* ================== PLATFORM CHANGES =================
+
+
+* ==================== TOOL CHANGES ====================
+
+
+* ==================== OTHER CHANGES ====================
+
+
+* ==================== FIXED BUGS ====================
+
+The following bugs have been fixed or resolved. Note that "n-i-bz"
+stands for "not in bugzilla" -- that is, a bug that was reported to us
+but never got a bugzilla entry. We encourage you to file bugs in
+bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather
+than mailing the developers (or mailing lists) directly -- bugs that
+are not entered into bugzilla tend to get forgotten about or ignored.
+
+To see details of a given bug, visit
+ https://bugs.kde.org/show_bug.cgi?id=XXXXXX
+where XXXXXX is the bug number as listed below.
+
+380397 s390x: __GI_strcspn() replacemenet needed
+
+
Release 3.13.0 (15 June 2017)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Modified: trunk/shared/vg_replace_strmem.c
==============================================================================
--- trunk/shared/vg_replace_strmem.c (original)
+++ trunk/shared/vg_replace_strmem.c Mon Jun 5 22:09:06 2017
@@ -1721,6 +1721,7 @@
#if defined(VGO_linux)
STRCSPN(VG_Z_LIBC_SONAME, strcspn)
+ STRCSPN(VG_Z_LIBC_SONAME, __GI_strcspn)
#elif defined(VGO_darwin)
|
|
From: Petar J. <mip...@gm...> - 2017-06-05 16:57:28
|
On Mon, Jun 5, 2017 at 1:21 PM, Murali Krishna <mur...@gm...> wrote: > > Could you please share with us, what has included additionally to the trunk > when compared to valgrind-3.12.0.tar.gz. > Also please confirm if there is any possibility of getting these additional > changes in the form of a patch so that i can use this officially. > Hi Murali, I am glad to hear you are not seeing the issues with the latest code. In less than two weeks, Valgrind 3.13 will be released, so the easiest solution for you would be to wait for it. In the meantime, you can use a tarball created at: ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.RC1.tar.bz2 (md5sum = a94957849869f1e50a16d60737cfcc29) Regards, Petar |