From fc47a58ea5d43ff1ce5fc30b9803af6d6e0eb493 Mon Sep 17 00:00:00 2001 From: Ivo Raisr Date: Sun, 13 Aug 2017 19:18:11 +0200 Subject: [PATCH] Fix VEX register allocator (v3) to work with HInstrSB, HInstrVec. It does not support If-Then-Else, though. --- VEX/priv/host_generic_reg_alloc3.c | 98 ++++++++++++++++-------------- VEX/priv/host_generic_regs.h | 4 +- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/VEX/priv/host_generic_reg_alloc3.c b/VEX/priv/host_generic_reg_alloc3.c index a1c64ee9a3..88644ec0e9 100644 --- a/VEX/priv/host_generic_reg_alloc3.c +++ b/VEX/priv/host_generic_reg_alloc3.c @@ -217,7 +217,7 @@ static inline void print_state( } } -static inline void emit_instr(HInstr* instr, HInstrArray* instrs_out, +static inline void emit_instr(HInstr* instr, HInstrVec* instrs_out, const RegAllocControl* con, const HChar* why) { if (DEBUG_REGALLOC) { @@ -237,7 +237,7 @@ static inline void emit_instr(HInstr* instr, HInstrArray* instrs_out, Returns rreg's index. */ static inline UInt spill_vreg( HReg vreg, UInt v_idx, UInt current_ii, VRegState* vreg_state, UInt n_vregs, - RRegState* rreg_state, UInt n_rregs, HInstrArray* instrs_out, + RRegState* rreg_state, UInt n_rregs, HInstrVec* instrs_out, const RegAllocControl* con) { /* Check some invariants first. */ @@ -320,10 +320,10 @@ static inline HReg find_vreg_to_spill( } if (hregIsInvalid(vreg_found)) { - vex_printf("doRegisterAllocation_v3: cannot find a register in class: "); + vex_printf("doRegisterAllocation: cannot find a register in class: "); ppHRegClass(target_hregclass); vex_printf("\n"); - vpanic("doRegisterAllocation_v3: cannot find a register."); + vpanic("doRegisterAllocation: cannot find a register."); } return vreg_found; @@ -391,9 +391,9 @@ static Bool find_free_rreg( Takes unallocated instructions and returns allocated instructions. */ -HInstrArray* doRegisterAllocation( +HInstrSB* doRegisterAllocation( /* Incoming virtual-registerised code. */ - HInstrArray* instrs_in, + HInstrSB* sb_in, /* Register allocator controls to use. */ const RegAllocControl* con @@ -401,8 +401,11 @@ HInstrArray* doRegisterAllocation( { vassert((con->guest_sizeB % LibVEX_GUEST_STATE_ALIGN) == 0); + /* TODO-JIT: for now, work only with the first HInstrVec. */ + HInstrVec* instrs_in = sb_in->insns; + /* The main register allocator state. */ - UInt n_vregs = instrs_in->n_vregs; + UInt n_vregs = sb_in->n_vregs; VRegState* vreg_state = NULL; if (n_vregs > 0) { vreg_state = LibVEX_Alloc_inline(n_vregs * sizeof(VRegState)); @@ -416,40 +419,42 @@ HInstrArray* doRegisterAllocation( vassert(n_rregs > 0); STATIC_ASSERT(N_RREGUNIVERSE_REGS == 64); - /* Info on register usage in the incoming instruction array. Computed once + /* Info on register usage in the incoming instructions. Computed once and remains unchanged, more or less; updated sometimes by the direct-reload optimisation. */ HRegUsage* reg_usage - = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->arr_used); + = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->insns_used); /* The live range numbers are signed shorts, and so limiting the number of instructions to 15000 comfortably guards against them overflowing 32k. */ - vassert(instrs_in->arr_used <= 15000); - - /* The output array of instructions. */ - HInstrArray* instrs_out = newHInstrArray(); - - -# define OFFENDING_VREG(_v_idx, _instr, _mode) \ - do { \ - vex_printf("\n\nOffending vreg = %u\n", (_v_idx)); \ - vex_printf("\nOffending instruction = "); \ - con->ppInstr((_instr), con->mode64); \ - vex_printf("\n"); \ - vpanic("doRegisterAllocation_v3: first event for vreg is #_mode# \ - (should be Write)"); \ + vassert(instrs_in->insns_used <= 15000); + + /* The output SB of instructions. */ + HInstrSB* sb_out = newHInstrSB(); + sb_out->n_vregs = n_vregs; + HInstrVec* instrs_out = sb_out->insns; + + +# define OFFENDING_VREG(_v_idx, _instr, _mode) \ + do { \ + vex_printf("\n\nOffending vreg = %u\n", (_v_idx)); \ + vex_printf("\nOffending instruction = "); \ + con->ppInstr((_instr), con->mode64); \ + vex_printf("\n"); \ + vpanic("doRegisterAllocation: first event for vreg is #_mode# \ + (should be Write)"); \ } while (0) -# define OFFENDING_RREG(_r_idx, _instr, _mode) \ - do { \ - vex_printf("\n\nOffending rreg = "); \ - con->ppReg(con->univ->regs[(_r_idx)]); \ - vex_printf("\nOffending instruction = "); \ - con->ppInstr((_instr), con->mode64); \ - vex_printf("\n"); \ - vpanic("doRegisterAllocation_v3: first event for rreg is #_mode# \ - (should be Write)"); \ +# define OFFENDING_RREG(_r_idx, _instr, _mode) \ + do { \ + vex_printf("\n\nOffending rreg = "); \ + con->ppReg(con->univ->regs[(_r_idx)]); \ + vex_printf("\nOffending instruction = "); \ + con->ppInstr((_instr), con->mode64); \ + vex_printf("\n"); \ + vpanic("doRegisterAllocation: first event for rreg is #_mode# \ + (should be Write)"); \ } while (0) @@ -468,7 +473,7 @@ HInstrArray* doRegisterAllocation( vreg_state, n_vregs, rreg_state, n_rregs, \ ®_usage[(_ii)], (_reg_class), \ reg_usage, (_ii) + 1, \ - instrs_in->arr_used - 1, con); \ + instrs_in->insns_used - 1, con); \ _r_free_idx = spill_vreg(vreg_to_spill, hregIndex(vreg_to_spill), \ (_ii), vreg_state, n_vregs, \ rreg_state, n_rregs, \ @@ -503,8 +508,13 @@ HInstrArray* doRegisterAllocation( /* --- Stage 1. Scan the incoming instructions. --- */ - for (UShort ii = 0; ii < instrs_in->arr_used; ii++) { - const HInstr* instr = instrs_in->arr[ii]; + for (UShort ii = 0; ii < instrs_in->insns_used; ii++) { + const HInstr* instr = instrs_in->insns[ii]; + + HInstrIfThenElse* hite = con->isIfThenElse(instr); + if (UNLIKELY(hite != NULL)) { + vpanic("doRegisterAllocation: If-Then-Else unsupported"); + } con->getRegUsage(®_usage[ii], instr, con->mode64); @@ -526,7 +536,7 @@ HInstrArray* doRegisterAllocation( con->ppInstr(instr, con->mode64); vex_printf("\n"); vex_printf("vreg %u (n_vregs %u)\n", v_idx, n_vregs); - vpanic("doRegisterAllocation_v3: out-of-range vreg"); + vpanic("doRegisterAllocation: out-of-range vreg"); } /* Note the register class. */ @@ -747,13 +757,13 @@ HInstrArray* doRegisterAllocation( /* --- State 3. Process instructions. --- */ - for (UShort ii = 0; ii < instrs_in->arr_used; ii++) { - HInstr* instr = instrs_in->arr[ii]; + for (UShort ii = 0; ii < instrs_in->insns_used; ii++) { + HInstr* instr = instrs_in->insns[ii]; if (DEBUG_REGALLOC) { vex_printf("\n====----====---- Instr %d ----====----====\n", ii); vex_printf("---- "); - con->ppInstr(instrs_in->arr[ii], con->mode64); + con->ppInstr(instrs_in->insns[ii], con->mode64); vex_printf("\n\nInitial state:\n"); print_state(con, vreg_state, n_vregs, rreg_state, n_rregs, ii); vex_printf("\n"); @@ -766,7 +776,7 @@ HInstrArray* doRegisterAllocation( Bool do_sanity_check = toBool( SANITY_CHECKS_EVERY_INSTR - || ii == instrs_in->arr_used - 1 + || ii == instrs_in->insns_used - 1 || (ii > 0 && (ii % 17) == 0) ); @@ -964,7 +974,7 @@ HInstrArray* doRegisterAllocation( 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 + instrs_in->insns[ii] with this new instruction, and recompute its reg_usage, so that the change is invisible to the standard-case handling that follows. */ if ((con->directReload != NULL) && (reg_usage[ii].n_vRegs <= 2)) { @@ -999,7 +1009,7 @@ HInstrArray* doRegisterAllocation( reg_usage[ii].vRegs[1])); } - HInstr* reloaded = con->directReload(instrs_in->arr[ii], + HInstr* reloaded = con->directReload(instrs_in->insns[ii], vreg_found, spill_offset); if (debug_direct_reload && (reloaded != NULL)) { vex_printf("[%3d] ", spill_offset); @@ -1011,7 +1021,7 @@ HInstrArray* doRegisterAllocation( /* Update info about the instruction, so it looks as if it had been in this form all along. */ instr = reloaded; - instrs_in->arr[ii] = reloaded; + instrs_in->insns[ii] = reloaded; con->getRegUsage(®_usage[ii], instr, con->mode64); if (debug_direct_reload) { vex_printf(" --> "); @@ -1135,7 +1145,7 @@ HInstrArray* doRegisterAllocation( } } - return instrs_out; + return sb_out; } /*----------------------------------------------------------------------------*/ diff --git a/VEX/priv/host_generic_regs.h b/VEX/priv/host_generic_regs.h index 8694922b1f..978e4b68a4 100644 --- a/VEX/priv/host_generic_regs.h +++ b/VEX/priv/host_generic_regs.h @@ -527,7 +527,7 @@ typedef /* Is this instruction actually HInstrIfThenElse? Returns pointer to HInstrIfThenElse if yes, NULL otherwise. */ - HInstrIfThenElse* (*isIfThenElse) (const HInstr*); + HInstrIfThenElse* (*isIfThenElse)(const HInstr*); /* Return insn(s) to spill/restore a real register to a spill slot offset. Also a function to move between registers. @@ -548,7 +548,7 @@ typedef RegAllocControl; extern HInstrSB* doRegisterAllocation( - HInstrSB* instrs_in, + HInstrSB* sb_in, const RegAllocControl* con ); -- 2.47.2