📄 alpha.c
字号:
else if (a >= 4 && c % 4 == 0) dst_align = 4; else if (a >= 2 && c % 2 == 0) dst_align = 2; } } /* * Load the entire block into registers. */ if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF) { enum machine_mode mode; tmp = XEXP (XEXP (orig_src, 0), 0); /* Don't use the existing register if we're reading more than is held in the register. Nor if there is not a mode that handles the exact size. */ mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); if (mode != BLKmode && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes) { if (mode == TImode) { data_regs[nregs] = gen_lowpart (DImode, tmp); data_regs[nregs+1] = gen_highpart (DImode, tmp); nregs += 2; } else data_regs[nregs++] = gen_lowpart (mode, tmp); goto src_done; } /* No appropriate mode; fall back on memory. */ orig_src = change_address (orig_src, GET_MODE (orig_src), copy_addr_to_reg (XEXP (orig_src, 0))); } ofs = 0; if (src_align >= 8 && bytes >= 8) { words = bytes / 8; for (i = 0; i < words; ++i) data_regs[nregs+i] = gen_reg_rtx(DImode); for (i = 0; i < words; ++i) { emit_move_insn (data_regs[nregs+i], change_address (orig_src, DImode, plus_constant (XEXP (orig_src, 0), ofs + i*8))); } nregs += words; bytes -= words * 8; ofs += words * 8; } if (src_align >= 4 && bytes >= 4) { words = bytes / 4; for (i = 0; i < words; ++i) data_regs[nregs+i] = gen_reg_rtx(SImode); for (i = 0; i < words; ++i) { emit_move_insn (data_regs[nregs+i], change_address (orig_src, SImode, plus_constant (XEXP (orig_src, 0), ofs + i*4))); } nregs += words; bytes -= words * 4; ofs += words * 4; } if (bytes >= 16) { words = bytes / 8; for (i = 0; i < words+1; ++i) data_regs[nregs+i] = gen_reg_rtx(DImode); alpha_expand_unaligned_load_words (data_regs + nregs, orig_src, words, ofs); nregs += words; bytes -= words * 8; ofs += words * 8; } if (!TARGET_BWX && bytes >= 8) { data_regs[nregs++] = tmp = gen_reg_rtx (DImode); alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0); bytes -= 8; ofs += 8; } if (!TARGET_BWX && bytes >= 4) { data_regs[nregs++] = tmp = gen_reg_rtx (SImode); alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0); bytes -= 4; ofs += 4; } if (bytes >= 2) { if (src_align >= 2) { do { data_regs[nregs++] = tmp = gen_reg_rtx (HImode); emit_move_insn (tmp, change_address (orig_src, HImode, plus_constant (XEXP (orig_src, 0), ofs))); bytes -= 2; ofs += 2; } while (bytes >= 2); } else if (!TARGET_BWX) { data_regs[nregs++] = tmp = gen_reg_rtx (HImode); alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0); bytes -= 2; ofs += 2; } } while (bytes > 0) { data_regs[nregs++] = tmp = gen_reg_rtx (QImode); emit_move_insn (tmp, change_address (orig_src, QImode, plus_constant (XEXP (orig_src, 0), ofs))); bytes -= 1; ofs += 1; } src_done: if (nregs > (int)(sizeof(data_regs)/sizeof(*data_regs))) abort(); /* * Now save it back out again. */ i = 0, ofs = 0; if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF) { enum machine_mode mode; tmp = XEXP (XEXP (orig_dst, 0), 0); mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1); if (GET_MODE (tmp) == mode) { if (nregs == 1) { emit_move_insn (tmp, data_regs[0]); i = 1; goto dst_done; } else if (nregs == 2 && mode == TImode) { /* Undo the subregging done above when copying between two TImode registers. */ if (GET_CODE (data_regs[0]) == SUBREG && GET_MODE (SUBREG_REG (data_regs[0])) == TImode) { emit_move_insn (tmp, SUBREG_REG (data_regs[0])); } else { rtx seq; start_sequence (); emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]); emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]); seq = get_insns (); end_sequence (); emit_no_conflict_block (seq, tmp, data_regs[0], data_regs[1], NULL_RTX); } i = 2; goto dst_done; } } /* ??? If nregs > 1, consider reconstructing the word in regs. */ /* ??? Optimize mode < dst_mode with strict_low_part. */ /* No appropriate mode; fall back on memory. We can speed things up by recognizing extra alignment information. */ orig_dst = change_address (orig_dst, GET_MODE (orig_dst), copy_addr_to_reg (XEXP (orig_dst, 0))); dst_align = GET_MODE_SIZE (GET_MODE (tmp)); } /* Write out the data in whatever chunks reading the source allowed. */ if (dst_align >= 8) { while (i < nregs && GET_MODE (data_regs[i]) == DImode) { emit_move_insn (change_address (orig_dst, DImode, plus_constant (XEXP (orig_dst, 0), ofs)), data_regs[i]); ofs += 8; i++; } } if (dst_align >= 4) { /* If the source has remaining DImode regs, write them out in two pieces. */ while (i < nregs && GET_MODE (data_regs[i]) == DImode) { tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32), NULL_RTX, 1, OPTAB_WIDEN); emit_move_insn (change_address (orig_dst, SImode, plus_constant (XEXP (orig_dst, 0), ofs)), gen_lowpart (SImode, data_regs[i])); emit_move_insn (change_address (orig_dst, SImode, plus_constant (XEXP (orig_dst, 0), ofs+4)), gen_lowpart (SImode, tmp)); ofs += 8; i++; } while (i < nregs && GET_MODE (data_regs[i]) == SImode) { emit_move_insn (change_address(orig_dst, SImode, plus_constant (XEXP (orig_dst, 0), ofs)), data_regs[i]); ofs += 4; i++; } } if (i < nregs && GET_MODE (data_regs[i]) == DImode) { /* Write out a remaining block of words using unaligned methods. */ for (words = 1; i+words < nregs ; ++words) if (GET_MODE (data_regs[i+words]) != DImode) break; if (words == 1) alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs); else alpha_expand_unaligned_store_words (data_regs+i, orig_dst, words, ofs); i += words; ofs += words * 8; } /* Due to the above, this won't be aligned. */ /* ??? If we have more than one of these, consider constructing full words in registers and using alpha_expand_unaligned_store_words. */ while (i < nregs && GET_MODE (data_regs[i]) == SImode) { alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs); ofs += 4; i++; } if (dst_align >= 2) while (i < nregs && GET_MODE (data_regs[i]) == HImode) { emit_move_insn (change_address (orig_dst, HImode, plus_constant (XEXP (orig_dst, 0), ofs)), data_regs[i]); i++; ofs += 2; } else while (i < nregs && GET_MODE (data_regs[i]) == HImode) { alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs); i++; ofs += 2; } while (i < nregs && GET_MODE (data_regs[i]) == QImode) { emit_move_insn (change_address (orig_dst, QImode, plus_constant (XEXP (orig_dst, 0), ofs)), data_regs[i]); i++; ofs += 1; } dst_done: if (i != nregs) abort(); return 1;}intalpha_expand_block_clear (operands) rtx operands[];{ rtx bytes_rtx = operands[1]; rtx align_rtx = operands[2]; HOST_WIDE_INT bytes = INTVAL (bytes_rtx); HOST_WIDE_INT align = INTVAL (align_rtx); rtx orig_dst = operands[0]; rtx tmp; HOST_WIDE_INT i, words, ofs = 0; if (bytes <= 0) return 1; if (bytes > MAX_MOVE_WORDS*8) return 0; /* Look for stricter alignment. */ tmp = XEXP (orig_dst, 0); if (GET_CODE (tmp) == REG) { if (REGNO_POINTER_ALIGN (REGNO (tmp)) > align) align = REGNO_POINTER_ALIGN (REGNO (tmp)); } else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 0)) == REG && GET_CODE (XEXP (tmp, 1)) == CONST_INT) { HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); if (a > align) { if (a >= 8 && c % 8 == 0) align = 8; else if (a >= 4 && c % 4 == 0) align = 4; else if (a >= 2 && c % 2 == 0) align = 2; } } else if (GET_CODE (tmp) == ADDRESSOF) { enum machine_mode mode; mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); if (GET_MODE (XEXP (tmp, 0)) == mode) { emit_move_insn (XEXP (tmp, 0), const0_rtx); return 1; } /* No appropriate mode; fall back on memory. */ orig_dst = change_address (orig_dst, GET_MODE (orig_dst), copy_addr_to_reg (tmp)); align = GET_MODE_SIZE (GET_MODE (XEXP (tmp, 0))); } /* Handle a block of contiguous words first. */ if (align >= 8 && bytes >= 8) { words = bytes / 8; for (i = 0; i < words; ++i) { emit_move_insn (change_address(orig_dst, DImode, plus_constant (XEXP (orig_dst, 0), ofs + i*8)), const0_rtx); } bytes -= words * 8; ofs += words * 8; } if (align >= 4 && bytes >= 4) { words = bytes / 4; for (i = 0; i < words; ++i) { emit_move_insn (change_address (orig_dst, SImode, plus_constant (XEXP (orig_dst, 0), ofs + i*4)), const0_rtx); } bytes -= words * 4; ofs += words * 4; } if (bytes >= 16) { words = bytes / 8; alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs); bytes -= words * 8; ofs += words * 8; } /* Next clean up any trailing pieces. We know from the contiguous block move that there are no aligned SImode or DImode hunks left. */ if (!TARGET_BWX && bytes >= 8) { alpha_expand_unaligned_store (orig_dst, const0_rtx, 8, ofs); bytes -= 8; ofs += 8; } if (!TARGET_BWX && bytes >= 4) { alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs); bytes -= 4; ofs += 4; } if (bytes >= 2) { if (align >= 2) { do { emit_move_insn (change_address (orig_dst, HImode, plus_constant (XEXP (orig_dst, 0), ofs)), const0_rtx); bytes -= 2; ofs += 2; } while (bytes >= 2); } else if (!TARGET_BWX) { alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs); bytes -= 2; ofs += 2; } } while (bytes > 0) { emit_move_insn (change_address (orig_dst, QImode, plus_constant (XEXP (orig_dst, 0), ofs)), const0_rtx); bytes -= 1; ofs += 1; } return 1;}/* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */intalpha_adjust_cost (insn, link, dep_insn, cost) rtx insn; rtx link; rtx dep_insn; int cost;{ rtx set, set_src; enum attr_type insn_type, dep_insn_type; /* If the dependence is an anti-dependence, there is no cost. For an output dependence, there is sometimes a cost, but it doesn't seem worth handling those few cases. */ if (REG_NOTE_KIND (link) != 0) return 0; /* If we can't recognize the insns, we can't really do anything. */ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) return cost; insn_type = get_attr_type (insn); dep_insn_type = get_attr_type (dep_insn); /* Bring in the user-defined memory latency. */ if (dep_insn_type == TYPE_ILD || dep_insn_type == TYPE_FLD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -