axe_transform.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. /*
  2. * Andrea Di Biagio
  3. * Politecnico di Milano, 2007
  4. *
  5. * axe_transform.c
  6. * Formal Languages & Compilers Machine, 2007/2008
  7. *
  8. */
  9. #include "axe_transform.h"
  10. #include "symbol_table.h"
  11. #include "cflow_constants.h"
  12. #include "reg_alloc_constants.h"
  13. #include "axe_errors.h"
  14. #include "axe_debug.h"
  15. extern int errorcode;
  16. extern int cflow_errorcode;
  17. typedef struct t_tempLabel
  18. {
  19. t_axe_label *labelID;
  20. int regID;
  21. } t_tempLabel;
  22. static t_axe_instruction * _createUnary (t_program_infos *program
  23. , int reg, t_axe_label *label, int opcode);
  24. static t_axe_instruction * createUnaryInstruction
  25. (t_program_infos *program, int reg, int opcode);
  26. static t_tempLabel * allocTempLabel(t_axe_label *labelID, int regID);
  27. static void freeTempLabel(t_tempLabel *tempLabel);
  28. static void finalizeListOfTempLabels(t_list *tempLabels);
  29. static int compareTempLabels(void *valA, void *valB);
  30. /* create new locations into the data segment in order to manage correctly
  31. * spilled variables */
  32. static void updateTheDataSegment
  33. (t_program_infos *program, t_list *tempLabels);
  34. static void updateTheCodeSegment
  35. (t_program_infos *program, t_cflow_Graph *graph);
  36. static t_list * _insertLoad(t_program_infos *program, t_cflow_Graph *graph
  37. , t_basic_block *block, t_cflow_Node *current_node
  38. , t_cflow_var *var, t_list *usedVars);
  39. static t_list * _insertStore(t_program_infos *program, t_cflow_Graph *graph
  40. , t_basic_block *block, t_cflow_Node *current_node
  41. , t_cflow_var *var, t_list *usedVars);
  42. /* create a load instruction without assigning it to program */
  43. static t_axe_instruction * createLoadInstruction
  44. (t_program_infos *program, int reg);
  45. /* create a store instruction without assigning it to program */
  46. static t_axe_instruction * createStoreInstruction
  47. (t_program_infos *program, int reg);
  48. /* update the control flow informations by unsing the result
  49. * of the register allocation process and a list of bindings
  50. * between new assembly labels and spilled variables */
  51. static void updatCflowInfos(t_program_infos *program, t_cflow_Graph *graph
  52. , t_reg_allocator *RA, t_list *label_bindings);
  53. /* this function returns a list of t_templabel containing binding
  54. * informations between spilled variables and labels that will point
  55. * to a memory block in the data segment */
  56. static t_list * retrieveLabelBindings(t_program_infos *program, t_reg_allocator *RA);
  57. int _insertLoadSpill(t_program_infos *program, int temp_register, int selected_register
  58. , t_cflow_Graph *graph, t_basic_block *current_block
  59. , t_cflow_Node *current_node, t_list *labelBindings, int before);
  60. int _insertStoreSpill(t_program_infos *program, int temp_register, int selected_register
  61. , t_cflow_Graph *graph, t_basic_block *current_block
  62. , t_cflow_Node *current_node, t_list *labelBindings, int before);
  63. static t_list * _insertStore(t_program_infos *program, t_cflow_Graph *graph
  64. , t_basic_block *current_block, t_cflow_Node *current_node
  65. , t_cflow_var *var, t_list *usedVars)
  66. {
  67. /* we have to insert a store instruction into the code */
  68. t_axe_instruction *storeInstr;
  69. t_cflow_Node *storeNode;
  70. /* create a load instruction */
  71. storeInstr = createStoreInstruction
  72. (program, var->ID);
  73. /* test if an error occurred */
  74. if (errorcode != AXE_OK) {
  75. free_Instruction(storeInstr);
  76. notifyError(errorcode);
  77. }
  78. if (storeInstr != NULL)
  79. {
  80. /* create a node for the store instruction */
  81. storeNode = allocNode (graph, storeInstr);
  82. if (cflow_errorcode != CFLOW_OK) {
  83. finalizeNode(storeNode);
  84. free_Instruction(storeInstr);
  85. return usedVars;
  86. }
  87. /* insert the node `loadNode' before `current_node' */
  88. insertNodeAfter(current_block, current_node, storeNode);
  89. /* update the list of usedVars */
  90. usedVars = removeElement(usedVars, storeNode->uses[0]);
  91. }
  92. return usedVars;
  93. }
  94. t_list * _insertLoad(t_program_infos *program, t_cflow_Graph *graph
  95. , t_basic_block *current_block, t_cflow_Node *current_node
  96. , t_cflow_var *var, t_list *usedVars)
  97. {
  98. /* we have to insert a load instruction into the code */
  99. t_axe_instruction *current_instr;
  100. t_axe_instruction *loadInstr;
  101. t_cflow_Node *loadNode;
  102. /* retrieve the current instruction from the current node */
  103. current_instr = current_node->instr;
  104. /* create a load instruction */
  105. loadInstr = createLoadInstruction
  106. (program, var->ID);
  107. /* test if an error occurred */
  108. if (errorcode != AXE_OK) {
  109. free_Instruction(loadInstr);
  110. notifyError(errorcode);
  111. }
  112. if (loadInstr != NULL)
  113. {
  114. /* create a node for the load instruction */
  115. loadNode = allocNode (graph, loadInstr);
  116. /* test if an error occurred */
  117. if (cflow_errorcode != CFLOW_OK) {
  118. finalizeNode(loadNode);
  119. free_Instruction(loadInstr);
  120. return usedVars;
  121. }
  122. /* update the label informations */
  123. if (current_instr->labelID != NULL) {
  124. loadInstr->labelID = current_instr->labelID;
  125. current_instr->labelID = NULL;
  126. }
  127. /* insert the node `loadNode' before `current_node' */
  128. insertNodeBefore(current_block, current_node, loadNode);
  129. /* update the list of usedVars */
  130. usedVars = addElement(usedVars, loadNode->def, -1);
  131. }
  132. return usedVars;
  133. }
  134. void updateTheCodeSegment(t_program_infos *program, t_cflow_Graph *graph)
  135. {
  136. t_list *current_bb_element;
  137. t_list *current_nd_element;
  138. t_basic_block *bblock;
  139. t_cflow_Node *node;
  140. /* preconditions */
  141. if (program == NULL)
  142. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  143. if (graph == NULL)
  144. notifyError(AXE_INVALID_CFLOW_GRAPH);
  145. current_bb_element = graph->blocks;
  146. while(current_bb_element != NULL)
  147. {
  148. bblock = (t_basic_block *) LDATA(current_bb_element);
  149. current_nd_element = bblock->nodes;
  150. while(current_nd_element != NULL)
  151. {
  152. node = (t_cflow_Node *) LDATA(current_nd_element);
  153. program->instructions =
  154. addElement(program->instructions, node->instr, -1);
  155. current_nd_element = LNEXT(current_nd_element);
  156. }
  157. current_bb_element = LNEXT(current_bb_element);
  158. }
  159. }
  160. void updateTheDataSegment(t_program_infos *program, t_list *labelBindings)
  161. {
  162. t_list *current_element;
  163. t_tempLabel *current_TL;
  164. t_axe_data *new_data_info;
  165. /* preconditions */
  166. if (program == NULL) {
  167. finalizeListOfTempLabels(labelBindings);
  168. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  169. }
  170. /* initialize the value of `current_element' */
  171. current_element = labelBindings;
  172. while(current_element != NULL)
  173. {
  174. current_TL = (t_tempLabel *) LDATA(current_element);
  175. new_data_info = alloc_data (DIR_WORD, 0, current_TL->labelID);
  176. if (new_data_info == NULL){
  177. finalizeListOfTempLabels(labelBindings);
  178. notifyError(AXE_OUT_OF_MEMORY);
  179. }
  180. /* update the list of directives */
  181. program->data = addElement(program->data, new_data_info, -1);
  182. current_element = LNEXT(current_element);
  183. }
  184. }
  185. t_axe_instruction * _createUnary (t_program_infos *program
  186. , int reg, t_axe_label *label, int opcode)
  187. {
  188. t_axe_instruction *result;
  189. /* preconditions */
  190. if (program == NULL) {
  191. errorcode = AXE_PROGRAM_NOT_INITIALIZED;
  192. return NULL;
  193. }
  194. if (label == NULL) {
  195. errorcode = AXE_INVALID_LABEL;
  196. return NULL;
  197. }
  198. /* create an instance of `t_axe_instruction' */
  199. result = alloc_instruction(opcode);
  200. if (result == NULL) {
  201. errorcode = AXE_OUT_OF_MEMORY;
  202. return NULL;
  203. }
  204. result->reg_1 = alloc_register(reg, 0);
  205. if (result->reg_1 == NULL) {
  206. errorcode = AXE_OUT_OF_MEMORY;
  207. free_Instruction(result);
  208. return NULL;
  209. }
  210. /* initialize an address info */
  211. result->address = alloc_address(LABEL_TYPE, 0, label);
  212. if (result->address == NULL) {
  213. errorcode = AXE_OUT_OF_MEMORY;
  214. free_Instruction(result);
  215. return NULL;
  216. }
  217. return result;
  218. }
  219. int compareTempLabels(void *valA, void *valB)
  220. {
  221. t_tempLabel *tlA;
  222. t_tempLabel *tlB;
  223. if (valA == NULL)
  224. return 0;
  225. if (valB == NULL)
  226. return 0;
  227. tlA = (t_tempLabel *) valA;
  228. tlB = (t_tempLabel *) valB;
  229. return (tlA->regID == tlB->regID);
  230. }
  231. t_tempLabel * allocTempLabel(t_axe_label *labelID, int regID)
  232. {
  233. t_tempLabel *result;
  234. /* preconditions */
  235. if (labelID == NULL) {
  236. errorcode = AXE_INVALID_LABEL;
  237. return NULL;
  238. }
  239. /* create a new temp-label */
  240. result = _AXE_ALLOC_FUNCTION(sizeof(t_tempLabel));
  241. if (result == NULL) {
  242. errorcode = AXE_OUT_OF_MEMORY;
  243. return NULL;
  244. }
  245. /* initialize the temp label */
  246. result->labelID = labelID;
  247. result->regID = regID;
  248. return result;
  249. }
  250. void freeTempLabel(t_tempLabel *tempLabel)
  251. {
  252. if (tempLabel != NULL)
  253. _AXE_FREE_FUNCTION(tempLabel);
  254. }
  255. void finalizeListOfTempLabels(t_list *tempLabels)
  256. {
  257. t_list *current_element;
  258. t_tempLabel *tempLabel;
  259. /* test the preconditions */
  260. if (tempLabels == NULL)
  261. return;
  262. /* assign to current_element the address of the first
  263. * element of the list `tempLabels' */
  264. current_element = tempLabels;
  265. while(current_element != NULL)
  266. {
  267. tempLabel = (t_tempLabel *) LDATA(current_element);
  268. if (tempLabel != NULL)
  269. freeTempLabel(tempLabel);
  270. current_element = LNEXT(current_element);
  271. }
  272. /* finalize the list of elements of type `t_tempLabel' */
  273. freeList(tempLabels);
  274. }
  275. void updateProgramInfos(t_program_infos *program
  276. , t_cflow_Graph *graph, t_reg_allocator *RA)
  277. {
  278. t_list *label_bindings;
  279. /* retrieve a list of t_templabels for the given RA infos.*/
  280. label_bindings = retrieveLabelBindings(program, RA);
  281. /* update the content of the data segment */
  282. updateTheDataSegment(program, label_bindings);
  283. /* update the control flow graph with the reg-alloc infos. */
  284. updatCflowInfos(program, graph, RA, label_bindings);
  285. /* erase the old code segment */
  286. freeList(program->instructions);
  287. program->instructions = NULL;
  288. /* update the code segment informations */
  289. updateTheCodeSegment(program, graph);
  290. /* finalize the list of tempLabels */
  291. finalizeListOfTempLabels(label_bindings);
  292. }
  293. t_list * retrieveLabelBindings(t_program_infos *program, t_reg_allocator *RA)
  294. {
  295. int counter;
  296. t_list *result;
  297. t_tempLabel *tlabel;
  298. t_axe_label *axe_label;
  299. /* preconditions */
  300. if (program == NULL)
  301. notifyError(AXE_PROGRAM_NOT_INITIALIZED);
  302. if (RA == NULL)
  303. notifyError(AXE_INVALID_REG_ALLOC);
  304. /* initialize the local variable `result' */
  305. result = NULL;
  306. tlabel = NULL;
  307. for (counter = 0; counter <= RA->varNum; counter++)
  308. {
  309. if (RA->bindings[counter] == RA_SPILL_REQUIRED)
  310. {
  311. /* retrieve a new label */
  312. axe_label = newLabel(program);
  313. if (axe_label == NULL)
  314. notifyError(AXE_INVALID_LABEL);
  315. /* create a new tempLabel */
  316. tlabel = allocTempLabel(axe_label, counter);
  317. /* add the current tlabel to the list of labelbindings */
  318. result = addElement(result, tlabel, -1);
  319. }
  320. }
  321. /* postcondition: return the list of bindings */
  322. return result;
  323. }
  324. t_axe_instruction * createUnaryInstruction
  325. (t_program_infos *program, int reg, int opcode)
  326. {
  327. char *varID;
  328. int sy_errorcode;
  329. t_axe_variable *axe_var;
  330. /* test the preconditions */
  331. if ((reg == REG_INVALID) || (reg == REG_0)) {
  332. errorcode = AXE_INVALID_REGISTER_INFO;
  333. return NULL;
  334. }
  335. if (program == NULL || program->sy_table == NULL) {
  336. errorcode = AXE_PROGRAM_NOT_INITIALIZED;
  337. return NULL;
  338. }
  339. /* initialize the value of errorcode */
  340. sy_errorcode = SY_TABLE_OK;
  341. varID = getIDfromLocation(program->sy_table, reg, &sy_errorcode);
  342. if (varID == NULL)
  343. return NULL;
  344. /* retrieve the variable associated with `varID' */
  345. axe_var = getVariable (program, varID);
  346. return _createUnary (program, reg, axe_var->labelID, opcode);
  347. }
  348. t_axe_instruction * createStoreInstruction
  349. (t_program_infos *program, int reg)
  350. {
  351. return createUnaryInstruction(program, reg, STORE);
  352. }
  353. t_axe_instruction * createLoadInstruction
  354. (t_program_infos *program, int reg)
  355. {
  356. return createUnaryInstruction(program, reg, LOAD);
  357. }
  358. t_cflow_Graph * insertLoadAndStoreInstr
  359. (t_program_infos *program, t_cflow_Graph *graph)
  360. {
  361. t_list *current_bb_element;
  362. t_basic_block *current_block;
  363. t_list *current_nd_element;
  364. t_cflow_Node *current_node;
  365. t_list *usedVars;
  366. /* assertions */
  367. assert(program != NULL);
  368. assert(graph != NULL);
  369. /* initialize the list of variables used by this basic block */
  370. usedVars = NULL;
  371. current_bb_element = graph->blocks;
  372. while (current_bb_element != NULL)
  373. {
  374. current_block = (t_basic_block *) LDATA(current_bb_element);
  375. /* retrieve the list of nodes for the current basic block */
  376. current_nd_element = current_block->nodes;
  377. while(current_nd_element != NULL)
  378. {
  379. current_node = (t_cflow_Node *) LDATA(current_nd_element);
  380. /* test if we have to insert a store */
  381. if ( (current_node->def != NULL)
  382. && ((current_node->def)->ID != REG_0) )
  383. {
  384. if (findElement(usedVars, current_node->def) == NULL)
  385. {
  386. usedVars = addElement(usedVars, current_node->def, -1);
  387. }
  388. }
  389. /* test if we have to insert a load */
  390. if ( (current_node->uses[0] != NULL)
  391. && ((current_node->uses[0])->ID != REG_0) )
  392. {
  393. if (findElement(usedVars, current_node->uses[0]) == NULL)
  394. {
  395. usedVars = _insertLoad(program, graph, current_block
  396. , current_node, current_node->uses[0], usedVars);
  397. }
  398. }
  399. if ( (current_node->uses[1] != NULL)
  400. && ((current_node->uses[1])->ID != REG_0) )
  401. {
  402. if (findElement(usedVars, current_node->uses[1]) == NULL)
  403. {
  404. usedVars = _insertLoad(program, graph, current_block
  405. , current_node, current_node->uses[1], usedVars);
  406. }
  407. }
  408. if ( (current_node->uses[2] != NULL)
  409. && ((current_node->uses[2])->ID != REG_0) )
  410. {
  411. if (findElement(usedVars, current_node->uses[2]) == NULL)
  412. {
  413. usedVars = _insertLoad(program, graph, current_block
  414. , current_node, current_node->uses[2], usedVars);
  415. }
  416. }
  417. /* retrieve the next element */
  418. current_nd_element = LNEXT(current_nd_element);
  419. }
  420. current_nd_element = getLastElement(current_block->nodes);
  421. while((current_nd_element != NULL) && (usedVars != NULL))
  422. {
  423. current_node = (t_cflow_Node *) LDATA(current_nd_element);
  424. /* test if we have to insert a store */
  425. if ( (current_node->uses[0] != NULL)
  426. && ((current_node->uses[0])->ID != REG_0) )
  427. {
  428. if (findElement(usedVars, current_node->uses[0]) != NULL)
  429. {
  430. usedVars = _insertStore(program, graph, current_block
  431. , current_node, current_node->uses[0], usedVars);
  432. }
  433. }
  434. /* test if we have to insert a store */
  435. if ( (current_node->uses[1] != NULL)
  436. && ((current_node->uses[1])->ID != REG_0) )
  437. {
  438. if (findElement(usedVars, current_node->uses[1]) != NULL)
  439. {
  440. usedVars = _insertStore(program, graph, current_block
  441. , current_node, current_node->uses[1], usedVars);
  442. }
  443. }
  444. /* test if we have to insert a store */
  445. if ( (current_node->uses[2] != NULL)
  446. && ((current_node->uses[2])->ID != REG_0) )
  447. {
  448. if (findElement(usedVars, current_node->uses[2]) != NULL)
  449. {
  450. usedVars = _insertStore(program, graph, current_block
  451. , current_node, current_node->uses[2], usedVars);
  452. }
  453. }
  454. /* test if we have to insert a store */
  455. if ( (current_node->def != NULL)
  456. && ((current_node->def)->ID != REG_0) )
  457. {
  458. if (findElement(usedVars, current_node->def) != NULL)
  459. {
  460. usedVars = _insertStore(program, graph, current_block
  461. , current_node, current_node->def, usedVars);
  462. }
  463. }
  464. /* retrieve the previous element */
  465. current_nd_element = LPREV(current_nd_element);
  466. }
  467. current_bb_element = LNEXT(current_bb_element);
  468. }
  469. /* free the list `usedVars' */
  470. freeList(usedVars);
  471. return graph;
  472. }
  473. void updatCflowInfos(t_program_infos *program, t_cflow_Graph *graph
  474. , t_reg_allocator *RA, t_list *label_bindings)
  475. {
  476. t_list *current_bb_element;
  477. t_basic_block *current_block;
  478. t_axe_instruction *current_instr;
  479. t_list *current_nd_element;
  480. t_cflow_Node *current_node;
  481. int current_row;
  482. int found;
  483. /* preconditions */
  484. assert(program != NULL);
  485. assert(graph != NULL);
  486. assert(RA != NULL);
  487. /* initialize local variables */
  488. current_row = 0;
  489. found = 0;
  490. current_bb_element = graph->blocks;
  491. while (current_bb_element != NULL)
  492. {
  493. int counter;
  494. int assignedRegisters[RA_MIN_REG_NUM][3];
  495. current_block = (t_basic_block *) LDATA(current_bb_element);
  496. assert(current_block != NULL);
  497. /* initialize used_Registers */
  498. for (counter = 0; counter < RA_MIN_REG_NUM; counter ++)
  499. {
  500. assignedRegisters[counter][0] = REG_INVALID; /* invalid register */
  501. assignedRegisters[counter][1] = 0; /* need write back */
  502. assignedRegisters[counter][2] = 0; /* currently used */
  503. }
  504. /* retrieve the list of nodes for the current basic block */
  505. current_nd_element = current_block->nodes;
  506. while(current_nd_element != NULL)
  507. {
  508. int used_Registers[3] = {-1, -1, -1};
  509. /* retrieve the data associated with the current node of the block */
  510. current_node = (t_cflow_Node *) LDATA(current_nd_element);
  511. /* fetch the current instruction */
  512. current_instr = current_node->instr;
  513. /* Test if a requested variable is already loaded into a register */
  514. if (current_instr->reg_1 != NULL)
  515. {
  516. if (RA->bindings[(current_instr->reg_1)->ID]
  517. == RA_SPILL_REQUIRED)
  518. {
  519. int current_row = 0;
  520. int found = 0;
  521. while ((current_row < RA_MIN_REG_NUM) && !found)
  522. {
  523. if (assignedRegisters[current_row][0]
  524. == (current_instr->reg_1)->ID)
  525. {
  526. /* update the value of used_Register */
  527. used_Registers[0] = current_row;
  528. /* update the value of `assignedRegisters` */
  529. /* set currently used flag */
  530. assignedRegisters[current_row][2] = 1;
  531. /* test if a write back is needed */
  532. if (! (current_instr->reg_1)->indirect)
  533. {
  534. /* if the current instruction is a STORE we don't need
  535. * to write back the value of reg_1 again in memory. */
  536. /* Also if the current instruction is a WRITE instruction
  537. * we don't have to set the flag "dirty" for the
  538. * register assignedRegisters[current_row], since reg_1
  539. * is "used" but not "defined" */
  540. if ( (current_instr->opcode != STORE)
  541. && (current_instr->opcode != AXE_WRITE) )
  542. {
  543. assignedRegisters[current_row][1] = 1;
  544. }
  545. /* if the current instruction is a STORE we have to
  546. * notify that the write back is happened by
  547. * resetting the flag "dirty" */
  548. if (current_instr->opcode == STORE)
  549. assignedRegisters[current_row][1] = 0;
  550. }
  551. /* notify that the value was found */
  552. found = 1;
  553. }
  554. current_row ++;
  555. }
  556. }
  557. }
  558. if (current_instr->reg_2 != NULL)
  559. {
  560. if (RA->bindings[(current_instr->reg_2)->ID]
  561. == RA_SPILL_REQUIRED)
  562. {
  563. int current_row = 0;
  564. int found = 0;
  565. while ((current_row < RA_MIN_REG_NUM) && !found)
  566. {
  567. if (assignedRegisters[current_row][0]
  568. == (current_instr->reg_2)->ID)
  569. {
  570. /* update the value of used_Register */
  571. used_Registers[1] = current_row;
  572. /* update the value of `assignedRegisters` */
  573. /* set currently used flag */
  574. assignedRegisters[current_row][2] = 1;
  575. /* notify that the value was found */
  576. found = 1;
  577. }
  578. current_row ++;
  579. }
  580. }
  581. }
  582. if (current_instr->reg_3 != NULL)
  583. {
  584. if (RA->bindings[(current_instr->reg_3)->ID]
  585. == RA_SPILL_REQUIRED)
  586. {
  587. int current_row = 0;
  588. int found = 0;
  589. while ((current_row < RA_MIN_REG_NUM) && !found)
  590. {
  591. if (assignedRegisters[current_row][0]
  592. == (current_instr->reg_3)->ID)
  593. {
  594. /* update the value of used_Register */
  595. used_Registers[2] = current_row;
  596. /* update the value of `assignedRegisters` */
  597. /* set currently used flag */
  598. assignedRegisters[current_row][2] = 1;
  599. /* notify that the value was found */
  600. found = 1;
  601. }
  602. current_row ++;
  603. }
  604. }
  605. }
  606. /* phase two */
  607. if (current_instr->reg_2 != NULL)
  608. {
  609. if ((RA->bindings[(current_instr->reg_2)->ID]
  610. == RA_SPILL_REQUIRED) && (used_Registers[1] == -1))
  611. {
  612. int current_row = 0;
  613. int found = 0;
  614. while ((current_row < RA_MIN_REG_NUM) && !found)
  615. {
  616. if (assignedRegisters[current_row][2] == 0)
  617. {
  618. int register_found = current_row + NUM_REGISTERS
  619. + 1 - RA_MIN_REG_NUM;
  620. if (assignedRegisters[current_row][1] == 1)
  621. {
  622. /* NEED WRITE BACK */
  623. _insertStoreSpill(program, assignedRegisters[current_row][0]
  624. , register_found, graph, current_block
  625. , current_node, label_bindings, 1);
  626. }
  627. _insertLoadSpill(program, (current_instr->reg_2)->ID
  628. , register_found, graph, current_block
  629. , current_node, label_bindings, 1);
  630. /* update the control informations */
  631. assignedRegisters[current_row][0] = (current_instr->reg_2)->ID;
  632. assignedRegisters[current_row][1] = 0;
  633. assignedRegisters[current_row][2] = 1;
  634. used_Registers[1] = current_row;
  635. found = 1;
  636. }
  637. current_row ++;
  638. }
  639. assert(found != 0);
  640. }
  641. }
  642. if (current_instr->reg_3 != NULL)
  643. {
  644. if ((RA->bindings[(current_instr->reg_3)->ID]
  645. == RA_SPILL_REQUIRED) && (used_Registers[2] == -1))
  646. {
  647. int current_row = 0;
  648. int found = 0;
  649. if ((current_instr->reg_3)->ID == (current_instr->reg_2)->ID)
  650. {
  651. used_Registers[2] = used_Registers[1];
  652. found = 1;
  653. }
  654. while ((current_row < RA_MIN_REG_NUM) && !found)
  655. {
  656. if (assignedRegisters[current_row][2] == 0)
  657. {
  658. int register_found = current_row + NUM_REGISTERS
  659. + 1 - RA_MIN_REG_NUM;
  660. if (assignedRegisters[current_row][1] == 1)
  661. {
  662. /* NEED WRITE BACK */
  663. _insertStoreSpill(program, assignedRegisters[current_row][0]
  664. , register_found, graph, current_block
  665. , current_node, label_bindings, 1);
  666. }
  667. _insertLoadSpill(program, (current_instr->reg_3)->ID
  668. , register_found, graph, current_block
  669. , current_node, label_bindings, 1);
  670. /* update the control informations */
  671. assignedRegisters[current_row][0] = (current_instr->reg_3)->ID;
  672. assignedRegisters[current_row][1] = 0;
  673. assignedRegisters[current_row][2] = 1;
  674. used_Registers[2] = current_row;
  675. found = 1;
  676. }
  677. current_row ++;
  678. }
  679. }
  680. }
  681. if (current_instr->reg_1 != NULL)
  682. {
  683. if ((RA->bindings[(current_instr->reg_1)->ID]
  684. == RA_SPILL_REQUIRED) && (used_Registers[0] == -1))
  685. {
  686. int current_row = 0;
  687. int found = 0;
  688. while ((current_row < RA_MIN_REG_NUM) && !found)
  689. {
  690. if (assignedRegisters[current_row][2] == 0)
  691. {
  692. int register_found = current_row + NUM_REGISTERS
  693. + 1 - RA_MIN_REG_NUM;
  694. if (assignedRegisters[current_row][1] == 1)
  695. {
  696. /* NEED WRITE BACK */
  697. _insertStoreSpill(program, assignedRegisters[current_row][0]
  698. , register_found, graph, current_block
  699. , current_node, label_bindings, 1);
  700. }
  701. /* test if we need to load the value from register */
  702. if ( (current_instr->reg_1)->indirect
  703. || (current_instr->opcode == AXE_WRITE))
  704. {
  705. _insertLoadSpill(program, (current_instr->reg_1)->ID
  706. , register_found, graph, current_block
  707. , current_node, label_bindings, 1);
  708. }
  709. /* update the control informations */
  710. assignedRegisters[current_row][0] = (current_instr->reg_1)->ID;
  711. if (! (current_instr->reg_1)->indirect)
  712. {
  713. if ( (current_instr->opcode != STORE)
  714. && (current_instr->opcode != AXE_WRITE) )
  715. {
  716. assignedRegisters[current_row][1] = 1;
  717. }
  718. if (current_instr->opcode == STORE)
  719. assignedRegisters[current_row][1] = 0;
  720. }
  721. assignedRegisters[current_row][2] = 1;
  722. used_Registers[0] = current_row;
  723. found = 1;
  724. }
  725. current_row ++;
  726. }
  727. assert(found != 0);
  728. }
  729. }
  730. /* update the instruction informations */
  731. if (current_instr->reg_1 != NULL)
  732. {
  733. if (used_Registers[0] != -1)
  734. {
  735. current_instr->reg_1->ID = used_Registers[0] + NUM_REGISTERS
  736. + 1 - RA_MIN_REG_NUM;
  737. assignedRegisters[used_Registers[0]][2] = 0;
  738. }
  739. else
  740. current_instr->reg_1->ID =
  741. RA->bindings[(current_instr->reg_1)->ID];
  742. }
  743. if (current_instr->reg_2 != NULL)
  744. {
  745. if (used_Registers[1] != -1)
  746. {
  747. current_instr->reg_2->ID = used_Registers[1] + NUM_REGISTERS
  748. + 1 - RA_MIN_REG_NUM;
  749. assignedRegisters[used_Registers[1]][2] = 0;
  750. }
  751. else
  752. current_instr->reg_2->ID =
  753. RA->bindings[(current_instr->reg_2)->ID];
  754. }
  755. if (current_instr->reg_3 != NULL)
  756. {
  757. if (used_Registers[2] != -1)
  758. {
  759. current_instr->reg_3->ID = used_Registers[2] + NUM_REGISTERS
  760. + 1 - RA_MIN_REG_NUM;
  761. assignedRegisters[used_Registers[2]][2] = 0;
  762. }
  763. else
  764. current_instr->reg_3->ID =
  765. RA->bindings[(current_instr->reg_3)->ID];
  766. }
  767. /* retrieve the previous element */
  768. current_nd_element = LNEXT(current_nd_element);
  769. }
  770. /* initialize used_Registers */
  771. for (counter = 0; counter < RA_MIN_REG_NUM; counter ++)
  772. {
  773. if (assignedRegisters[counter][1] == 1)
  774. {
  775. /* NEED WRITE BACK */
  776. _insertStoreSpill(program, assignedRegisters[counter][0]
  777. , (counter + NUM_REGISTERS + 1 - RA_MIN_REG_NUM)
  778. , graph, current_block
  779. , current_node, label_bindings, 1);
  780. }
  781. }
  782. /* retrieve the next basic block element */
  783. current_bb_element = LNEXT(current_bb_element);
  784. }
  785. }
  786. int _insertStoreSpill(t_program_infos *program, int temp_register, int selected_register
  787. , t_cflow_Graph *graph, t_basic_block *current_block
  788. , t_cflow_Node *current_node, t_list *labelBindings, int before)
  789. {
  790. t_axe_instruction *storeInstr;
  791. t_axe_instruction *current_instr;
  792. t_cflow_Node *storeNode;
  793. t_list *elementFound;
  794. t_tempLabel pattern;
  795. t_tempLabel *tlabel;
  796. /* initialize current_instr */
  797. current_instr = current_node->instr;
  798. pattern.regID = temp_register;
  799. elementFound = CustomfindElement (labelBindings
  800. , &pattern, compareTempLabels);
  801. if (elementFound == NULL) {
  802. finalizeNode(storeNode);
  803. errorcode = AXE_TRANSFORM_ERROR;
  804. return -1;
  805. }
  806. tlabel = (t_tempLabel *) LDATA(elementFound);
  807. assert(tlabel != NULL);
  808. /* create a store instruction */
  809. storeInstr = _createUnary (program
  810. , selected_register, tlabel->labelID, STORE);
  811. /* test if an error occurred */
  812. if (errorcode != AXE_OK) {
  813. free_Instruction(storeInstr);
  814. return -1;
  815. }
  816. /* create a node for the load instruction */
  817. storeNode = allocNode (graph, storeInstr);
  818. if (cflow_errorcode != CFLOW_OK) {
  819. finalizeNode(storeNode);
  820. free_Instruction(storeInstr);
  821. errorcode = AXE_TRANSFORM_ERROR;
  822. return -1;
  823. }
  824. /* test if we have to insert the node `storeNode' before `current_node'
  825. * inside the basic block */
  826. if (before == 0)
  827. insertNodeAfter(current_block, current_node, storeNode);
  828. else
  829. insertNodeBefore(current_block, current_node, storeNode);
  830. return 0;
  831. }
  832. int _insertLoadSpill(t_program_infos *program, int temp_register, int selected_register
  833. , t_cflow_Graph *graph, t_basic_block *block
  834. , t_cflow_Node *current_node, t_list *labelBindings, int before)
  835. {
  836. t_axe_instruction *loadInstr;
  837. t_axe_instruction *current_instr;
  838. t_cflow_Node *loadNode;
  839. t_list *elementFound;
  840. t_tempLabel pattern;
  841. t_tempLabel *tlabel;
  842. /* initialize current_instr */
  843. current_instr = current_node->instr;
  844. pattern.regID = temp_register;
  845. elementFound = CustomfindElement (labelBindings
  846. , &pattern, compareTempLabels);
  847. if (elementFound == NULL) {
  848. finalizeNode(loadNode);
  849. errorcode = AXE_TRANSFORM_ERROR;
  850. return -1;
  851. }
  852. tlabel = (t_tempLabel *) LDATA(elementFound);
  853. assert(tlabel != NULL);
  854. /* create a load instruction */
  855. loadInstr = _createUnary (program
  856. , selected_register, tlabel->labelID, LOAD);
  857. /* test if an error occurred */
  858. if (errorcode != AXE_OK) {
  859. free_Instruction(loadInstr);
  860. finalizeNode(loadNode);
  861. return -1;
  862. }
  863. /* update the value of storeInstr and instr */
  864. (loadInstr->reg_1)->ID = selected_register;
  865. /* create a node for the load instruction */
  866. loadNode = allocNode (graph, loadInstr);
  867. /* test if an error occurred */
  868. if (cflow_errorcode != CFLOW_OK) {
  869. finalizeNode(loadNode);
  870. free_Instruction(loadInstr);
  871. errorcode = AXE_TRANSFORM_ERROR;
  872. return -1;
  873. }
  874. if ((current_node->instr)->labelID != NULL)
  875. {
  876. /* modify the label informations */
  877. loadInstr->labelID = (current_node->instr)->labelID;
  878. (current_node->instr)->labelID = NULL;
  879. }
  880. if (before == 1)
  881. /* insert the node `loadNode' before `current_node' */
  882. insertNodeBefore(block, current_node, loadNode);
  883. else
  884. insertNodeAfter(block, current_node, loadNode);
  885. return 0;
  886. }