PageRenderTime 1556ms CodeModel.GetById 143ms app.highlight 1239ms RepoModel.GetById 157ms app.codeStats 1ms

/opengles/src/codegen/instruction.c

http://ftk.googlecode.com/
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