/* * Description: * Moves an instruction from the execution stage to common data bus (if possible) * Inputs: * current_cycle: the cycle we are at * Returns: * None */ void execute_To_CDB(int current_cycle) { /* ECE552: YOUR CODE GOES HERE */ // Remove all finished stores. { int i, j; for (i = 0; i < FU_INT_SIZE; i++) { if (fuINT[i] != NULL && IS_STORE(fuINT[i]->op) && current_cycle >= FU_INT_LATENCY + fuINT[i]->tom_execute_cycle) { remove_insn(fuINT[i], reservINT, RESERV_INT_SIZE); fuINT[i] = NULL; } } } // Find oldest instruction that is ready to be broadcasted on the CDB. { int i; instruction_t* insn = NULL; for (i = 0; i < FU_INT_SIZE; i++) { if (fuINT[i] != NULL && current_cycle >= FU_INT_LATENCY + fuINT[i]->tom_execute_cycle && (insn == NULL || fuINT[i]->index < insn->index)) { insn = fuINT[i]; } } for (i = 0; i < FU_FP_SIZE; i++) { if (fuFP[i] != NULL && current_cycle >= FU_FP_LATENCY + fuFP[i]->tom_execute_cycle && (insn == NULL || fuFP[i]->index < insn->index)) { insn = fuFP[i]; } } // If instruction is found, remove it from RSs and FUs. // Then, set cycle it enters CDB and put it on the CDB. if (insn != NULL) { remove_insn(insn, reservINT, RESERV_INT_SIZE); remove_insn(insn, reservFP, RESERV_FP_SIZE); remove_insn(insn, fuINT, FU_INT_SIZE); remove_insn(insn, fuFP, FU_FP_SIZE); insn->tom_cdb_cycle = current_cycle; commonDataBus = insn; } } }
void replace_call_placeholder (rtx insn, sibcall_use_t use) { if (use == sibcall_use_tail_recursion) emit_insn_before (XEXP (PATTERN (insn), 2), insn); else if (use == sibcall_use_sibcall) emit_insn_before (XEXP (PATTERN (insn), 1), insn); else if (use == sibcall_use_normal) emit_insn_before (XEXP (PATTERN (insn), 0), insn); else abort (); /* Turn off LABEL_PRESERVE_P for the tail recursion label if it exists. We only had to set it long enough to keep the jump pass above from deleting it as unused. */ if (XEXP (PATTERN (insn), 3)) LABEL_PRESERVE_P (XEXP (PATTERN (insn), 3)) = 0; /* "Delete" the placeholder insn. */ remove_insn (insn); }
static unsigned int rest_of_handle_simplify_got (void) { df_ref ref; rtx use = NULL_RTX; int i, n_symbol, n_access = 0; struct got_access_info* got_accesses; htab_t var_table = htab_create (VAR_TABLE_SIZE, htab_hash_pointer, htab_eq_pointer, NULL); rtx pic_reg = targetm.got_access.get_pic_reg (); gcc_assert (pic_reg); ref = DF_REG_USE_CHAIN (REGNO (pic_reg)); got_accesses = XNEWVEC(struct got_access_info, DF_REG_USE_COUNT (REGNO (pic_reg))); /* Check if all uses of pic_reg are loading global address through the default method. */ while (ref) { rtx_insn* insn = DF_REF_INSN (ref); /* Check for the special USE insn, it is not a real usage of pic_reg. */ if (GET_CODE (PATTERN (insn)) == USE) use = insn; else { /* If an insn both set and use pic_reg, it is in the process of constructing the value of pic_reg. We should also ignore it. */ rtx set = single_set (insn); if (!(set && SET_DEST (set) == pic_reg)) { rtx offset_reg; rtx offset_insn; rtx symbol = targetm.got_access.loaded_global_var (insn, &offset_reg, &offset_insn); if (symbol) { rtx* slot = (rtx*) htab_find_slot (var_table, symbol, INSERT); if (*slot == HTAB_EMPTY_ENTRY) *slot = symbol; gcc_assert (set); got_accesses[n_access].symbol = symbol; got_accesses[n_access].offset_reg = offset_reg; got_accesses[n_access].address_reg = SET_DEST (set); got_accesses[n_access].load_insn = insn; got_accesses[n_access].offset_insn = offset_insn; n_access++; } else { /* This insn doesn't load a global address, but it has other unexpected usage of pic_reg, give up. */ free (got_accesses); htab_delete (var_table); return 0; } } } ref = DF_REF_NEXT_REG(ref); } /* Check if we can simplify it. */ n_symbol = htab_elements (var_table); gcc_assert (n_symbol <= n_access); if (!targetm.got_access.can_simplify_got_access (n_symbol, n_access)) { free (got_accesses); htab_delete (var_table); return 0; } /* Rewrite the global address loading insns. */ for (i=0; i<n_access; i++) targetm.got_access.load_global_address (got_accesses[i].symbol, got_accesses[i].offset_reg, got_accesses[i].address_reg, got_accesses[i].load_insn, got_accesses[i].offset_insn); /* Since there is no usage of pic_reg now, we can remove it. */ if (use) remove_insn (use); targetm.got_access.clear_pic_reg (); free (got_accesses); htab_delete (var_table); return 0; }