예제 #1
0
void Emit(char * filename)
{
	Var * var;

	EmitOpen(filename);

	VarUse();

	if (Verbose(NULL)) {

		PrintHeader(1, "Variables");

		for(var = VarFirst(); var != NULL; var = VarNext(var)) {
			if (var->write >= 1 || var->read >= 1) {
				if (var->mode == INSTR_VAR && !VarIsReg(var) && !VarIsLabel(var)) {
					PrintVar(var); PrintEOL();
				}
			}
		}

		PrintHeader(1, "Output");
	} // verbose

	EmitLabels();

	//TODO: ProcessUsedProc
//	if (!EmitProc(&ROOT_PROC)) goto failure;
	EmitProc(&ROOT_PROC);
	EmitProcedures();
	EmitAsmIncludes();	
	EmitInstrOp(INSTR_CODE_END, NULL, NULL, NULL);
	VarEmitAlloc();
	EmitInstrOp(INSTR_SRC_END, NULL, NULL, NULL);
	EmitClose();
}
예제 #2
0
void PrintDelete()
{
	UInt8 color;
	if (G_VERBOSE) {
		color = PrintColor(OPTIMIZE_COLOR);
		Print(" => void"); PrintEOL();
		PrintColor(color);
	}
}
예제 #3
0
void VarSetPrint(VarSet * set)
{
	VarTuple * tuple;
	UInt16 cnt, i;
	for(cnt = set->count, tuple = set->arr, i = 0; cnt>0; cnt--, tuple++, i++) {
		PrintVar(tuple->key);
		PrintEOL();
	}
}
예제 #4
0
void PrintInsert(Instr * i)
{
	UInt8 color;
	if (G_VERBOSE) {
		color = PrintColor(OPTIMIZE_COLOR);
		Print(" + | ");
		EmitInstrInline(i);
		PrintColor(color);
		PrintEOL();
	}
}
예제 #5
0
Bool OptimizeLoop(Var * proc, InstrBlock * header, InstrBlock * end)
/*
1. Find loop (starting with inner loops)
   - Every jump to label preceding the jump (backjump) forms a label
   - In nested labels, we encounter the backjump first
				<code1>
			l1@
				<code2>
			l2@
				<code3>
				if.. l2@
				<code4>
				if.. l3@
				<code5>

2. Select variable to put to register
   - Most used variable should be used
   - Some variables are already moved to index register (this is considered use too)

3. Compute cost of moving the variable to register

*/
{
	Instr * i, initial, ti, * last_mod;
	Var * top_var, * reg, * top_reg, * orig_result;
	UInt16 r, regi, changed;
	UInt32 var_size;
	Int32 q, top_q, n;
	Bool init, top_init;
	InstrBlock * blk, * last_mod_blk;
	InstrBlock * blk_exit;
	Bool var_modified;
	Bool verbose;
	Rule * rule;
	UInt8 color;

	blk_exit = end->next;

	G_VERBOSE = verbose = Verbose(proc);
	VarResetUse();
	InstrVarUse(header, blk_exit);
	InstrVarLoopDependent(header, end);

	// When processing, we assign var to register
	for(regi = 0; regi < CPU->REG_CNT; regi++) CPU->REG[regi]->var = NULL;

	while(top_var = FindMostUsedVar()) {

//		if (Verbose(proc)) {
//			Print("Most user var: "); PrintVar(top_var); PrintEOL();
//		}

		top_var->read = top_var->write = 0;
		var_size = VarByteSize(top_var);

		//====== Select the best register for the given variable
		//      let %A,%A   => index -3
		//      use of register instead of variable -1
		//      spill +3

		top_q = 0; top_reg = NULL; top_init = false;

		for(regi = 0; regi < CPU->REG_CNT; regi++) {

			reg = CPU->REG[regi];
			if (FlagOn(reg->submode, SUBMODE_IN|SUBMODE_OUT)) continue;		// exclude input/output registers
			if (reg->type->range.max == 1) continue;						// exclude flag registers
			if (var_size != VarByteSize(reg)) continue;						// exclude registers with different byte size
			if (reg->var != NULL) continue;

			if (InstrRule2(INSTR_LET, reg, top_var, NULL)) {

	//			if (StrEqual(reg->name, "x") && StrEqual(top_var->name, "i")) {
	//				Print(" ");
	//			}
				q = UsageQuotient(header, end, top_var, reg, &init);

				if (q < top_q) {
					top_q = q;
					top_reg = reg;
					top_init = init;
				}
			}
		}

		if (top_reg == NULL) continue;

		reg = top_reg;
		if (Verbose(proc)) {
			color = PrintColor(OPTIMIZE_COLOR);
			PrintFmt("*** Loop %d..%d\n", header->seq_no, end->seq_no);
			Print("Var: "); PrintVarVal(top_var); PrintEOL();
			Print("Register: "); PrintVarName(top_reg); PrintEOL();
			PrintFmt("Quotient: %d\n", top_q);
			PrintColor(color);
		}

		//TODO: If there is Let reg = var and var is not top_var, we need to spill store

		//=== Replace the use of registers

//		PrintProc(proc);

		ResetValues();
		initial.op = INSTR_LET; initial.result = top_reg; initial.arg1 = top_var; initial.arg2 = NULL;

		var_modified = false;
		// Generate instruction initializing the register used to replace the variable
		// before the start of the loop.
		// We only do this, if the variable is not initialized inside the loop.

//		if (FlagOn(top_var->flags, VarUninitialized) && !top_init) {
//			top_init = true;
//		}

 		if (top_init) {
			LoopInsertPrologue(proc, header, INSTR_LET, top_reg, top_var, NULL);
			VarSetSrcInstr(top_reg, &initial);
		}
		r = 0;

		last_mod = NULL;

		for(blk = header; blk != blk_exit; blk = blk->next) {
			if (verbose) PrintBlockHeader(blk);
			for(i = blk->first, n=0; i != NULL; i = i->next) {
retry:
				n++;
				if (i->op == INSTR_LINE) {
					if (verbose) { PrintInstrLine(n); EmitInstrInline(i); PrintEOL(); }
					continue;
				}

				// Delete unnecessary assignment
				if (i->op == INSTR_LET) {
					if (!InVar(i->arg1) && !OutVar(i->result) && VarContains(i->result, i->arg1)) {
del:
						if (verbose) { PrintInstrLine(n); EmitInstrInline(i); }
del2:					if (verbose) { PrintDelete(); }
						i = InstrDelete(blk, i);
						if (i == NULL) break;
						goto retry;	//continue;
					}
				}

				// Load the register with variable if necessary
				if (InstrReadsVar(i, top_var)) {
					if (!VarContains(top_reg, top_var)) {
						if (!(i->op == INSTR_LET && i->result == top_reg && i->arg1 == top_var)) {
							InstrInsertRule(blk, i, INSTR_LET, top_reg, top_var, NULL);
						}
					}
				}

				if (i->op == INSTR_LET && (i->result == top_var && i->arg1 == top_reg)) {
					r++;
					goto del;
				}

				if (InstrSpill(i, top_var)) {
					InstrInsertRule(blk, i, INSTR_LET, top_var, top_reg, NULL);
				}

				if (verbose) { PrintInstrLine(n); EmitInstrInline(i); }

				orig_result = i->result;

				memcpy(&ti, i, sizeof(Instr));
				changed = VarTestReplace(&ti.result, top_var, reg);
				r += changed;
				changed += VarTestReplace(&ti.arg1, top_var, reg);
				changed += VarTestReplace(&ti.arg2, top_var, reg);

				// If the instruction used variable, that contains same value as replaced register, use the register instead
				if (ti.arg1 != reg && VarContains(ti.arg1, reg)) {
					changed += VarTestReplace(&ti.result, ti.arg1, reg);
					changed += VarTestReplace(&ti.arg2, ti.arg1, reg);
					changed += VarTestReplace(&ti.arg1, ti.arg1, reg);
				}

				if (changed > 0) {

					if (i->op == INSTR_LET && ti.result == ti.arg1) {
						goto del2;
					}

					rule = InstrRule(&ti);
					if (rule != NULL && (i->rule->cycles >= rule->cycles)) {
						InstrReplaceVar(i, top_var, top_reg);

						if (i->arg1 != reg && VarContains(i->arg1, reg)) {
							VarTestReplace(&i->result, i->arg1, reg);
							VarTestReplace(&i->arg2, i->arg1, reg);
							VarTestReplace(&i->arg1, i->arg1, reg);
						}

						i->rule = rule;
						CheckInstr(i);
						PrintChange(i);
					}

				}

				if (verbose) PrintEOL();
				ResetValue(i->result);
				if (orig_result == top_var) {
//					if (!InstrIsSelfReferencing(i)) {
						VarSetSrcInstr(i->result, &initial);
//					} else {
//						VarSetSrcInstr(i->result, NULL);
//					}
					last_mod = i; last_mod_blk = blk;
				} else {
					VarSetSrcInstr(i->result, i);
				}
			}
		}

		// Value of register is not known at the end of loop, but it is not initialized at the beginning of the loop
		// We must load it before first use.

		if (!top_init && last_mod) {
			InstrInsertRule(last_mod_blk, last_mod->next, INSTR_LET, top_var, top_reg, NULL);
		}

		// If we replaced some destination by the register, store the register to destination
		if (r > 0) {
			// There may be exit label as part of the loop
			// We need to spill after it

			if (!VarIsConst(top_var)) {
				if (blk_exit == NULL || blk_exit->callers != NULL || blk_exit->from != end) {
					blk_exit = InstrBlockAlloc();
					blk_exit->to = end->to;
					blk_exit->next = end->to;
					end->next = blk_exit;
					end->to   = blk_exit;
				}
				InstrInsertRule(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL);
			}
//			InstrInsert(blk_exit, blk_exit->first, INSTR_LET, top_var, top_reg, NULL);
		}

		if (FlagOn(top_var->flags, VarLoopDependent)) {
			reg->flags |= VarLoopDependent;
		}

		return true;
	}
	return false;
}
예제 #6
0
void VM_Dsr::EOL( QString /*value*/, long line, long level )
{
    PrintEOL( line, level );
}