jit_regalloc.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * Copyright (C) 2021 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "jit_utils.h"
  6. #include "jit_compiler.h"
  7. #if BH_DEBUG != 0
  8. #define VREG_DEF_SANITIZER
  9. #endif
  10. /**
  11. * A uint16 stack for storing distances of occurrences of virtual
  12. * registers.
  13. */
  14. typedef struct UintStack {
  15. /* Capacity of the stack. */
  16. uint32 capacity;
  17. /* Top index of the stack. */
  18. uint32 top;
  19. /* Elements of the vector. */
  20. uint32 elem[1];
  21. } UintStack;
  22. static bool
  23. uint_stack_push(UintStack **stack, unsigned val)
  24. {
  25. unsigned capacity = *stack ? (*stack)->capacity : 0;
  26. unsigned top = *stack ? (*stack)->top : 0;
  27. bh_assert(top <= capacity);
  28. if (top == capacity) {
  29. const unsigned elem_size = sizeof((*stack)->elem[0]);
  30. unsigned new_capacity = capacity ? capacity + capacity / 2 : 4;
  31. UintStack *new_stack =
  32. jit_malloc(offsetof(UintStack, elem) + elem_size * new_capacity);
  33. if (!new_stack)
  34. return false;
  35. new_stack->capacity = new_capacity;
  36. new_stack->top = top;
  37. if (*stack)
  38. memcpy(new_stack->elem, (*stack)->elem, elem_size * top);
  39. jit_free(*stack);
  40. *stack = new_stack;
  41. }
  42. (*stack)->elem[(*stack)->top++] = val;
  43. return true;
  44. }
  45. static int
  46. uint_stack_top(UintStack *stack)
  47. {
  48. return stack->elem[stack->top - 1];
  49. }
  50. static void
  51. uint_stack_delete(UintStack **stack)
  52. {
  53. jit_free(*stack);
  54. *stack = NULL;
  55. }
  56. static void
  57. uint_stack_pop(UintStack **stack)
  58. {
  59. bh_assert((*stack)->top > 0);
  60. /**
  61. * TODO: the fact of empty distances stack means there is no instruction
  62. * using current JitReg anymore. so shall we release the HardReg and clean
  63. * VirtualReg information?
  64. */
  65. if (--(*stack)->top == 0)
  66. uint_stack_delete(stack);
  67. }
  68. /**
  69. * Information of a virtual register.
  70. */
  71. typedef struct VirtualReg {
  72. /* The hard register allocated to this virtual register. */
  73. JitReg hreg;
  74. /* The spill slot allocated to this virtual register. */
  75. JitReg slot;
  76. /* The hard register allocated to global virtual registers. It is 0
  77. for local registers, whose lifetime is within one basic block. */
  78. JitReg global_hreg;
  79. /* Distances from the beginning of basic block of all occurrences of the
  80. virtual register in the basic block. */
  81. UintStack *distances;
  82. } VirtualReg;
  83. /**
  84. * Information of a hard register.
  85. */
  86. typedef struct HardReg {
  87. /* The virtual register this hard register is allocated to. */
  88. JitReg vreg;
  89. } HardReg;
  90. /**
  91. * Information of a spill slot.
  92. */
  93. typedef struct SpillSlot {
  94. /* The virtual register this spill slot is allocated to. */
  95. JitReg vreg;
  96. } SpillSlot;
  97. typedef struct RegallocContext {
  98. /* The compiler context. */
  99. JitCompContext *cc;
  100. /* Information of virtual registers. The register allocation must
  101. not increase the virtual register number during the allocation
  102. process. */
  103. VirtualReg *vregs[JIT_REG_KIND_L32];
  104. /* Information of hard registers. */
  105. HardReg *hregs[JIT_REG_KIND_L32];
  106. /* Number of elements in the spill_slots array. */
  107. uint32 spill_slot_num;
  108. /* Information of spill slots. */
  109. SpillSlot *spill_slots;
  110. /* The last define-released hard register. */
  111. JitReg last_def_released_hreg;
  112. } RegallocContext;
  113. /**
  114. * Get the VirtualReg structure of the given virtual register.
  115. *
  116. * @param rc the regalloc context
  117. * @param vreg the virtual register
  118. *
  119. * @return the VirtualReg structure of the given virtual register
  120. */
  121. static VirtualReg *
  122. rc_get_vr(RegallocContext *rc, JitReg vreg)
  123. {
  124. unsigned kind = jit_reg_kind(vreg);
  125. unsigned no = jit_reg_no(vreg);
  126. bh_assert(jit_reg_is_variable(vreg));
  127. bh_assert(kind < JIT_REG_KIND_L32);
  128. return &rc->vregs[kind][no];
  129. }
  130. /**
  131. * Get the HardReg structure of the given hard register.
  132. *
  133. * @param rc the regalloc context
  134. * @param hreg the hard register
  135. *
  136. * @return the HardReg structure of the given hard register
  137. */
  138. static HardReg *
  139. rc_get_hr(RegallocContext *rc, JitReg hreg)
  140. {
  141. unsigned kind = jit_reg_kind(hreg);
  142. unsigned no = jit_reg_no(hreg);
  143. bh_assert(jit_reg_is_variable(hreg) && jit_cc_is_hreg(rc->cc, hreg));
  144. bh_assert(kind < JIT_REG_KIND_L32);
  145. return &rc->hregs[kind][no];
  146. }
  147. /**
  148. * Get the SpillSlot structure of the given slot.
  149. *
  150. * @param rc the regalloc context
  151. * @param slot the constant register representing the slot index
  152. *
  153. * @return the SpillSlot of the given slot
  154. */
  155. static SpillSlot *
  156. rc_get_spill_slot(RegallocContext *rc, JitReg slot)
  157. {
  158. unsigned index = jit_cc_get_const_I32(rc->cc, slot);
  159. bh_assert(index < rc->spill_slot_num);
  160. return &rc->spill_slots[index];
  161. }
  162. /**
  163. * Get the stride in the spill slots of the register.
  164. *
  165. * @param reg a virtual register
  166. *
  167. * @return stride in the spill slots
  168. */
  169. static unsigned
  170. get_reg_stride(JitReg reg)
  171. {
  172. static const uint8 strides[] = { 0, 1, 2, 1, 2, 2, 4, 8, 0 };
  173. uint32 kind = jit_reg_kind(reg);
  174. bh_assert(kind <= JIT_REG_KIND_L32);
  175. return strides[kind];
  176. }
  177. /**
  178. * Allocate a spill slot for the given virtual register.
  179. *
  180. * @param rc the regalloc context
  181. * @param vreg the virtual register
  182. *
  183. * @return the spill slot encoded in a constant register
  184. */
  185. static JitReg
  186. rc_alloc_spill_slot(RegallocContext *rc, JitReg vreg)
  187. {
  188. const unsigned stride = get_reg_stride(vreg);
  189. unsigned mask, new_num, i, j;
  190. SpillSlot *slots;
  191. bh_assert(stride > 0);
  192. for (i = 0; i < rc->spill_slot_num; i += stride)
  193. for (j = i;; j++) {
  194. if (j == i + stride)
  195. /* Found a free slot for vreg. */
  196. goto found;
  197. if (rc->spill_slots[j].vreg)
  198. break;
  199. }
  200. /* No free slot, increase the slot number. */
  201. mask = stride - 1;
  202. /* Align the slot index. */
  203. i = (rc->spill_slot_num + mask) & ~mask;
  204. new_num = i == 0 ? 32 : i + i / 2;
  205. if (!(slots = jit_calloc(sizeof(*slots) * new_num)))
  206. return 0;
  207. if (rc->spill_slots)
  208. memcpy(slots, rc->spill_slots, sizeof(*slots) * rc->spill_slot_num);
  209. jit_free(rc->spill_slots);
  210. rc->spill_slots = slots;
  211. rc->spill_slot_num = new_num;
  212. found:
  213. /* Now, i is the first slot for vreg. */
  214. if ((i + stride) * 4 > rc->cc->spill_cache_size)
  215. /* No frame space for the spill area. */
  216. return 0;
  217. /* Allocate the slot(s) to vreg. */
  218. for (j = i; j < i + stride; j++)
  219. rc->spill_slots[j].vreg = vreg;
  220. return jit_cc_new_const_I32(rc->cc, i);
  221. }
  222. /**
  223. * Free a spill slot.
  224. *
  225. * @param rc the regalloc context
  226. * @param slot_reg the constant register representing the slot index
  227. */
  228. static void
  229. rc_free_spill_slot(RegallocContext *rc, JitReg slot_reg)
  230. {
  231. if (slot_reg) {
  232. SpillSlot *slot = rc_get_spill_slot(rc, slot_reg);
  233. const JitReg vreg = slot->vreg;
  234. const unsigned stride = get_reg_stride(vreg);
  235. unsigned i;
  236. for (i = 0; i < stride; i++)
  237. slot[i].vreg = 0;
  238. }
  239. }
  240. static void
  241. rc_destroy(RegallocContext *rc)
  242. {
  243. unsigned i, j;
  244. for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
  245. const unsigned vreg_num = jit_cc_reg_num(rc->cc, i);
  246. if (rc->vregs[i])
  247. for (j = 0; j < vreg_num; j++)
  248. uint_stack_delete(&rc->vregs[i][j].distances);
  249. jit_free(rc->vregs[i]);
  250. jit_free(rc->hregs[i]);
  251. }
  252. jit_free(rc->spill_slots);
  253. }
  254. static bool
  255. rc_init(RegallocContext *rc, JitCompContext *cc)
  256. {
  257. unsigned i, j;
  258. memset(rc, 0, sizeof(*rc));
  259. rc->cc = cc;
  260. for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
  261. const unsigned vreg_num = jit_cc_reg_num(cc, i);
  262. const unsigned hreg_num = jit_cc_hreg_num(cc, i);
  263. if (vreg_num > 0
  264. && !(rc->vregs[i] = jit_calloc(sizeof(VirtualReg) * vreg_num)))
  265. goto fail;
  266. if (hreg_num > 0
  267. && !(rc->hregs[i] = jit_calloc(sizeof(HardReg) * hreg_num)))
  268. goto fail;
  269. /* Hard registers can only be allocated to themselves. */
  270. for (j = 0; j < hreg_num; j++)
  271. rc->vregs[i][j].global_hreg = jit_reg_new(i, j);
  272. }
  273. return true;
  274. fail:
  275. rc_destroy(rc);
  276. return false;
  277. }
  278. /**
  279. * Check whether the given register is an allocation candidate, which
  280. * must be a variable register that is not fixed hard register.
  281. *
  282. * @param cc the compilation context
  283. * @param reg the register
  284. *
  285. * @return true if the register is an allocation candidate
  286. */
  287. static bool
  288. is_alloc_candidate(JitCompContext *cc, JitReg reg)
  289. {
  290. return (jit_reg_is_variable(reg)
  291. && (!jit_cc_is_hreg(cc, reg) || !jit_cc_is_hreg_fixed(cc, reg)));
  292. }
  293. #ifdef VREG_DEF_SANITIZER
  294. static void
  295. check_vreg_definition(RegallocContext *rc, JitInsn *insn)
  296. {
  297. JitRegVec regvec = jit_insn_opnd_regs(insn);
  298. JitReg *regp, reg_defined = 0;
  299. unsigned i, first_use = jit_insn_opnd_first_use(insn);
  300. /* check if there is the definition of an vr before its references */
  301. JIT_REG_VEC_FOREACH(regvec, i, regp)
  302. {
  303. VirtualReg *vr = NULL;
  304. if (!is_alloc_candidate(rc->cc, *regp))
  305. continue;
  306. /* a strong assumption that there is only one defined reg */
  307. if (i < first_use) {
  308. reg_defined = *regp;
  309. continue;
  310. }
  311. /**
  312. * both definition and references are in one instruction,
  313. * like MOV i3, i3
  314. */
  315. if (reg_defined == *regp)
  316. continue;
  317. vr = rc_get_vr(rc, *regp);
  318. bh_assert(vr->distances);
  319. }
  320. }
  321. #endif
  322. /**
  323. * Collect distances from the beginning of basic block of all occurrences of
  324. * each virtual register.
  325. *
  326. * @param rc the regalloc context
  327. * @param basic_block the basic block
  328. *
  329. * @return distance of the end instruction if succeeds, -1 otherwise
  330. */
  331. static int
  332. collect_distances(RegallocContext *rc, JitBasicBlock *basic_block)
  333. {
  334. JitInsn *insn;
  335. int distance = 1;
  336. JIT_FOREACH_INSN(basic_block, insn)
  337. {
  338. #if WASM_ENABLE_SHARED_MEMORY != 0
  339. /* fence insn doesn't have any operand, hence, no regs involved */
  340. if (insn->opcode == JIT_OP_FENCE) {
  341. continue;
  342. }
  343. #endif
  344. JitRegVec regvec = jit_insn_opnd_regs(insn);
  345. unsigned i;
  346. JitReg *regp;
  347. #ifdef VREG_DEF_SANITIZER
  348. check_vreg_definition(rc, insn);
  349. #endif
  350. /* NOTE: the distance may be pushed more than once if the
  351. virtual register occurs multiple times in the
  352. instruction. */
  353. JIT_REG_VEC_FOREACH(regvec, i, regp)
  354. if (is_alloc_candidate(rc->cc, *regp))
  355. if (!uint_stack_push(&(rc_get_vr(rc, *regp))->distances, distance))
  356. return -1;
  357. /* Integer overflow check, normally it won't happen, but
  358. we had better add the check here */
  359. if (distance >= INT32_MAX)
  360. return -1;
  361. distance++;
  362. }
  363. return distance;
  364. }
  365. static JitReg
  366. offset_of_spill_slot(JitCompContext *cc, JitReg slot)
  367. {
  368. return jit_cc_new_const_I32(cc, cc->spill_cache_offset
  369. + jit_cc_get_const_I32(cc, slot) * 4);
  370. }
  371. /**
  372. * Reload the virtual register from memory. Reload instruction will
  373. * be inserted after the given instruction.
  374. *
  375. * @param rc the regalloc context
  376. * @param vreg the virtual register to be reloaded
  377. * @param cur_insn the current instruction after which the reload
  378. * insertion will be inserted
  379. *
  380. * @return the reload instruction if succeeds, NULL otherwise
  381. */
  382. static JitInsn *
  383. reload_vreg(RegallocContext *rc, JitReg vreg, JitInsn *cur_insn)
  384. {
  385. VirtualReg *vr = rc_get_vr(rc, vreg);
  386. HardReg *hr = rc_get_hr(rc, vr->hreg);
  387. JitInsn *insn = NULL;
  388. if (vreg == rc->cc->exec_env_reg)
  389. /* Reload exec_env_reg with LDEXECENV. */
  390. insn = jit_cc_new_insn(rc->cc, LDEXECENV, vr->hreg);
  391. else
  392. /* Allocate spill slot if not yet and reload from there. */
  393. {
  394. JitReg fp_reg = rc->cc->fp_reg, offset;
  395. if (!vr->slot && !(vr->slot = rc_alloc_spill_slot(rc, vreg)))
  396. /* Cannot allocate spill slot (due to OOM or frame size limit). */
  397. return NULL;
  398. offset = offset_of_spill_slot(rc->cc, vr->slot);
  399. switch (jit_reg_kind(vreg)) {
  400. case JIT_REG_KIND_I32:
  401. insn = jit_cc_new_insn(rc->cc, LDI32, vr->hreg, fp_reg, offset);
  402. break;
  403. case JIT_REG_KIND_I64:
  404. insn = jit_cc_new_insn(rc->cc, LDI64, vr->hreg, fp_reg, offset);
  405. break;
  406. case JIT_REG_KIND_F32:
  407. insn = jit_cc_new_insn(rc->cc, LDF32, vr->hreg, fp_reg, offset);
  408. break;
  409. case JIT_REG_KIND_F64:
  410. insn = jit_cc_new_insn(rc->cc, LDF64, vr->hreg, fp_reg, offset);
  411. break;
  412. case JIT_REG_KIND_V64:
  413. insn = jit_cc_new_insn(rc->cc, LDV64, vr->hreg, fp_reg, offset);
  414. break;
  415. case JIT_REG_KIND_V128:
  416. insn =
  417. jit_cc_new_insn(rc->cc, LDV128, vr->hreg, fp_reg, offset);
  418. break;
  419. case JIT_REG_KIND_V256:
  420. insn =
  421. jit_cc_new_insn(rc->cc, LDV256, vr->hreg, fp_reg, offset);
  422. break;
  423. default:
  424. bh_assert(0);
  425. }
  426. }
  427. if (insn)
  428. jit_insn_insert_after(cur_insn, insn);
  429. bh_assert(hr->vreg == vreg);
  430. hr->vreg = vr->hreg = 0;
  431. return insn;
  432. }
  433. /**
  434. * Spill the virtual register (which cannot be exec_env_reg) to memory.
  435. * Spill instruction will be inserted after the given instruction.
  436. *
  437. * @param rc the regalloc context
  438. * @param vreg the virtual register to be reloaded
  439. * @param cur_insn the current instruction after which the reload
  440. * insertion will be inserted
  441. *
  442. * @return the spill instruction if succeeds, NULL otherwise
  443. */
  444. static JitInsn *
  445. spill_vreg(RegallocContext *rc, JitReg vreg, JitInsn *cur_insn)
  446. {
  447. VirtualReg *vr = rc_get_vr(rc, vreg);
  448. JitReg fp_reg = rc->cc->fp_reg, offset;
  449. JitInsn *insn;
  450. /* There is no chance to spill exec_env_reg. */
  451. bh_assert(vreg != rc->cc->exec_env_reg);
  452. bh_assert(vr->hreg && vr->slot);
  453. offset = offset_of_spill_slot(rc->cc, vr->slot);
  454. switch (jit_reg_kind(vreg)) {
  455. case JIT_REG_KIND_I32:
  456. insn = jit_cc_new_insn(rc->cc, STI32, vr->hreg, fp_reg, offset);
  457. break;
  458. case JIT_REG_KIND_I64:
  459. insn = jit_cc_new_insn(rc->cc, STI64, vr->hreg, fp_reg, offset);
  460. break;
  461. case JIT_REG_KIND_F32:
  462. insn = jit_cc_new_insn(rc->cc, STF32, vr->hreg, fp_reg, offset);
  463. break;
  464. case JIT_REG_KIND_F64:
  465. insn = jit_cc_new_insn(rc->cc, STF64, vr->hreg, fp_reg, offset);
  466. break;
  467. case JIT_REG_KIND_V64:
  468. insn = jit_cc_new_insn(rc->cc, STV64, vr->hreg, fp_reg, offset);
  469. break;
  470. case JIT_REG_KIND_V128:
  471. insn = jit_cc_new_insn(rc->cc, STV128, vr->hreg, fp_reg, offset);
  472. break;
  473. case JIT_REG_KIND_V256:
  474. insn = jit_cc_new_insn(rc->cc, STV256, vr->hreg, fp_reg, offset);
  475. break;
  476. default:
  477. bh_assert(0);
  478. return NULL;
  479. }
  480. if (insn)
  481. jit_insn_insert_after(cur_insn, insn);
  482. return insn;
  483. }
  484. /**
  485. * Allocate a hard register for the virtual register. Necessary
  486. * reload instruction will be inserted after the given instruction.
  487. *
  488. * @param rc the regalloc context
  489. * @param vreg the virtual register
  490. * @param insn the instruction after which the reload insertion will
  491. * be inserted
  492. * @param distance the distance of the current instruction
  493. *
  494. * @return the hard register allocated if succeeds, 0 otherwise
  495. */
  496. static JitReg
  497. allocate_hreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance)
  498. {
  499. const int kind = jit_reg_kind(vreg);
  500. const HardReg *hregs;
  501. unsigned hreg_num;
  502. JitReg hreg, vreg_to_reload = 0;
  503. int min_distance = distance, vr_distance;
  504. VirtualReg *vr = rc_get_vr(rc, vreg);
  505. unsigned i;
  506. bh_assert(kind < JIT_REG_KIND_L32);
  507. hregs = rc->hregs[kind];
  508. hreg_num = jit_cc_hreg_num(rc->cc, kind);
  509. if (hreg_num == 0)
  510. /* Unsupported hard register kind. */
  511. {
  512. jit_set_last_error(rc->cc, "unsupported hard register kind");
  513. return 0;
  514. }
  515. if (vr->global_hreg)
  516. /* It has globally allocated register, we can only use it. */
  517. {
  518. if ((vreg_to_reload = (rc_get_hr(rc, vr->global_hreg))->vreg))
  519. if (!reload_vreg(rc, vreg_to_reload, insn))
  520. return 0;
  521. return vr->global_hreg;
  522. }
  523. /* Use the last define-released register if its kind is correct and
  524. it's free so as to optimize for two-operand instructions. */
  525. if (jit_reg_kind(rc->last_def_released_hreg) == kind
  526. && (rc_get_hr(rc, rc->last_def_released_hreg))->vreg == 0)
  527. return rc->last_def_released_hreg;
  528. /* No hint given, just try to pick any free register. */
  529. for (i = 0; i < hreg_num; i++) {
  530. hreg = jit_reg_new(kind, i);
  531. if (jit_cc_is_hreg_fixed(rc->cc, hreg))
  532. continue;
  533. if (hregs[i].vreg == 0)
  534. /* Found a free one, return it. */
  535. return hreg;
  536. }
  537. /* No free registers, need to spill and reload one. */
  538. for (i = 0; i < hreg_num; i++) {
  539. if (jit_cc_is_hreg_fixed(rc->cc, jit_reg_new(kind, i)))
  540. continue;
  541. vr = rc_get_vr(rc, hregs[i].vreg);
  542. /* TODO: since the hregs[i] is in use, its distances should be valid */
  543. vr_distance = vr->distances ? uint_stack_top(vr->distances) : 0;
  544. if (vr_distance < min_distance) {
  545. min_distance = vr_distance;
  546. vreg_to_reload = hregs[i].vreg;
  547. hreg = jit_reg_new(kind, i);
  548. }
  549. }
  550. bh_assert(min_distance < distance);
  551. if (!reload_vreg(rc, vreg_to_reload, insn))
  552. return 0;
  553. return hreg;
  554. }
  555. /**
  556. * Allocate a hard register for the virtual register if not allocated
  557. * yet. Necessary spill and reload instructions will be inserted
  558. * before/after and after the given instruction. This operation will
  559. * convert the virtual register's state from 1 or 3 to 2.
  560. *
  561. * @param rc the regalloc context
  562. * @param vreg the virtual register
  563. * @param insn the instruction after which the spill and reload
  564. * insertions will be inserted
  565. * @param distance the distance of the current instruction
  566. *
  567. * @return the hard register allocated to the virtual register if
  568. * succeeds, 0 otherwise
  569. */
  570. static JitReg
  571. allocate_for_vreg(RegallocContext *rc, JitReg vreg, JitInsn *insn, int distance)
  572. {
  573. VirtualReg *vr = rc_get_vr(rc, vreg);
  574. if (vr->hreg)
  575. /* It has had a hard register, reuse it. */
  576. return vr->hreg;
  577. /* Not allocated yet. */
  578. if ((vr->hreg = allocate_hreg(rc, vreg, insn, distance)))
  579. (rc_get_hr(rc, vr->hreg))->vreg = vreg;
  580. return vr->hreg;
  581. }
  582. /**
  583. * Clobber live registers.
  584. *
  585. * @param rc the regalloc context
  586. * @param is_native whether it's native ABI or JITed ABI
  587. * @param insn the instruction after which the reload insertion will
  588. * be inserted
  589. *
  590. * @return true if succeeds, false otherwise
  591. */
  592. static bool
  593. clobber_live_regs(RegallocContext *rc, bool is_native, JitInsn *insn)
  594. {
  595. unsigned i, j;
  596. for (i = JIT_REG_KIND_VOID; i < JIT_REG_KIND_L32; i++) {
  597. const unsigned hreg_num = jit_cc_hreg_num(rc->cc, i);
  598. for (j = 0; j < hreg_num; j++) {
  599. JitReg hreg = jit_reg_new(i, j);
  600. bool caller_saved =
  601. (is_native ? jit_cc_is_hreg_caller_saved_native(rc->cc, hreg)
  602. : jit_cc_is_hreg_caller_saved_jitted(rc->cc, hreg));
  603. if (caller_saved && rc->hregs[i][j].vreg)
  604. if (!reload_vreg(rc, rc->hregs[i][j].vreg, insn))
  605. return false;
  606. }
  607. }
  608. return true;
  609. }
  610. /**
  611. * Do local register allocation for the given basic block
  612. *
  613. * @param rc the regalloc context
  614. * @param basic_block the basic block
  615. * @param distance the distance of the last instruction of the basic block
  616. *
  617. * @return true if succeeds, false otherwise
  618. */
  619. static bool
  620. allocate_for_basic_block(RegallocContext *rc, JitBasicBlock *basic_block,
  621. int distance)
  622. {
  623. JitInsn *insn;
  624. JIT_FOREACH_INSN_REVERSE(basic_block, insn)
  625. {
  626. #if WASM_ENABLE_SHARED_MEMORY != 0
  627. /* fence insn doesn't have any operand, hence, no regs involved */
  628. if (insn->opcode == JIT_OP_FENCE) {
  629. continue;
  630. }
  631. #endif
  632. JitRegVec regvec = jit_insn_opnd_regs(insn);
  633. unsigned first_use = jit_insn_opnd_first_use(insn);
  634. unsigned i;
  635. JitReg *regp;
  636. distance--;
  637. JIT_REG_VEC_FOREACH_DEF(regvec, i, regp, first_use)
  638. if (is_alloc_candidate(rc->cc, *regp)) {
  639. const JitReg vreg = *regp;
  640. VirtualReg *vr = rc_get_vr(rc, vreg);
  641. if (!(*regp = allocate_for_vreg(rc, vreg, insn, distance)))
  642. return false;
  643. /* Spill the register if required. */
  644. if (vr->slot && !spill_vreg(rc, vreg, insn))
  645. return false;
  646. bh_assert(uint_stack_top(vr->distances) == distance);
  647. uint_stack_pop(&vr->distances);
  648. /* Record the define-released hard register. */
  649. rc->last_def_released_hreg = vr->hreg;
  650. /* Release the hreg and spill slot. */
  651. rc_free_spill_slot(rc, vr->slot);
  652. (rc_get_hr(rc, vr->hreg))->vreg = 0;
  653. vr->hreg = vr->slot = 0;
  654. }
  655. if (insn->opcode == JIT_OP_CALLBC) {
  656. if (!clobber_live_regs(rc, false, insn))
  657. return false;
  658. /* The exec_env_reg is implicitly used by the callee. */
  659. if (!allocate_for_vreg(rc, rc->cc->exec_env_reg, insn, distance))
  660. return false;
  661. }
  662. else if (insn->opcode == JIT_OP_CALLNATIVE) {
  663. if (!clobber_live_regs(rc, true, insn))
  664. return false;
  665. }
  666. JIT_REG_VEC_FOREACH_USE(regvec, i, regp, first_use)
  667. if (is_alloc_candidate(rc->cc, *regp)) {
  668. if (!allocate_for_vreg(rc, *regp, insn, distance))
  669. return false;
  670. }
  671. JIT_REG_VEC_FOREACH_USE(regvec, i, regp, first_use)
  672. if (is_alloc_candidate(rc->cc, *regp)) {
  673. VirtualReg *vr = rc_get_vr(rc, *regp);
  674. bh_assert(uint_stack_top(vr->distances) == distance);
  675. uint_stack_pop(&vr->distances);
  676. /* be sure that the hreg exists and hasn't been spilled out */
  677. bh_assert(vr->hreg != 0);
  678. *regp = vr->hreg;
  679. }
  680. }
  681. return true;
  682. }
  683. bool
  684. jit_pass_regalloc(JitCompContext *cc)
  685. {
  686. RegallocContext rc = { 0 };
  687. unsigned label_index, end_label_index;
  688. JitBasicBlock *basic_block;
  689. VirtualReg *self_vr;
  690. bool retval = false;
  691. if (!rc_init(&rc, cc))
  692. return false;
  693. /* NOTE: don't allocate new virtual registers during allocation
  694. because the rc->vregs array is fixed size. */
  695. /* TODO: allocate hard registers for global virtual registers here.
  696. Currently, exec_env_reg is the only global virtual register. */
  697. self_vr = rc_get_vr(&rc, cc->exec_env_reg);
  698. JIT_FOREACH_BLOCK_ENTRY_EXIT(cc, label_index, end_label_index, basic_block)
  699. {
  700. int distance;
  701. /* TODO: initialize hreg for live-out registers. */
  702. self_vr->hreg = self_vr->global_hreg;
  703. (rc_get_hr(&rc, cc->exec_env_reg))->vreg = cc->exec_env_reg;
  704. /**
  705. * TODO: the allocation of a basic block keeps using vregs[]
  706. * and hregs[] from previous basic block
  707. */
  708. if ((distance = collect_distances(&rc, basic_block)) < 0)
  709. goto cleanup_and_return;
  710. if (!allocate_for_basic_block(&rc, basic_block, distance))
  711. goto cleanup_and_return;
  712. /* TODO: generate necessary spills for live-in registers. */
  713. }
  714. retval = true;
  715. cleanup_and_return:
  716. rc_destroy(&rc);
  717. return retval;
  718. }