diff options
author | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-04-03 15:06:12 +0000 |
---|---|---|
committer | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-04-03 15:06:12 +0000 |
commit | 701e46d0e8a0465eb15923f104e7d741c4b1c8ca (patch) | |
tree | 28cfaed9a88de9b20638576026f15f0a1d8b06e6 /gcc/recog.c | |
parent | 71a7798b95e455db6c69e9e5207232fda5730bc5 (diff) | |
download | gcc-701e46d0e8a0465eb15923f104e7d741c4b1c8ca.tar.gz |
2001-04-03 Jakub Jelinek <jakub@redhat.com>
David S. Miller <davem@pierdol.cobaltmicro.com>
Andrew MacLeod <amacleod@redhat.com>
Use byte offsets in SUBREGs instead of words.
* alias.c (nonlocal_mentioned_p): Use subreg_regno function.
* caller-save.c (mark_set_regs): Change callers of subreg_hard_regno
to pass new argument.
(add_stored_regs): Use subreg_regno_offset function.
* calls.c (expand_call): For non-paradoxical SUBREG take endianess
into account.
(precompute_arguments): Use gen_lowpart_SUBREG.
* combine.c (try_combine): Replace explicit XEXP with SUBREG_REG.
(combine_simplify_rtx): Rework to use SUBREG_BYTE.
(simplify_set): Rework to use SUBREG_BYTE.
(expand_field_assignment): Use SUBREG_BYTE.
(make_extraction): Use SUBREG_BYTE.
(if_then_else_cond): Use SUBREG_BYTE.
(apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments.
(gen_lowpart_for_combine): Compute full byte offset.
* cse.c (mention_regs): Use SUBREG_BYTE.
(remove_invalid_subreg_refs): Rework to use SUBREG_BYTE.
(canon_hash): Use SUBREG_BYTE.
(fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword.
(gen_lowpart_if_possible): Formatting.
* dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos
correctly.
* dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
(mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
(loc_descriptor): Fixup explicit XEXP into SUBREG_REG
* dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
(output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
(output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
* emit-rtl.c (gen_rtx_SUBREG): New function, used to verify
certain invariants about SUBREGs the compiler creates.
(gen_lowpart_SUBREG): New function.
(subreg_hard_regno): New function to get the final register number.
(gen_lowpart_common): Use SUBREG_BYTE.
(gen_imagpart): Spacing nits.
(subreg_realpart_p): Use SUBREG_BYTE.
(gen_highpart): Use SUBREG_BYTE.
(subreg_lowpart_p): Always compute endian corrected goal offset,
even at the byte level, then compare against that.
(constant_subword): New function, pulled out all constant cases
from operand_subword and changed second argument name to offset.
(operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early
and call constant_subword to do the work. Return const0_rtx if
looking for a word outside of OP.
(operand_subword_force): Change second arg name to offset.
* expmed.c (store_bit_field): Use SUBREG_BYTE.
(store_split_bit_field): Use SUBREG_BYTE.
(extract_bit_field): Use SUBREG_BYTE.
(extract_split_bit_field): Use SUBREG_BYTE.
(expand_shift): Use SUBREG_BYTE.
* expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG.
* final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE.
* flow.c (set_noop_p): Use SUBREG_BYTE.
(mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead.
* function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG.
(fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian
correction code.
(optimize_bit_field): Use SUBREG_BYTE.
(purge_addressof_1): Use SUBREG_BYTE.
(purge_single_hard_subreg_set): Use subreg_regno_offset function.
(assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are
actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true.
* gengenrtl.c (special_rtx): Add SUBREG.
* global.c (mark_reg_store): Use SUBREG_BYTE.
(set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE.
* ifcvt (noce_emit_move_insn): Use SUBREG_BYTE.
* integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure
final byte offset is congruent to subreg's mode size.
(subst_constants): Use SUBREG_BYTE.
(mark_stores): Use subreg_regno_offset function.
* jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset
function and SUBREG_BYTE.
* local-alloc.c (combine_regs): Use subreg_regno_offset function.
(reg_is_born): Use subreg_hard_regno.
* recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte
endian correction code. Don't combine subregs unless resulting
offset aligns with type. Fix subreg constant extraction for DImode.
Simplify SUBREG of VOIDmode CONST_DOUBLE.
(general_operand): Remove dead mode_altering_drug code.
(indirect_operand): Use SUBREG_BYTE.
(constrain_operands): Use subreg_regno_offset function.
* reg-stack.c (get_true_reg): Use subreg_regno_offset function.
* regmove.c (regmove_optimize): Use SUBREG_BYTE.
(optimize_reg_copy_3): Use gen_lowpart_SUBREG.
* regs.h (REG_SIZE): Allow target to override.
(REGMODE_NATURAL_SIZE): New macro which target can override.
* reload.c (reload_inner_reg_of_subreg): subreg_regno should be used
on the entire subreg rtx.
(push_reload): Use SUBREG_BYTE in comments and code.
(find_dummy_reload): Use subreg_regno_offset. Only adjust offsets
for hard registers inside subregs.
(operands_match_p): Use subreg_regno_offset.
(find_reloads): Use SUBREG_BYTE and only advance offset for subregs
containing hard regs.
(find_reload_toplev): Use SUBREG_BYTE. Remove byte endian
corrections when fixing up MEM subregs.
(find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and
subreg_regno_offset where appropriate.
(find_reloads_subreg_address): Use SUBREG_BYTE. Remove
byte endian corrections when fixing up MEM subregs.
(subst_reloads): When combining two subregs, make sure final
offset is congruent to subreg's mode size.
(find_replacement): Use SUBREG_BYTE and subreg_regno_offset.
(refers_to_regno_for_reload_p): Use subreg_regno.
(reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset.
* reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian
correction code for memory subreg fixups.
(forget_old_reload_1): Use subreg_regno_offset.
(choose_reload_regs): Use subreg_regno.
(emit_input_reload_insns): Use SUBREG_BYTE.
(reload_combine_note_store): Use subreg_regno_offset.
(move2add_note_store): Use subreg_regno_offset.
* resource.c (update_live_status, mark_referenced_resources): Use
subreg_regno function.
(mark_set_resources): Use subreg_regno function.
* rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE.
(subreg_regno_offset, subreg_regno): Define prototypes.
(subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions.
(gen_lowpart_SUBREG): Add prototype.
* rtl.texi (subreg): Update to reflect new byte offset representation.
Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now.
* rtlanal.c (refers_to_regno_p): Use subreg_regno.
(reg_overlap_mentioned_p): Use subreg_regno.
(replace_regs); Make sure final offset of combined subreg is
congruent to size of subreg's mode.
(subreg_regno_offset): New function.
(subreg_regno): New function.
* sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE.
* sdbout.c (sdbout_symbol): Compute offset using alter_subreg.
* stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG.
* tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead.
(SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides.
* config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno.
(a29k_get_reloaded_address): Use SUBREG_BYTE.
(print_operand): Use SUBREG_BYTE.
* config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE.
* config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE.
(arm_reload_out_hi): Use SUBREG_BYTE.
* config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset
instead of SUBREG_WORD.
(d30v_print_operand_memory_reference): Use subreg_regno_offset.
* config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix
SUBREG creation to use byte offset.
* config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit
inverted load insns): Fix explicit rtl subregs to use byte
offsets.
* config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3,
udivsi3, umodsi3): Generate SUBREGs with byte offsets.
* config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE.
* config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl
to use byte offsets.
(unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets.
* config/i960/i960.md (extendhisi2): Generate SUBREGs with byte
offsets, also make sure it is congruent to SUBREG's mode size.
(extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2,
unnamed ldob insn): Generate SUBREGs with byte offset.
(zero_extendqihi2): SUBREG's are byte offsets.
* config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE.
(m68hc11_gen_highpart): Use SUBREG_BYTE.
* config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2,
zero-extendqisi2): Generate SUBREGs with byte offset.
(umulsidi3, mulsidi3, subreghi1ashrdi_const32,
subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit
subregs in rtl to use byte offsets.
* config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset.
* config/mips/mips.c (mips_move_1word): Use subreg_regno_offset.
(mips_move_2words): Use subreg_regno_offset.
(mips_secondary_reload_class): Use subreg_regno_offset.
* config/mips/mips.md (DImode plus, minus, move, and logical op
splits): Fixup explicit subregs in rtl to use byte offsets.
* config/mn10200/mn10200.c (print_operand): Use subreg_regno function.
* config/mn10300/mn10300.c (print_operand): Use subreg_regno function.
* config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in
rtl to use byte offsets.
* config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE.
* config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit
subregs to use byte offsets.
* config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1):
Fixup explicit subregs in rtl to use byte offsets.
* config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE
and remove byte endian correction code.
* config/sh/sh.c (output_movedouble): Use subreg_regno.
(gen_ashift_hi): Use SUBREG_BYTE.
(regs_used): Use subreg_regno_offset.
(machine_dependent_reorg): Use subreg_regno_offset.
* config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE.
* config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno.
(movdf_i4): Subregs are byte offsets now.
* config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE.
* config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed.
(REGMODE_NATURAL_SIZE): Override.
(REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode.
* config/sparc/sparc.md (TFmode move splits): Generate SUBREGs
with byte offsets.
(zero_extendhisi2, zero_extendqidi2_insn, extendhisi2,
extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn,
extendqidi2): Generate SUBREGs with byte offsets, also make sure
it is congruent to SUBREG's mode size.
(smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte
offsets.
(cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc,
cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2,
lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper
SUBREG_BYTE offset for non-paradoxical subregs in patterns.
* config/v850/v850.c (print_operand, output_move_double): Use
subreg_regno function.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41058 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/recog.c')
-rw-r--r-- | gcc/recog.c | 150 |
1 files changed, 99 insertions, 51 deletions
diff --git a/gcc/recog.c b/gcc/recog.c index 1596a019067..e278f985529 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -517,13 +517,15 @@ validate_replace_rtx_1 (loc, from, to, object) if (GET_CODE (XEXP (x, 0)) == SUBREG) { if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD) - to = operand_subword (to, SUBREG_WORD (XEXP (x, 0)), + to = operand_subword (to, + (SUBREG_BYTE (XEXP (x, 0)) + / UNITS_PER_WORD), 0, GET_MODE (from)); else if (GET_MODE_CLASS (GET_MODE (from)) == MODE_INT && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) <= HOST_BITS_PER_WIDE_INT)) { - int i = SUBREG_WORD (XEXP (x, 0)) * BITS_PER_WORD; + int i = SUBREG_BYTE (XEXP (x, 0)) * BITS_PER_UNIT; HOST_WIDE_INT valh; unsigned HOST_WIDE_INT vall; @@ -569,26 +571,21 @@ validate_replace_rtx_1 (loc, from, to, object) break; case SUBREG: - /* In case we are replacing by constant, attempt to simplify it to non-SUBREG - expression. We can't do this later, since the information about inner mode - may be lost. */ + /* In case we are replacing by constant, attempt to simplify it to + non-SUBREG expression. We can't do this later, since the information + about inner mode may be lost. */ if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from)) { - if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD - && GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD - && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) - { - rtx temp = operand_subword (to, SUBREG_WORD (x), - 0, GET_MODE (from)); - if (temp) - { - validate_change (object, loc, temp, 1); - return; - } - } - if (subreg_lowpart_p (x)) + int offset, part; + unsigned HOST_WIDE_INT val; + + /* A paradoxical SUBREG of a VOIDmode constant is the same constant, + since we are saying that the high bits don't matter. */ + if (GET_MODE (to) == VOIDmode + && (GET_MODE_SIZE (GET_MODE (x)) + >= GET_MODE_SIZE (GET_MODE (from)))) { - rtx new = gen_lowpart_if_possible (GET_MODE (x), to); + rtx new = gen_lowpart_if_possible (GET_MODE (x), to); if (new) { validate_change (object, loc, new, 1); @@ -596,13 +593,67 @@ validate_replace_rtx_1 (loc, from, to, object) } } - /* A paradoxical SUBREG of a VOIDmode constant is the same constant, - since we are saying that the high bits don't matter. */ - if (GET_MODE (to) == VOIDmode - && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (from))) + offset = SUBREG_BYTE (x) * BITS_PER_UNIT; + switch (GET_CODE (to)) { - validate_change (object, loc, to, 1); - return; + case CONST_DOUBLE: + if (GET_MODE (to) != VOIDmode) + break; + + part = offset >= HOST_BITS_PER_WIDE_INT; + if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT + && BYTES_BIG_ENDIAN) + || (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT + && WORDS_BIG_ENDIAN)) + part = !part; + val = part ? CONST_DOUBLE_HIGH (to) : CONST_DOUBLE_LOW (to); + offset %= HOST_BITS_PER_WIDE_INT; + + /* FALLTHROUGH */ + case CONST_INT: + if (GET_CODE (to) == CONST_INT) + val = INTVAL (to); + + { + /* Avoid creating bogus SUBREGs */ + enum machine_mode mode = GET_MODE (x); + enum machine_mode inner_mode = GET_MODE (from); + + /* We've already picked the word we want from a double, so + pretend this is actually an integer. */ + if (GET_CODE (to) == CONST_DOUBLE) + inner_mode = SImode; + + if (GET_MODE_CLASS (mode) != MODE_INT) + abort (); + + if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN) + { + if (WORDS_BIG_ENDIAN) + offset = GET_MODE_BITSIZE (inner_mode) + - GET_MODE_BITSIZE (mode) - offset; + if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN + && GET_MODE_SIZE (mode) < UNITS_PER_WORD) + offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode) + - 2 * (offset % BITS_PER_WORD); + } + + if (offset >= HOST_BITS_PER_WIDE_INT) + to = ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx; + else + { + val >>= offset; + if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT) + val = trunc_int_for_mode (val, mode); + to = GEN_INT (val); + } + + validate_change (object, loc, to, 1); + return; + } + + default: + break; } } @@ -612,15 +663,26 @@ validate_replace_rtx_1 (loc, from, to, object) && rtx_equal_p (SUBREG_REG (x), from)) { if (GET_MODE (x) == GET_MODE (SUBREG_REG (to)) - && SUBREG_WORD (x) == 0 && SUBREG_WORD (to) == 0) + && SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0) { validate_change (object, loc, SUBREG_REG (to), 1); return; } - validate_change (object, loc, - gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to), - SUBREG_WORD (x) + SUBREG_WORD (to)), 1); + /* Make sure the 2 byte counts added together are an even unit + of x's mode, and combine them if so. Otherwise we run + into problems with something like: + (subreg:HI (subreg:QI (SI:55) 3) 0) + we end up with an odd offset into a HI which is invalid. */ + + if (SUBREG_BYTE (to) % GET_MODE_SIZE (GET_MODE (x)) == 0) + validate_change (object, loc, + gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to), + SUBREG_BYTE(x) + SUBREG_BYTE (to)), + 1); + else + validate_change (object, loc, to, 1); + return; } @@ -636,15 +698,10 @@ validate_replace_rtx_1 (loc, from, to, object) && ! MEM_VOLATILE_P (to) && GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to))) { - int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + int offset = SUBREG_BYTE (x); enum machine_mode mode = GET_MODE (x); rtx new; - if (BYTES_BIG_ENDIAN) - offset += (MIN (UNITS_PER_WORD, - GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) - - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))); - new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset)); MEM_COPY_ATTRIBUTES (new, to); validate_change (object, loc, new, 1); @@ -694,8 +751,8 @@ validate_replace_rtx_1 (loc, from, to, object) int offset = pos / BITS_PER_UNIT; rtx newmem; - /* If the bytes and bits are counted differently, we - must adjust the offset. */ + /* If the bytes and bits are counted differently, we + must adjust the offset. */ if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN) offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) - offset); @@ -1040,7 +1097,6 @@ general_operand (op, mode) enum machine_mode mode; { register enum rtx_code code = GET_CODE (op); - int mode_altering_drug = 0; if (mode == VOIDmode) mode = GET_MODE (op); @@ -1078,11 +1134,6 @@ general_operand (op, mode) op = SUBREG_REG (op); code = GET_CODE (op); -#if 0 - /* No longer needed, since (SUBREG (MEM...)) - will load the MEM into a reload reg in the MEM's own mode. */ - mode_altering_drug = 1; -#endif } if (code == REG) @@ -1113,8 +1164,6 @@ general_operand (op, mode) return 0; win: - if (mode_altering_drug) - return ! mode_dependent_address_p (XEXP (op, 0)); return 1; } @@ -1467,13 +1516,9 @@ indirect_operand (op, mode) if (! reload_completed && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM) { - register int offset = SUBREG_WORD (op) * UNITS_PER_WORD; + register int offset = SUBREG_BYTE (op); rtx inner = SUBREG_REG (op); - if (BYTES_BIG_ENDIAN) - offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op))) - - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner)))); - if (mode != VOIDmode && GET_MODE (op) != mode) return 0; @@ -2482,7 +2527,10 @@ constrain_operands (strict) { if (GET_CODE (SUBREG_REG (op)) == REG && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER) - offset = SUBREG_WORD (op); + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), + GET_MODE (SUBREG_REG (op)), + SUBREG_BYTE (op), + GET_MODE (op)); op = SUBREG_REG (op); } |