*参照元 [#sb70ac68] #backlinks *説明 [#o5eaa716] -パス: [[gcc-8.3/gcc/function.c]] -FIXME: これは何? --説明 **引数 [#m8f34270] -rtx_insn *insn -- --[[gcc-8.3/gcc/rtx_insn]] **返り値 [#dcf3ce13] -なし **参考 [#if684389] *実装 [#s03f4a77] /* A subroutine of instantiate_virtual_regs. Instantiate any virtual registers present inside of insn. The result will be a valid insn. */ static void instantiate_virtual_regs_in_insn (rtx_insn *insn) { poly_int64 offset; int insn_code, i; bool any_change = false; rtx set, new_rtx, x; rtx_insn *seq; - --[[gcc-8.3/gcc/poly_int64]] --[[gcc-8.3/gcc/insn_code]] --[[gcc-8.3/gcc/rtx]] --[[gcc-8.3/gcc/rtx_insn]] /* There are some special cases to be handled first. */ set = single_set (insn); - --[[gcc-8.3/gcc/single_set()]] if (set) { /* We're allowed to assign to a virtual register. This is interpreted to mean that the underlying register gets assigned the inverse transformation. This is used, for example, in the handling of non-local gotos. */ new_rtx = instantiate_new_reg (SET_DEST (set), &offset); - --[[gcc-8.3/gcc/instantiate_new_reg()]] --[[gcc-8.3/gcc/SET_DEST()]] if (new_rtx) { start_sequence (); instantiate_virtual_regs_in_rtx (&SET_SRC (set)); x = simplify_gen_binary (PLUS, GET_MODE (new_rtx), SET_SRC (set), gen_int_mode (-offset, GET_MODE (new_rtx))); x = force_operand (x, new_rtx); if (x != new_rtx) emit_move_insn (new_rtx, x); seq = get_insns (); end_sequence (); - --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/instantiate_virtual_regs_in_rtx()]] --[[gcc-8.3/gcc/SET_SRC()]] --[[gcc-8.3/gcc/simplify_gen_binary()]] --[[gcc-8.3/gcc/GET_MODE()]] --[[gcc-8.3/gcc/SET_SRC()]] --[[gcc-8.3/gcc/gen_int_mode()]] --[[gcc-8.3/gcc/force_operand()]] --[[gcc-8.3/gcc/emit_move_insn()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] emit_insn_before (seq, insn); delete_insn (insn); return; } - --[[gcc-8.3/gcc/emit_insn_before()]] --[[gcc-8.3/gcc/delete_insn()]] /* Handle a straight copy from a virtual register by generating a new add insn. The difference between this and falling through to the generic case is avoiding a new pseudo and eliminating a move insn in the initial rtl stream. */ new_rtx = instantiate_new_reg (SET_SRC (set), &offset); if (new_rtx && maybe_ne (offset, 0) && REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) > LAST_VIRTUAL_REGISTER) { - --[[gcc-8.3/gcc/instantiate_new_reg()]] --[[gcc-8.3/gcc/SET_SRC()]] --[[gcc-8.3/gcc/maybe_ne()]] --[[gcc-8.3/gcc/REG_P()]] --[[gcc-8.3/gcc/REGNO()]] --[[gcc-8.3/gcc/SET_DEST()]] start_sequence (); x = expand_simple_binop (GET_MODE (SET_DEST (set)), PLUS, new_rtx, gen_int_mode (offset, GET_MODE (SET_DEST (set))), SET_DEST (set), 1, OPTAB_LIB_WIDEN); if (x != SET_DEST (set)) emit_move_insn (SET_DEST (set), x); seq = get_insns (); end_sequence (); - --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/expand_simple_binop()]] --[[gcc-8.3/gcc/GET_MODE()]] --[[gcc-8.3/gcc/SET_DEST()]] --[[gcc-8.3/gcc/gen_int_mode()]] --[[gcc-8.3/gcc/emit_move_insn()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] emit_insn_before (seq, insn); delete_insn (insn); return; } - --[[gcc-8.3/gcc/emit_insn_before()]] --[[gcc-8.3/gcc/delete_insn()]] extract_insn (insn); insn_code = INSN_CODE (insn); - --[[gcc-8.3/gcc/extract_insn()]] --[[gcc-8.3/gcc/INSN_CODE()]] /* Handle a plus involving a virtual register by determining if the operands remain valid if they're modified in place. */ poly_int64 delta; if (GET_CODE (SET_SRC (set)) == PLUS && recog_data.n_operands >= 3 && recog_data.operand_loc[1] == &XEXP (SET_SRC (set), 0) && recog_data.operand_loc[2] == &XEXP (SET_SRC (set), 1) && poly_int_rtx_p (recog_data.operand[2], &delta) && (new_rtx = instantiate_new_reg (recog_data.operand[1], &offset))) { - --[[gcc-8.3/gcc/poly_int64]] --[[gcc-8.3/gcc/XEXP()]] --[[gcc-8.3/gcc/SET_SERC()]] --[[gcc-8.3/gcc/poly_int_rtx_p()]] --[[gcc-8.3/gcc/instantiate_new_reg()]] offset += delta; /* If the sum is zero, then replace with a plain move. */ if (known_eq (offset, 0) && REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) > LAST_VIRTUAL_REGISTER) { - --[[gcc-8.3/gcc/known_eq()]] --[[gcc-8.3/gcc/REG_P()]] --[[gcc-8.3/gcc/REGNO()]] --[[gcc-8.3/gcc/SET_DEST()]] start_sequence (); emit_move_insn (SET_DEST (set), new_rtx); seq = get_insns (); end_sequence (); - --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/expand_move_insn()]] --[[gcc-8.3/gcc/SET_DEST()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/emit_move_insn()]] --[[gcc-8.3/gcc/end_sequence()]] emit_insn_before (seq, insn); delete_insn (insn); return; } - --[[gcc-8.3/gcc/emit_insn_before()]] --[[gcc-8.3/gcc/delete_insn()]] x = gen_int_mode (offset, recog_data.operand_mode[2]); - --[[gcc-8.3/gcc/gen_int_mode()]] /* Using validate_change and apply_change_group here leaves recog_data in an invalid state. Since we know exactly what we want to check, do those two by hand. */ if (safe_insn_predicate (insn_code, 1, new_rtx) && safe_insn_predicate (insn_code, 2, x)) { - --[[gcc-8.3/gcc/safe_insn_predicate()]] *recog_data.operand_loc[1] = recog_data.operand[1] = new_rtx; *recog_data.operand_loc[2] = recog_data.operand[2] = x; any_change = true; /* Fall through into the regular operand fixup loop in order to take care of operands other than 1 and 2. */ } } } else { extract_insn (insn); insn_code = INSN_CODE (insn); } - --[[gcc-8.3/gcc/extract_insn()]] --[[gcc-8.3/gcc/INSN_CODE()]] /* In the general case, we expect virtual registers to appear only in operands, and then only as either bare registers or inside memories. */ for (i = 0; i < recog_data.n_operands; ++i) { x = recog_data.operand[i]; switch (GET_CODE (x)) { - --[[gcc-8.3/gcc/GET_CODE()]] case MEM: { rtx addr = XEXP (x, 0); if (!instantiate_virtual_regs_in_rtx (&addr)) continue; start_sequence (); x = replace_equiv_address (x, addr, true); /* It may happen that the address with the virtual reg was valid (e.g. based on the virtual stack reg, which might be acceptable to the predicates with all offsets), whereas the address now isn't anymore, for instance when the address is still offsetted, but the base reg isn't virtual-stack-reg anymore. Below we would do a force_reg on the whole operand, but this insn might actually only accept memory. Hence, before doing that last resort, try to reload the address into a register, so this operand stays a MEM. */ if (!safe_insn_predicate (insn_code, i, x)) { addr = force_reg (GET_MODE (addr), addr); x = replace_equiv_address (x, addr, true); } seq = get_insns (); end_sequence (); if (seq) emit_insn_before (seq, insn); - --[[gcc-8.3/gcc/rtx]] --[[gcc-8.3/gcc/XEXP()]] --[[gcc-8.3/gcc/instantiate_virtual_regs_in_rtx()]] --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/safe_insn_predicate()]] --[[gcc-8.3/gcc/force_reg()]] --[[gcc-8.3/gcc/replace_equiv_address()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] --[[gcc-8.3/gcc/emit_insn_before()]] } break; case REG: new_rtx = instantiate_new_reg (x, &offset); if (new_rtx == NULL) continue; if (known_eq (offset, 0)) x = new_rtx; - --[[gcc-8.3/gcc/instantiate_new_reg()]] --[[gcc-8.3/gcc/known_eq()]] else { start_sequence (); /* Careful, special mode predicates may have stuff in insn_data[insn_code].operand[i].mode that isn't useful to us for computing a new value. */ /* ??? Recognize address_operand and/or "p" constraints to see if (plus new offset) is a valid before we put this through expand_simple_binop. */ x = expand_simple_binop (GET_MODE (x), PLUS, new_rtx, gen_int_mode (offset, GET_MODE (x)), NULL_RTX, 1, OPTAB_LIB_WIDEN); seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); - --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] --[[gcc-8.3/gcc/emit_insn_before()]] } break; case SUBREG: new_rtx = instantiate_new_reg (SUBREG_REG (x), &offset); if (new_rtx == NULL) continue; if (maybe_ne (offset, 0)) - --[[gcc-8.3/gcc/instantiate_new_reg()]] --[[gcc-8.3/gcc/maybe_ne()]] { start_sequence (); new_rtx = expand_simple_binop (GET_MODE (new_rtx), PLUS, new_rtx, gen_int_mode (offset, GET_MODE (new_rtx)), NULL_RTX, 1, OPTAB_LIB_WIDEN); seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); } x = simplify_gen_subreg (recog_data.operand_mode[i], new_rtx, GET_MODE (new_rtx), SUBREG_BYTE (x)); gcc_assert (x); break; - --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/expand_simple_binop()]] --[[gcc-8.3/gcc/GET_MODE()]] --[[gcc-8.3/gcc/gen_int_mode()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] --[[gcc-8.3/gcc/emit_insn_before()]] --[[gcc-8.3/gcc/simplify_gen_subreg()]] --[[gcc-8.3/gcc/SUBREG_BYTE()]] --[[gcc-8.3/gcc/gcc_assert()]] default: continue; } /* At this point, X contains the new value for the operand. Validate the new value vs the insn predicate. Note that asm insns will have insn_code -1 here. */ if (!safe_insn_predicate (insn_code, i, x)) { start_sequence (); if (REG_P (x)) { gcc_assert (REGNO (x) <= LAST_VIRTUAL_REGISTER); x = copy_to_reg (x); } else x = force_reg (insn_data[insn_code].operand[i].mode, x); seq = get_insns (); end_sequence (); if (seq) emit_insn_before (seq, insn); } - --[[gcc-8.3/gcc/safe_insn_predicate()]] --[[gcc-8.3/gcc/start_sequence()]] --[[gcc-8.3/gcc/REG_P()]] --[[gcc-8.3/gcc/gcc_assert()]] --[[gcc-8.3/gcc/REGNO()]] --[[gcc-8.3/gcc/copy_to_reg()]] --[[gcc-8.3/gcc/force_reg()]] --[[gcc-8.3/gcc/get_insns()]] --[[gcc-8.3/gcc/end_sequence()]] --[[gcc-8.3/gcc/emit_insn_before()]] *recog_data.operand_loc[i] = recog_data.operand[i] = x; any_change = true; } if (any_change) { /* Propagate operand changes into the duplicates. */ for (i = 0; i < recog_data.n_dups; ++i) *recog_data.dup_loc[i] = copy_rtx (recog_data.operand[(unsigned)recog_data.dup_num[i]]); /* Force re-recognition of the instruction for validation. */ INSN_CODE (insn) = -1; } - --[[gcc-8.3/gcc/copy_rtx()]] --[[gcc-8.3/gcc/INSN_CODE()]] if (asm_noperands (PATTERN (insn)) >= 0) { if (!check_asm_operands (PATTERN (insn))) { error_for_asm (insn, "impossible constraint in %<asm%>"); /* For asm goto, instead of fixing up all the edges just clear the template and clear input operands (asm goto doesn't have any output operands). */ if (JUMP_P (insn)) { rtx asm_op = extract_asm_operands (PATTERN (insn)); ASM_OPERANDS_TEMPLATE (asm_op) = ggc_strdup (""); ASM_OPERANDS_INPUT_VEC (asm_op) = rtvec_alloc (0); ASM_OPERANDS_INPUT_CONSTRAINT_VEC (asm_op) = rtvec_alloc (0); } else delete_insn (insn); } } - --[[gcc-8.3/gcc/PATTERN()]] --[[gcc-8.3/gcc/error_for_asm()]] --[[gcc-8.3/gcc/JUMP_P()]] --[[gcc-8.3/gcc/extract_asm_operands()]] --[[gcc-8.3/gcc/ASM_OPERANDS_TEMPLATE()]] --[[gcc-8.3/gcc/ggc_strdup()]] --[[gcc-8.3/gcc/ASM_OPERANDS_INPUT_VEC()]] --[[gcc-8.3/gcc/rtvec_alloc()]] --[[gcc-8.3/gcc/ASM_OPERANDS_INPUT_CONSTRAINT_VEC()]] --[[gcc-8.3/gcc/rtvec_alloc()]] else { if (recog_memoized (insn) < 0) fatal_insn_not_found (insn); } - --[[gcc-8.3/gcc/recog_memoized()]] --[[gcc-8.3/gcc/fatal_insn_not_found()]] } *コメント [#yd59f977]