📄 expr.c
字号:
if (QUEUED_INSN (y)) { register rtx temp = gen_reg_rtx (GET_MODE (new)); emit_insn_before (gen_move_insn (temp, new), QUEUED_INSN (y)); return temp; } return new; } /* Otherwise, recursively protect the subexpressions of all the kinds of rtx's that can contain a QUEUED. */ if (code == MEM) { rtx tem = protect_from_queue (XEXP (x, 0), 0); if (tem != XEXP (x, 0)) { x = copy_rtx (x); XEXP (x, 0) = tem; } } else if (code == PLUS || code == MULT) { rtx new0 = protect_from_queue (XEXP (x, 0), 0); rtx new1 = protect_from_queue (XEXP (x, 1), 0); if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) { x = copy_rtx (x); XEXP (x, 0) = new0; XEXP (x, 1) = new1; } } return x; } /* If the increment has not happened, use the variable itself. */ if (QUEUED_INSN (x) == 0) return QUEUED_VAR (x); /* If the increment has happened and a pre-increment copy exists, use that copy. */ if (QUEUED_COPY (x) != 0) return QUEUED_COPY (x); /* The increment has happened but we haven't set up a pre-increment copy. Set one up now, and use it. */ QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x))); emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)), QUEUED_INSN (x)); return QUEUED_COPY (x);}/* Return nonzero if X contains a QUEUED expression: if it contains anything that will be altered by a queued increment. We handle only combinations of MEM, PLUS, MINUS and MULT operators since memory addresses generally contain only those. */static intqueued_subexp_p (x) rtx x;{ register enum rtx_code code = GET_CODE (x); switch (code) { case QUEUED: return 1; case MEM: return queued_subexp_p (XEXP (x, 0)); case MULT: case PLUS: case MINUS: return (queued_subexp_p (XEXP (x, 0)) || queued_subexp_p (XEXP (x, 1))); default: return 0; }}/* Perform all the pending incrementations. */voidemit_queue (){ register rtx p; while (p = pending_chain) { QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p)); pending_chain = QUEUED_NEXT (p); }}static voidinit_queue (){ if (pending_chain) abort ();}/* Copy data from FROM to TO, where the machine modes are not the same. Both modes may be integer, or both may be floating. UNSIGNEDP should be nonzero if FROM is an unsigned type. This causes zero-extension instead of sign-extension. */voidconvert_move (to, from, unsignedp) register rtx to, from; int unsignedp;{ enum machine_mode to_mode = GET_MODE (to); enum machine_mode from_mode = GET_MODE (from); int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT; int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT; enum insn_code code; rtx libcall; /* rtx code for making an equivalent value. */ enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND); to = protect_from_queue (to, 1); from = protect_from_queue (from, 0); if (to_real != from_real) abort (); /* If FROM is a SUBREG that indicates that we have already done at least the required extension, strip it. We don't handle such SUBREGs as TO here. */ if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from))) >= GET_MODE_SIZE (to_mode)) && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp) from = gen_lowpart (to_mode, from), from_mode = to_mode; if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to)) abort (); if (to_mode == from_mode || (from_mode == VOIDmode && CONSTANT_P (from))) { emit_move_insn (to, from); return; } if (to_real) { rtx value; if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)) { /* Try converting directly if the insn is supported. */ if ((code = can_extend_p (to_mode, from_mode, 0)) != CODE_FOR_nothing) { emit_unop_insn (code, to, from, UNKNOWN); return; } } #ifdef HAVE_trunchfqf2 if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctqfqf2 if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncsfqf2 if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncdfqf2 if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncxfqf2 if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctfqf2 if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode) { emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctqfhf2 if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode) { emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncsfhf2 if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode) { emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncdfhf2 if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode) { emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncxfhf2 if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode) { emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctfhf2 if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode) { emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncsftqf2 if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode) { emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncdftqf2 if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode) { emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncxftqf2 if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode) { emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctftqf2 if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode) { emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncdfsf2 if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode) { emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncxfsf2 if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode) { emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctfsf2 if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode) { emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_truncxfdf2 if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode) { emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN); return; }#endif#ifdef HAVE_trunctfdf2 if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode) { emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN); return; }#endif libcall = (rtx) 0; switch (from_mode) { case SFmode: switch (to_mode) { case DFmode: libcall = extendsfdf2_libfunc; break; case XFmode: libcall = extendsfxf2_libfunc; break; case TFmode: libcall = extendsftf2_libfunc; break; default: break; } break; case DFmode: switch (to_mode) { case SFmode: libcall = truncdfsf2_libfunc; break; case XFmode: libcall = extenddfxf2_libfunc; break; case TFmode: libcall = extenddftf2_libfunc; break; default: break; } break; case XFmode: switch (to_mode) { case SFmode: libcall = truncxfsf2_libfunc; break; case DFmode: libcall = truncxfdf2_libfunc; break; default: break; } break; case TFmode: switch (to_mode) { case SFmode: libcall = trunctfsf2_libfunc; break; case DFmode: libcall = trunctfdf2_libfunc; break; default: break; } break; default: break; } if (libcall == (rtx) 0) /* This conversion is not implemented yet. */ abort (); value = emit_library_call_value (libcall, NULL_RTX, 1, to_mode, 1, from, from_mode); emit_move_insn (to, value); return; } /* Now both modes are integers. */ /* Handle expanding beyond a word. */ if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode) && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD) { rtx insns; rtx lowpart; rtx fill_value; rtx lowfrom; int i; enum machine_mode lowpart_mode; int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD); /* Try converting directly if the insn is supported. */ if ((code = can_extend_p (to_mode, from_mode, unsignedp)) != CODE_FOR_nothing) { /* If FROM is a SUBREG, put it into a register. Do this so that we always generate the same set of insns for better cse'ing; if an intermediate assignment occurred, we won't be doing the operation directly on the SUBREG. */ if (optimize > 0 && GET_CODE (from) == SUBREG) from = force_reg (from_mode, from); emit_unop_insn (code, to, from, equiv_code); return; } /* Next, try converting via full word. */ else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD && ((code = can_extend_p (to_mode, word_mode, unsignedp)) != CODE_FOR_nothing)) { if (GET_CODE (to) == REG) emit_insn (gen_rtx (CLOBBER, VOIDmode, to)); convert_move (gen_lowpart (word_mode, to), from, unsignedp); emit_unop_insn (code, to, gen_lowpart (word_mode, to), equiv_code); return; } /* No special multiword conversion insn; do it by hand. */ start_sequence (); /* Since we will turn this into a no conflict block, we must ensure that the source does not overlap the target. */ if (reg_overlap_mentioned_p (to, from)) from = force_reg (from_mode, from); /* Get a copy of FROM widened to a word, if necessary. */ if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD) lowpart_mode = word_mode; else lowpart_mode = from_mode; lowfrom = convert_to_mode (lowpart_mode, from, unsignedp); lowpart = gen_lowpart (lowpart_mode, to); emit_move_insn (lowpart, lowfrom); /* Compute the value to put in each remaining word. */ if (unsignedp) fill_value = const0_rtx; else {#ifdef HAVE_slt if (HAVE_slt && insn_operand_mode[(int) CODE_FOR_slt][0] == word_mode && STORE_FLAG_VALUE == -1) { emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX, lowpart_mode, 0, 0); fill_value = gen_reg_rtx (word_mode); emit_insn (gen_slt (fill_value)); } else#endif { fill_value = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -