/opengles/src/codegen/instruction.c
C | 2091 lines | 1544 code | 445 blank | 102 comment | 237 complexity | badf588d200dee8f4004d79840481a17 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/****************************************************************************/ 2/* */ 3/* Copyright (c) 2004, Hans-Martin Will. All rights reserved. */ 4/* */ 5/* Redistribution and use in source and binary forms, with or without */ 6/* modification, are permitted provided that the following conditions are */ 7/* met: */ 8/* */ 9/* * Redistributions of source code must retain the above copyright */ 10/* notice, this list of conditions and the following disclaimer. */ 11/* */ 12/* * Redistributions in binary form must reproduce the above copyright */ 13/* notice, this list of conditions and the following disclaimer in the */ 14/* documentation and/or other materials provided with the distribution. */ 15/* */ 16/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ 17/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ 18/* LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */ 19/* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER */ 20/* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */ 21/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, */ 22/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ 23/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 24/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 25/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 26/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 27/* */ 28/****************************************************************************/ 29 30 31#include <stdarg.h> 32#include "instruction.h" 33#include "bitset.h" 34#include "arm-codegen.h" 35 36 37static cg_virtual_reg_t ** add_reg(cg_virtual_reg_t * reg, 38 cg_virtual_reg_t ** dest, 39 cg_virtual_reg_t * const * limit) 40{ 41 if (dest != limit) 42 *dest++ = reg; 43 44 return dest; 45} 46 47 48static cg_virtual_reg_t ** add_reg_list(cg_virtual_reg_list_t * list, 49 cg_virtual_reg_t ** dest, 50 cg_virtual_reg_t * const * limit) 51{ 52 while (list) 53 { 54 dest = add_reg(list->reg, dest, limit); 55 list = list->next; 56 } 57 58 return dest; 59} 60 61 62static void add_interference(cg_heap_t * heap, cg_virtual_reg_t * source, cg_virtual_reg_t * target) 63{ 64 cg_virtual_reg_list_t ** iter; 65 cg_virtual_reg_list_t * node; 66 67 source = source->representative; 68 target = target->representative; 69 70 if (source == target) 71 return; 72 73 for (iter = &source->interferences; *iter; iter = &(*iter)->next) 74 { 75 if ((*iter)->reg == target) 76 return; 77 } 78 79 node = (cg_virtual_reg_list_t *) cg_heap_allocate(heap, sizeof(cg_virtual_reg_list_t)); 80 node->next = NULL; 81 node->reg = target; 82 83 *iter = node; 84} 85 86 87/****************************************************************************/ 88/* Determine the set of defined registers for the instruction passed in. */ 89/* dest points to a buffer into which the result will be stored, limit */ 90/* specifies an upper limit on this buffer. The return value will be */ 91/* pointing right after the last register stored in the destanation area. */ 92/****************************************************************************/ 93cg_virtual_reg_t ** cg_inst_def(const cg_inst_t * inst, 94 cg_virtual_reg_t ** dest, 95 cg_virtual_reg_t * const * limit) 96{ 97 switch (inst->base.kind) 98 { 99 case cg_inst_unary: 100 case cg_inst_arm_unary_immed: 101 case cg_inst_arm_unary_shift_reg: 102 case cg_inst_arm_unary_shift_immed: 103 dest = add_reg(inst->unary.dest_value, dest, limit); 104 105 if (inst->unary.dest_flags) 106 dest = add_reg(inst->unary.dest_flags, dest, limit); 107 108 return dest; 109 110 case cg_inst_binary: 111 case cg_inst_arm_binary_immed: 112 case cg_inst_arm_binary_shift_reg: 113 case cg_inst_arm_binary_shift_immed: 114 dest = add_reg(inst->binary.dest_value, dest, limit); 115 116 if (inst->binary.dest_flags) 117 dest = add_reg(inst->binary.dest_flags, dest, limit); 118 119 return dest; 120 121 case cg_inst_compare: 122 case cg_inst_arm_compare_immed: 123 case cg_inst_arm_compare_shift_reg: 124 case cg_inst_arm_compare_shift_immed: 125 return add_reg(inst->compare.dest_flags, dest, limit); 126 127 default: 128 ; 129 } 130 131 switch (inst->base.kind) 132 { 133 case cg_inst_load: 134 case cg_inst_arm_load_immed_offset: 135 case cg_inst_arm_load_reg_offset: 136 return add_reg(inst->load.dest, dest, limit); 137 138 case cg_inst_store: 139 case cg_inst_arm_store_immed_offset: 140 case cg_inst_arm_store_reg_offset: 141 return dest; 142 143 case cg_inst_load_immed: 144 return add_reg(inst->immed.dest, dest, limit); 145 146 case cg_inst_branch_label: 147 case cg_inst_branch_cond: 148 return dest; 149 150 case cg_inst_phi: 151 return add_reg(inst->phi.dest, dest, limit); 152 153 case cg_inst_call: 154 if (inst->call.dest) 155 return add_reg(inst->call.dest, dest, limit); 156 else 157 return dest; 158 159 case cg_inst_ret: 160 return dest; 161 162 // ARM specific formats 163 default: 164 assert(0); 165 } 166 167 return dest; 168} 169 170 171/****************************************************************************/ 172/* Determine the set of used registers for the instruction passed in. */ 173/* dest points to a buffer into which the result will be stored, limit */ 174/* specifies an upper limit on this buffer. The return value will be */ 175/* pointing right after the last register stored in the destanation area. */ 176/****************************************************************************/ 177cg_virtual_reg_t ** cg_inst_use(const cg_inst_t * inst, 178 cg_virtual_reg_t ** dest, 179 cg_virtual_reg_t * const * limit) 180{ 181 switch (inst->base.kind) 182 { 183 case cg_inst_unary: 184 return add_reg(inst->unary.operand.source, dest, limit); 185 186 case cg_inst_arm_unary_immed: 187 return dest; 188 189 case cg_inst_arm_unary_shift_reg: 190 dest = add_reg(inst->unary.operand.shift_reg.source, dest, limit); 191 return add_reg(inst->unary.operand.shift_reg.shift, dest, limit); 192 193 case cg_inst_arm_unary_shift_immed: 194 return add_reg(inst->unary.operand.shift_immed.source, dest, limit); 195 196 case cg_inst_binary: 197 dest = add_reg(inst->binary.source, dest, limit); 198 return add_reg(inst->binary.operand.source, dest, limit); 199 200 case cg_inst_arm_binary_immed: 201 return add_reg(inst->binary.source, dest, limit); 202 203 case cg_inst_arm_binary_shift_reg: 204 dest = add_reg(inst->binary.source, dest, limit); 205 dest = add_reg(inst->binary.operand.shift_reg.source, dest, limit); 206 return add_reg(inst->binary.operand.shift_reg.shift, dest, limit); 207 208 case cg_inst_arm_binary_shift_immed: 209 dest = add_reg(inst->binary.source, dest, limit); 210 return add_reg(inst->binary.operand.shift_immed.source, dest, limit); 211 212 case cg_inst_compare: 213 dest = add_reg(inst->compare.source, dest, limit); 214 return add_reg(inst->compare.operand.source, dest, limit); 215 216 case cg_inst_arm_compare_immed: 217 return add_reg(inst->compare.source, dest, limit); 218 219 case cg_inst_arm_compare_shift_reg: 220 dest = add_reg(inst->compare.source, dest, limit); 221 dest = add_reg(inst->compare.operand.shift_reg.source, dest, limit); 222 return add_reg(inst->compare.operand.shift_reg.shift, dest, limit); 223 224 case cg_inst_arm_compare_shift_immed: 225 dest = add_reg(inst->compare.source, dest, limit); 226 return add_reg(inst->compare.operand.shift_immed.source, dest, limit); 227 228 case cg_inst_load: 229 return add_reg(inst->load.mem.base, dest, limit); 230 231 case cg_inst_arm_load_immed_offset: 232 return add_reg(inst->load.mem.immed_offset.base, dest, limit); 233 234 case cg_inst_arm_load_reg_offset: 235 dest = add_reg(inst->load.mem.reg_offset.base, dest, limit); 236 return add_reg(inst->load.mem.reg_offset.offset, dest, limit); 237 238 case cg_inst_store: 239 dest = add_reg(inst->store.source, dest, limit); 240 return add_reg(inst->store.mem.base, dest, limit); 241 242 case cg_inst_arm_store_immed_offset: 243 dest = add_reg(inst->store.source, dest, limit); 244 return add_reg(inst->store.mem.immed_offset.base, dest, limit); 245 246 case cg_inst_arm_store_reg_offset: 247 dest = add_reg(inst->store.source, dest, limit); 248 dest = add_reg(inst->store.mem.reg_offset.base, dest, limit); 249 return add_reg(inst->store.mem.reg_offset.offset, dest, limit); 250 251 case cg_inst_load_immed: 252 return dest; 253 254 case cg_inst_branch_label: 255 return dest; 256 257 case cg_inst_branch_cond: 258 return add_reg(inst->branch.cond, dest, limit); 259 260 case cg_inst_phi: 261 return add_reg_list(inst->phi.regs, dest, limit); 262 263 case cg_inst_call: 264 return add_reg_list(inst->call.args, dest, limit); 265 266 case cg_inst_ret: 267 if (inst->ret.result) 268 return add_reg(inst->ret.result, dest, limit); 269 else 270 return dest; 271 272 // ARM specific formats 273 default: 274 assert(0); 275 } 276 277 return dest; 278} 279 280 281void mark_instruction_used(cg_inst_t * inst) 282{ 283 cg_virtual_reg_t * buffer[16]; 284 cg_virtual_reg_t **iter, ** end; 285 286 if (inst->base.used) 287 return; 288 289 inst->base.used = 1; 290 291 end = cg_inst_use(inst, buffer, buffer + 16); 292 293 for (iter = buffer; iter != end; ++iter) 294 { 295 cg_virtual_reg_t * reg = *iter; 296 297 if (reg->def && !reg->def->base.used) 298 mark_instruction_used(reg->def); 299 } 300} 301 302 303void cg_module_eliminate_dead_code(cg_module_t * module) 304{ 305 cg_proc_t * proc; 306 cg_block_t * block; 307 cg_inst_t * inst, ** pinst; 308 309 /************************************************************************/ 310 /* Mark all instructions as unused */ 311 /************************************************************************/ 312 313 for (proc = module->procs; proc; proc = proc->next) 314 { 315 for (block = proc->blocks; block; block = block->next) 316 { 317 for (inst = block->insts.head; inst; inst = inst->base.next) 318 { 319 inst->base.used = 0; 320 } 321 } 322 } 323 324 /************************************************************************/ 325 /* mark used instructions */ 326 /************************************************************************/ 327 328 for (proc = module->procs; proc; proc = proc->next) 329 { 330 for (block = proc->blocks; block; block = block->next) 331 { 332 for (inst = block->insts.head; inst; inst = inst->base.next) 333 { 334 if (inst->base.kind == cg_inst_store || 335 inst->base.kind == cg_inst_arm_store_immed_offset || 336 inst->base.kind == cg_inst_arm_store_reg_offset || 337 inst->base.kind == cg_inst_ret || 338 inst->base.kind == cg_inst_call || 339 inst->base.kind == cg_inst_branch_cond || 340 inst->base.kind == cg_inst_branch_label) 341 { 342 mark_instruction_used(inst); 343 } 344 } 345 } 346 } 347 348 /************************************************************************/ 349 /* remove un-used instructions */ 350 /************************************************************************/ 351 352 for (proc = module->procs; proc; proc = proc->next) 353 { 354 for (block = proc->blocks; block; block = block->next) 355 { 356 for (pinst = &block->insts.head; *pinst; ) 357 { 358 if ((*pinst)->base.used) 359 { 360 pinst = &(*pinst)->base.next; 361 } 362 else 363 { 364 *pinst = (*pinst)->base.next; 365 } 366 } 367 } 368 } 369} 370 371 372static void block_dataflow(cg_block_t * block) 373{ 374 cg_inst_t * inst; 375 376 block->def = cg_bitset_create(block->proc->module->heap, block->proc->num_registers); 377 block->use = cg_bitset_create(block->proc->module->heap, block->proc->num_registers); 378 block->live_in = cg_bitset_create(block->proc->module->heap, block->proc->num_registers); 379 block->live_out = cg_bitset_create(block->proc->module->heap, block->proc->num_registers); 380 381 for (inst = block->insts.head; inst; inst = inst->base.next) 382 { 383 cg_virtual_reg_t * buffer[64]; 384 cg_virtual_reg_t **iter, ** end = cg_inst_use(inst, buffer, buffer + 64); 385 386 for (iter = buffer; iter != end; ++iter) 387 { 388 cg_virtual_reg_t * use = *iter; 389 390 if (!CG_BITSET_TEST(block->def, use->reg_no)) 391 { 392 /* if the register has not been defined yet it means we received it as */ 393 /* input to the block */ 394 395 CG_BITSET_SET(block->use, use->reg_no); 396 } 397 } 398 399 end = cg_inst_def(inst, buffer, buffer + 64); 400 401 for (iter = buffer; iter != end; ++iter) 402 { 403 cg_virtual_reg_t * def = *iter; 404 CG_BITSET_SET(block->def, def->reg_no); 405 } 406 } 407 408 cg_bitset_assign(block->live_in, block->use); 409} 410 411 412static void proc_dataflow(cg_proc_t * proc) 413{ 414 int changed; 415 cg_block_t * block; 416 cg_block_list_t * list; 417 418 // for each block establish def and use sets 419 420 for (block = proc->blocks; block; block = block->next) 421 block_dataflow(block); 422 423 // repeat until no further change: 424 // live_out(b) := U live_in(b), b in succ(b) 425 // live_in(b) := live_in(b) U (live_out(b) \ def(b)) 426 do 427 { 428 changed = 0; 429 430 for (block = proc->blocks; block; block = block->next) 431 { 432 for (list = block->succ; list; list = list->next) 433 changed |= cg_bitset_union(block->live_out, list->block->live_in); 434 435 changed |= cg_bitset_union_minus(block->live_in, block->live_out, block->def); 436 } 437 438 } 439 while (changed); 440} 441 442 443static void add_successor(cg_block_t * block, cg_block_t * succ) 444{ 445 cg_block_list_t * list = cg_heap_allocate(block->proc->module->heap, sizeof(cg_block_list_t)); 446 list->block = succ; 447 list->next = block->succ; 448 block->succ = list; 449} 450 451 452static void add_predecessor(cg_block_t * block, cg_block_t * pred) 453{ 454 cg_block_list_t * list = cg_heap_allocate(block->proc->module->heap, sizeof(cg_block_list_t)); 455 list->block = pred; 456 list->next = block->pred; 457 block->pred = list; 458} 459 460 461static void proc_controlflow(cg_proc_t * proc) 462{ 463 // for each block determine list of preedecessor and successor blocks 464 cg_block_t * block; 465 cg_inst_t * inst; 466 467 for (block = proc->blocks; block; block = block->next) 468 { 469 int last_inst_is_bra = 0; 470 471 for (inst = block->insts.head; inst; inst = inst->base.next) 472 { 473 if (inst->base.kind == cg_inst_branch_cond || 474 inst->base.kind == cg_inst_branch_label) 475 { 476 cg_block_t * target = inst->branch.target->block; 477 478 add_successor(block, target); 479 add_predecessor(target, block); 480 } 481 482 last_inst_is_bra = inst->base.opcode == cg_op_bra; 483 } 484 485 if (!last_inst_is_bra && block->next) 486 { 487 add_successor(block, block->next); 488 add_predecessor(block->next, block); 489 } 490 } 491} 492 493 494void cg_module_dataflow(cg_module_t * module) 495{ 496 // perform def/use and liveliness analysis 497 cg_proc_t * proc; 498 499 for (proc = module->procs; proc != (cg_proc_t *) 0; proc = proc->next) 500 { 501 proc_controlflow(proc); 502 proc_dataflow(proc); 503 } 504} 505 506 507static int is_arm_unary_data_opcode(cg_opcode_t opcode) { 508 switch (opcode) { 509 case cg_op_not: 510 return 1; 511 512 default: 513 return 0; 514 } 515} 516 517static int is_arm_binary_data_opcode(cg_opcode_t opcode) { 518 switch (opcode) { 519 case cg_op_add: 520 case cg_op_and: 521 case cg_op_or: 522 case cg_op_sub: 523 case cg_op_xor: 524 case cg_op_fadd: 525 case cg_op_fsub: 526 case cg_op_min: 527 case cg_op_max: 528 return 1; 529 530 default: 531 return 0; 532 } 533} 534 535static int is_shift_or_rotate(cg_opcode_t opcode) { 536 switch (opcode) { 537 case cg_op_asr: 538 case cg_op_lsr: 539 case cg_op_lsl: 540 return 1; 541 542 default: 543 return 0; 544 } 545} 546 547static int is_arm_data_proc_immediate(U32 value) { 548 // preliminary rule 549 int shift; 550 551 if ((value & 0xff) == value) { 552 return 1; 553 } 554 555 for (shift = 2; shift <= 12; shift += 2) { 556 if (((0xff << shift) & value) == value) 557 return 1; 558 } 559 560 return 0; 561} 562 563 564typedef enum 565{ 566 amode_register, 567 amode_immed, 568 amode_shift_immed, 569 amode_shift_reg 570} 571amode_t; 572 573 574typedef enum 575{ 576 dmode_register, 577 dmode_immed_offset, 578 dmode_reg_offset 579} 580dmode_t; 581 582 583 584static amode_t consolidate_amode(cg_data_operand_t * operand) 585{ 586 cg_inst_t * source_inst; 587 588 if (!operand->source->def) 589 return amode_register; 590 591 source_inst = operand->source->def; 592 593 switch (source_inst->base.kind) 594 { 595 case cg_inst_load_immed: 596 // constant 597 { 598 if (is_arm_const(source_inst->immed.value)) 599 { 600 operand->immed = source_inst->immed.value; 601 return amode_immed; 602 } 603 } 604 605 break; 606 607 case cg_inst_binary: 608 // check for general shift -> shift reg 609 610 { 611 switch (source_inst->base.opcode) 612 { 613 case cg_op_asr: 614 operand->shift_reg.source = source_inst->binary.source; 615 operand->shift_reg.op = cg_shift_asr; 616 operand->shift_reg.shift = source_inst->binary.operand.source; 617 return amode_shift_reg; 618 619 case cg_op_lsr: 620 operand->shift_reg.source = source_inst->binary.source; 621 operand->shift_reg.op = cg_shift_lsr; 622 operand->shift_reg.shift = source_inst->binary.operand.source; 623 return amode_shift_reg; 624 625 case cg_op_lsl: 626 operand->shift_reg.source = source_inst->binary.source; 627 operand->shift_reg.op = cg_shift_lsl; 628 operand->shift_reg.shift = source_inst->binary.operand.source; 629 return amode_shift_reg; 630 } 631 } 632 633 break; 634 635 case cg_inst_arm_binary_immed: 636 // maybe we already consolidated the shift -> shift immed 637 638 { 639 switch (source_inst->base.opcode) 640 { 641 case cg_op_asr: 642 operand->shift_immed.source = source_inst->binary.source; 643 operand->shift_immed.op = cg_shift_asr; 644 operand->shift_immed.shift = source_inst->binary.operand.immed; 645 return amode_shift_immed; 646 647 case cg_op_lsr: 648 operand->shift_immed.source = source_inst->binary.source; 649 operand->shift_immed.op = cg_shift_lsr; 650 operand->shift_immed.shift = source_inst->binary.operand.immed; 651 return amode_shift_immed; 652 653 case cg_op_lsl: 654 operand->shift_immed.source = source_inst->binary.source; 655 operand->shift_immed.op = cg_shift_lsl; 656 operand->shift_immed.shift = source_inst->binary.operand.immed; 657 return amode_shift_immed; 658 } 659 } 660 661 break; 662 663 default: 664 break; 665 } 666 667 return amode_register; 668} 669 670 671static dmode_t consolidate_dmode(cg_mem_operand_t * operand) 672{ 673 cg_inst_t * source_inst = operand->base->def; 674 675 if (!source_inst) 676 return dmode_register; 677 678 if (source_inst->base.opcode == cg_op_add && 679 source_inst->base.kind == cg_inst_binary) 680 { 681 operand->reg_offset.base = source_inst->binary.source; 682 operand->reg_offset.offset = source_inst->binary.operand.source; 683 return dmode_reg_offset; 684 } 685 else if (source_inst->base.opcode == cg_op_add && 686 source_inst->base.kind == cg_inst_arm_binary_immed && 687 source_inst->binary.operand.immed >= 0 && 688 source_inst->binary.operand.immed <= 0xff) 689 { 690 operand->immed_offset.base = source_inst->binary.source; 691 operand->immed_offset.offset = source_inst->binary.operand.immed; 692 return dmode_immed_offset; 693 } 694 695 return dmode_register; 696} 697 698 699static void inst_amode(cg_inst_t * inst) 700{ 701 switch (inst->base.kind) 702 { 703 case cg_inst_unary: 704 if (is_arm_unary_data_opcode(inst->base.opcode)) 705 { 706 amode_t amode = consolidate_amode(&inst->unary.operand); 707 708 switch (amode) 709 { 710 case amode_immed: 711 inst->base.kind = cg_inst_arm_unary_immed; 712 break; 713 714 case amode_shift_immed: 715 inst->base.kind = cg_inst_arm_unary_shift_immed; 716 break; 717 718 case amode_shift_reg: 719 inst->base.kind = cg_inst_arm_unary_shift_reg; 720 break; 721 722 default: 723 break; 724 } 725 726 } 727 728 break; 729 730 case cg_inst_binary: 731 if (is_arm_binary_data_opcode(inst->base.opcode)) 732 { 733 amode_t amode = consolidate_amode(&inst->binary.operand); 734 735 switch (amode) 736 { 737 case amode_immed: 738 inst->base.kind = cg_inst_arm_binary_immed; 739 break; 740 741 case amode_shift_immed: 742 inst->base.kind = cg_inst_arm_binary_shift_immed; 743 break; 744 745 case amode_shift_reg: 746 inst->base.kind = cg_inst_arm_binary_shift_reg; 747 break; 748 749 default: 750 break; 751 } 752 753 } 754 else switch (inst->base.opcode) 755 { 756 case cg_op_asr: 757 case cg_op_lsr: 758 case cg_op_lsl: 759 { 760 cg_inst_t * source_inst = inst->binary.operand.source->def; 761 762 if (source_inst && source_inst->base.kind == cg_inst_load_immed) 763 { 764 inst->binary.operand.immed = source_inst->immed.value; 765 inst->base.kind = cg_inst_arm_binary_immed; 766 } 767 } 768 769 break; 770 771 } 772 773 break; 774 775 case cg_inst_compare: 776 { 777 amode_t amode = consolidate_amode(&inst->compare.operand); 778 779 switch (amode) 780 { 781 case amode_immed: 782 inst->base.kind = cg_inst_arm_compare_immed; 783 break; 784 785 case amode_shift_immed: 786 inst->base.kind = cg_inst_arm_compare_shift_immed; 787 break; 788 789 case amode_shift_reg: 790 inst->base.kind = cg_inst_arm_compare_shift_reg; 791 break; 792 793 default: 794 break; 795 } 796 } 797 798 break; 799 800 case cg_inst_load: 801 { 802 dmode_t dmode = consolidate_dmode(&inst->load.mem); 803 804 switch (dmode) 805 { 806 case dmode_reg_offset: 807 inst->base.kind = cg_inst_arm_load_reg_offset; 808 break; 809 810 case dmode_immed_offset: 811 inst->base.kind = cg_inst_arm_load_immed_offset; 812 break; 813 814 default: 815 break; 816 } 817 } 818 819 break; 820 821 case cg_inst_store: 822 { 823 dmode_t dmode = consolidate_dmode(&inst->store.mem); 824 825 switch (dmode) 826 { 827 case dmode_reg_offset: 828 inst->base.kind = cg_inst_arm_store_reg_offset; 829 break; 830 831 case dmode_immed_offset: 832 inst->base.kind = cg_inst_arm_store_immed_offset; 833 break; 834 835 default: 836 break; 837 } 838 } 839 840 break; 841 842 default: 843 break; 844 } 845} 846 847 848void cg_module_amode(cg_module_t * module) 849{ 850 cg_proc_t * proc; 851 cg_block_t * block; 852 cg_inst_t * inst; 853 854 for (proc = module->procs; proc; proc = proc->next) 855 { 856 for (block = proc->blocks; block; block = block->next) 857 { 858 for (inst = block->insts.head; inst; inst = inst->base.next) 859 { 860 inst_amode(inst); 861 } 862 } 863 } 864} 865 866 867static void proc_allocate_variables(cg_proc_t * proc) 868{ 869 cg_virtual_reg_t * reg; 870 size_t arg_count = proc->num_args; 871 size_t arg_offset = 0; 872 873 proc->num_registers = 0; 874 proc->local_storage = 0; 875 876 for (reg = proc->registers; reg; reg = reg->next) 877 { 878 reg->fp_offset = ~0; 879 reg->reg_no = ~0; 880 } 881 882 for (reg = proc->registers; reg && arg_count; reg = reg->next, arg_count--) 883 { 884 reg->reg_no = reg->representative->reg_no = proc->num_registers++; 885 reg->fp_offset = reg->representative->fp_offset = arg_offset; 886 arg_offset += sizeof(U32); 887 } 888 889 for (; reg ; reg = reg->next) 890 { 891 if (reg->representative->reg_no == ~0) 892 { 893 reg->representative->reg_no = proc->num_registers++; 894 } 895 896 reg->reg_no = reg->representative->reg_no; 897 } 898} 899 900 901void cg_module_allocate_variables(cg_module_t * module) 902{ 903 // allocate local variables in stack frame 904 cg_proc_t * proc; 905 906 cg_module_unify_registers(module); 907 908 for (proc = module->procs; proc; proc = proc->next) 909 proc_allocate_variables(proc); 910} 911 912 913static cg_virtual_reg_t * find_set(cg_virtual_reg_t * reg) 914{ 915 cg_virtual_reg_t * result; 916 917 if (!reg->representative || reg->representative == reg) 918 return reg; 919 920 result = find_set(reg->representative); 921 922 if (result != reg->representative) 923 reg->representative = result; 924 925 return result; 926} 927 928 929static void find_union(cg_virtual_reg_t * first, cg_virtual_reg_t * second) 930{ 931 cg_virtual_reg_t * first_set = find_set(first); 932 cg_virtual_reg_t * second_set = find_set(second); 933 934 second_set->representative = first_set; 935} 936 937 938void cg_module_unify_registers(cg_module_t * module) 939{ 940 cg_proc_t * proc; 941 cg_block_t * block; 942 cg_inst_t * inst; 943 cg_virtual_reg_t * reg; 944 945 for (proc = module->procs; proc; proc = proc->next) 946 { 947 /********************************************************************/ 948 /* Initialize all registers as being distinct */ 949 /********************************************************************/ 950 951 for (reg = proc->registers; reg; reg = reg->next) 952 { 953 reg->representative = reg; 954 } 955 956 /********************************************************************/ 957 /* Perform union-find for all registers that occur in a phi */ 958 /* instruction */ 959 /********************************************************************/ 960 961 for (block = proc->blocks; block; block = block->next) 962 { 963 cg_virtual_reg_list_t * list; 964 965 for (inst = block->insts.head; inst && inst->base.opcode == cg_op_phi; 966 inst = inst->base.next) 967 { 968 for (list = inst->phi.regs; list; list = list->next) 969 { 970 find_union(inst->phi.dest, list->reg); 971 } 972 } 973 } 974 975 /********************************************************************/ 976 /* Flatten out indirections so that there is at most one level of */ 977 /* indirection between any register and its representative */ 978 /********************************************************************/ 979 980 for (reg = proc->registers; reg; reg = reg->next) 981 { 982 find_set(reg); 983 } 984 } 985} 986 987 988 989static void proc_inst_def(cg_proc_t * proc) 990{ 991 cg_virtual_reg_t * reg; 992 cg_block_t * block; 993 cg_inst_t * inst; 994 995 /************************************************************************/ 996 /* Clear out def and use information associated with virtual registers */ 997 /************************************************************************/ 998 999 for (reg = proc->registers; reg; reg = reg->next) 1000 { 1001 reg->def = (cg_inst_t *) 0; 1002 reg->use = (cg_inst_list_t *) 0; 1003 } 1004 1005 /************************************************************************/ 1006 /* Add def and use information for each register */ 1007 /************************************************************************/ 1008 1009 for (block = proc->blocks; block; block = block->next) 1010 { 1011 for (inst = block->insts.head; inst; inst = inst->base.next) 1012 { 1013 cg_virtual_reg_t * buffer[64]; 1014 cg_virtual_reg_t **iter, ** end = cg_inst_def(inst, buffer, buffer + 64); 1015 1016 for (iter = buffer; iter != end; ++iter) 1017 { 1018 cg_virtual_reg_t * reg = *iter; 1019 assert(reg->def == (cg_inst_t *) 0); 1020 reg->def = inst; 1021 } 1022 } 1023 } 1024} 1025 1026 1027void cg_module_inst_def(cg_module_t * module) 1028{ 1029 cg_proc_t * proc; 1030 1031 for (proc = module->procs; proc; proc = proc->next) 1032 proc_inst_def(proc); 1033} 1034 1035 1036static void proc_inst_use_chains(cg_proc_t * proc) 1037{ 1038 cg_virtual_reg_t * reg; 1039 cg_block_t * block; 1040 cg_inst_t * inst; 1041 1042 /************************************************************************/ 1043 /* Clear out def and use information associated with virtual registers */ 1044 /************************************************************************/ 1045 1046 for (reg = proc->registers; reg; reg = reg->next) 1047 { 1048 reg->def = (cg_inst_t *) 0; 1049 reg->use = (cg_inst_list_t *) 0; 1050 } 1051 1052 /************************************************************************/ 1053 /* Add def qand use information for each register */ 1054 /************************************************************************/ 1055 1056 for (block = proc->blocks; block; block = block->next) 1057 { 1058 for (inst = block->insts.head; inst; inst = inst->base.next) 1059 { 1060 cg_virtual_reg_t * buffer[64]; 1061 cg_virtual_reg_t **iter, ** end = cg_inst_use(inst, buffer, buffer + 64); 1062 1063 for (iter = buffer; iter != end; ++iter) 1064 { 1065 cg_virtual_reg_t * reg = *iter; 1066 cg_inst_list_t * list = cg_heap_allocate(proc->module->heap, sizeof(cg_inst_list_t)); 1067 list->inst = inst; 1068 list->next = reg->use; 1069 reg->use = list; 1070 } 1071 } 1072 } 1073} 1074 1075 1076void cg_module_inst_use_chains(cg_module_t * module) 1077{ 1078 cg_proc_t * proc; 1079 1080 for (proc = module->procs; proc; proc = proc->next) 1081 proc_inst_use_chains(proc); 1082} 1083 1084 1085/****************************************************************************/ 1086 1087cg_module_t * cg_module_create(cg_heap_t * heap) 1088{ 1089 cg_module_t * module = cg_heap_allocate(heap, sizeof(cg_module_t)); 1090 module->heap = heap; 1091 1092 return module; 1093} 1094 1095 1096cg_proc_t * cg_proc_create(cg_module_t * module) 1097{ 1098 cg_proc_t * proc = cg_heap_allocate(module->heap, sizeof (cg_proc_t)); 1099 proc->next = module->procs; 1100 module->procs = proc; 1101 proc->module = module; 1102 1103 return proc; 1104} 1105 1106cg_block_t * cg_block_create(cg_proc_t * proc, int weight) 1107{ 1108 cg_block_t * block = cg_heap_allocate(proc->module->heap, sizeof (cg_block_t)); 1109 1110 if (proc->blocks) 1111 { 1112 proc->last_block->next = block; 1113 proc->last_block = block; 1114 } 1115 else 1116 { 1117 proc->blocks = proc->last_block = block; 1118 } 1119 1120 block->proc = proc; 1121 block->weight = weight; 1122 1123 return block; 1124} 1125 1126 1127cg_virtual_reg_t * cg_virtual_reg_create(cg_proc_t * proc, cg_reg_type_t type) 1128{ 1129 cg_virtual_reg_t * reg = cg_heap_allocate(proc->module->heap, sizeof (cg_virtual_reg_t)); 1130 reg->reg_no = proc->num_registers++; 1131 reg->type = type; 1132 1133 if (proc->registers) 1134 { 1135 proc->last_register->next = reg; 1136 proc->last_register = reg; 1137 } 1138 else 1139 { 1140 proc->registers = proc->last_register = reg; 1141 } 1142 1143 return reg; 1144} 1145 1146 1147cg_virtual_reg_list_t * cg_create_virtual_reg_list(cg_heap_t * heap, ...) 1148{ 1149 va_list marker; 1150 cg_virtual_reg_list_t * result = NULL, ** current = &result; 1151 1152 va_start(marker, heap); /* Initialize variable arguments. */ 1153 1154 do 1155 { 1156 cg_virtual_reg_t * reg = va_arg(marker, cg_virtual_reg_t *); 1157 1158 if (!reg) 1159 break; 1160 1161 *current = cg_heap_allocate(heap, sizeof(cg_virtual_reg_list_t)); 1162 (*current)->reg = reg; 1163 1164 current = &(*current)->next; 1165 } 1166 while (1); 1167 1168 va_end(marker); /* Reset variable arguments. */ 1169 1170 return result; 1171} 1172 1173 1174// add an instruction to a block 1175static void block_add(cg_block_t * block, cg_inst_t * inst) 1176{ 1177 inst->base.block = block; 1178 1179 if (block->insts.head) 1180 { 1181 block->insts.tail->base.next = inst; 1182 block->insts.tail = inst; 1183 } 1184 else 1185 { 1186 block->insts.head = block->insts.tail = inst; 1187 } 1188} 1189 1190 1191static cg_inst_t * inst_create(cg_block_t * block, size_t size, 1192 cg_inst_kind_t kind, cg_opcode_t op 1193 CG_INST_DEBUG_ARG_DECL) 1194{ 1195 cg_inst_t * inst = (cg_inst_t *) 1196 cg_heap_allocate(block->proc->module->heap, size); 1197 block_add(block, inst); 1198 1199 inst->base.kind = kind; 1200 inst->base.opcode = op; 1201 CG_INST_SET_DEBUG(inst); 1202 1203 return inst; 1204} 1205 1206 1207cg_inst_t * cg_create_inst_unary(cg_block_t * block, 1208 cg_opcode_t op, 1209 cg_virtual_reg_t * dest, 1210 cg_virtual_reg_t * source 1211 CG_INST_DEBUG_ARG_DECL) 1212{ 1213 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_unary_t), cg_inst_unary, op CG_INST_DEBUG_PASS); 1214 1215 assert(dest->type == cg_reg_type_general); 1216 assert(source->type == cg_reg_type_general); 1217 1218 inst->unary.dest_value = dest; 1219 inst->unary.operand.source = source; 1220 1221 return inst; 1222} 1223 1224 1225cg_inst_t * cg_create_inst_unary_s(cg_block_t * block, 1226 cg_opcode_t op, 1227 cg_virtual_reg_t * dest, 1228 cg_virtual_reg_t * flags, 1229 cg_virtual_reg_t * source 1230 CG_INST_DEBUG_ARG_DECL) 1231{ 1232 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_unary_t), cg_inst_unary, op CG_INST_DEBUG_PASS); 1233 1234 assert(dest->type == cg_reg_type_general); 1235 assert(flags->type == cg_reg_type_flags); 1236 assert(source->type == cg_reg_type_general); 1237 1238 inst->unary.dest_value = dest; 1239 inst->unary.dest_flags = flags; 1240 inst->unary.operand.source = source; 1241 1242 return inst; 1243} 1244 1245 1246cg_inst_t * cg_create_inst_binary(cg_block_t * block, 1247 cg_opcode_t op, 1248 cg_virtual_reg_t * dest, 1249 cg_virtual_reg_t * source, 1250 cg_virtual_reg_t * operand 1251 CG_INST_DEBUG_ARG_DECL) 1252{ 1253 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_binary_t), cg_inst_binary, op CG_INST_DEBUG_PASS); 1254 1255 assert(dest->type == cg_reg_type_general); 1256 assert(source->type == cg_reg_type_general); 1257 assert(operand->type == cg_reg_type_general); 1258 1259 inst->binary.dest_value = dest; 1260 inst->binary.source = source; 1261 inst->binary.operand.source = operand; 1262 1263 return inst; 1264} 1265 1266 1267cg_inst_t * cg_create_inst_binary_s(cg_block_t * block, 1268 cg_opcode_t op, 1269 cg_virtual_reg_t * dest, 1270 cg_virtual_reg_t * flags, 1271 cg_virtual_reg_t * source, 1272 cg_virtual_reg_t * operand 1273 CG_INST_DEBUG_ARG_DECL) 1274{ 1275 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_binary_t), cg_inst_binary, op CG_INST_DEBUG_PASS); 1276 1277 assert(dest->type == cg_reg_type_general); 1278 assert(flags->type == cg_reg_type_flags); 1279 assert(source->type == cg_reg_type_general); 1280 assert(operand->type == cg_reg_type_general); 1281 1282 inst->binary.dest_value = dest; 1283 inst->binary.dest_flags = flags; 1284 inst->binary.source = source; 1285 inst->binary.operand.source = operand; 1286 1287 return inst; 1288} 1289 1290 1291cg_inst_t * cg_create_inst_compare(cg_block_t * block, 1292 cg_opcode_t op, 1293 cg_virtual_reg_t * dest, 1294 cg_virtual_reg_t * source, 1295 cg_virtual_reg_t * operand 1296 CG_INST_DEBUG_ARG_DECL) 1297{ 1298 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_compare_t), cg_inst_compare, op CG_INST_DEBUG_PASS); 1299 1300 assert(dest->type == cg_reg_type_flags); 1301 assert(source->type == cg_reg_type_general); 1302 assert(operand->type == cg_reg_type_general); 1303 1304 inst->compare.dest_flags = dest; 1305 inst->compare.source = source; 1306 inst->compare.operand.source = operand; 1307 1308 return inst; 1309} 1310 1311 1312cg_inst_t * cg_create_inst_load(cg_block_t * block, 1313 cg_opcode_t op, 1314 cg_virtual_reg_t * dest, 1315 cg_virtual_reg_t * mem 1316 CG_INST_DEBUG_ARG_DECL) 1317{ 1318 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_load_t), cg_inst_load, op CG_INST_DEBUG_PASS); 1319 1320 assert(dest->type == cg_reg_type_general); 1321 assert(mem->type == cg_reg_type_general); 1322 1323 inst->load.dest = dest; 1324 inst->load.mem.base = mem; 1325 1326 return inst; 1327} 1328 1329 1330cg_inst_t * cg_create_inst_store(cg_block_t * block, 1331 cg_opcode_t op, 1332 cg_virtual_reg_t * source, 1333 cg_virtual_reg_t * mem 1334 CG_INST_DEBUG_ARG_DECL) 1335{ 1336 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_store_t), cg_inst_store, op CG_INST_DEBUG_PASS); 1337 1338 assert(source->type == cg_reg_type_general); 1339 assert(mem->type == cg_reg_type_general); 1340 1341 inst->store.source = source; 1342 inst->store.mem.base = mem; 1343 1344 return inst; 1345} 1346 1347 1348cg_inst_t * cg_create_inst_load_immed(cg_block_t * block, 1349 cg_opcode_t op, 1350 cg_virtual_reg_t * dest, 1351 U32 value 1352 CG_INST_DEBUG_ARG_DECL) 1353{ 1354 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_load_immed_t), cg_inst_load_immed, op CG_INST_DEBUG_PASS); 1355 1356 assert(dest->type == cg_reg_type_general); 1357 1358 inst->immed.dest = dest; 1359 inst->immed.value = value; 1360 1361 return inst; 1362} 1363 1364 1365cg_inst_t * cg_create_inst_branch_label(cg_block_t * block, 1366 cg_opcode_t op, 1367 cg_block_ref_t * target 1368 CG_INST_DEBUG_ARG_DECL) 1369{ 1370 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_branch_t), cg_inst_branch_label, op CG_INST_DEBUG_PASS); 1371 1372 inst->branch.target = target; 1373 1374 return inst; 1375} 1376 1377 1378cg_inst_t * cg_create_inst_branch_cond(cg_block_t * block, 1379 cg_opcode_t op, 1380 cg_virtual_reg_t * flags, 1381 cg_block_ref_t * target 1382 CG_INST_DEBUG_ARG_DECL) 1383{ 1384 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_branch_t), cg_inst_branch_cond, op CG_INST_DEBUG_PASS); 1385 1386 assert(flags->type == cg_reg_type_flags); 1387 1388 inst->branch.cond = flags; 1389 inst->branch.target = target; 1390 1391 return inst; 1392} 1393 1394 1395cg_inst_t * cg_create_inst_phi(cg_block_t * block, 1396 cg_opcode_t op, 1397 cg_virtual_reg_t * dest, 1398 cg_virtual_reg_list_t * regs 1399 CG_INST_DEBUG_ARG_DECL) 1400{ 1401 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_phi_t), cg_inst_phi, op CG_INST_DEBUG_PASS); 1402 1403 inst->phi.dest = dest; 1404 inst->phi.regs = regs; 1405 1406 return inst; 1407} 1408 1409 1410cg_inst_t * cg_create_inst_call_proc(cg_block_t * block, 1411 cg_opcode_t op, 1412 cg_proc_t * proc, 1413 cg_virtual_reg_list_t * args 1414 CG_INST_DEBUG_ARG_DECL) 1415{ 1416 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_call_t), cg_inst_call, op CG_INST_DEBUG_PASS); 1417 1418 inst->call.proc = proc; 1419 inst->call.args = args; 1420 1421 return inst; 1422} 1423 1424 1425cg_inst_t * cg_create_inst_call_func(cg_block_t * block, 1426 cg_opcode_t op, 1427 cg_virtual_reg_t * dest, 1428 cg_proc_t * proc, 1429 cg_virtual_reg_list_t * args 1430 CG_INST_DEBUG_ARG_DECL) 1431{ 1432 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_call_t), cg_inst_call, op CG_INST_DEBUG_PASS); 1433 1434 assert(dest->type == cg_reg_type_general); 1435 1436 inst->call.dest = dest; 1437 inst->call.proc = proc; 1438 inst->call.args = args; 1439 1440 return inst; 1441} 1442 1443 1444cg_inst_t * cg_create_inst_ret(cg_block_t * block, 1445 cg_opcode_t op 1446 CG_INST_DEBUG_ARG_DECL) 1447{ 1448 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_ret_t), cg_inst_ret, op CG_INST_DEBUG_PASS); 1449 1450 /* nothing */ 1451 1452 return inst; 1453} 1454 1455 1456cg_inst_t * cg_create_inst_ret_value(cg_block_t * block, 1457 cg_opcode_t op, 1458 cg_virtual_reg_t * value 1459 CG_INST_DEBUG_ARG_DECL) 1460{ 1461 cg_inst_t * inst = inst_create(block, sizeof(cg_inst_ret_t), cg_inst_ret, op CG_INST_DEBUG_PASS); 1462 1463 assert(value->type == cg_reg_type_general); 1464 1465 inst->ret.result = value; 1466 1467 return inst; 1468} 1469 1470 1471cg_block_ref_t * cg_block_ref_create(cg_proc_t * proc) 1472{ 1473 cg_block_ref_t * result = (cg_block_ref_t *) cg_heap_allocate(proc->module->heap, sizeof(cg_block_ref_t)); 1474 return result; 1475} 1476 1477static const char * const opcodes[] = 1478{ 1479 "nop", 1480 "add", "and", "asr", "cmp", "div", 1481 "lsl", "lsr", "mod", "mul", "neg", 1482 "not", "or", "sub", "xor", 1483 "min", "max", 1484 "fadd", "fcmp", "fdiv", "fmul", "fneg", 1485 "fsub", "finv", "fsqrt", "abs", "log2", 1486 "trunc", "round", "fcnv", 1487 "beq", "bge", "ble", "bgt", "blt", 1488 "bne", "bra", 1489 "ldb", "ldh", "ldi", "ldw", "stb", 1490 "sth", "stw", 1491 "call", "ret", "phi" 1492}; 1493 1494static const char * const shift_opcodes[] = 1495{ 1496 "lsl", 1497 "lsr", 1498 "asr", 1499 "ror" 1500} 1501; 1502 1503static void inst_dump(cg_inst_t * inst, FILE * out) 1504{ 1505 cg_virtual_reg_list_t * list; 1506 1507#ifndef NDEBUG 1508 fprintf(out, "%8.8s %5.5d: ", inst->base.file, inst->base.line); 1509#endif 1510 1511 switch (inst->base.kind) 1512 { 1513 case cg_inst_unary: 1514 if (inst->unary.dest_flags) 1515 { 1516 fprintf(out, "\t%s\t(r%d, r%d), r%d\n", opcodes[inst->base.opcode], 1517 inst->unary.dest_value->reg_no, inst->unary.dest_flags->reg_no, inst->unary.operand.source->reg_no); 1518 } 1519 else 1520 { 1521 fprintf(out, "\t%s\tr%d, r%d\n", opcodes[inst->base.opcode], 1522 inst->unary.dest_value->reg_no, inst->unary.operand.source->reg_no); 1523 } 1524 1525 break; 1526 1527 case cg_inst_binary: 1528 if (inst->binary.dest_flags) 1529 { 1530 fprintf(out, "\t%s\t(r%d, r%d), r%d, r%d\n", opcodes[inst->base.opcode], 1531 inst->binary.dest_value->reg_no, inst->binary.dest_flags->reg_no, 1532 inst->binary.source->reg_no, 1533 inst->binary.operand.source->reg_no); 1534 } 1535 else 1536 { 1537 fprintf(out, "\t%s\tr%d, r%d, r%d\n", opcodes[inst->base.opcode], 1538 inst->binary.dest_value->reg_no, inst->binary.source->reg_no, 1539 inst->binary.operand.source->reg_no); 1540 } 1541 1542 break; 1543 1544 case cg_inst_compare: 1545 fprintf(out, "\t%s\tr%d, r%d, r%d\n", opcodes[inst->base.opcode], 1546 inst->compare.dest_flags->reg_no, inst->compare.source->reg_no, 1547 inst->compare.operand.source->reg_no); 1548 break; 1549 1550 case cg_inst_load: 1551 fprintf(out, "\t%s\tr%d, r%d\n", opcodes[inst->base.opcode], 1552 inst->load.dest->reg_no, inst->load.mem.base->reg_no); 1553 break; 1554 1555 case cg_inst_store: 1556 fprintf(out, "\t%s\tr%d, r%d\n", opcodes[inst->base.opcode], 1557 inst->store.source->reg_no, inst->store.mem.base->reg_no); 1558 break; 1559 1560 case cg_inst_load_immed: 1561 fprintf(out, "\t%s\tr%d, %d\n", opcodes[inst->base.opcode], 1562 inst->immed.dest->reg_no, inst->immed.value); 1563 break; 1564 1565 case cg_inst_branch_label: 1566 fprintf(out, "\t%s\t%p\n", opcodes[inst->base.opcode], 1567 inst->branch.target->block); 1568 break; 1569 1570 case cg_inst_branch_cond: 1571 fprintf(out, "\t%s\tr%d, %p\n", opcodes[inst->base.opcode], 1572 inst->branch.cond->reg_no, inst->branch.target->block); 1573 break; 1574 1575 case cg_inst_phi: 1576 fprintf(out, "\t%s\tr%d", opcodes[inst->base.opcode], 1577 inst->phi.dest->reg_no); 1578 1579 for (list = inst->phi.regs; list; list = list->next) 1580 { 1581 fprintf(out, ", r%d", list->reg->reg_no); 1582 } 1583 1584 fprintf(out, "\n"); 1585 break; 1586 1587 case cg_inst_call: 1588 if (inst->call.dest) 1589 { 1590 fprintf(out, "\t%s\tr%d, %p", opcodes[inst->base.opcode], 1591 inst->call.dest->reg_no, inst->call.proc); 1592 } 1593 else 1594 { 1595 fprintf(out, "\t%s\t%p", opcodes[inst->base.opcode], 1596 inst->call.proc); 1597 } 1598 1599 for (list = inst->call.args; list; list = list->next) 1600 { 1601 fprintf(out, ", r%d", list->reg->reg_no); 1602 } 1603 1604 fprintf(out, "\n"); 1605 break; 1606 1607 case cg_inst_ret: 1608 if (inst->ret.result) 1609 { 1610 fprintf(out, "\t%s\tr%d\n", opcodes[inst->base.opcode], 1611 inst->ret.result->reg_no); 1612 } 1613 else 1614 { 1615 fprintf(out, "\t%s\n", opcodes[inst->base.opcode]); 1616 } 1617 1618 break; 1619 1620 case cg_inst_arm_unary_immed: 1621 if (inst->unary.dest_flags) 1622 { 1623 fprintf(out, "\t%s\t(r%d, r%d), %d\n", opcodes[inst->base.opcode], 1624 inst->unary.dest_value->reg_no, inst->unary.dest_flags->reg_no, inst->unary.operand.immed); 1625 } 1626 else 1627 { 1628 fprintf(out, "\t%s\tr%d, %d\n", opcodes[inst->base.opcode], 1629 inst->unary.dest_value->reg_no, inst->unary.operand.immed); 1630 } 1631 1632 break; 1633 1634 case cg_inst_arm_unary_shift_reg: 1635 if (inst->unary.dest_flags) 1636 { 1637 fprintf(out, "\t%s\t(r%d, r%d), r%d %s r%d\n", opcodes[inst->base.opcode], 1638 inst->unary.dest_value->reg_no, inst->unary.dest_flags->reg_no, 1639 inst->unary.operand.shift_reg.source->reg_no, 1640 shift_opcodes[inst->unary.operand.shift_reg.op], 1641 inst->unary.operand.shift_reg.shift->reg_no); 1642 } 1643 else 1644 { 1645 fprintf(out, "\t%s\tr%d, r%d %s r%d\n", opcodes[inst->base.opcode], 1646 inst->unary.dest_value->reg_no, 1647 inst->unary.operand.shift_reg.source->reg_no, 1648 shift_opcodes[inst->unary.operand.shift_reg.op], 1649 inst->unary.operand.shift_reg.shift->reg_no); 1650 } 1651 1652 break; 1653 1654 case cg_inst_arm_unary_shift_immed: 1655 if (inst->unary.dest_flags) 1656 { 1657 fprintf(out, "\t%s\t(r%d, r%d), r%d %s %d\n", opcodes[inst->base.opcode], 1658 inst->unary.dest_value->reg_no, inst->unary.dest_flags->reg_no, 1659 inst->unary.operand.shift_immed.source->reg_no, 1660 shift_opcodes[inst->unary.operand.shift_immed.op], 1661 inst->unary.operand.shift_immed.shift); 1662 } 1663 else 1664 { 1665 fprintf(out, "\t%s\tr%d, r%d %s %d\n", opcodes[inst->base.opcode], 1666 inst->unary.dest_value->reg_no, 1667 inst->unary.operand.shift_immed.source->reg_no, 1668 shift_opcodes[inst->unary.operand.shift_immed.op], 1669 inst->unary.operand.shift_immed.shift); 1670 } 1671 1672 break; 1673 1674 case cg_inst_arm_binary_immed: 1675 if (inst->binary.dest_flags) 1676 { 1677 fprintf(out, "\t%s\t(r%d, r%d), r%d, %d\n", opcodes[inst->base.opcode], 1678 inst->binary.dest_value->reg_no, inst->binary.dest_flags->reg_no, 1679 inst->binary.source->reg_no, 1680 inst->binary.operand.immed); 1681 } 1682 else 1683 { 1684 fprintf(out, "\t%s\tr%d, r%d, %d\n", opcodes[inst->base.opcode], 1685 inst->binary.dest_value->reg_no, 1686 inst->binary.source->reg_no, 1687 inst->binary.operand.immed); 1688 } 1689 1690 break; 1691 1692 case cg_inst_arm_binary_shift_reg: 1693 if (inst->binary.dest_flags) 1694 { 1695 fprintf(out, "\t%s\t(r%d, r%d), r%d, r%d %s r%d\n", opcodes[inst->base.opcode], 1696 inst->binary.dest_value->reg_no, inst->binary.dest_flags->reg_no, 1697 inst->binary.source->reg_no, 1698 inst->binary.operand.shift_reg.source->reg_no, 1699 shift_opcodes[inst->binary.operand.shift_reg.op], 1700 inst->binary.operand.shift_reg.shift->reg_no); 1701 } 1702 else 1703 { 1704 fprintf(out, "\t%s\tr%d, r%d, r%d %s r%d\n", opcodes[inst->base.opcode], 1705 inst->binary.dest_value->reg_no, 1706 inst->binary.source->reg_no, 1707 inst->binary.operand.shift_reg.source->reg_no, 1708 shift_opcodes[inst->binary.operand.shift_reg.op], 1709 inst->binary.operand.shift_reg.shift->reg_no); 1710 } 1711 1712 break; 1713 1714 case cg_inst_arm_binary_shift_immed: 1715 if (inst->binary.dest_flags) 1716 { 1717 fprintf(out, "\t%s\t(r%d, r%d), r%d, r%d %s %d\n", opcodes[inst->base.opcode], 1718 inst->binary.dest_value->reg_no, inst->binary.dest_flags->reg_no, 1719 inst->binary.source->reg_no, 1720 inst->binary.operand.shift_immed.source->reg_no, 1721 shift_opcodes[inst->binary.operand.shift_immed.op], 1722 inst->binary.operand.shift_immed.shift); 1723 } 1724 else 1725 { 1726 fprintf(out, "\t%s\tr%d, r%d, r%d %s %d\n", opcodes[inst->base.opcode], 1727 inst->binary.dest_value->reg_no, 1728 inst->binary.source->reg_no, 1729 inst->binary.operand.shift_immed.source->reg_no, 1730 shift_opcodes[inst->binary.operand.shift_immed.op], 1731 inst->binary.operand.shift_immed.shift); 1732 } 1733 1734 break; 1735 1736 case cg_inst_arm_compare_immed: 1737 fprintf(out, "\t%s\tr%d, r%d, %d\n", opcodes[inst->base.opcode], 1738 inst->compare.dest_flags->reg_no, inst->compare.source->reg_no, 1739 inst->compare.operand.immed); 1740 break; 1741 1742 case cg_inst_arm_compare_shift_reg: 1743 fprintf(out, "\t%s\tr%d, r%d, r%d %s r%d\n", opcodes[inst->base.opcode], 1744 inst->compare.dest_flags->reg_no, inst->compare.source->reg_no, 1745 inst->compare.operand.shift_reg.source->reg_no, 1746 shift_opcodes[inst->compare.operand.shift_reg.op], 1747 inst->compare.operand.shift_reg.shift->reg_no); 1748 break; 1749 1750 case cg_inst_arm_compare_shift_immed: 1751 fprintf(out, "\t%s\tr%d, r%d, r%d %s %d\n", opcodes[inst->base.opcode], 1752 inst->compare.dest_flags->reg_no, inst->compare.source->reg_no, 1753 inst->compare.operand.shift_immed.source->reg_no, 1754 shift_opcodes[inst->compare.operand.shift_immed.op], 1755 inst->compare.operand.shift_immed.shift); 1756 break; 1757 1758 case cg_inst_arm_load_immed_offset: 1759 fprintf(out, "\t%s\tr%d, (r%d, %d)\n", opcodes[inst->base.opcode], 1760 inst->load.dest->reg_no, inst->load.mem.immed_offset.base->reg_no, 1761 inst->load.mem.immed_offset.offset); 1762 break; 1763 1764 case cg_inst_arm_load_reg_offset: 1765 fprintf(out, "\t%s\tr%d, (r%d, r%d)\n", opcodes[inst->base.opcode], 1766 inst->load.dest->reg_no, inst->load.mem.reg_offset.base->reg_no, 1767 inst->load.mem.reg_offset.offset->reg_no); 1768 break; 1769 1770 case cg_inst_arm_store_immed_offset: 1771 fprintf(out, "\t%s\tr%d, (r%d, %d)\n", opcodes[inst->base.opcode], 1772 inst->store.source->reg_no, inst->store.mem.immed_offset.base->reg_no, 1773 inst->store.mem.immed_offset.offset); 1774 break; 1775 1776 case cg_inst_arm_store_reg_offset: 1777 fprintf(out, "\t%s\tr%d, (r%d, r%d)\n", opcodes[inst->base.opcode], 1778 inst->store.source->reg_no, inst->store.mem.reg_offset.base->reg_no, 1779 inst->store.mem.reg_offset.offset->reg_no); 1780 break; 1781 1782 case cg_inst_none: 1783 default: 1784 fprintf(out, "\t<ILLEGAL INSTRUCTION>\n"); 1785 ; 1786 } 1787} 1788 1789 1790static void dump_bitset(const char * name, cg_bitset_t * bitset, FILE * out) 1791{ 1792 if (bitset) 1793 { 1794 const char * separator = " "; 1795 size_t index; 1796 1797 fprintf(out, "; %s = {", name); 1798 1799 for (index = 0; index < bitset->elements; ++index) 1800 { 1801 if (CG_BITSET_TEST(bitset, index)) 1802 { 1803 fprintf(out, "%s%d", separator, index); 1804 separator = ", "; 1805 } 1806 } 1807 1808 fprintf(out, " }\n"); 1809 } 1810} 1811 1812 1813void dump_register_info(cg_virtual_reg_t * reg, FILE * out) 1814{ 1815 cg_virtual_reg_list_t * list; 1816 1817 fprintf(out, "\tr%d [U: $%d, D: $%d] => ", reg->reg_no, reg->use_cost, reg->def_cost); 1818 1819 for (list = reg->interferences; list; list = list->next) 1820 { 1821 fprintf(out, "%d ", list->reg->reg_no); 1822 } 1823 1824 fprintf(out, "\n"); 1825} 1826 1827 1828void cg_module_dump(cg_module_t * module, FILE * out) 1829{ 1830 cg_proc_t * proc; 1831 cg_block_t * block; 1832 cg_inst_t * inst; 1833 cg_virtual_reg_t * reg; 1834 1835 for (proc = module->procs; proc; proc = proc->next) 1836 { 1837 for (block = proc->blocks; block; block = block->next) 1838 { 1839 fprintf(out, "%p:\n", block); 1840 dump_bitset("def", block->def, out); 1841 dump_bitset("use", block->use, out); 1842 dump_bitset("in", block->live_in, out); 1843 dump_bitset("out", block->live_out, out); 1844 1845 for (inst = block->insts.head; inst; inst = inst->base.next) 1846 { 1847 inst_dump(inst, out); 1848 } 1849 1850 fprintf(out, "\n"); 1851 } 1852 1853 fprintf(out, "\n\n"); 1854 fprintf(out, "Interference information\n"); 1855 1856 for (reg = proc->registers; reg; reg = reg->next) 1857 { 1858 if (reg->representative == NULL || reg->representative == reg) 1859 dump_register_info(reg, out); 1860 } 1861 } 1862} 1863 1864 1865static void inst_list_append(cg_inst_list_head_t * insts, cg_inst_t * inst) 1866{ 1867 if (insts->head) 1868 { 1869 assert(insts->tail); 1870 insts->tail->base.next = inst; 1871 inst->base.next = NULL; 1872 insts->tail = inst; 1873 } 1874 else 1875 { 1876 assert(!insts->tail); 1877 inst->base.next = NULL; 1878 insts->head = insts->tail = inst; 1879 } 1880} 1881 1882 1883static void block_reschedule(cg_block_t * block, cg_inst_list_head_t * insts) 1884{ 1885} 1886 1887 1888static void block_reorder_instructions(cg_block_t * block) 1889{ 1890 // phi, branch, ret have to stay in order 1891 1892 cg_inst_t * insts = block->insts.head; 1893 block->insts.head = block->insts.tail = NULL; 1894 1895 /* copy all phi instructions back in place */ 1896 1897 while (insts && insts->base.opcode == cg_op_phi) 1898 { 1899 cg_inst_t * inst = insts; 1900 insts = inst->base.next; 1901 inst_list_append(&block->insts, inst); 1902 } 1903 1904 while (insts) 1905 { 1906 /* collect the next sequence of instructions until we reach a branch or ret */ 1907 cg_inst_list_head_t temp_list; 1908 cg_inst_t * last_inst; 1909 memset(&temp_list, 0, sizeof temp_list); 1910 1911 do 1912 { 1913 last_inst = insts; 1914 insts = insts->base.next; 1915 inst_list_append(&temp_list, last_inst); 1916 } 1917 while (insts && last_inst->base.opcode != cg_op_beq && 1918 last_inst->base.opcode != cg_op_bne && 1919 last_inst->base.opcode != cg_op_blt && 1920 last_inst->base.opcode != cg_op_bgt && 1921 last_inst->base.opcode != cg_op_ble && 1922 last_inst->base.opcode != cg_op_bge && 1923 last_inst->base.opcode != cg_op_bra && 1924 last_inst->base.opcode != cg_op_ret); 1925 1926 block_reschedule(block, &temp_list); 1927 } 1928} 1929 1930 1931void cg_module_reorder_instructions(cg_module_t * module) 1932{ 1933 cg_proc_t * proc; 1934 cg_block_t * block; 1935 1936 for (proc = module->procs; proc; proc = proc->next) 1937 { 1938 for (block = proc->blocks; block; block = block->next) 1939 { 1940 block_reorder_instructions(block); 1941 } 1942 } 1943} 1944 1945 1946static void count_uses(int * result, cg_block_t * block) 1947{ 1948 cg_inst_t * inst; 1949 size_t num_registers = block->proc->num_registers; 1950 size_t regno; 1951 1952 for (regno = 0; regno != num_registers; ++regno) 1953 { 1954 result[regno] = 0; 1955 } 1956 1957 for (inst = block->insts.head; inst != (cg_inst_t *) 0; inst = inst->base.next) 1958 { 1959 cg_virtual_reg_t * buffer[64]; 1960 cg_virtual_reg_t **iter, ** end = cg_inst_use(inst, buffer, buffer + 64); 1961 1962 for (iter = buffer; iter != end; ++iter) 1963 { 1964 regno = (*iter)->reg_no; 1965 ++result[regno]; 1966 } 1967 } 1968} 1969 1970 1971static void block_interferences(cg_block_t * block) 1972{ 1973 cg_proc_t * proc = block->proc; 1974 cg_heap_t * heap = proc->module->heap; 1975 cg_inst_t * inst; 1976 size_t outer_index, inner_index; 1977 1978 // for any registers live in input, create an edge and add them to current list of live registers 1979 // create list of uses for each instruction 1980 // iterate over instructions: 1981 // for each def, add edge to all live registers 1982 // add def to live registers 1983 // for each use, remove current use from use list; if # uses = 0 and not in live out, remove variable from live register set 1984 1985 cg_bitset_t * live = cg_bitset_create(heap, block->live_in->elements); 1986 int * uses = (int *) malloc(sizeof(int *) * proc->num_registers); 1987 1988 assert(proc->num_registers == block->live_in->elements); 1989 1990 count_uses(uses, block); 1991 cg_bitset_assign(live, block->live_in); 1992 1993 for (outer_index = 0; outer_index < live->elements - 1; ++outer_index) 1994 { 1995 if (!CG_BITSET_TEST(live, outer_index)) 1996 continue; 1997 1998 for (inner_index = outer_index + 1; inner_index < live->elements; ++inner_index) 1999 { 2000 if (CG_BITSET_TEST(live, inner_index)) 2001 { 2002 add_interferen…
Large files files are truncated, but you can click here to view the full file