int main( void ) { int i = 0; int Pay = 0 ; int Price = 0; int UnitCount = 0; int* CoinUnits = NULL; int* Change = NULL; printf("동전의 가짓수를 입력하세요 :"); scanf( "%d", &UnitCount ); CoinUnits = (int*) malloc( sizeof(int) * UnitCount ); Change = (int*) malloc( sizeof(int) * UnitCount ); for ( i=0; i<UnitCount; i++ ) { printf("[%d] 번째 동전의 단위를 입력하세요 : ", i ); scanf( "%d", &CoinUnits[i] ); } qsort( CoinUnits, UnitCount, sizeof(int), Compare ); printf("물건 가격을 입력하세요 : "); scanf( "%d", &Price ); printf("손님이 지불한 돈은 얼마입니까? : "); scanf( "%d", &Pay ); GetChange( Price, Pay, CoinUnits, Change, UnitCount ); PrintChange( CoinUnits, Change, UnitCount); return 0; }
static STATUS_T CmdPrint( wAction_t action, coOrd pos ) /* * Print command: * * 3 Sub-states: * Select - grid coordinates are computed and the selected page is marked. * Move - grid base (currPrintGrid.orig) is moved. * Rotate - grid base and angle is rotated about selected point. */ { STATUS_T rc = C_CONTINUE; static BOOL_T downShift; switch (action) { case C_START: if (!wPrintInit()) return C_TERMINATE; printScale = iPrintScale; if (printWin == NULL) { rminScale_999.low = 1; if (printScale < rminScale_999.low) printScale = rminScale_999.low; print_d.scale = printScale; printWin = ParamCreateDialog( &printPG, MakeWindowTitle(_("Print")), _("Print"), DoPrintPrint, (paramActionCancelProc)Reset, TRUE, NULL, 0, PrintDlgUpdate ); } wShow( printWin ); SetPageSize( TRUE ); if (currPrintGrid.size.x == 0.0) { currPrintGrid.size.x = maxPageSize.x; currPrintGrid.size.y = maxPageSize.y; } if (currPrintGrid.size.x >= maxPageSize.x) currPrintGrid.size.x = maxPageSize.x; if (currPrintGrid.size.y >= maxPageSize.y) currPrintGrid.size.y = maxPageSize.y; newPrintGrid = currPrintGrid; ParamLoadControls( &printPG ); DrawPrintGrid(); pageCount = 0; LOG( log_print, 2, ( "Page size = %0.3f %0.3f\n", currPrintGrid.size.x, currPrintGrid.size.y ) ) PrintChange( CHANGE_MAP|CHANGE_UNITS ); ParamGroupRecord( &printPG ); ParamLoadMessage( &printPG, I_PAGECNT, "0 pages" ); ParamDialogOkActive( &printPG, FALSE ); ChangeDim(); InfoMessage( _("Select pages to print, or drag to move print grid") ); downShift = FALSE; ParamControlActive( &printPG, I_RULER, currPrintGrid.angle == 0 ); return C_CONTINUE; case C_DOWN: downShift = FALSE; if (MyGetKeyState()&WKEY_SHIFT) { newPrintGrid = currPrintGrid; rc = GridAction( C_DOWN, pos, &newPrintGrid.orig, &newPrintGrid.angle ); downShift = TRUE; } return C_CONTINUE; case C_MOVE: if (downShift) { rc = GridAction( action, pos, &newPrintGrid.orig, &newPrintGrid.angle ); ParamLoadControls( &printPG ); } return C_CONTINUE; case C_UP: if (downShift) { rc = GridAction( action, pos, &newPrintGrid.orig, &newPrintGrid.angle ); ParamLoadControls( &printPG ); DrawPrintGrid(); currPrintGrid = newPrintGrid; ChangeDim(); DrawPrintGrid(); downShift = FALSE; } return C_CONTINUE; case C_LCLICK: SelectPage( pos ); return C_CONTINUE; case C_RDOWN: downShift = FALSE; if (MyGetKeyState()&WKEY_SHIFT) { newPrintGrid = currPrintGrid; rc = GridAction( action, pos, &newPrintGrid.orig, &newPrintGrid.angle ); downShift = TRUE; } return rc; case C_RMOVE: if (downShift) { rc = GridAction( action, pos, &newPrintGrid.orig, &newPrintGrid.angle ); ParamLoadControls( &printPG ); } return rc; case C_RUP: if (downShift) { rc = GridAction( action, pos, &newPrintGrid.orig, &newPrintGrid.angle ); ParamLoadControls( &printPG ); DrawPrintGrid(); currPrintGrid = newPrintGrid; ChangeDim(); DrawPrintGrid(); downShift = FALSE; ParamControlActive( &printPG, I_RULER, currPrintGrid.angle == 0 ); } return rc; case C_REDRAW: DrawPrintGrid(); return C_TERMINATE; case C_CANCEL: if (printWin == NULL) return C_TERMINATE; PrintClear(); DrawPrintGrid(); wHide( printWin ); return C_TERMINATE; case C_OK: DoPrintPrint( NULL ); return C_TERMINATE; case C_CMDMENU: wMenuPopupShow( printGridPopupM ); return C_CONTINUE; default: return C_CONTINUE; } }
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; }